I'm trying to port an application I'm developing to autotools. I'm not an expert in writing makefiles and it's a requisite for me to be able to use autotools.
In particular, the structure of the project is the following:
..
../src/Main.cpp
../src/foo/
../src/foo/x.cpp
../src/foo/y.cpp
../src/foo/A/k.cpp
../src/foo/A/Makefile.am
../src/foo/Makefile.am
../src/bar/
../src/bar/z.cpp
../src/bar/w.cpp
../src/bar/Makefile.am
../inc/foo/
../inc/bar/
../inc/foo/A
../configure.in
../Makefile.am
The root folder of the project contains a "src" folder containing the main of the program AND a number of subfolders containing the other sources of the program. The root of the project also contains an "inc" folder containing the .h files that are nothing more than the definitions of the classes in "src", thus "inc" reflects the structure of "src".
I have written the following configure.in in the root:
AC_INIT([PNAME], [1.0])
AC_CONFIG_SRCDIR([src/Main.cpp])
AC_CONFIG_HEADER([config.h])
AC_PROG_CXX
AC_PROG_CC
AC_PROG_LIBTOOL
AM_INIT_AUTOMAKE([foreign])
AC_CONFIG_FILES([Makefile
src/Makefile
src/foo/Makefile
src/foo/A/Makefile
src/bar/Makefile])
AC_OUTPUT
And the following is ../Makefile.am
SUBDIRS = src
and then in ../src where the main of the project is contained:
bin_PROGRAMS = pname
gsi_SOURCES = Main.cpp
AM_CPPFLAGS = -I../../inc/foo\
-I../../inc/foo/A \
-I../../inc/bar/
pname_LDADD= foo/libfoo.a bar/libbar.a
SUBDIRS = foo bar
and in ../src/foo
noinst_LIBRARIES = libfoo.a
libfoo_a_SOURCES = \
x.cpp \
y.cpp
AM_CPPFLAGS = \
-I../../inc/foo \
-I../../inc/foo/A \
-I../../inc/bar
And the analogous in src/bar.
The problem is that after calling automake and autoconf, when calling "make" the compilation fails. In particular, the program enters the directory src, then foo and creates libfoo.a, but the same fail for libbar.a, with the following error:
Making all in bar
make[3]: Entering directory `/user/Raffo/project/src/bar'
make[3]: *** No rule to make target `all'. Stop.
I have read the autotools documentation, but I'm not able to find a similar example to the one I am working on. Unfortunately I can't change the directory structure as this is a fixed requisite of the project I'm working on.
I don't know if you can help me or give me any hint, but maybe you can guess the error or give me a link to a similar structured example.
Thank you.
if it fails in src/bar, why is src/bar/Makefile.am the only code that you do not post?
and btw, you should use $(srcdir) or $(top_srcdir) rather than referring to relative paths like "../../" (this comes in handy if people want to produce binaries without poluuting the source directory)
Related
I am new to C/C++ and to gnu makefiles especially. Momentarily I have a makefile that automatically generates a list of all sources and headers in one directory in order to make the output binary.
as my project grows I surely do not want to lump all source and header files into one directory. but instead create (nested) subdirectories.......
Is there a way - I guess taking as starting point subdirs := $(wildcard */) - and further involving for... in... ($subdirs) to first only generate a list of the source and header files in the subdirectories and nested subdirectories ? Maybe later with addition of a make call for the sources and headers of every subdirectory ?
Thank you very much.
Yours sincerly
von Spotz
You can use $(shell) and script it:
ALL_SOURCES := $(shell find * -name '*.cpp' -print)
(assuming you use .cpp as a C++ source file extension). You should have full and complete documentation of make already installed:
info -f make
I have a working directory as below:
./
|----HelloWorld/
|----|----main.cpp
|----|----Makefile.am
|----Pet/
|----|----Pet.h
|----|----Pet.cpp
|----build/
|----configure.ac
|----Makefile.am
I would like to use the autotool to construct makefile and then build the project in the build directory.
The ./configure.ac is
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([Hello], [1.0], [qub#oregonstate.edu])
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
AC_CONFIG_SRCDIR([HelloWorld/main.cpp])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CXX
AC_PROG_CC
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
The ./Makefile.am is
include HelloWorld/Makefile.am
Note that I'm using the include to make sure the exe locates at the directory where the make command runs.
The ./HelloWorld/Makefile.am is
AM_CPPFLAGS=-I%D%/../Pet/ -I%D% -I%C%
#VPATH = ./HelloWorld ./Pet
bin_PROGRAMS=hello
hello_SOURCES=%D%/../Pet/Pet.h
hello_SOURCES+=%D%/../Pet/Pet.cpp
hello_SOURCES+=%D%/main.cpp
In case some people would like to try on their own computer, I attach other source codes here:
main.cpp
#include <stdio.h>
#include <vector>
#include "Pet.h"
int main() {
printf("Hello World\n");
std::vector<Pet*> all_pets;
Pet *dog = new Pet(string("Apple"));
all_pets.push_back(dog);
Pet *cat = new Pet(string("Pear"));
all_pets.push_back(cat);
for (int i = 0; i < all_pets.size(); i++) {
all_pets[i]->showName();
}
return 0;
}
**Pet.h**
#pragma once
#include <string>
using namespace std;
class Pet
{
public:
Pet(string name);
~Pet();
void showName();
void showIndex();
string _name;
int _index;
};
Pet.cpp
#include "Pet.h"
Pet::Pet(string name)
{
_name = name;
srand(2345);
_index = (rand() % 100);
}
Pet::~Pet()
{
}
void Pet::showIndex()
{
printf("Index is %d\n", _index);
}
void Pet::showName()
{
printf("Name is %s\n", _name.c_str());
}
Problem Statement
Can successfully create makefile by run
./ $autoreconf --install
Can successfully build the project at root directory with using following commands
./ $./configure
./ $make
Get error when building in directory ./build. Commands are:
./build/ $../configure
./build/ $make
Got an error as below image shows:
build error image
I think this error is caused by the compiler cannot successfully find the header files. My first question is Why the AM_CPPFLAGS=-I%D%/../Pet/ -I%D% -I%C% in makefile.am cannot solve this problem?
Since the compiler will create the .o files in the build directory with making the build tree has the same subdirectory layout as the source tree. So I can fix this problem by copy the Pet.h file to \build\Pet. However, this means I always need to copy the header files to the build directory, which is not convenient.
I find some info about VPATH. So I commented out #VPATH = ./HelloWorld ./Pet in ./HelloWorld/Makefile.am. However, it will give me a new problem:
automake error image
My assumption is the VPATH setting somehow conflicts with the include makefile.am. My second question is How can I use the VPATH correctly with using include makefile?
Why the AM_CPPFLAGS=-I%D%/../Pet/ -I%D% -I%C% in makefile.am cannot solve this problem?
Because %D% and %C% produce paths to the included makefile fragment relative to the makefile that includes it, not relative to the build directory. They are not intended or suited for handling out-of-source building, though when used correctly, they do not interfere with that.
How can I use the VPATH correctly with using include makefile?
You are overthinking the problem. Automake supports out-of-source building automatically. You don't need to (and shouldn't) set up VPATH yourself.
You are also making trouble for yourself with the Makefile include directive. That directive definitely has good uses, but you would do better here by either consolidating everything into the top-level Makefile.am or by setting up for recursive make. You shouldn't need that %D% and %C% stuff.
Automake will set up VPATH for you, and that takes care of locating prerequisites when you perform an out-of-source build. For the most part, you just specify paths to sources and targets relative to the location of your Makefile.am and / or configure.ac.
Occasionally you do need to refer to the source directory, and in that case you should use the appropriate one of $(srcdir), $(top_srcdir), $(abs_srcdir), or $(abs_top_srcdir) to ensure that out-of-source builds work correctly.
Your project layout is a bit odd, but either one of these alternatives ought to do it:
Recursive
Makefile.am
SUBDIRS = HelloWorld
HelloWorld/Makefile.am
# VPATH helps *make* identify prerequisites, but the compiler doesn't know about it.
# We therefore need to give compiler options with real paths. But we shouldn't need
# any extra options to support sources that #include headers via (correct) paths expressed
# relative to the sources' own location.
AM_CPPFLAGS = -I$(srcdir)/../Pet
# Note: builds 'hello' in subdirectory HelloWorld/ of the build directory
bin_PROGRAMS = hello
hello_SOURCES = \
../Pet/Pet.h \
../Pet/Pet.cpp \
main.cpp
Non-recursive
Makefile.am
AM_CPPFLAGS = -I$(srcdir)/Pet
# Builds 'hello' directly in the build directory
bin_PROGRAMS = hello
hello_SOURCES = \
Pet/Pet.h \
Pet/Pet.cpp \
HelloWorld/main.cpp
HelloWorld/Makefile.am
(none)
Either way, you perform an out-of-source build just as you were trying to do: change to the wanted build directory, creating it first if necessary, run the configure script from there via an appropriate path, and then proceed with make.
$ mkdir build
$ cd build
$ path/to/configure
$ make
I accidently fix the problem by changing the ./HelloWorld/Makefile.am to
AM_CPPFLAGS=-I%D%/../../Pet/ -I%D% -I%C%
#VPATH = ../Pet
#srcdir = #srcdir#
#VPATH = %D/Pet/
bin_PROGRAMS=hello
hello_SOURCES=%D%/../../Pet/Pet.h
hello_SOURCES+=%D%/../Pet/Pet.cpp
hello_SOURCES+=%D%/main.cpp
Note that the path of hello_SOURCES are changed and header path is different from source path. But why would this solve the problem?
How to compile and link third party libraries with automake?
My file structure is:
program/
|
+--src/
| |
| +--Makefile.am
| +--main.cpp
|
+--lib/
| |
| +--Makefile.am
| +--library.cpp
|
+--Makefile.am
+--configure.ac
+--README
Contents of automake files are pretty generic:
# src/Makefile.am
bin_PROGRAMS = program
program_SOURCES = main.cpp
# Makefile.am
SUBDIRS = src lib
dist_doc_DATA = README
# configure.ac
AC_INIT([program], [1.0])
AM_INIT_AUTOMAKE([-Wall])
AC_PROG_CXX
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile src/Makefile lib/Makefile])
AC_OUTPUT
What should be the contents of lib/Makefile.am?
(Not sure why you said "third-party" when you appear to have control of the library code yourself... For more info related to creating and working with libraries using Automake, I refer you to the GNU Automake manual's section on libraries)
lib/Makefile.am
lib_LIBRARIES = libYOURLIB.a
libYOURLIB_a_SOURCES = library.cpp
You can use noinst_lib_LIBRARIES if you don't want to install the library itself. Note that I'm assuming you want to build a static library only. See the Building A Shared Library section of the GNU Automake manual for integrating with Libtool to produce a shared library. You can do it manually of course, but it's a lot easier with Libtool as it takes care of various platform differences.
To link your library to program, you'd add the following lines insrc/Makefile.am:
program_DEPENDENCIES = $(top_builddir)/lib/libYOURLIB.a
program_LDADD = $(top_builddir)/lib/libYOURLIB.a
The _DEPENDENCIES line simply tells Automake that program relies on lib/libYOURLIB.a being built first, and the _LDADD line simply adds the library to the linker command.
The above assumes that you have a rule to build the library already. Since you're using SUBDIRS, you received a "no rule to make target XXXXXX" build failure, which indicates that you don't (at least from the perspective of the Makefile in the src subdirectory). To remedy this, you can try the following in src/Makefile.am (taken from "Re: library dependency" on the GNU Automake mailing list archives):
FORCE:
$(top_builddir)/lib/libYOURLIB.a: FORCE
<TAB>(cd $(top_builddir)/lib && $(MAKE) $(AM_MAKEFLAGS) libYOURLIB.a)
You can also simply make lib a subdirectory of src as your comment indicated of course and make it simpler.
Alternatively, you can stop using a recursive build setup and use what is perhaps a simpler non-recursive build setup. See GNU Automake Manual ยง7.3: An Alternative Approach to Subdirectories and Non-recursive Automake for some information on that, but the general idea would be to alter things to allow for :
configure.ac
AM_INIT_AUTOMAKE([-Wall subdir-objects])
...
AC_CONFIG_FILES([Makefile])
Makefile.am
# Instead of using the SUBDIRS variable.
include src/Makefile.am.inc
include lib/Makefile.am.inc
dist_doc_DATA = README
lib/Makefile.am renamed to lib/Makefile.am.inc
# Full path relative to the top directory.
lib_LIBRARIES = lib/libYOURLIB.a
lib_libYOURLIB_a_SOURCES = lib/library.cpp
src/Makefile.am renamed to src/Makefile.am.inc
# Full path relative to the top directory.
bin_PROGRAMS = bin/program
bin_program_SOURCES = src/main.cpp
bin_program_DEPENDENCIES = lib/libYOURLIB.a
bin_program_LDADD = lib/libYOURLIB.a
Renaming the files is optional (you could always just include src/Makefile.am), but it helps to denote that it isn't meant to be a standalone Automake source file.
Also, supposing that lib/library.cpp and src/main.cpp both #include "library.hpp", and it's in another directory, you might also want to use AM_CPPFLAGS = -I $(top_srcdir)/include for all files or obj_program_CPPFLAGS = -I include for all source files that are used in building bin/program, assuming library.hpp is in program/include. I'm not sure if $(top_srcdir) is right when another project includes your entire program source directory in its own SUBDIRS variable, but $(srcdir) will always refer to the top-level program directory in the case of a non-recursive automake, making it perhaps more useful in larger projects that include this package as a component.
I'm creating a software project and I wanted to use autotools to do the makefile and etc. script generation for me, I manually created Makefile.am and configure.in files, and I'm using the autogen.sh script from here. The problem comes when attempting to build the project in a separate 'build' directory, e.g. if I go:
mkdir build
cd build
../configure
make
The configure step works fine, but when running make I get:
make all-recursive
Making all in src
/bin/sh: line 0: cd: src: No such file or directory
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2
Any tips to get this working? Or should I give up and try something simpler/different.
I plan for this to be a reasonably simple C++ project, and the only dependency I plan to have is on the boost unit testing framework, and to do most development in Eclipse IDE.
there's a bug in your src/Makefile.am, line#17:
swin-adventure_SOURCES = src/main.cc
should really read:
swin-adventure_SOURCES = main.cc
since you are already in the src/ directory (unless there's a src/src/ subfolder)
there's another bug, as you are using special characters in your _SOURCES variabes: swin-adventure_SOURCES has the forbidden - character; try to normalize that to swin_adventure_SOURCES
finally, you are trying to assign a value to bin_PROGRAMS multiple times (and each time the same value), try to avoid that.
something like:
## Additional flags to pass to aclocal when it is invoked automatically at
## make time. The ${ACLOCAL_FLAGS} variable is picked up from the environment
## to provide a way for the user to supply additional arguments.
ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}
## Define an executable target "swin-adventure", which will be installed into the
## directory named by the predefined variable $(bindir).
bin_PROGRAMS = swin-adventure
## Define the list of source files for the "swin-adventure" target. The file
## extension .cc is recognized by Automake, and causes it to produce rules
## which invoke the C++ compiler to produce an object file (.o) from each
## source file. The ## header files (.h) do not result in object files by
## themselves, but will be included in distribution archives of the project.
swin_adventure_SOURCES = main.cc
I have a problem because i have never written any makefile. So if any could help me I become happy. I have a lot of different .o files, which stored in the different folders. For example:
folder1: obj1.o
folder2: obj2.o
folder3: obj3.o
I need makefile, which will build the library from files which I send to makefile like param. Param should be makefile too and include info about folders where stored necessary files.
For example I would like to build lib from objects stored at folder1 and folder2 without folder3. So makefile which I send as param to the main makefile must include routes to folder1 and folder2:
local_libs := ../folder1
local_libs += ../folder2
main makefile should parse that info and call libtool utilite for creating lib from files at this folders. Could anybody help?
I suppose it is easy for realization, example will be great!
You need a rule that inputs the .o files, outputs the .a file and calls the ar command to do the work. Something like:
lib.a: $(OBJECTS)
${AR} -cr ${#} ${^}
GNU make does not support passing parameters "to the makefile" on the command line.
You have two basic mechanism for setting parameters to be used by make while executing a makefile (I'm assuming that you are using GNU make, and not all of his advice will apply to other makes):
Write to submakefiles, possibly using a script. If you makefile has a line like
include file.mk
gmake will include the contents of file.mk. Change the contents of file.mk and you change the behavior of your makefile.
Make can take variable values from environment variables when set. This provides a powerful mechanism for letting the user customize the behavior of your makefile.