Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.
cmake
Introduction and best practices
Daniel Pfeifer
May 21, 2015
daniel@pfeifer-mail.de
interest over time
2005 2007 2009 2011 2013 2015
autoconf
automake
bjam
cmake
scons
0https://www.google.com/trends/explore...
what is cmake?
according to its website
Welcome to CMake, the cross-platform, open-source build system.
CMake is a family of tools design...
cmake’s position among build systems
standalone Make, NMake, SCons, Jom, BJam, Ninja
integrated Visual Studio, Xcode, Ecli...
cmake is simple
> ls zlib-1.2.8
amiga/ as400/ contrib/ doc/
examples/ msdos/ nintendods/ old/
qnx/ test/ watcom/ win32/
ad...
reduce your maintenance ...
You write a single configuration that CMake understands.
CMake takes care that it works on all ...
... unless you break it!
Don’t make any assumption about the platform or compiler!
7
cmake is fast!
I was quite surprised with the speed of building Quantum GIS
codebase in comparison to Autotools.2
Task CMa...
the cmake cache
∙ Compiler and platform test results are cached in
CMakeCache.txt.
∙ You can modify this file and re-run CM...
cmake’s graphical cache editor
10
cmake’s position on the time axis
past CMake generates build systems.
today CMake is integrated into IDEs.
future IDEs run...
modes of operation
cmake as a build system generator
1 > cmake [<options>] <path>
∙ If the specified path contains a CMakeCache.txt, it is tre...
cmake as a build system generator
Issues:
∙ The commands mkdir and time are not portable.
∙ With cmake . you may accidenta...
cmake’s command-line tool mode
1 > cmake -E <command> [<options>...]
Run cmake -E help for a summary of commands.
1 > cmak...
use cmake to run the build system
1 > cmake --build build 
2 --target mylibrary 
3 --config Release 
4 --clean-first
Just ...
cmake as a scripting language
1 > cat hello_world.cmake
2 foreach(greet Hello Goodbye)
3 message(”${greet}, World!”)
4 end...
Resist the bash/perl/python temptation!
18
commands for projects
cmake_minimum_required()
Sets the mimimum required version of CMake.
1 cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
∙ P...
project()
Set the name and version; enable languages.
1 project(<name> VERSION <version> LANGUAGES CXX)
∙ CMake sets sever...
add_subdirectory()
Embed projects as sub-projects.
1 add_subdirectory(<sourcedir> [<binarydir>])
∙ CMake creates a Makefile...
hint!
Make sure that all your projects can be built both standalone and as
a subproject of another project:
∙ Don’t assume...
find_package()
Finds preinstalled dependencies
1 find_package(Qt5 REQUIRED COMPONENTS Widgets)
∙ Can set some variables an...
add_executable()
Add an executable target.
1 add_executable(tool
2 main.cpp
3 another_file.cpp
4 )
5 add_executable(my::to...
add_library()
Add a library target.
1 add_library(foo STATIC
2 foo1.cpp
3 foo2.cpp
4 )
5 add_library(my::foo ALIAS foo)
∙ ...
things to remember
∙ Always add namespaced aliases for libraries.
∙ Dont’t make libraries STATIC/SHARED unless they cannot...
usage requirements
usage requirements signature
1 target_<usage requirement>(<target>
2 <PRIVATE|PUBLIC|INTERFACE> <lib> ...
3 [<PRIVATE|PUBL...
target_link_libraries()
Set libraries as dependency.
1 target_link_libraries(foobar
2 PUBLIC my::foo
3 PRIVATE my::bar
4 )...
things to remember
∙ Prefer to link against namespaced targets.
∙ Specify the dependencies are private or public.
∙ Avoid ...
target_include_directories()
Set include directories.
1 target_include_directories(foo
2 PUBLIC include
3 PRIVATE src
4 )
...
things to remember
∙ Avoid the include_directories() command.
33
target_compile_definitions()
Set compile definitions (preprocessor constants).
1 target_compile_definitions(foo
2 PRIVATE S...
things to remember
∙ Avoid the add_definitions() command.
∙ Avoid adding definitions to CMAKE_<LANG>_FLAGS.
35
target_compile_options()
Set compile options/flags.
1 if(CMAKE_COMPILER_IS_GNUCXX)
2 target_compile_options(foo
3 PUBLIC -f...
things to remember
∙ Wrap compiler specific options in an appropriate condition.
∙ Avoid the add_compile_options() command....
target_compile_features()
Set required compiler features.
1 target_compile_features(foo
2 PUBLIC
3 cxx_auto_type
4 cxx_ran...
things to remember
∙ Don’t add -std=c++11 to CMAKE_<LANG>_FLAGS.
∙ Don’t pass -std=c++11 to target_compile_options().
39
best practices
goal: no custom variables
variables are fragile
1 set(PROJECT foobar)
2 set(LIBRARIES foo)
3
4 if(WIN32)
5 list(APPEND LIBRARIES bar)
6 endif()
7
8 ...
variables are fragile
Hard to diagnose:
bar links against foo! But only on Windows!
1 set(PROJECT foobar)
2 set(LIBRARIES ...
variables are fragile
This is better:
Without variables the code is more robust and easier to read.
1 target_link_librarie...
don’t use file(glob)!
Not recommended:
1 file(GLOB sources ”*.cpp”)
2 add_library(mylib ${sources})
∙ file(GLOB) is useful...
list all sources explicitly
1 add_library(mylib
2 main.cpp
3 file1.cpp
4 file2.cpp
5 )
45
Explicit is better than implicit
46
goal: no custom functions
picking on myself
∙ I wrote many custom functions.
∙ Experience tought me: Most of the time it is a bad idea.
48
just don’t
1 magic_project(<name> ...)
49
why no custom functions?
∙ Remember what I said about the project() command?
∙ The signature of project() was extended rec...
just don’t
1 magic_add_library(<name>
2 SOURCES
3 <list of sources>
4 LIBRARIES
5 <list of libraries>
6 )
51
why no custom functions?
∙ How to add platform specific libraries?
∙ Harder to get started for contributors.
∙ Maintenance!...
so you wrote a custom function ...
∙ Contribute it to CMake!
∙ If it is accepted, it is no longer a custom function.
∙ Oth...
summary
summary
∙ CMake is widely used, fast, cross-platform.
∙ Build system generator plus platform abstraction.
∙ Manage build t...
Thank you!
56
Nächste SlideShare
Wird geladen in …5
×

CMake - Introduction and best practices

48.822 Aufrufe

Veröffentlicht am

Slides of a presentation I gave 21 May 2015 for the C++ user group meeting.
http://www.meetup.com/MUCplusplus/events/222396899/

Veröffentlicht in: Software
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • @Bjarke Freund-Hansen You don't. You either use the feature-based enabling like on slide 39, or `set_target_properties` with `CXX_STANDARD` and `CXX_STANDARD_REQUIRED`.
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • Daniel, on page 40 you write about not adding -std=c++11 to CMAKE__FLAGS nor pass it to target_compiler_options(). But, where do I put it then?
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • On slide 24 you say to not assume your project root is the build root. I understand the intent, but I am at a loss as to how to implement that. In particular how does one do this for dependencies. For example, when I use boost or opencv, I put the find_package for each in the top level project. But without additional logic, the find_package commands should not be exercised in a sub-project. Can you point to an example of how you achieve this goal? Thanks!
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • Great explanation of modern CMake! Do you mind if I present you slides verbatim? (With proper attribution of course!) Also, would you mind sharing the slides in their original format?
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier

CMake - Introduction and best practices

  1. 1. cmake Introduction and best practices Daniel Pfeifer May 21, 2015 daniel@pfeifer-mail.de
  2. 2. interest over time 2005 2007 2009 2011 2013 2015 autoconf automake bjam cmake scons 0https://www.google.com/trends/explore#q=autoconf,automake,bjam,cmake,scons 1
  3. 3. what is cmake?
  4. 4. according to its website Welcome to CMake, the cross-platform, open-source build system. CMake is a family of tools designed to build, test and package software. CMake is used to control the software compilation process using simple platform and compiler independent configuration files. CMake generates native makefiles and workspaces that can be used in the compiler environment of your choice.1 1http://www.cmake.org/ 3
  5. 5. cmake’s position among build systems standalone Make, NMake, SCons, Jom, BJam, Ninja integrated Visual Studio, Xcode, Eclipse generators Autotools, CMake, GYP 4
  6. 6. cmake is simple > ls zlib-1.2.8 amiga/ as400/ contrib/ doc/ examples/ msdos/ nintendods/ old/ qnx/ test/ watcom/ win32/ adler32.c ChangeLog CMakeLists.txt compress.c configure crc32.c crc32.h deflate.c deflate.h FAQ gzclose.c gzguts.h gzlib.c gzread.c gzwrite.c INDEX infback.c inffast.c inffast.h inffixed.h inflate.c inflate.h inftrees.c inftrees.h make_vms.com Makefile Makefile.in README treebuild.xml trees.c trees.h uncompr.c zconf.h zconf.h.in zlib.3 zlib.3.pdf zlib.h zlib.map zlib.pc.in zlib2ansi zutil.c zutil.h 5
  7. 7. reduce your maintenance ... You write a single configuration that CMake understands. CMake takes care that it works on all compilers and platforms. 6
  8. 8. ... unless you break it! Don’t make any assumption about the platform or compiler! 7
  9. 9. cmake is fast! I was quite surprised with the speed of building Quantum GIS codebase in comparison to Autotools.2 Task CMake Autotools Configure 0:08 0:61 Make 12:15 21:16 Install 0:20 0:36 Total 12:43 22:43 2http://blog.qgis.org/node/16.html 8
  10. 10. the cmake cache ∙ Compiler and platform test results are cached in CMakeCache.txt. ∙ You can modify this file and re-run CMake. ∙ CMake also provides graphical cache editors. 9
  11. 11. cmake’s graphical cache editor 10
  12. 12. cmake’s position on the time axis past CMake generates build systems. today CMake is integrated into IDEs. future IDEs run CMake as a background process.3 3http://public.kitware.com/pipermail/cmake-developers/2015-April/025012.html 11
  13. 13. modes of operation
  14. 14. cmake as a build system generator 1 > cmake [<options>] <path> ∙ If the specified path contains a CMakeCache.txt, it is treated as a build directory where the build system is reconfigured and regenerated. ∙ Otherwise the specified path is treated as the source directory and the current working directory is treated as build directory. 1 > mkdir build 2 > cd build 3 > time cmake .. 4 > time cmake . 5 > time make 13
  15. 15. cmake as a build system generator Issues: ∙ The commands mkdir and time are not portable. ∙ With cmake . you may accidentally perform an in-source configure. ∙ Who said that make is the right build command? 1 > mkdir build 2 > cd build 3 > time cmake .. 4 > time cmake . 5 > time make mylibrary 14
  16. 16. cmake’s command-line tool mode 1 > cmake -E <command> [<options>...] Run cmake -E help for a summary of commands. 1 > cmake -E make_directory build 2 > cmake -E chdir cmake -E time cmake .. 3 > cmake -E time cmake build 15
  17. 17. use cmake to run the build system 1 > cmake --build build 2 --target mylibrary 3 --config Release 4 --clean-first Just don’t: 1 > ‘grep ’CMAKE_MAKE_PROGRAM:’ CMakeCache.txt 2 | awk -F= ’{print $2}’‘ mylibrary 16
  18. 18. cmake as a scripting language 1 > cat hello_world.cmake 2 foreach(greet Hello Goodbye) 3 message(”${greet}, World!”) 4 endforeach() 5 6 > cmake -P hello_world.cmake 7 Hello, World! 8 Goodbye, World! No configure or generate step is performed and the cache is not modified. 17
  19. 19. Resist the bash/perl/python temptation! 18
  20. 20. commands for projects
  21. 21. cmake_minimum_required() Sets the mimimum required version of CMake. 1 cmake_minimum_required(VERSION 3.2 FATAL_ERROR) ∙ Prefer the latest version of CMake. ∙ Please don’t set 2.8 as the minimum. ∙ If you use 2.6 or 2.4, God kills a kitten. 20
  22. 22. project() Set the name and version; enable languages. 1 project(<name> VERSION <version> LANGUAGES CXX) ∙ CMake sets several variables based on project(). ∙ Call to project() must be direct, not through a function/macro/include. ∙ CMake will add a call to project() if not found on the top level. 21
  23. 23. add_subdirectory() Embed projects as sub-projects. 1 add_subdirectory(<sourcedir> [<binarydir>]) ∙ CMake creates a Makefile/Solution for each subproject. ∙ The subproject does not have to reside in a subfolder. 22
  24. 24. hint! Make sure that all your projects can be built both standalone and as a subproject of another project: ∙ Don’t assume that your project root is the build root. ∙ Don’t modify global compile/link flags. ∙ Don’t make any global changes! 23
  25. 25. find_package() Finds preinstalled dependencies 1 find_package(Qt5 REQUIRED COMPONENTS Widgets) ∙ Can set some variables and define imported targets. ∙ Supports components. 24
  26. 26. add_executable() Add an executable target. 1 add_executable(tool 2 main.cpp 3 another_file.cpp 4 ) 5 add_executable(my::tool ALIAS tool) 25
  27. 27. add_library() Add a library target. 1 add_library(foo STATIC 2 foo1.cpp 3 foo2.cpp 4 ) 5 add_library(my::foo ALIAS foo) ∙ Libraries can be STATIC, SHARED, MODULE, or INTERFACE. ∙ Default can be controlled with BUILD_SHARED_LIBS. 26
  28. 28. things to remember ∙ Always add namespaced aliases for libraries. ∙ Dont’t make libraries STATIC/SHARED unless they cannot be built otherwise. ∙ Leave the control of BUILD_SHARED_LIBS to your clients! 27
  29. 29. usage requirements
  30. 30. usage requirements signature 1 target_<usage requirement>(<target> 2 <PRIVATE|PUBLIC|INTERFACE> <lib> ... 3 [<PRIVATE|PUBLIC|INTERFACE> <lib> ... ] ...] 4 ) PRIVATE Only used for this target. PUBLIC Used for this target and all targets that link against it. INTERFACE Only used for targets that link against this library. 29
  31. 31. target_link_libraries() Set libraries as dependency. 1 target_link_libraries(foobar 2 PUBLIC my::foo 3 PRIVATE my::bar 4 ) 30
  32. 32. things to remember ∙ Prefer to link against namespaced targets. ∙ Specify the dependencies are private or public. ∙ Avoid the link_libraries() command. ∙ Avoid the link_directories() command. ∙ No need to call add_dependencies(). 31
  33. 33. target_include_directories() Set include directories. 1 target_include_directories(foo 2 PUBLIC include 3 PRIVATE src 4 ) 32
  34. 34. things to remember ∙ Avoid the include_directories() command. 33
  35. 35. target_compile_definitions() Set compile definitions (preprocessor constants). 1 target_compile_definitions(foo 2 PRIVATE SRC_DIR=${Foo_SOURCE_DIR} 3 ) 34
  36. 36. things to remember ∙ Avoid the add_definitions() command. ∙ Avoid adding definitions to CMAKE_<LANG>_FLAGS. 35
  37. 37. target_compile_options() Set compile options/flags. 1 if(CMAKE_COMPILER_IS_GNUCXX) 2 target_compile_options(foo 3 PUBLIC -fno-elide-constructors 4 ) 5 endif() 36
  38. 38. things to remember ∙ Wrap compiler specific options in an appropriate condition. ∙ Avoid the add_compile_options() command. ∙ Avoid adding options to CMAKE_<LANG>_FLAGS. 37
  39. 39. target_compile_features() Set required compiler features. 1 target_compile_features(foo 2 PUBLIC 3 cxx_auto_type 4 cxx_range_for 5 PRIVATE 6 cxx_variadic_templates 7 ) ∙ CMake will add required compile flags. ∙ Errors if the compiler is not supported. 38
  40. 40. things to remember ∙ Don’t add -std=c++11 to CMAKE_<LANG>_FLAGS. ∙ Don’t pass -std=c++11 to target_compile_options(). 39
  41. 41. best practices
  42. 42. goal: no custom variables
  43. 43. variables are fragile 1 set(PROJECT foobar) 2 set(LIBRARIES foo) 3 4 if(WIN32) 5 list(APPEND LIBRARIES bar) 6 endif() 7 8 target_link_libraries(${Project} 9 ${LIBRARIES} 10 ) 42
  44. 44. variables are fragile Hard to diagnose: bar links against foo! But only on Windows! 1 set(PROJECT foobar) 2 set(LIBRARIES foo) 3 4 if(WIN32) 5 list(APPEND LIBRARIES bar) 6 endif() 7 8 target_link_libraries(${Project} 9 ${LIBRARIES} 10 ) 42
  45. 45. variables are fragile This is better: Without variables the code is more robust and easier to read. 1 target_link_libraries(foobar PRIVATE my::foo) 2 3 if(WIN32) 4 target_link_libraries(foobar PRIVATE my::bar) 5 endif() 43
  46. 46. don’t use file(glob)! Not recommended: 1 file(GLOB sources ”*.cpp”) 2 add_library(mylib ${sources}) ∙ file(GLOB) is useful in scripting mode. ∙ Don’t use it in configure mode! 44
  47. 47. list all sources explicitly 1 add_library(mylib 2 main.cpp 3 file1.cpp 4 file2.cpp 5 ) 45
  48. 48. Explicit is better than implicit 46
  49. 49. goal: no custom functions
  50. 50. picking on myself ∙ I wrote many custom functions. ∙ Experience tought me: Most of the time it is a bad idea. 48
  51. 51. just don’t 1 magic_project(<name> ...) 49
  52. 52. why no custom functions? ∙ Remember what I said about the project() command? ∙ The signature of project() was extended recently. 50
  53. 53. just don’t 1 magic_add_library(<name> 2 SOURCES 3 <list of sources> 4 LIBRARIES 5 <list of libraries> 6 ) 51
  54. 54. why no custom functions? ∙ How to add platform specific libraries? ∙ Harder to get started for contributors. ∙ Maintenance! 52
  55. 55. so you wrote a custom function ... ∙ Contribute it to CMake! ∙ If it is accepted, it is no longer a custom function. ∙ Otherwise, the reason for rejection should give you a hint. ∙ The maintainers are very helpful and experienced. 53
  56. 56. summary
  57. 57. summary ∙ CMake is widely used, fast, cross-platform. ∙ Build system generator plus platform abstraction. ∙ Manage build targets with usage requirements. ∙ Goal: No custom variables. ∙ Goal: No custom functions. 55
  58. 58. Thank you! 56

×