C-Programmierung

Compilation mit CMake

Modulkonzept Beispiel | | Debugging

CMake = cross-platform build tool

Automatisiert das Compilieren und Linken von C/C++ Modulen:

Einfaches Beispiel fĂĽr folgendes Haupt- und ein Neben-Modul:

main.cpp:

#include <stdio.h> /* system headers */
#include "square.h" /* local headers */

int main() /* main function */
{
   double x=10; /* local initialized variable */
   printf("square of %g is %g\n", x, square(x));
   return(0); /* error code 0 means ok */
}

square.h (module header):

#ifndef SQUARE_H /* guard */
#define SQUARE_H

double square(double x);   // function prototype

#endif /* end of guard */

square.cpp (module implementation):

#include "square.h" /* module header */

double square(double x)
   {return(x*x);}          // function implementation

FĂĽr das obige Beispiel definieren wir nun ein CMake Projektdatei, welche CMake die Quelltextdateien mitteilt, welche zu einem Programm kompiliert und gelinkt werden sollen. Dazu mĂĽssen in der Datei CMakeLists.txt die CMake-Variablen HDRS und SRCS entsprechend definiert werden.

CMakeLists.txt:

PROJECT(MyProject)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++98")

SET(HDRS square.h) # module headers go here (*.h)
SET(SRCS main.cpp square.cpp) # module implementations go here (*.cpp)

ADD_EXECUTABLE(main ${HDRS} ${SRCS}) # compile and link main executable

Wir starten CMake im Projektverzeichnis mit der Kommandozeile:

cmake .

Dies erzeugt aus der CMakeLists.txt Datei ein sogenanntes Makefile fĂĽr das Unix Make-Tool. Wenn wir nun das Make-Tool starten, so erzeugt dieses durch Aufruf der GCC Toolchain ein ausfĂĽhrbares Programm:

make


Beispielablauf anhand eines CMake Beispiels, das via SVN vom SVN Server “Schorsch” heruntergeladen wird:

svn co svn://schorsch.efi.fh-nuernberg.de/cmake.cpp

Beispielablauf:

~/Desktop> svn co svn://schorsch.efi.fh-nuernberg.de/cmake.cpp
A    cmake.cpp/main.cpp
A    cmake.cpp/module.cpp
A    cmake.cpp/module.h
A    cmake.cpp/CMakeLists.txt
Checked out revision 1.
~/Desktop>  cd cmake.cpp/
~/Desktop/cmake.cpp> cmake .
-- The C compiler identification is GNU 4.2.1
-- The CXX compiler identification is GNU 4.2.1
-- Checking whether C compiler has -isysroot
-- Checking whether C compiler has -isysroot - yes
-- Checking whether C compiler supports OSX deployment target flag
-- Checking whether C compiler supports OSX deployment target flag - yes
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Checking whether CXX compiler has -isysroot
-- Checking whether CXX compiler has -isysroot - yes
-- Checking whether CXX compiler supports OSX deployment target flag
-- Checking whether CXX compiler supports OSX deployment target flag - yes
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/roettger/Desktop/cmake.cpp
~/Desktop/cmake.cpp> make
Scanning dependencies of target MyProject
[ 50%] Building CXX object CMakeFiles/MyProject.dir/module.cpp.o
Linking CXX static library libMyProject.a
[ 50%] Built target MyProject
Scanning dependencies of target main
[100%] Building CXX object CMakeFiles/main.dir/main.cpp.o
Linking CXX executable main
[100%] Built target main

Die jeweiligen Kommandozeilen zum Aufruf der GCC Toolchain lassen sich mit folgendem Kommando mitverfolgen:

make VERBOSE=1

Beispielablauf:

~/Desktop/cmake.cpp> make VERBOSE=1
make -f CMakeFiles/Makefile2 all
make -f CMakeFiles/MyProject.dir/build.make CMakeFiles/MyProject.dir/depend
cd /Users/roettger/Desktop/cmake.cpp && /Users/roettger/bin/cmake -E cmake_depends "Unix Makefiles" /Users/roettger/Desktop/cmake.cpp /Users/roettger/Desktop/cmake.cpp /Users/roettger/Desktop/cmake.cpp /Users/roettger/Desktop/cmake.cpp /Users/roettger/Desktop/cmake.cpp/CMakeFiles/MyProject.dir/DependInfo.cmake --color=
make -f CMakeFiles/MyProject.dir/build.make CMakeFiles/MyProject.dir/build
[ 50%] Building CXX object CMakeFiles/MyProject.dir/module.cpp.o
/usr/bin/c++    -I/Users/roettger/Desktop/cmake.cpp    -o CMakeFiles/MyProject.dir/module.cpp.o -c /Users/roettger/Desktop/cmake.cpp/module.cpp
Linking CXX static library libMyProject.a
/Users/roettger/bin/cmake -P CMakeFiles/MyProject.dir/cmake_clean_target.cmake
/Users/roettger/bin/cmake -E cmake_link_script CMakeFiles/MyProject.dir/link.txt --verbose=1
/usr/bin/ar cr libMyProject.a  CMakeFiles/MyProject.dir/module.cpp.o
/usr/bin/ranlib libMyProject.a
[ 50%] Built target MyProject
make -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/depend
cd /Users/roettger/Desktop/cmake.cpp && /Users/roettger/bin/cmake -E cmake_depends "Unix Makefiles" /Users/roettger/Desktop/cmake.cpp /Users/roettger/Desktop/cmake.cpp /Users/roettger/Desktop/cmake.cpp /Users/roettger/Desktop/cmake.cpp /Users/roettger/Desktop/cmake.cpp/CMakeFiles/main.dir/DependInfo.cmake --color=
make -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/build
[100%] Building CXX object CMakeFiles/main.dir/main.cpp.o
/usr/bin/c++    -I/Users/roettger/Desktop/cmake.cpp    -o CMakeFiles/main.dir/main.cpp.o -c /Users/roettger/Desktop/cmake.cpp/main.cpp
Linking CXX executable main
/Users/roettger/bin/cmake -E cmake_link_script CMakeFiles/main.dir/link.txt --verbose=1
/usr/bin/c++    -Wl,-search_paths_first -Wl,-headerpad_max_install_names   CMakeFiles/main.dir/main.cpp.o  -o main  libMyProject.a 
[100%] Built target main

Zum AusfĂĽhren des erzeugten Programms geben wir nun ein:

./main

Oder alles noch einmal zusammen:

cmake . && make && ./main

Falls ein Modulquelltext verändert wurde, so kompiliert und linkt CMake/Make automatisch nur das veränderte Modul und ebenso alle Module, welche von diesem veränderten Module eventuell abhängen (sogenannte dependencies) neu:

make

Beispielablauf:

[ 50%] Built target MyProject
[100%] Built target main

CMake kann aus der selben Projektdefinition auch Projekte für Visual C++ oder XCode erzeugen. Standardmässig erzeugt es aber Makefiles für Unix. Weil die Projektdefinition nicht von der jeweiligen Plattform abhängt, ist diese Art der Projektdefinition plattformunabhängig.

Siehe auch:

Tipp: KDevelop kann CMake Projekte importieren. D.h. Sie müssen auch mit CMake nicht auf den Komfort einer IDE verzichten, sind aber prinzipiell nicht auf einen bestimmte Plattform wie bei Visual-C/C++ beschränkt.

Noch ein Tipp: Um einen bestimmten Compiler-Standard, also z.B. den C++ Standard 2011 vorzugeben, fĂĽgen wir die folgende Zeile im CMakeLists.txt hinzu:

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

Prinzipiell gibt es die Standards c++98, c++03, c++11, c++14, c++17, usw…

Empfohlen ist fĂĽr die elektronische Abgabe der c++98 Standard!

Modulkonzept Beispiel | | Debugging

Options: