views:

210

answers:

1

I am trying to migrate my application from manual build to autoconf, which is working very nicely so far. But I have one static library that I can't figure out how to integrate. That library will NOT be located in the usual library locations - the location of the binary (.a file) and header (.h file) will be given as a configure argument. (Notably, even if I move the .a file to /usr/lib or anywhere else I can think of, it still won't work.) It is also not named traditionally (it does not start with "lib" or "l").

Manual compilation is working with these (directory is not predictable - this is just an example):

gcc ...  -I/home/john/mystuff  /home/john/mystuff/helper.a

(Uh, I actually don't understand why the .a file is referenced directly, not with -L or anything. Yes, I have a half-baked understanding of building C programs.)

So, in my configure.ac, I can use the relevant configure argument to successfully find the header (.h file) using AC_CHECK_HEADER. Inside the AC_CHECK_HEADER I then add the location to CPFLAGS and the #include of the header file in the actual C code picks it up nicely.

Given a configure argument that has been put into $location and the name of the needed files are helper.h and helper.a (which are both in the same directory), here is what works so far:

AC_CHECK_HEADER([$location/helper.h], 
    [AC_DEFINE([HAVE_HELPER_H], [1], [found helper.h]) 
    CFLAGS="$CFLAGS -I$location"])

Where I run into difficulties is getting the binary (.a file) linked in. No matter what I try, I always get an error about undefined references to the function calls for that library. I'm pretty sure it's a linkage issue, because I can fuss with the C code and make an intentional error in the function calls to that library which produces earlier errors that indicate that the function prototypes have been loaded and used to compile.

I tried adding the location that contains the .a file to LDFLAGS and then doing a AC_CHECK_LIB but it is not found.

Maybe my syntax is wrong, or maybe I'm missing something more fundamental, which would not be surprising since I'm a newbie and don't really know what I'm doing.

Here is what I have tried:

AC_CHECK_HEADER([$location/helper.h], 
    [AC_DEFINE([HAVE_HELPER_H], [1], [found helper.h]) 
    CFLAGS="$CFLAGS -I$location"; 
    LDFLAGS="$LDFLAGS -L$location"; 
    AC_CHECK_LIB(helper)])

No dice. AC_CHECK_LIB is looking for -lhelper I guess (or libhelper?) so I'm not sure if that's a problem, so I tried this, too (omit AC_CHECK_LIB and include the .a directly in LDFLAGS), without luck:

AC_CHECK_HEADER([$location/helper.h], 
    [AC_DEFINE([HAVE_HELPER_H], [1], [found helper.h]) 
    CFLAGS="$CFLAGS -I$location"; 
    LDFLAGS="$LDFLAGS -L$location/helper.a"])

To emulate the manual compilation, I tried removing the -L but that doesn't help:

AC_CHECK_HEADER([$location/helper.h], 
    [AC_DEFINE([HAVE_HELPER_H], [1], [found helper.h]) 
    CFLAGS="$CFLAGS -I$location"; 
    LDFLAGS="$LDFLAGS $location/helper.a"])

I tried other combinations and permutations, but I think I might be missing something more fundamental....

================ UPDATE

I got it to work with a hard-coded path to the .a file in Makefile.am using _LDADD like this:

myprog_LDADD=/home/john/mystuff/helper.a

But I can't predict the location of the .a file. For some reason, defining myprog_LDADD in configure.ac doesn't work (I wish it did, so I can use my dynamic location variable), and no combination of changes to LDFLAGS, myprog_LDFLAGS, AM_LDFLAGS seems to work.

If, in Makefile.am, I try to use the variable location that is defined in configure.ac, it doesn't work

myprog_LDADD=($location)helper.a

================ UPDATE

I think I figured it out, but since I have no idea what I'm doing, I'd REALLY appreciate some feedback. I used AC_SUBST() to get myprog_LDADD to work from configure.ac, so the final solution looks like this:

AC_CHECK_HEADER([$location/helper.h], 
    [AC_DEFINE([HAVE_HELPER_H], [1], [found helper.h]) 
    CFLAGS="$CFLAGS -I$location" 
    myprog_LDADD="$location/helper.a" 
    AC_SUBST(myprog_LDADD)])
A: 

You can set the location in configure.ac:

LOCATION=/home/john/mystuff
AC_SUBST(LOCATION)

AC_SUBST defines the variable $LOCATION in all your Makefile.ams and also replaces all occurrences of @LOCATION@ with the contents of $LOCATION. So then in your Makefile.am you can do

myprog_CPPFLAGS="-I$LOCATION"
myprog_LDADD="$LOCATION/helper.a"

PS. The reason why you need to reference the library directly is because -l looks for a properly-named library (e.g. libhelper.a) in the system library directories. However, since there's not all that much difference between a static library and an object file, there's no need to magically reference it using -l; you can just compile it into your program like you are doing now.

ptomato
OK, thank you. Seeing what you've suggested, it looks like I did pretty much the same thing, by using AC_SUBST() to propagate myprog_LDADD to the Makefiles. Is there anything wrong with my method compared to yours?THANK YOU FOR THE HELP!!!!!!
EBM
Additionally, is there some reason putting helper.a into LDFLAGS doesn't work but adding it to myprog_LDADD does? I obviously don't understand the difference between the two. Again, THANK YOU.
EBM
Your method defines myprog_LDADD in all of the makefiles, not just the one you need it in. This could potentially cause problems.
ptomato
Sorry, last question - I notice people seem to always suggest adding include paths to CXXFLAGS along with CFLAGS. I only added to CFLAGS... is that going to be problematic?
EBM
LDFLAGS is for linker flags, LDADD is for libraries to be linked in. The difference is explained in the Automake manual here: http://www.gnu.org/software/automake/manual/html_node/Linking.html#Linking
ptomato
Not CXXFLAGS - it's CPPFLAGS. CXX is C plus plus, CPP is C preprocessor. The moronic naming is because the C preprocessor was invented before C++, I suppose. The reason they go in CPPFLAGS is that #include directives are processed by the C preprocessor.
ptomato
You are VERY KIND to help. Any comment on whether I need to worry about CXXFLAGS?
EBM
Don't worry about CXXFLAGS if you're not using C++. By the way, you might want to read this: http://www.lrde.epita.fr/~adl/autotools.html -- I never understood autotools properly until I read it, but it helped me tremendously.
ptomato
Oops, overlapping comments. Sorry about that.Regarding CXXFLAGS, I have seen it suggested in places like:http://stackoverflow.com/questions/517580/library-resolution-with-autoconfAnd I swear I saw someone specifically say CXX should be used and NOT CPP. What you say regarding the preprocessor makes a lot of sense, however what does adding an include path to CXX do?And how does CFLAGS relate to all this? Right now I'm only adding my path to CFLAGS and it works fine....
EBM
CXXFLAGS go to the C++ compiler, for example g++, and CFLAGS go to the C compiler, for example gcc. What I _think_, but am not certain about, is that putting `-I` in CFLAGS or CXXFLAGS works okay, because gcc and g++ use the same preprocessor, call it automatically, and pass along any preprocessor flags that they get. If you ever decided to split up those stages of compilation, you would have problems.
ptomato
THANK YOU, ptomato! I **REALLY** appreciate your patience with me and taking your time to follow up.
EBM