Evaluate automake variable only once - makefile

We are using automake & autoconf to build our multi-package software. I was wondering how to fill a variable with the output of e.g. shell-scripts once and reuse this, e.g. for needed include dirs
INCLUDES := -I`some-ext-config --incdir`
Using := instead of = here makes this variable filled once so some-ext-config will only be called once (AFAIK this comes from plain make). Of course INCLUDES is the depreciated cousin of AM_CPPFLAGS, but would I have used that one instead, the shell script would have been called for each compile.
Using INCLUDES instead of AM_CPPFLAGS is an acceptable solution for me (though I imagine there might be portability issues), but I have no solution for e.g. LDFLAGS for a libtool library
libmylib_la_LDFLAGS := `some-ext-config --ldflags` # will always be evaluated
What is the general solution inside automake if I want to make sure these external tools are not called multiple times? I would like to stay away from using an obvious AC_SUBST in configure.ac since we have to make sure our packages can be build both from subdirectories (some configure.ac in there) and with an recursive make from the top-level and a configure.ac there which shouldn't need to know too much about the different subprojects.

:= is GNU-make specific, so you are advised to use just = in automake. If you do not want to run the shell script everytime INCLUDES (or AM_CPPFLAGS, does not matter, it would occur with either), then run the script in configure.ac and use variable substitution via AC_SUBST. That is essentially what pkg-config would do — and come to speak of it, you could just use that instead of some-ext-config if there is a .pc file.
# configure.ac
libfoo_CPPFLAGS=$(some-ext-config --incdir);
libfoo_LIBS=$(some-ext-config --libs);
AC_SUBST([libfoo_CPPFLAGS])
AC_SUBST([libfoo_LIBS])
# Makefile.am
AM_CPPFLAGS = -Iwhatever ${libfoo_CPPFLAGS}
bin_PROGRAMS = foo
foo_LDADD = ${libfoo_LIBS}

This is a more lengthy explanation of what I suggested in a comment to jørgensen's answer.
I understand your top-level configure.ac must generate the makefiles of multiple sub-projects, and performs the required tests so that you don't have to run the configure in any subproject (a sub-configure serves only when you want to work on this particular sub-project).
In that case, you want to avoid duplicating as much stuff as possible from various configure.ac. I suggest you factor all the code of the sub-configure that must also be performed by the top-level configure in an m4 macro. This includes tests, AC_SUBSTS, and Makefile declarations.
For instance using only one-subproject. Here is a top-level ./configure.ac:
AC_INIT([toplevel], [1.0])
AM_INIT_AUTOMAKE([foreign -Werror])
SUB1_COMMON([sub1/]) dnl Stuff from the subproject
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
With ./Makefile.am:
ACLOCAL_AMFLAGS = -I sub1/m4
SUBDIRS = sub1
Now here is sub1/configure.ac for the sub-project:
AC_INIT([sub1], [1.0])
AM_INIT_AUTOMAKE([foreign -Werror])
AC_CONFIG_MACRO_DIR([m4])
SUB1_COMMON
AC_OUTPUT
With SUB1_COMMON defined in m4/common.m4:
AC_DEFUN([SUB1_COMMON],
[AC_SUBST([PYTHON3LIB], [`pkg-config --libs python3`])
AC_CONFIG_FILES([$1Makefile])])
And finally sub1/Makefile.am is just:
ACLOCAL_AMFLAGS = -I m4
# Build something.
...
The SUB1_COMMON contains all the code you want to share between the two configure.ac files, and use argument $1 to relocate the config files appropriately. In this example, the variable PYTHON3LIB will be defined regardless of which configure were run.

Related

make variables that depend on a target

I have a Variable in make that is dependant on a file that must be built before the variable can be set, is there a way to get this to work?
parsable_file: dependancies
commands to make parsable_file
targets=$(shell parse_cmd parsable_file)
$(targets): parsable_file
command to make targets
.phony: all
all:$(targets)
If I run $ make parsable_file && make all this will work (I get an error that parse_cmd cant find parsable_file but it works), but just make all will not work. Is there a Make idiom for this?
Set the variable in a file that you include in the main makefile and include a rule in the main makefile for how to build it (the one you already have should be fine).
I believe that will do what you want.
See Including Other Makefiles and How Makefiles Are Remade (which is linked from the first section) for more details on this concept.
Also, unless parseable_file has a usage independent from that parse_cmd call, it should be possible to do the creation and the parsing at the same time and just have the resulting makefile contain the correct value for $(targets) in one step.

canonical way to use pkg-config variables in Makefile.am

