I'm trying to create a very simple build script using the autoconf/automake tool chain (mostly as a learning exercise.)
Most examples seem to indicate that you need a separate Makefile.am in every source directory, and that the Makefile.am file in the project root should include a SUBDIRS directive which tells autoconf where to look for additional Makefiles.
I thought it might be possible, for a very simple project, to have a single Makefile.am in the project root directory. However, when I try to do this, and run the generated configure script - it creates a single Makefile in the project root which is empty (0 bytes.)
I'm not really sure what I'm doing wrong here.
So, my directory structure is extremely simple:
MyProject
---src
------myproject.cpp
---Makefile.am
---configure.ac
The configure.ac file is minimal:
AC_INIT(myproject, 1.0)
AC_MSG_NOTICE([My Project])
AC_PROG_CXX
AC_LANG(C++)
AC_CHECK_HEADERS(iostream)
AC_CONFIG_SRCDIR(src/myproject.cpp)
AM_INIT_AUTOMAKE(MyProject, 1.0)
AC_OUTPUT(Makefile)
And the Makefile.am is also very simple:
bin_PROGRAMS = myproject
myproject_SOURCES = src/myproject.cpp
myproject_CPPFLAGS = --std=c++11
I run:
autoconf configure.ac > configure
When I run the configure script, there are no errors.
Then I see it generated a Makefile in the project root directory:
# ls -lh | grep Make
-rw-r--r-- 1 root root 0 Nov 8 16:13 Makefile
-rw-r--r-- 1 root root 98 Nov 8 15:53 Makefile.am
-rw-r--r-- 1 root root 0 Nov 8 15:00 Makefile.in
And you can see, the Makefile it generated is completely empty.
So I'm obviously misunderstanding something fundamental about how autoconf/automake is supposed to work. What am I doing incorrectly here?
I had the same problem - where automake would generate empty Makefiles. I don't know why it happened, but I fixed it by deleting all the files generated by autoconf, e.g. Makefile.in (the zero-byte Makefile.in is definitely bad).
You can also try autoreconf -if
That's interesting, I have tried to reproduce your case and I got different, albeit expected results.
The AM_INIT_AUTOMAKE invocation is obsolete, you should write AM_INIT_AUTOMAKE([foreign]). The foreign tells automake not to complain about missing README, ChangeLog, etc.
You have your Makefile.am in a different folder than source files. Although it is OK, the new automake should complain that it is a forward-incompatibility, I got this on the output (automake 1.15):
Makefile.am:2: warning: source file 'src/myproject.cpp' is in a subdirectory,
Makefile.am:2: but option 'subdir-objects' is disabled
automake: warning: possible forward-incompatibility.
automake: At least a source file is in a subdirectory, but the 'subdir-objects'
automake: automake option hasn't been enabled. For now, the corresponding output
...
Those are just warnings though.
Anyway, instead of running just autoconf, I have ran autoreconf -i (or -i -f to be sure --- the -f option overwrites all files those tool generate). Autoreconf runs autoconf, automake and other tools in the right order for you.
After autoreconf finished, I got a configure script that worked as expected and after running it, I got a correct Makefile, too.
Related
I am having some trouble to compile GCC. When I try to compile it, this error appears:
Makefile:26: *** missing separator. Stop.
The line 26 refers to the first line of this condition:
#if gcc
ifeq (,$(.VARIABLES)) # The variable .VARIABLES, new with 3.80, is never empty.
$(error GNU make version 3.80 or newer is required.)
endif
#endif gcc
I already tried to insert a TAB between the keywords but it didn't work. The only thing I tried and seems to work is to change the condition to:
ifeq ($(gcc),)
ifeq (,$(.VARIABLES)) # The variable .VARIABLES, new with 3.80, is never empty.
$(error GNU make version 3.80 or newer is required.)
endif
endif
Informations:
Make log: http://pastebin.com/t5eNYJd5
Make log (after changing the condition): http://pastebin.com/HHjQKdDx
My make version is: 4.0.
GCC version I am trying to build: 5.2.0
I am using fedora 22.
I've got a workaround. The problem is that the Makefile contains hundreds of '#if', therefore, I would like to know why is it using '#if' if they do not work ?
Thanks in advance.
I stumbled upon this same problem. This question is a little old and it looks like you found a workaround, but I'll document my findings here as well for the People of the Future.
Background
GCC currently requires you to perform an out-of-source build. Based on the commands shown, some of the documentation and online QA implies that this is valid:
svn checkout svn://gcc.gnu.org/svn/gcc/trunk gcc;
gcc/configure <configure options>;
make -j 8 && make install;
This nests the source directory in the build directory, but I would expect that to count as "out-of-source." Running without -j 8 still produced the problem. I did this on a RHEL6 system, using GNU make 4.2. I was attempting to build GCC 8.0.0.
Solution
I found that making the source and build directories adjacent rather than creating builddir/sourcedir resolved the problem.
Additional info
Here's are relevant snippets from the GCC build instructions:
We use srcdir to refer to the toplevel source directory for GCC; we use objdir to refer to the toplevel build/object directory.
...
If you obtained the sources via SVN, srcdir must refer to the top gcc directory, the one where the MAINTAINERS file can be found, and not its gcc subdirectory, otherwise the build will fail.
...
First, we highly recommend that GCC be built into a separate directory from the sources which does not reside within the source tree. This is how we generally build GCC; building where srcdir == objdir should still work, but doesn’t get extensive testing; building where objdir is a subdirectory of srcdir is unsupported.
Depending on your definition of "source tree", these instructions may or may not proscribe building the way I first attempted. They should probably be updated to clarify this case.
As to the specific reason that Makefile won't run, that snippet is not valid make syntax - if is not a make keyword, and referenced variables must be enclosed like so: $(varname). # simply prevents the command from being echoed.
Rather, this is supposed to be multiline interpolated bash. This StackOverflow answer shows this being done in a Makefile, but it's done as part of a recipe. I see no evidence that this is valid as a standalone entity.
In the correctly-generated Makefile, the section you posted is absent, and all interpolated bash appears in a recipe.
Automake 1.14 is causing us a few issues. At first, automake errored with the complaint:
warning: source file 'X' is in a subdirectory but option 'subdir-objects' is disabled
So I enabled subdir-objects, but now it isn't recompiling some files. For example, lets say
src/a/foo.c is compiled in SUBDIR a but in src/b, I would like to compile it again with different preprocessor flags, however since ../a/foo.o already exists, make doesn't rebuild it. This is because subdir-objects changes am_b_OBJECTS to look for ../a/foo.o instead of foo.o. Is there a way I can get around the original complaint and instruct make to build the file a second time with the appropriate preprocessor flags? This all worked on previous versions of automake.
I would settle for executing rm ../a/foo.o before compiling src/b but I don't know how to edit the Makefile.am to make that happen.
This happens if you're using subdir-objects under the same tree from different Makefile.am files. As automake can't see you're using the same source file with different parameters it'll assume it was rebuilt correctly.
The proper solution to this is to not use separate Makefile.am files and instead rephrase the build system as non-recursive automake and so in that case it would then build foo.c as foo-a.o and foo-b.o.
I have a project with autotools: automake, autoconf.
I want to prohibit make from remaking files configure, Makefile.in, etc; just to do compile job.
Some of files are edited by hand, and I know that I should not to do this. (Or the project was updated from CVS with all generated files stored in CVS).
But at the moment I have no correct version autotools installed.
What must be modification times of this files (which must be newer/older):
aclocal.m4
configure.in
confdb/ax_prefix_config_h.m4
Makefile.am
Makefile.in
Makefile
configure
config.status
Or: what sequence of touch commands must I do to achieve my goal?
First of all, if you edit a generated file directly, it wouldn't be rebuilt anyway, because it is then newer then its prerequisites.
Then, there are two separate things going on here: config.status and Makefile are created during the build. It's hard to prevent these from being remade during the build unless you make their timestamps newer.
The other files are generated by the various autotools. Recent versions of Automake do not create rules by default that remake them automatically. Depending on your package, you might want to use the configure option --disable-maintainer-mode. The Automake documentation contains some more interesting information about that option.
One trick I sometimes use with a package that I don't know much about or that has a pretty messed up build system is to run something like
make all AUTOCONF=: AUTOHEADER=: AUTOMAKE=: ACLOCAL=:
so that if these programs happen to be called, a noop would be substituted.
touch confdb/*.m4
touch configure.in
touch *.m4
touch *.am
touch Makefile.in */Makefile.in
touch *config.h.in */*config.h.in
touch configure
touch config.status
touch config.h
touch Makefile
Problems with automake & cvs are described here http://www.gnu.org/s/hello/manual/automake/CVS.html
Try to explicitly tell make those files should not be remade, via command-line
$ make -o configure -o Makefile.in
or by using MAKEFLAGS
$ MAKEFLAGS="-o configure -o Makefile.in" make
The excerpt from GNU make's manual
‘-o file’
‘--old-file=file’
‘--assume-old=file’
Do not remake the file file even if it is older than its prerequisites, and do not remake
anything on account of changes in file. Essentially the file is treated as very old and
its rules are ignored. See Avoiding Recompilation of Some Files.
If yours autotools template correctly uses $(MAKE) for subdirs, there should be no problems.
I have seen both in different things I have configured. What I the difference? Is it notable to use only one? Or does it not matter which one to use?
configure.ac and configure.in are two possible names for the master Autoconf source file, which is processed by autoconf to generate the configure shell script. configure.ac is preferred for new packages, configure.in is an older name which still works. (The .in suffix is now recommended to be used only for files which will be processed by config.status, which is the result of running configure.)
Makefile.am is an Automake source file. Automake processes it and generates Makefile.in, which is then further processed by config.status to generate the final Makefile. An Automake-generated Makefile.in is not meant to be edited by hand. However, if a project doesn't use Automake (but does use Autoconf), then it will only have a Makefile.in which is hand-edited.
For further details see http://www.gnu.org/software/autoconf/manual/html_node/Making-configure-Scripts.html - particularly the diagrams.
These two files are mostly seen in open source projects.
What are they for, and how do they work?
Makefile.am is a programmer-defined file and is used by automake to generate the Makefile.in file (the .am stands for automake).
The configure script typically seen in source tarballs will use the Makefile.in to generate a Makefile.
The configure script itself is generated from a programmer-defined file named either configure.ac or configure.in (deprecated). I prefer .ac (for autoconf) since it differentiates it from the generated Makefile.in files and that way I can have rules such as make dist-clean which runs rm -f *.in. Since it is a generated file, it is not typically stored in a revision system such as Git, SVN, Mercurial or CVS, rather the .ac file would be.
Read more on GNU Autotools.
Read about make and Makefile first, then learn about automake, autoconf, libtool, etc.
Simple example
Shamelessly adapted from: http://www.gnu.org/software/automake/manual/html_node/Creating-amhello.html and tested on Ubuntu 14.04 Automake 1.14.1.
Makefile.am
SUBDIRS = src
dist_doc_DATA = README.md
README.md
Some doc.
configure.ac
AC_INIT([automake_hello_world], [1.0], [bug-automake#gnu.org])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_PROG_CC
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([
Makefile
src/Makefile
])
AC_OUTPUT
src/Makefile.am
bin_PROGRAMS = autotools_hello_world
autotools_hello_world_SOURCES = main.c
src/main.c
#include <config.h>
#include <stdio.h>
int main (void) {
puts ("Hello world from " PACKAGE_STRING);
return 0;
}
Usage
autoreconf --install
mkdir build
cd build
../configure
make
sudo make install
autotools_hello_world
sudo make uninstall
This outputs:
Hello world from automake_hello_world 1.0
Notes
autoreconf --install generates several template files which should be tracked by Git, including Makefile.in. It only needs to be run the first time.
make install installs:
the binary to /usr/local/bin
README.md to /usr/local/share/doc/automake_hello_world
On GitHub for you to try it out.
DEVELOPER runs autoconf and automake:
autoconf -- creates shippable configure script
(which the installer will later run to make the Makefile)
‘autoconf’ is a macro processor.
It converts configure.ac, which is a shell script using macro instructions, into configure, a full-fledged shell script.
automake - creates shippable Makefile.in data file
(which configure will later read to make the Makefile)
Automake helps with creating portable and GNU-standard compliant Makefiles.
‘automake’ creates complex Makefile.ins from simple Makefile.ams
INSTALLER runs configure, make and sudo make install:
./configure # Creates Makefile (from Makefile.in).
make # Creates the application (from the Makefile just created).
sudo make install # Installs the application
# Often, by default its files are installed into /usr/local
INPUT/OUTPUT MAP
Notation below is roughly: inputs --> programs --> outputs
DEVELOPER runs these:
configure.ac -> autoconf -> configure (script) --- (*.ac = autoconf)
configure.in --> autoconf -> configure (script) --- (configure.in depreciated. Use configure.ac)
Makefile.am -> automake -> Makefile.in ----------- (*.am = automake)
INSTALLER runs these:
Makefile.in -> configure -> Makefile (*.in = input file)
Makefile -> make ----------> (puts new software in your downloads or temporary directory)
Makefile -> make install -> (puts new software in system directories)
"autoconf is an extensible package of M4 macros that produce shell scripts to automatically configure software source code packages. These scripts can adapt the packages to many kinds of UNIX-like systems without manual user intervention. Autoconf creates a configuration script for a package from a template file that lists the operating system features that the package can use, in the form of M4 macro calls."
"automake is a tool for automatically generating Makefile.in files compliant with the GNU Coding Standards. Automake requires the use of Autoconf."
Manuals:
GNU AutoTools (The definitive manual on this stuff)
m4 (used by autoconf)
autoconf
automake
Free online tutorials:
Using GNU Autotools
Example:
The main configure.ac used to build LibreOffice is over 12k lines of code, (but there are also 57 other configure.ac files in subfolders.)
From this my generated configure is over 41k lines of code.
And while the Makefile.in and Makefile are both only 493 lines of code. (But, there are also 768 more Makefile.in's in subfolders.)
reference :
Makefile.am -- a user input file to automake
configure.in -- a user input file to autoconf
autoconf generates configure from configure.in
automake gererates Makefile.in from Makefile.am
configure generates Makefile from Makefile.in
For ex:
$]
configure.in Makefile.in
$] sudo autoconf
configure configure.in Makefile.in ...
$] sudo ./configure
Makefile Makefile.in