I'm working on a C++ project that uses autoconf
& automake
, and I'm struggling to correctly set up the include paths in *CPPFLAGS
. I've read about 3 hours worth of documents, and I can't figure it out yet. I'm not looking for a hack, but for the correct way to do this. Here is my conundrum.
As I see it, there are 3 completely different sources for include paths:
- External libraries that must be installed along with my package, which are configured by
configure --with-XXX=<PATH>
. - Within my package, some source files use
#include <file.h>
even whenfile.h
is part of the package, so to compile them, I must set the include path correctly. (Note, it's not an option to edit all these files.) - Whimsical (or not) standards specify the user must be allowed to specify their own (extra) include paths. That is, I shouldn't be setting
CPPFLAGS
at all.
In my current setup:
- Type 1 paths are set inside
configure.ac
byAC_SUBST(CPPFLAGS, "$CPPFLAGS -I<path>")
. - Type 2 paths are set inside
Makefile.am
bytest_CPPFLAGS = -I<path>
. - Type 3 cannot be set. More exactly, if the user sets
CPPFLAGS
before runningmake
, this overrides Type 1 settings, causing compilation to fail. Of course, the user could try to useCXXFLAGS
instead, but that one has a different use (remember, I'm asking for the correct way to do this, not a hack).
I tried to fix this by setting Type 1 paths using AM_CPPFLAGS
inside configure.ac
. (For reference: if you set AM_CPPFLAGS
instead of CPPFLAGS
, but you still need to run some checks such as AC_CHECK_HEADERS
, you need to temporarily set CPPFLAGS
and then revert it for the checks to work; this is explained here.) This frees up CPPFLAGS
for Type 3 paths, but unfortunately the compilation fails because the Makefile
-s that gets produced by configure
will only use AM_CPPFLAGS
if no specialized <target>_CPPFLAGS
exists. So, if test_CPPFLAGS
exists with a Type 2 path, compiling test
will fail because it doesn't get the Type 1 path.
A fix would be to specify inside Makefile.am
to always use AM_CPPFLAGS
. But is this "by the book"? Can I do this in a global way, or do I have to edit every single target_CPPFLAGS
? Is there another "correct" solution?
I know it's difficult to get a straight answer from the autotools manuals. There are a couple of good start-to-finish tutorials here and here.
There isn't a standard variable for package-specific
*CPPFLAGS
in autoconf.configure
can be invoked withCPPFLAGS=...
, and automake will add thisCPPFLAGS
to the relevant makefile rules - search forCPPFLAGS
in aMakefile.in
file for examples. For that reason, I suggest that you not use this variable for anything else.Add flags in
Makefile.am
to theAM_CPPFLAGS
variable (the default for all preprocessor calls) or override individual preprocessor flags withtarget_CPPFLAGS
. In the example of a 3rd party library, it's best to use a name like:FOO_CPPFLAGS
to hold preprocessor options, e.g.,and in the
Makefile.am
:The
top_srcdir
variable is defined byconfigure
- I use it to illustrate the 2nd case. Let's say you havefile.h
in another directoryother
, under the top-level directory.-I$(top_srcdir)
allows you to include it as<other/file.h>
. Alternatively,-I$(top_srcdir)/other
would allow you to include it as<file.h>
.Another useful preset variable is
srcdir
- the current directory.-I$(srcdir)
is added toAM_CPPFLAGS
by default. So iffile.h
is in the current directory you can include it with<file.h>
or even"file.h"
. Ifother
was a 'sibling' directory,-I$(srcdir)/..
would allow you to include<other/file.h>
, and-I$(srcdir)/../other
would allow<file.h>
.I'd also add that some packages install a pkg-config
.pc
file. Provided the installation of pkg-config is set up to search the right directories, you might find thePKG_CHECK_MODULES
macro very useful.