Project

General

Profile

Actions

BuildSystem » History » Revision 3

« Previous | Revision 3/12 (diff) | Next »
fixeria, 03/14/2023 09:44 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 Makefile.in files,
  • Autoconf - a tool for generating configure scripts, and
  • 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 configure.ac and 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 configure.ac and 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.

Weird syntax

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.

Makefile.am variables

There are not that many of them, but it's easy to get confused.

Binaries

  • bin_PROGRAMS - executable files, which will be installed during make install
  • noinst_PROGRAMS - executable files, which will not be installed during make install
  • check_PROGRAMS - executable files, which will only be compiled during make check and will not be installed during make install

TIP: It's recommended to use check_PROGRAMS for tests, so that they won't be compiled during make all.

AM_CPPFLAGS, AM_CFLAGS, AM_CXXFLAGS

  • AM_CPPFLAGS is for the preprocessor flags like -I$(top_srcdir)/include or -DHAVE_FOOBAR
  • AM_CFLAGS is for the C compiler flags applying to C source files only
    • This is where you put stuff like $(LIBOSMOCORE_CFLAGS)
    • Avoid putting -O3, -g, -ggdb there, let the user decide of these flags
      • One exception is -Wall, and sometimes -g in tests
  • AM_CXXFLAGS is 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 osmo_app_CPPFLAGS, osmo_app_CFLAGS, and osmo_app_CXXFLAGS variables.

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: gcc $(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_LDFLAGS is for the liker flags like -version-info, -no-install, -no-undefined
  • LDADD is a list of libraries that implicitly applies to all binaries and libs within the current file (unless overridden)
  • osmo_app_LDADD is a list of libraries for osmo-app binary (not for libraries)
  • libosmo_lib_LIBADD is a list of libraries for libosmo-lib library (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 LDADD/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 -no-install to AM_LDFLAGS in 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.

TIP: Using -no-undefined (AM_LDFLAGS) is desirable for libraries which do not depend on external symbols defined in apps linking against them.

Files (0)

Updated by fixeria about 1 year ago · 3 revisions

Add picture from clipboard (Maximum size: 48.8 MB)