A bunch of projects foo-A-B, foo-B-C, foo-A-C etc. each depend on foo-A, foo-B, foo-C etc.
Each of foo-X installs a pkg-config file (foo-X.pc.in) which contains a variable srcdir=#datarootdir#/foo/foo-B. A foo-X-Y project needs to refer to files in Xsrcdir and Ysrcdir.
Currently we do it like this in configure.ac:
PKG_CHECK_MODULES([foo_X], [foo-X])
AC_ARG_VAR(XSRC, "Source directory for foo-X")
AS_IF([test -z "$XSRC"], [XSRC=`pkg-config --variable=srcdir foo-X`])
(so Makefile.am gets to have rules like compile "$XSRC"/file.bar $#). This also lets developers override XSRC on running ./configure.
My question: is there a more canonical way to use non-standard pkg-config variables in autotools configury/makefiles? For e.g. libdir, I see pkg-config sets the variables itself so no configure.ac line is needed apart from PKG_CHECK_MODULES; are there other m4 macros we should be using?
I know this is fairly late, but since somebody was asking me about this recently, I thought it might be worth answering this too.
What you're looking for is PKG_CHECK_VAR, indeed most of that code can be replaced by a single line:
PKG_CHECK_VAR([XSRC], [foo-X], [srcdir], ,
AC_MSG_FAILURE([Unable to find value for XSRC]))
The error message is a bit less clear than the one triggered by PKG_CHECK_MODULES, but it also triggers in case the srcdir variable is not defined.
I wrote some more details as part of my Autotools Mythbuster.

Out of tree kernel modules: Multiple module, single Makefile, same source file, different build options

I am building a set of Linux kernel modules using shared source code. From what I understand, the Makefile has to be named "Makefile" so I have to use the same Makefile to build two different modules. How can I build two different modules, within the same Makefile, with the same source code, but with two different build options?
For example, my modules are called module1 and module2. So I have the following line to define them:
obj-m := module1.o module2.o
Among other files, both module1 and module2 need to use the same source file code.c, but built with different build options. So say for example, the Makefile contains the following lines:
module1-objs = module1_code.o other_code.o
module2-objs = module2_code.o other_code.o
I want module1_code.o and module2_code.o to be built from code.c, but with different options. Specifically, I want one module1_code.o with a macro defined -DPREPROCEFFOR_FLAG=1, and module2_code.o built without the macro.
From what I understand, the system of Makefiles used in Linux implicitly infers that for an object file called "code.o", the source file is called "code.c", so how would I achieve this? Is is possible? Is there a better way to do this?
You have a problem here, because you obviously have code.c being compiled differently when -DPREPROCEFFOR_FLAG=1 is defined, but once it's compiled into code.o, make won't care about preprocessor flags or whatever because code.o will be already up to date.
You need a way to build code.c to different object files with different C flags. There's probably a clean way to do this (had no chance with O= for out of tree modules), but here's my innelegant yet effective solution for the moment:
my_modules:
cp code.c code_noflags.c
cp code.c code_withflags.c
make -C $$KDIR M=$$PWD modules
rm code_noflags.c code_withflags.c
# module objects
obj-m := module1.o module2.o
# module1 specifics
module1-y := code_withflags.o
CFLAGS_code_withflags.o := -DPREPROCEFFOR_FLAG=1
# module2 specifics
module2-y := code_noflags.o
Just call:
$ make KDIR=/path/to/kernel
You can verify the preprocessor flag is passed to the source file for the right object with:
$ make KDIR=/path/to/kernel V=1 | grep PREPRO
You could also have two separate directories for each module, if this is possible, and have a symbolic link code.c in each one pointing to the common real code.c. However, this is still hackish and doesn't feel right.
One simple solution is, continuing from your Makefile
obj-m := module1.o module2.o
module1-objs = module1_code.o other_code.o
module2-objs = module2_code.o other_code.o
to add two more source files, module1_code.c and module2_code.c.
Then module1_code.c just looks like:
#define PREPROCEFFOR_FLAG 1
#include "code.c"
and module2_code.c is:
#include "code.c"
Or if you like, change the names in the Makefile and source files so that the second include without a define isn't necessary. Also you could make the two source files nothing but an include and use the CFLAGS_module1_code.o variable to add the -D... option to the compiler if you prefer.
This is similar to what happens in the upstream kernel with arch/x86/boot/video-vesa.c and arch/x86/realmode/rm/video-vesa.c etc., where the realmode file just contains:
#include "../../boot/video-vesa.c"
and the video-vesa.c code ends up getting compiled twice with different compiler flags.
This seems preferable to copying the source files, since you end up with a mess there if you want to use the O=... option to the kernel build to keep a clean source tree and build in a separate object tree.

How to delay effect of "include" directive in Makefile.am until make (avoid "include" being seen by Automake)?

My Makefile.am includes a file (with various defined variables), for example:
include make.config
...
The problem is that this file is in turn generated by a tool (i.e. config.generator.sh) based on some input file (i.e. input.dat). The straightforward and wrong idea would be to add a rule to generate make.config:
make.config : input.dat
config.generator.sh input.dat > make.config
include make.config
...
Although this content is perfectly working makefile on its own without automake, the idea is doomed with automake. The make.config file is included by automake before I even have a chance to execute make (and it fails as the file is not yet generated):
automake: cannot open < make.config: No such file or directory
Is there a way to postpone effect of include directive until make is run (possibly by using another directive)?
There is probably a way to simply run arbitrary commands before any makefile generation is done (i.e. AC_CONFIG_COMMANDS*). But the question is more complicated because the config.generator.sh is supposed to use executables which are in turn also generated during the same build process (so there is a dependency chain which logically has to be managed by makefiles from the same project). The documentation simply confirms the logic without providing alternatives.
The solution is described in this email of Automake's mailing list.
The idea is to use include directives inside small regular "wrapper" makefile and include Automake-generated Makefile into it (note the upper case M). Because makefile is not an Automake template, the include works as expected triggering builds for non-existing files.
Note that:
By default make utility will search for makefile first (not for Makefile) making this approach working seamlessly.
It is still recommended to specify all rules inside Makefile.am and keep the "wrapper" makefile simple. The rules for non-existing files will naturally come from the generated Makefile anyway.
I've come across the same annoying problem today when moving my OCaml project to Autotools. My solution is to use autoconf's substitution to go around automake. For the above example, I'd add a substitution to configure.ac:
AC_SUBST([include_make_config], ["include make.config"])
and adjust Makefile.am, replacing the include directive with the autoconf variable reference:
make.config : input.dat
config.generator.sh input.dat > make.config
#include_make_config#
...
automake doesn't touch the #include_make_config# line so it gets carried over into the generated Makefile.in. When autoconf takes over, it substitutes the variable with include make.config in the final Makefile.
Note: I use this with OCaml's ocamldep dependency generator.

With autoconf/automake, how do I specify include file paths?

Let's say I want to have the generate makefile pass some specific header paths to g++.
What do I need to add to configure.ac or Makefile.am to specify this?
(note - I do not want to pass it in the CPPFLAGS with ./configure. I want those paths baked in before that step)
EDIT:
Specifically, I want to to include let's say /usr/include/freetype and /mypath/include.
I put AC_CHECK_HEADERS([freetype/config/ftheader.h]) and it passes, but doesn't seem to add it to the -I passed to g++.
I also did try adding CPPFLAGS=-I.:/usr/include/freetype:/mypath/include, but it screws up and puts -I twice, the first as -I. and it ignores the 2nd -I.
Since the question was about what to put in an automakefile, I would have thought AM_CPPFLAGS was the right variable to use to add includes and defines for all C/C++ compiles. See http://www.gnu.org/software/automake/manual/html_node/Program-Variables.html
Example:
AM_CPPFLAGS = -I/usr/local/custom/include/path
Hard coding paths into the package files is absolutely the wrong thing to do. If you choose to do that, then you need to be aware that you are violating the basic rules of building a package with the autotools. If you specify /mypath/include in your package files, you are specifying things specific to your machine in a package that is intended to work on all machines; clearly that is wrong. It looks like what you want is for your package (when built on your machine) to look for header files in /mypath. That is easy to accomplish without bastardizing your package. There are (at least) 3 ways to do it:
Use a config.site file. In /usr/local/share/config.site (create this file if necessary), add the line:
CPPFLAGS="$CPPFLAGS -I/mypath/include"
Now any package using an autoconf generated configure script with the default prefix (/usr/local) will append -I/mypath/include to CPPFLAGS and the headers in /mypath/include will be found.
If you want the assignment to be made for all builds (not just those to be installed in /usr/local), you can use this:
Put the same line specifying CPPFLAGS in $HOME/config.site, and set CONFIG_SITE=$HOME/config.site in the environment of your default shell. Now, whenever you run an autoconf generated configure script, the assignments from $HOME/config.site will be made.
Simply specify CPPFLAGS in the environment of your default shell.
All of these solutions have two primary advantages over modifying your build files. First, they will work for all autoconf generated packages (as long as they follow the rules and don't do things like assigning user variables such as CPPFLAGS in the build files). Second, they do not put your machine specific information into a package that ought to work on all machines.

Resources