Automake default rule for targets with no extension? - makefile

Is there a generic was to specify a rule for something that goes from something with an extension to something with no extension? (in this case, '.in' to '')?
I have a project that's using automake. I have some config file templates that need substitutions before installing them. For example, I have a 'foo.ini.in' file that I want to use to create 'foo.ini'. I have a few of these scattered throughout the codebase. However, for each one, I need to create a custom Makefile rule to make them work. Is there a better way? I currently do this in Makefile.am:
bazdir=$(libdir)/#PACKAGE_NAME#/baz
EXTRA_DIST = foo.ini.in bar.ini.in
CLEANFILES = foo.ini bar.ini
foo.ini: foo.ini.in
sed -e 's|#LIBDIR#|$(bazdir)|g' $< > $#
bar.ini: bar.ini.in
sed -e 's|#LIBDIR#|$(bazdir)|g' $< > $#
This works fine, but I need to duplicate the rule for every file. I'd like to write one rule that will do the substitution for any 'ini.in' files to 'ini' files. I've tried:
%.ini.in: %.ini
sed ....
but autoconf complains that % pattern substitution is a non-portable gnumake-ism. It also doesn't like
.ini.in.ini:
sed .....
.. which I can't really blame it for not liking, because I can't even parse that.
Is there a way to do this?
NOTE: I can not use AC_CONFIG_FILES to do this substitution, because 'bazdir' is not fully expanded in that case.

Fortunately, there's a much better way: let the 'configured' files be generated from the templates using the configure script itself. As I mentioned in the comment, I don't see any reason to try to expand $bazdir in the Makefile.am itself. Maybe you can clear this up for me if there's some special reason for this.
In the configure.ac script, substitution variables are defined with the AC_SUBST macro. I'm guessing you want to replace LIBDIR with the value of $bazdir. Note that LIBDIR isn't a good choice of name, as libdir is already used in configure scripts; so let's use a variable name prepended with a project name: BAZ_LIBDIR
1/. set bazdir in the configure script: bazdir="${libdir}/${PACKAGE_NAME}/baz", and substitute with: AC_SUBST(BAZ_LIBDIR, $bazdir). Alternatively, just assign the value to BAZ_LIBDIR and use the single argument form of AC_SUBST. BAZ_LIBDIR is now ready for substitution...
2/. At the end of configure.ac, specify the files to be generated from their <file>.in templates, with AC_CONFIG_FILES. Typically this will list Makefile's, as well as data files, where the .in suffix is implicit.
Assuming a projectdir tree... could be any sort of tree layout of course:
BAZ_LIBDIR="${libdir}/${PACKAGE_NAME}/baz"
AC_SUBST(BAZ_LIBDIR)
...
AC_CONFIG_FILES([Makefile projectdir/Makefile])
AC_CONFIG_FILES([projectdir/foo.ini projectdir/bar.ini])
...
AC_OUTPUT
Instances of #BAZ_LIBDIR# in the <file>.ini.in files will be replaced with the substitution value. No arcane sed invocations are required to generate <file>.ini files.
Another nice feature is that you needn't add foo.ini.in or bar.ini.in to the EXTRA_DIST variable in the Makefile.am - and make distclean will clean the bar.ini and foo.ini files.

Related

The difference between .mk file and Makefile

I've just begun to study Porting Android. And I come across a new type of file which is .mk file. It's is an extension of Makefile but I don't know what it is different from a Makefile ? So, can somebody help you clarify them. Thanks very much !
A make file can have any name. The -f option of make is used to specify which file to use:
make -f foobar
You can even use -f several times:
make -f foo -f bar
In which case make processes the files in order (or, equivalently, concatenates the files and processes the result).
makefile and Makefile are special names because if make is called without the -f option it automatically searches for them, in this order, and use the first it finds. Note that GNU make also considers GNUmakefile, and prefers it over makefile and Makefile. Other make implementations can have other default names.
The .mk extension is a more or less standard extension for make files that have other names than the defaults. It is a reasonable extension if you want humans to quickly understand what these files are: convert.mk is more informative than foobar. Some editors use this extension to identify the file type and apply syntax coloring. They usually apply the same syntax coloring to makefile and Makefile.

Make file with multiple potential dependencies

