Gnu make: Generate a list of all subdirectories - c++

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

Related

Compile a single file under CMake project?

I'm developing a C++ project which is going to be enclosed on a bigger one.
I've seen that on the bigger project (is a Qt application and it's being generated from qmake) I am able to compile a single file from the linux command line, just entering the relative path to the specific file as an argument to make.
On the other hand, I'm using CMake for my own project. When I modify some code for a compilation unit and I have to modify its header file, I have to wait a long time to compile its dependencies and then its own source file. But there are some situations in which I would prefer to check whether the source code in the *.cc file is compilable without errors.
Is there a way to generate a Makefile from CMake the way qmake does this? Switching to qmake is not an option anymore.
You do not have to add extra custom targets to your CMake scripts, as the Makefiles generated by CMake already contain .o targets for each .cc file. E.g. if you have a source file called mySourceFile.cc, there will be a Makefile in your build directory that defines a target called <Some Path>/mySourceFile.cc.o. If you cd into your build directory, you can use grep or ack-grep to locate the Makefile that defines this target, then cd into that Makefile's directory and build it.
E.g. suppose the command ack-grep mySourceFile.cc.o prints something like:
foo/bar/Makefile
119:x/y/z/mySourceFile.o: x/y/z/mySourceFile.cc.o
123:x/y/z/mySourceFile.cc.o:
124: # recipe for building target
Then you can build mySourceFile.cc.o by doing:
cd foo/bar && make x/y/z/mySourceFile.cc.o
CMake doesn't have a generic built-in way of doing this (it's an open issue), but if you're using the Ninja generator, you can can use a special Ninja syntax for building just the direct outputs of a given source file. For example, to compile just foo.o you would use:
ninja /path/to/foo.cpp^
Not out-of-the box. CMake does not expose those "internal" makefile rules in the main makefile.
You can do this only if you consider what kind of file structure CMake uses internally. You can e.g. for compiling a single .obj files using CMake generated makefiles call
make -f CMakeFiles/myProg.dir/build.make CMakeFiles/myProg.dir/main.cc.obj
when you have something like
cmake_minimum_required(VERSION 3.1)
project(myProg CXX)
file(WRITE "main.cc" "int main()\n{\nreturn 0;\n}")
add_executable(myProg main.cc)
To build src/foo.cpp alone:
cmake --build . --target src/foo.cpp.o
No, CMake does not offer built-in support to compile single files.
You have to add a target for each object file, maybe by a function iterating over all files of a directory.
Others have suggested ways to find the target name (ending in .cpp.o) from the .cpp filename, but if you already know the name of a target that will trigger compilation of the .cpp file and you're using ninja this suggestion should be easier.
First build the target:
ninja TriggersCppCompilationLib
Assuming your file was changed or was not yet built, ninja will print the full target name. When you see the name come up, hit enter so it is not overwritten. Then simply copy the name from the terminal (e.g. using tmux copy mode).

automake third party libraries

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.

autotools: no rule to make target all

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)

How to compile multiple files in ROOT

I wrote a C++ program (with a main.cpp, and various header and implementation files) that compiles fine under g++. Now I am trying to compile it in Cern's ROOT library, but I do not know how to, since the only way I know how to compile files in ROOT is by using .L main.cpp.
How can I include multiple files in ROOT?
The most reliable way to use ROOT (at least historically and currently) is to ignore the interpreter other than for the simplest explorations and explicitly compile your C++ programs against the ROOT libraries. For example, use
g++ MySource.cc `root-config --libs --cflags` -o foo
to compile an executable "foo" from a single source file. For more info on that helper script run "root-config --help".
Multi-file programs/libraries are nothing special provided that you supply the required args to point at the ROOT libraries and headers (and that the libs are available in LD_LIBRARY_PATH at runtime.) Standard C++ guides will explain that step if needed. You can safely put this into a makefile, too.
For my money this is both easier and more reliable than using the .L etc. commands in the CINT interpreter. Last time I tried, ACLiC was actually compiling against a temporary (and mangled) version of the specified source file, so any error messages from the compiler were pretty much useless!
I use CMake to compile my ROOT-based projects.
If you have a project directory proj/ and it contains src/ and bin/, you'll need 3 CMakeList.txt files, one in each directory.
A simple example CMakeList.txt in the main project directory:
cmake_minimum_required(VERSION 2.6)
project (SOME_PROJ_NAME)
add_subdirectory(src)
add_subdirectory(bin)
src/ directory is where you keep your .h and .cxx proj. library files. Example CMakeList.txt file:
# get all the *.cxx filenames, to compile them into a lib
file(GLOB SOME_PROJ_LIB_SRCS "${PROJECT_SOURCE_DIR}/src/*.cxx")
# include ROOT library and include files
include_directories(/path/to/root/dir/include/dir)
link_directories(/path/to/root/dir/lib/dir)
# and compile src into a library
add_library(Proj_lib_name ${SOME_PROJ_LIB_SRCS})
# here, list the ROOT libraries you require
target_link_libraries(Proj_lib_name dl Core Cint RIO Net Hist Graf Graf3d Gpad Tree Rint Postscript Matrix Physics MathCore Thread Gui pthread m)
bin/ directory is where you keep your app .cxx files and it has a CMakeList.txt file:
include_directories(${PROJECT_SOURCE_DIR}/src)
link_directories(${PROJECT_SOURCE_DIR}/src)
include_directories(/path/to/root/dir/include/dir)
link_directories(/path/to/root/dir/lib/dir)
add_executable(example_app.exe example_app.cxx)
target_link_libraries(example_app.exe Proj_lib_name dl Core Cint RIO Net Hist Graf Graf3d Gpad Tree Rint Postscript Matrix Physics MathCore Thread Gui pthread m)
Finally, to compile ROOT-based code with CMake, out of source, you create a "build" dir in your top level project dir, so that your dir structure looks like this:
proj/
bin/
build/
src/
Then
cd build
cmake ..
Your binaries will be located in build/bin/ directory
Hope this helps.
It appears that I would simply .L <filename> for each file I want, since .L tells ROOT to "load the contents of file in memory." Though now I am not too sure which order to load the files in, as they are giving me errors.

makefile which build the library (lib.a)from the list of object files (*.o)

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.