Lecture 7a Buildsys

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 87

Programming

Lecture 7a

Simon Scheidegger
Roadmap of this slide-deck

1. Automated builds: Make (Jump-start)

2. Automated builds: Make (extended example – self-study)

3. Automated builds: Cmake


Before we start
1. For this lecture only , choose the indicated app on Nuvolos
1. Choose this app today for Lecture 7a: JupyterLab for Programming

2. Before running make, please make sure to type in a console


conda activate /dhlib/py2
Make: Work-flow
See https://software-carpentry.org/
Manual interference
Manual interference – necessary?
Worry about replicability
Worry about replicability
Automate as much as possible

See demo_1/make (later – for self-study)


Automate as much as possible
1. Automated builds – Make

The make utility is a software tool for managing and maintaining
computer programs consisting many component files.

The make utility automatically determines which pieces of a large program
need to be recompiled, and issues commands to recompile them.

Make reads its instruction from Makefile (called the descriptor file) by
default.

Makefile sets a set of rules to determine which parts of a program
need to be recompile, and issues command to recompile them.

Makefile is a way of automating software building procedure and other
complex tasks with dependencies.

Makefile contains:

dependency rules

macros and

suffix (or implicit) rules.
C++ code to compile

See demo_1/makefile_jumpstart
Command Line Approach to Compile


g++ -c hello.cpp main.cpp factorial.cpp

ls *.o
factorial.o hello.o main.o

g++ -o prog factorial.o hello.o main.o

./ prog
Hello World!
The factorial of 5 is 120

Suppose we later modified hello.cpp, we need to:

g++ -c hello.cpp

g++ -o prog factorial.o hello.o main.o

See demo_1/makefile_jumpstart
Example Makefile
# This is a comment line
CC=g++
# CFLAGS will be the options passed to the compiler.
CFLAGS= -c -Wall

all: prog

prog: main.o factorial.o hello.o


$(CC) main.o factorial.o hello.o -o prog

main.o: main.cpp
$(CC) $(CFLAGS) main.cpp

factorial.o: factorial.cpp
$(CC) $(CFLAGS) factorial.cpp

hello.o: hello.cpp
$(CC) $(CFLAGS) hello.cpp

clean:
rm -rf *.o

See demo_1/makefile_jumpstart
Basic Makefile Structure
Dependency rules

A rule consists of three parts, one or more targets, zero or more
dependencies, and zero or more commands in the form:

target: dependencies
<tab> commands to make target

<tab> character MUST NOT be replaced be spaces.

A “target” is usually the name of a file (e.g. executable or object
files). It can also be the name of an action (e.g. clean)

“dependencies” are files that are used as input to create the
target.

Each “command” in a rule is interpreted by a shell to be executed.

By default, make uses /bin/sh shell.

Typing “make target” will:
1. Make sure all the dependencies are up to date.
2. If target is older than any dependency, recreate it using the
specified commands.

See demo_1/makefile_jumpstart
Basic Makefile Structure (cont’d)


By default, typing “make” creates first target in Makefile.


Since prog depends on main.o factorial.o hello.o, all of object files
must exist and be up-to-date.

make will check for them and recreating them if necessary.


Phony targets

A phony target is one that isn't really the name of a file.

It will only have a list of commands and no dependencies.

E.g. clean:
rm -rf *.o

See demo_1/makefile_jumpstart
Basic Makefile Structure (cont’d)

Macros

By using macros, we can avoid repeating text entries and makefile is
easy to modify.

Macro definitions have the form:
NAME = text string
e.g. we have: CC=g++

Macros are referred to by placing the name in either parentheses or
curly braces and preceding it with $ sign.
– E.g. $(CC) main.o factorial.o hello.o -o prog

See demo_1/makefile_jumpstart
Basic Makefile Structure (cont’d)
Internal Macros

Internal macros are predefined in make.

“make -p” to display a listing of all the macros, suffix rules and targets
in effect for the current build.

Special macros

The macro @ evaluates to the name of the current target.
– E.g.
prog1 : $(objs)
$(CXX) -o $@ $(objs)

is equivalent to

prog1 : $(objs)
$(CXX) -o prog1 $(objs)

See demo_1/makefile_jumpstart
Basic Makefile Structure (cont’d)
Suffix rules
A way to define default rules or implicit rules that make can use to build a program.
There are double-suffix and single-suffix.

Suffix rules are obsolete and are supported for compatibility. Use pattern rules (a rule
contains character ‘%’) if possible.

Doubles-suffix is defined by the source suffix and the target suffix . E.g.
.cpp.o:
$(CC) $(CFLAGS) -c $<

