Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CPlusPlusNotesForProfessionals.pdf
Скачиваний:
47
Добавлен:
20.05.2023
Размер:
5.11 Mб
Скачать

Chapter 130: Build Systems

C++, like C, has a long and varied history regarding compilation workflows and build processes. Today, C++ has various popular build systems that are used to compile programs, sometimes for multiple platforms within one build system. Here, a few build systems will be reviewed and analyzed.

Section 130.1: Generating Build Environment with CMake

CMake generates build environments for nearly any compiler or IDE from a single project definition. The following examples will demonstrate how to add a CMake file to the cross-platform "Hello World" C++ code.

CMake files are always named "CMakeLists.txt" and should already exist in every project's root directory (and possibly in sub-directories too.) A basic CMakeLists.txt file looks like:

cmake_minimum_required(VERSION 2.4) project(HelloWorld) add_executable(HelloWorld main.cpp)

See it live on Coliru.

This file tells CMake the project name, what file version to expect, and instructions to generate an executable called "HelloWorld" that requires main.cpp.

Generate a build environment for your installed compiler/IDE from the command line:

> cmake .

Build the application with:

> cmake --build .

This generates the default build environment for the system, depending on the OS and installed tools. Keep source code clean from any build artifacts with use of "out-of-source" builds:

>mkdir build

>cd build

>cmake ..

>cmake --build .

CMake can also abstract the platform shell's basic commands from the previous example:

>cmake -E make_directory build

>cmake -E chdir build cmake ..

>cmake --build build

CMake includes generators for a number of common build tools and IDEs. To generate makefiles for Visual Studio's nmake:

>cmake -G "NMake Makefiles" ..

>nmake

GoalKicker.com – C++ Notes for Professionals

625

Section 130.2: Compiling with GNU make

Introduction

The GNU Make (styled make) is a program dedicated to the automation of executing shell commands. GNU Make is one specific program that falls under the Make family. Make remains popular among Unix-like and POSIX-like operating systems, including those derived from the Linux kernel, Mac OS X, and BSD.

GNU Make is especially notable for being attached to the GNU Project, which is attached to the popular GNU/Linux operating system. GNU Make also has compatible versions running on various flavors of Windows and Mac OS X. It is also a very stable version with historical significance that remains popular. It is for these reasons that GNU Make is often taught alongside C and C++.

Basic rules

To compile with make, create a Makefile in your project directory. Your Makefile could be as simple as:

Makefile

#Set some variables to use in our command

#First, we set the compiler to be g++ CXX=g++

#Then, we say that we want to compile with g++'s recommended warnings and some extra ones. CXXFLAGS=-Wall -Wextra -pedantic

#This will be the output file

EXE=app

SRCS=main.cpp

#When you call `make` at the command line, this "target" is called.

#The $(EXE) at the right says that the `all` target depends on the `$(EXE)` target.

#$(EXE) expands to be the content of the EXE variable

#Note: Because this is the first target, it becomes the default target if `make` is called without target

all: $(EXE)

#This is equivalent to saying

#app: $(SRCS)

#$(SRCS) can be separated, which means that this target would depend on each file.

#Note that this target has a "method body": the part indented by a tab (not four spaces).

#When we build this target, make will execute the command, which is:

#g++ -Wall -Wextra -pedantic -o app main.cpp

#I.E. Compile main.cpp with warnings, and output to the file ./app

$(EXE): $(SRCS)

@$(CXX) $(CXXFLAGS) -o $@ $(SRCS)

#This target should reverse the `all` target. If you call

#make with an argument, like `make clean`, the corresponding target

#gets called.

clean:

@rm -f $(EXE)

NOTE: Make absolutely sure that the indentations are with a tab, not with four spaces. Otherwise, you'll get an error of Makefile:10: *** missing separator. Stop.

GoalKicker.com – C++ Notes for Professionals

626

To run this from the command-line, do the following:

$ cd ~/Path/to/project $ make

$ ls

app main.cpp Makefile

$ ./app Hello World!

$ make clean $ ls

main.cpp Makefile

Incremental builds

When you start having more files, make becomes more useful. What if you edited a.cpp but not b.cpp? Recompiling b.cpp would take more time.

With the following directory structure:

.

+-- src

|+-- a.cpp

|+-- a.hpp

|

+--

b.cpp

|

+--

b.hpp

+-- Makefile

This would be a good Makefile:

Makefile

CXX=g++

CXXFLAGS=-Wall -Wextra -pedantic

EXE=app

SRCS_GLOB=src/*.cpp

SRCS=$(wildcard $(SRCS_GLOB))

OBJS=$(SRCS:.cpp=.o)

all: $(EXE)

$(EXE): $(OBJS)

@$(CXX) -o $@ $(OBJS)

depend: .depend

.depend: $(SRCS)

@-rm -f ./.depend

@$(CXX) $(CXXFLAGS) -MM $^>>./.depend

clean:

-rm -f $(EXE) -rm $(OBJS) -rm *~

-rm .depend

include .depend

GoalKicker.com – C++ Notes for Professionals

627

Again watch the tabs. This new Makefile ensures that you only recompile changed files, minimizing compile time.

Documentation

For more on make, see the o cial documentation by the Free Software Foundation, the stackoverflow documentation and dmckee's elaborate answer on stackoverflow.

Section 130.3: Building with SCons

You can build the cross-platform "Hello World" C++ code, using Scons - A Python-language software construction tool.

First, create a file called SConstruct (note that SCons will look for a file with this exact name by default). For now, the file should be in a directory right along your hello.cpp. Write in the new file the line

Program('hello.cpp')

Now, from the terminal, run scons. You should see something like

$ scons

scons: Reading SConscript files ...

scons: done reading SConscript files. scons: Building targets ...

g++ -o hello.o -c hello.cpp g++ -o hello hello.o

scons: done building targets.

(although the details will vary depending on your operating system and installed compiler).

The Environment and Glob classes will help you further configure what to build. E.g., the SConstruct file

env=Environment(CPPPATH='/usr/include/boost/', CPPDEFINES=[],

LIBS=[], SCONS_CXX_STANDARD="c++11"

)

env.Program('hello', Glob('src/*.cpp'))

builds the executable hello, using all cpp files in src. Its CPPPATH is /usr/include/boost and it specifies the C++11 standard.

Section 130.4: Autotools (GNU)

Introduction

The Autotools are a group of programs that create a GNU Build System for a given software package. It is a suite of tools that work together to produce various build resources, such as a Makefile (to be used with GNU Make). Thus, Autotools can be considered a de facto build system generator.

Some notable Autotools programs include:

Autoconf

Automake (not to be confused with make)

In general, Autotools is meant to generate the Unix-compatible script and Makefile to allow the following command

GoalKicker.com – C++ Notes for Professionals

628