BuildSystem » History » Revision 7
« Previous |
| Next »
fixeria, 03/14/2023 10:25 PM
The Build System¶
The build system is basically a suite of tools that helps developers to "translate" source code files into executable binaries and libraries. Examples of such systems are GNU Make, GNU Autotools, CMake, QMake, and Ninja. The majority of Osmocom projects is employing GNU Autotools, except these very few using CMake (mostly GNU Radio related projects) and hand-written Makefiles. Thus this page will be focusing on the GNU Autotools, which is supposed to make things simple for all of us, but sometimes becomes a PITA and a source of confusion for many.
GNU Autotools Essentials¶
GNU Autotools includes the following tools:
- Automake - a tool for automatically generating
- Autoconf - a tool for generating
- Libtool - a tool for building static and shared libraries.
These tools are usually available in package repositories of many Linux distributions.
GNU Autotools Basic Usage¶
The usual sequence of commands is as follows:
$ autoreconf -fi $ ./configure $ make $ make check # optionally $ sudo make install
autoreconf scans the current directory for
Makefile.am taking them as the input, converts
Makefile.am files to
Makefile.in, and generates the
configure script. The
configure script performs dozens of checks, finds suitable compilers and linkers, scans for
Makefile.in files and generates the usual
Makefile files from them. Finally,
make follows the rules listed in automatically generated
Makefile files, and invokes compilers, linkers, and other tools on the source files.
GNU Autotools For Developers¶
This Work-in-Progress section is for those who want to understand and write their own
Makefile.am files. It's not a complete guide and definitely not for beginners, please refer to documentation of the respective GNU projects. The main focus here in on common problems and corner cases we faced during development.
Yes, it is. Even worse, while a typical
Makefile.am mostly contains specifically-named variables listing source files and their dependencies (i.e. libraries),
configure.ac employs rather archaic m4 language, so you may often find yourself googling the basic syntax of simple constructs like conditional statements and never remembering them. The good news is that you can include the usual Makefile-like rules in
Makefile.am files, but this should be avoided unless it's absolutely necessary due to potential portability problems.
There are not that many of them, but it's easy to get confused.
bin_PROGRAMS- executable files, which will be installed during
noinst_PROGRAMS- executable files, which will not be installed during
check_PROGRAMS- executable files, which will only be compiled during
make checkand will not be installed during
TIP: It's recommended to use
check_PROGRAMS for tests, so that they won't be compiled during
There exist static and shared libraries, see https://stackoverflow.com/questions/2649334/difference-between-static-and-shared-libraries.
Libtool adds another layer of discrimination: regular static libraries (
.a) and libtool archives (
.la), see https://www.linuxfromscratch.org/blfs/view/svn/introduction/la-files.html.
lib_LTLIBRARIES- list of shared libraries (libtool
*.sofiles), to be installed during
noinst_LTLIBRARIES- list of static libraries (libtool
.*laarchives), not installed during
noinst_LIBRARIES- list of static libraries (regular
.aarchives), not installed during
*.la libraries can depend on other libraries, regular
*.a libraries cannot. Here is an example:
# static libtool library, not going to be installed noinst_LTLIBRARIES = libosmo-foo.la libosmo_foo_la_SOURCES = src/foo.c libosmo_foo_la_LIBADD = $(TALLOC_LIBS) # shared libtool library, to be installed, depends on libosmo-foo.la lib_LTLIBRARIES = libosmo-bar.la libosmo_bar_la_SOURCES = src/bar.c libosmo_bar_la_LIBADD = \ $(top_builddir)/src/libosmo-foo.la $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(NULL)
In the example above
libosmo-bar.la (dynamic lib) depends on
libosmo-foo.la (static lib). Among with
LIBOSMOGSM_LIBS, the resulting
libosmo-bar.so will additionally depend on
$(TALLOC_LIBS) because it's a dependency of
NOTE: It's recommended to list repository-local libs (
libosmo-foo.la in the example above) first, not after any of the external dependencies (e.g.
$(LIBOSMOCORE_LIBS)). Otherwise you may experience weird problems when running binaries within the repository, loading system-installed libs instead of the local ones.
AM_CPPFLAGS, AM_CFLAGS, AM_CXXFLAGS¶
AM_CPPFLAGSis for the preprocessor flags like
AM_CFLAGSis for the C compiler flags applying to C source files only
- This is where you put stuff like
- Avoid putting
-ggdbthere, let the user decide of these flags
- One exception is
-Wall, and sometimes
- One exception is
- This is where you put stuff like
AM_CXXFLAGSis similar to
AM_CFLAGS, but applies to C++ source files only
These variables apply to all binaries and libraries within the current file.
You can overwrite them using per-binary/-library
AM_CPPFLAGS = -I$(top_srcdir)/include AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) # global AM_CPPFLAGS and AM_CFLAGS apply to osmo-app bin_PROGRAMS = osmo-app osmo_app_SOURCES = app.c # osmo-app wants to have additional CFLAGS osmo_app_CFLAGS = $(AM_CFLAGS) $(LIBOSMO_FOO_CFLAGS) # osmo-app wants to redefine global CFLAGS osmo_app_CFLAGS = $(LIBOSMO_BAR_CFLAGS)
NOTE: In some projects you may see both preprocessor flags and compiler flags in
AM_CPPFLAGS. This works because the compiler usually comes with a preprocessor, and the resulting Makefile rule looks like this:
$(CC) $(AM_CPPFLAGS) $(AM_CFLAGS) .... Though it's still desirable to have preprocessor and compiler flags in the proper variables, at least for the sake of clarity.
AM_LDFLAGS vs LDADD, _LDADD and _LIBADD¶
AM_LDFLAGSis for the liker flags like
LDADDis a list of libraries that implicitly applies to all binaries and libs within the current file (unless overridden)
osmo_app_LDADDis a list of libraries for
osmo-appbinary (not for libraries)
libosmo_lib_LIBADDis a list of libraries for
libosmo-liblibrary (not for binaries)
NOTE: It's a common mistake to put libraries into
AM_LDFLAGS, please use the other three variables for that. The key difference is that
AM_LDFLAGS appears first in the linker's command line, while the
LIBADD ones appear last. By having libraries listed in
AM_LDFLAGS, you may experience weird problems running tests from
check_PROGRAMS, which may load system-installed libraries instead of the repository-local ones.
TIP: It's a good practice to put
tests/Makefile.am. This option should be used for any executables which are used only for testing, or for generating other files and are consequently never installed. By specifying this option, we are telling Libtool that the executable it links will only ever be executed from where it is built in the build tree. Libtool is usually able to considerably speed up the link process for such executables.
AM_LDFLAGS) is desirable for libraries which do not depend on external symbols defined in apps linking against them.
Updated by fixeria 6 days ago · 7 revisions