I'm trying to make a make file for a static page generator, and I'm using jinja and pandoc so far, and the idea is to have a file structure as such
.
|-content
|-public
|-templates
|-Makefile
VPATH=public
TARGETS=$(find content -regex ".*(htm|md)" | sed -e "s/md$/htm/g;s/^content/public/g")
all: $(TARGETS)
#echo fullbuild
public/%: content/%
content/%.md:
# Pandoc script
pandoc -i $# -o ${${#:.md=.htm}:content=public}
content/%.htm:
# Jinja Script
The problem I'm having (At least I think that's it) is that according to me the syntax is
# For a final result
target: dependency
commands
# A rule for dependency
dependency:
commands
My dependencies are in the content dir and my targets are in the public dir that may or may not exist yet, and almost all the files I generate will be htm files, and in that case if the target is public/some/route/to/file.htm the dependency will be any of this two content/some/route/to/file.(htm|md).
I can easily generate by walking the content dir, and changing extensions.
How should I write the rules properly, so
- Make knows where to "watch" for changes every time I do a make, because right now it points that every file is up to date
- How do I indicate properly the dependency of a file to it's content file.
This rule:
public/%: content/%
does nothing because pattern rules without recipes delete existing pattern rules, they don't define new pattern rules.
It's very simple, you should write two rules like this:
public/%.htm: content/%.md:
# Pandoc script
pandoc -i $< -o $#
public/%.htm: content/%.htm
# Jinja Script
Here's a hint: whenever you're writing a makefile recipe and you discover that you need to create a target which is different than exactly $#, unmodified, immediately stop what you're doing and back up: you've taken a wrong turn.

How to make install using path with space and dot

I want to make install(sudo make install) using path with space and dot. (e.g. /Applications/Sample App.app/Contents/Resources)
However, following error invoked.
ginstall: target 'App.app/Contents/Resources/lib/libserialport.a' is not a directory
If I use the path with only space, sudo make install really works well with \ escape character.
Makefiles and pathnames which contain spaces do not mix well. Make uses whitespace to split strings into lists. For example, of you write this:
SOURCES = foo.c bar.c baz.c
OBJECTS = $(patsubst %.c,%.o, $(SOURCES))
program: $(OBJECTS)
Then make will treat the variables SOURCES and OBJECTS as lists of strings, split on whitespace characters, and program will depend on the three items foo.o, bar.o, baz.o.
Make does not know at all that some strings should not be split this way (because they refer to pathnames). Like many early scripting languages, it is completely based on string interpolation. This is true for the shell script fragments used to write the build steps as well.
There are some workarounds possible, but they all depend on how variables are used within the makefile. Recursive makefiles can pose additional problems if the contents of these variables are passed down explicitly to the invoked make command using the shell.
In some cases, the fix is rather simple, so if there is an install rule like this:
install: program
$(INSTALL) -m 755 program $(DESTDIR)$(bindir)/program
It may be sufficient to add quotes, like this:
install: program
$(INSTALL) -m 755 program "$(DESTDIR)$(bindir)/program"
But this really depends on the makefile in question.
If the project uses automake (like libserialport), the simplest solution is to use the DESTDIR support in the generated makefile to install the whole thing to a path which does not contain spaces, and then move it to the final destination afterwards. This assumes that the project does not internally embed the final installation path, though.

Evaluate automake variable only once

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.

Default rules in Make

Is there a mechanism in make to allow for default global implicit rules that are available anywhere, similar to the built-in rules?
Make provides some built-inimplicit rules for compiling C/C++/Fortran files, without even requiring a Makefile for simple cases. However, when compiling other languages (e.g. Go programming language files), a Makefile is always required. I would like to extend my Makeenvironment to have implicit rules available by default.
This is not normally desirable, as it would cause your Makefile to be less portable; it wouldn't work on somebody else's machine if they didn't have it set up that way.
However, if you want to do this, create a "global" Makefile somewhere with your default rules for Go files, then add its path to the MAKEFILES environment variable. This global Makefile will be processed before any Makefile when you run "make", just as if you had included its source at the top of the file.
I'm assuming you're referring to the fact that you can do
make hello.o
and make will automatically know how to make the .o from a .c file (or indeed from a .f or .p, if one exists) - but you want to do this for custom file types (say, building a .bar from a .foo.
The most portable way of doing this is as follows (in your Makefile):
.SUFFIXES: .foo .bar
.foo.bar:
foo2bar -in $> -out $#
The first line (.SUFFIXES) warns make that you'll be treating these as special suffixes; the second line says "here's a recipe for making a .bar from a .foo. The third line gives the command for doing this - $> and $# get changed by make to the input and output filenames.
NOTE: The indent for the third line MUST be a tab character.
A much more flexible method, that only works with GNU make, is to use its support for implicit rules. If you can guarantee you'll be using GNU make then this is probably to be recommended.
While I agree with dmazzoni, I just though I'd add my make recipe for a Go Makefile:
# Include default Golang Make magic
include $(GOROOT)/src/Make.$(GOARCH)
# Hack the following line
your_program: your_program.$O
$(LD) -o $# $^
# Compiles .go-files into architecture-specific binaries
%.$O: %.go
$(GC) -o $# $^
clean:
rm your_program *.$O
(Note: the $O is DOLLAR + UPPERCASE-o - not zero!)
While I haven't tested it on all the machines I have available, i believe it should port fairly well.

Resources