– This rule tells make that .o files are made from .cpp files.
– $< is a special macro which in this case stands for a .cpp file that is used to
produce a .o file.

This is equivalent to the pattern rule “%.o : %.cpp”
%.o : %.cpp
$(CC) $(CFLAGS) -c $<

Command line macros



Macros can be defined on the command line.
– E.g. make DEBUG_FLAG=-g

See demo_1/makefile_jumpstart
How Does Make Work?


The make utility compares the modification time of the target file with the
modification times of the dependency files.

Any dependency file that has a more recent modification time than its target file forces
the target file to be recreated.

By default, the first target file is the one that is built.

Other targets are checked only if they are dependencies for the first target.

Except for the first target, the order of the targets does not matter.

The make utility will build them in the order required.

See demo_1/makefile_jumpstart
A new Makefile
# This is a comment line
CC=g++
# CFLAGS will be the options passed to the compiler.
CFLAGS=-c –Wall
OBJECTS = main.o hello.o factorial.o

all: prog

prog: $(OBJECTS)
$(CC) $(OBJECTS) -o prog

%.o: %.cpp
$(CC) $(CFLAGS) $<

clean:
rm -rf *.o

See demo_1/makefile_jumpstart or http://www.gnu.org/software/make/manual/html_node/


2. Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
Step-by-Step
3. CMake: a cross-platform build system

Is a cross-platform build system

Unix/Linux

MacOS X

Windows


Build instructions in a file called CMakeLists.txt get
translated into the build system of your choice

Makefiles

Microsoft Visual Studio projects

Xcode projects


We will just show a few examples. Read tutorials for more

https://cmake.org/examples/

https://cmake.org/cmake-tutorial/
Compile an application
See demo_1/CMake_examples
Running CMake to create makefiles


Either use a CMake GUI or the command line tool

Run cmake GUI in the build directory (that you create/choose)

cd build-directory (e.g.,mkdir install, cd install)


cmake source-directory (e.g., cmake ../)

Optionally specify where files should be installed
cmake –DCMAKE_INSTALL_PREFIX=install-path source-directory


Note that absolute paths must be given.

Use ccmake or the GUI to adjust build settings, compiler flags, ...
Building after creating makefiles


Now just build it like with makefiles:

Build all: make


Build a specific target: make square.exe
Cleaning the build: make clean
Installing: make install


Set the environment variable VERBOSE to see more details:

make VERBOSE=1
Variables you might want to customize


CMAKE_BUILD_TYPE can be set to

Release

Debug

...

CMAKE_*_FLAGS* can be set to control compiling and
linking

CMAKE_INSTALL_PREFIX sets where files are installed
Alternatively create a project file


On the Mac

cmake –G Xcode source-directory


open Square.xcodeproj


On Windows use the Cmake GUI to create a VisualStudio
project
Creating and using a static library
demo_1/CMake_examples/square_cmake_static_lib
Creating and using a dynamic library
demo_1/CMake_examples/square_cmake_shared_li
b
Choosing between static and dynamic

Use options and variables to let the user change build settings
Configuring files, step 1
demo_1/CMake_examples/square_cmake_version


CMake variables can be inserted into files, to configure the
sources before building them.

First create an “input” file containing placeholders:

// file version.cpp.in

#include "square.hpp"

#define SQUARE_VERSION_MAJOR "@Square_VERSION_MAJOR@"


#define SQUARE_VERSION_MINOR "@Square_VERSION_MINOR@”

std::string square::version()
{
return SQUARE_VERSION_MAJOR"."SQUARE_VERSION_MINOR;
}
Configuring files, step 2

Then set the variables in the CMakeLists.txt and configure the file:

# CMakeLists.txt

set(Square_VERSION_MAJOR 1)
set(Square_VERSION_MINOR 0)

# create the source file, substituting variables

configure_file (
"${PROJECT_SOURCE_DIR}/version.cpp.in"
"${PROJECT_BINARY_DIR}/version.cpp"
)
More commands...

Perform the commands in a subdirectory
add_subdirectory( dir )

Set additional include directories
include_directories( dir )

Set directories containing libraries
link_directories ( dir )

Set compiler definitions
add_definitions ( -D...)
There is much more

There are many more features:

Finding libraries (e.g. BLAS, LAPACK, MPI, HDF5, Boost, ...)

Defining functions

Setting build options

Looping over variables

Creating installer packages

Creating and running unit tests


Some of these we will encounter over the next weeks...


For others, read the manuals and tutorials

https://cmake.org/examples/

https://cmake.org/cmake-tutorial/

You might also like