SlideShare ist ein Scribd-Unternehmen logo
1 von 106
Downloaden Sie, um offline zu lesen
Effective CMake
a random selection of best practices
Daniel Pfeifer
June 7, 2017
daniel@pfeifer-mail.de
Opening
Why?
The way you use CMake affects your users!
1
CMake’s similarities with C++
• big userbase, industry dominance
• focus on backwards compatibility
• complex, feature rich, ”multi paradigm”
• bad reputation, ”bloated”, ”horrible syntax”
• some not very well known features
2
Standards
0https://xkcd.com/927/
3
CMake is code.
Use the same principles for CMakeLists.txt
and modules as for the rest of your codebase.
3
Language
Organization
Directories that contain a CMakeLists.txt are the entry point for
the build system generator. Subdirectories may be
added with add_subdirectory() and must contain a
CMakeLists.txt too.
Scripts are <script>.cmake files that can be executed with
cmake -P <script>.cmake.
Not all commands are supported.
Modules are <script>.cmake files located in the
CMAKE_MODULE_PATH.
Modules can be loaded with the include() command.
4
Commands
1 command_name(space separated list of strings)
• Scripting commands change state of command processor
• set variables
• change behavior of other commands
• Project commands
• create build targets
• modify build targets
• Command invocations are not expressions.
5
Variables
1 set(hello world)
2 message(STATUS "hello, ${hello}")
• Set with the set() command.
• Expand with ${}.
• Variables and values are strings.
• Lists are ;-separated strings.
• CMake variables are not environment variables
(unlike Makefile).
• Unset variable expands to empty string.
6
Comments
1 # a single line comment
2
3 #[==[
4 multi line comments
5
6 #[=[
7 may be nested
8 #]=]
9 #]==]
7
Generator expressions
1 target_compile_definitions(foo PRIVATE
2 "VERBOSITY=$<IF:$<CONFIG:Debug>,30,10>"
3 )
• Generator expressions use the $<> syntax.
• Not evaluated by command interpreter.
It is just a string with $<>.
• Evaluated during build system generation.
• Not supported in all commands (obviously).
8
Custom Commands
Two types of commands
• Commands can be added with function() or macro().
• Difference is like in C++.
• When a new command replaces an existing command,
the old one can be accessed with a _ prefix.
9
Custom command: Function
1 function(my_command input output)
2 # ...
3 set(${output} ... PARENT_SCOPE)
4 endfunction()
5 my_command(foo bar)
• Variables are scoped to the function, unless set with
PARENT_SCOPE.
• Available variables: input, output, ARGC, ARGV, ARGN, ARG0, ARG1,
ARG2, …
• Example: ${output} expands to bar.
10
Custom command: Macro
1 macro(my_command input output)
2 # ...
3 endmacro()
4 my_command(foo bar)
• No extra scope.
• Text replacements: ${input}, ${output}, ${ARGC}, ${ARGV},
${ARGN}, ${ARG0}, ${ARG1}, ${ARG2}, …
• Example: ${output} is replaced by bar.
11
Create macros to wrap commands
that have output parametes.
Otherwise, create a function.
11
Evolving CMake code
Deprecate CMake commands
1 macro(my_command)
2 message(DEPRECATION
3 "The my_command command is deprecated!")
4 _my_command(${ARGV})
5 endmacro()
12
Deprecate CMake variables
1 set(hello "hello world!")
2
3 function(__deprecated_var var access)
4 if(access STREQUAL "READ_ACCESS")
5 message(DEPRECATION
6 "The variable '${var}' is deprecated!")
7 endif()
8 endfunction()
9
10 variable_watch(hello __deprecated_var)
13
Variables are so CMake 2.8.12.
Modern CMake is about Targets and Properties!
13
Targets and Properties
Look Ma, no Variables!
1 add_library(Foo foo.cpp)
2 target_link_libraries(Foo PRIVATE Bar::Bar)
3
4 if(WIN32)
5 target_sources(Foo PRIVATE foo_win32.cpp)
6 target_link_libraries(Foo PRIVATE Bar::Win32Support)
7 endif()
14
Avoid custom variables
in the arguments of project commands.
14
Don’t use file(GLOB) in projects.
14
Imagine Targets as Objects
• Constructors:
• add_executable()
• add_library()
• Member variables:
• Target properties (too many to list here).
• Member functions:
• get_target_property()
• set_target_properties()
• get_property(TARGET)
• set_property(TARGET)
• target_compile_definitions()
• target_compile_features()
• target_compile_options()
• target_include_directories()
• target_link_libraries()
• target_sources()
15
Forget those commands:
add_compile_options()
include_directories()
link_directories()
link_libraries()
15
Example:
1 target_compile_features(Foo
2 PUBLIC
3 cxx_strong_enums
4 PRIVATE
5 cxx_lambdas
6 cxx_range_for
7 )
• Adds cxx_strong_enums to the target properties
COMPILE_FEATURES and INTERFACE_COMPILE_FEATURES.
• Adds cxx_lambdas;cxx_range_for to the target property
COMPILE_FEATURES.
16
Get your hands off CMAKE_CXX_FLAGS!
16
Build Specification and Usage Requirements
• Non-INTERFACE_ properties define
the build specification of a target.
• INTERFACE_ properties define
the usage requirements of a target.
17
Build Specification and Usage Requirements
• PRIVATE populates the non-INTERFACE_ property.
• INTERFACE populates the INTERFACE_ property.
• PUBLIC populates both.
18
Use target_link_libraries()
to express direct dependencies!
18
Example:
1 target_link_libraries(Foo
2 PUBLIC Bar::Bar
3 PRIVATE Cow::Cow
4 )
• Adds Bar::Bar to the target properties LINK_LIBRARIES and
INTERFACE_LINK_LIBRARIES.
• Adds Cow::Cow to the target property LINK_LIBRARIES.
19
Example:
1 target_link_libraries(Foo
2 PUBLIC Bar::Bar
3 PRIVATE Cow::Cow
4 )
• Adds Bar::Bar to the target properties LINK_LIBRARIES and
INTERFACE_LINK_LIBRARIES.
• Adds Cow::Cow to the target property LINK_LIBRARIES.
• Effectively adds all INTERFACE_<property> of Bar::Bar to
<property> and INTERFACE_<property>.
• Effectively adds all INTERFACE_<property> of Cow::Cow to
<property>.
19
Example:
1 target_link_libraries(Foo
2 PUBLIC Bar::Bar
3 PRIVATE Cow::Cow
4 )
• Adds Bar::Bar to the target properties LINK_LIBRARIES and
INTERFACE_LINK_LIBRARIES.
• Adds Cow::Cow to the target property LINK_LIBRARIES.
• Effectively adds all INTERFACE_<property> of Bar::Bar to
<property> and INTERFACE_<property>.
• Effectively adds all INTERFACE_<property> of Cow::Cow to
<property>.
• Adds $<LINK_ONLY:Cow::Cow> to INTERFACE_LINK_LIBRARIES.
19
Pure usage reqiurements
1 add_library(Bar INTERFACE)
2 target_compile_definitions(Bar INTERFACE BAR=1)
• INTERFACE libraries have no build specification.
• They only have usage requirements.
20
Don’t abuse requirements!
Eg: -Wall is not a requirement!
20
Project Boundaries
How to use external libraries
Always like this:
1 find_package(Foo 2.0 REQUIRED)
2 # ...
3 target_link_libraries(... Foo::Foo ...)
21
FindFoo.cmake
1 find_path(Foo_INCLUDE_DIR foo.h)
2 find_library(Foo_LIBRARY foo)
3 mark_as_advanced(Foo_INCLUDE_DIR Foo_LIBRARY)
4
5 include(FindPackageHandleStandardArgs)
6 find_package_handle_standard_args(Foo
7 REQUIRED_VARS Foo_LIBRARY Foo_INCLUDE_DIR
8 )
9
10 if(Foo_FOUND AND NOT TARGET Foo::Foo)
11 add_library(Foo::Foo UNKNOWN IMPORTED)
12 set_target_properties(Foo::Foo PROPERTIES
13 IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
14 IMPORTED_LOCATION "${Foo_LIBRARY}"
15 INTERFACE_INCLUDE_DIRECTORIES "${Foo_INCLUDE_DIR}"
16 )
17 endif()
22
FindPNG.cmake
if(PNG_FIND_QUIETLY)
set(_FIND_ZLIB_ARG QUIET)
endif()
find_package(ZLIB ${_FIND_ZLIB_ARG})
if(ZLIB_FOUND)
find_path(PNG_PNG_INCLUDE_DIR png.h
/usr/local/include/libpng # OpenBSD
)
list(APPEND PNG_NAMES png libpng)
unset(PNG_NAMES_DEBUG)
set(_PNG_VERSION_SUFFIXES 17 16 15 14 12)
if (PNG_FIND_VERSION MATCHES "^([0-9]+).([0-9]+)(..*)?$")
set(_PNG_VERSION_SUFFIX_MIN "${CMAKE_MATCH_1}${CMAKE_MATCH_2}")
if (PNG_FIND_VERSION_EXACT)
set(_PNG_VERSION_SUFFIXES ${_PNG_VERSION_SUFFIX_MIN})
else ()
string(REGEX REPLACE
"${_PNG_VERSION_SUFFIX_MIN}.*" "${_PNG_VERSION_SUFFIX_MIN}"
_PNG_VERSION_SUFFIXES "${_PNG_VERSION_SUFFIXES}")
endif ()
unset(_PNG_VERSION_SUFFIX_MIN)
endif ()
foreach(v IN LISTS _PNG_VERSION_SUFFIXES)
list(APPEND PNG_NAMES png${v} libpng${v})
list(APPEND PNG_NAMES_DEBUG png${v}d libpng${v}d)
endforeach()
unset(_PNG_VERSION_SUFFIXES)
# For compatibility with versions prior to this multi-config search, honor
# any PNG_LIBRARY that is already specified and skip the search.
if(NOT PNG_LIBRARY)
find_library(PNG_LIBRARY_RELEASE NAMES ${PNG_NAMES})
find_library(PNG_LIBRARY_DEBUG NAMES ${PNG_NAMES_DEBUG})
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
select_library_configurations(PNG)
mark_as_advanced(PNG_LIBRARY_RELEASE PNG_LIBRARY_DEBUG)
endif()
unset(PNG_NAMES)
unset(PNG_NAMES_DEBUG)
# Set by select_library_configurations(), but we want the one from
# find_package_handle_standard_args() below.
unset(PNG_FOUND)
if (PNG_LIBRARY AND PNG_PNG_INCLUDE_DIR)
# png.h includes zlib.h. Sigh.
set(PNG_INCLUDE_DIRS ${PNG_PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} )
set(PNG_INCLUDE_DIR ${PNG_INCLUDE_DIRS} ) # for backward compatibility
set(PNG_LIBRARIES ${PNG_LIBRARY} ${ZLIB_LIBRARY})
if (CYGWIN)
if(BUILD_SHARED_LIBS)
# No need to define PNG_USE_DLL here, because it's default for Cygwin.
else()
set (PNG_DEFINITIONS -DPNG_STATIC)
endif()
endif ()
if(NOT TARGET PNG::PNG)
add_library(PNG::PNG UNKNOWN IMPORTED)
set_target_properties(PNG::PNG PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "${PNG_DEFINITIONS}"
INTERFACE_INCLUDE_DIRECTORIES "${PNG_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES ZLIB::ZLIB)
if(EXISTS "${PNG_LIBRARY}")
set_target_properties(PNG::PNG PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${PNG_LIBRARY}")
endif()
if(EXISTS "${PNG_LIBRARY_RELEASE}")
set_property(TARGET PNG::PNG APPEND PROPERTY
IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(PNG::PNG PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
IMPORTED_LOCATION_RELEASE "${PNG_LIBRARY_RELEASE}")
endif()
if(EXISTS "${PNG_LIBRARY_DEBUG}")
set_property(TARGET PNG::PNG APPEND PROPERTY
IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(PNG::PNG PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
IMPORTED_LOCATION_DEBUG "${PNG_LIBRARY_DEBUG}")
endif()
endif()
endif ()
if (PNG_PNG_INCLUDE_DIR AND EXISTS "${PNG_PNG_INCLUDE_DIR}/png.h")
file(STRINGS "${PNG_PNG_INCLUDE_DIR}/png.h" png_version_str REGEX "^#define[ t]+PNG_LIBPNG_VER_STRING[ t]+".+"")
string(REGEX REPLACE "^#define[ t]+PNG_LIBPNG_VER_STRING[ t]+"([^"]+)".*" "1" PNG_VERSION_STRING "${png_version_str}")
unset(png_version_str)
endif ()
endif()
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
find_package_handle_standard_args(PNG
REQUIRED_VARS PNG_LIBRARY PNG_PNG_INCLUDE_DIR
VERSION_VAR PNG_VERSION_STRING)
mark_as_advanced(PNG_PNG_INCLUDE_DIR PNG_LIBRARY )
23
Use a Find module for third party libraries
that are not built with CMake.
23
Use a Find module for third party libraries
that are not built with CMake.
that do not support clients to use CMake.
23
Use a Find module for third party libraries
that are not built with CMake.
that do not support clients to use CMake.
Also, report this as a bug to their authors.
23
Export your library interface!
1 find_package(Bar 2.0 REQUIRED)
2 add_library(Foo ...)
3 target_link_libraries(Foo PRIVATE Bar::Bar)
4
5 install(TARGETS Foo EXPORT FooTargets
6 LIBRARY DESTINATION lib
7 ARCHIVE DESTINATION lib
8 RUNTIME DESTINATION bin
9 INCLUDES DESTINATION include
10 )
11 install(EXPORT FooTargets
12 FILE FooTargets.cmake
13 NAMESPACE Foo::
14 DESTINATION lib/cmake/Foo
15 )
24
Export your library interface!
1 include(CMakePackageConfigHelpers)
2 write_basic_package_version_file("FooConfigVersion.cmake"
3 VERSION ${Foo_VERSION}
4 COMPATIBILITY SameMajorVersion
5 )
6 install(FILES "FooConfig.cmake" "FooConfigVersion.cmake"
7 DESTINATION lib/cmake/Foo
8 )
1 include(CMakeFindDependencyMacro)
2 find_dependency(Bar 2.0)
3 include("${CMAKE_CURRENT_LIST_DIR}/FooTargets.cmake")
25
Export the right information!
Warning:
The library interface may change during installation. Use the
BUILD_INTERFACE and INSTALL_INTERFACE generator expressions as
filters.
1 target_include_directories(Foo PUBLIC
2 $<BUILD_INTERFACE:${Foo_BINARY_DIR}/include>
3 $<BUILD_INTERFACE:${Foo_SOURCE_DIR}/include>
4 $<INSTALL_INTERFACE:include>
5 )
26
Creating Packages
CPack
• CPack is a packaging tool distributed with CMake.
• set() variables in CPackConfig.cmake, or
• set() variables in CMakeLists.txt and include(CPack).
27
Write your own CPackConfig.cmake
and include() the one
that is generated by CMake.
27
CPack secret
The variable CPACK_INSTALL_CMAKE_PROJECTS is a list of quadruples:
1. Build directory
2. Project Name
3. Project Component
4. Directory
28
Packaging multiple configurations
1. Make sure different configurations don’t collide:
1 set(CMAKE_DEBUG_POSTFIX "-d")
2. Create separate build directories for debug, release.
3. Use this CPackConfig.cmake:
1 include("release/CPackConfig.cmake")
2 set(CPACK_INSTALL_CMAKE_PROJECTS
3 "debug;Foo;ALL;/"
4 "release;Foo;ALL;/"
5 )
29
Package Management
My requirements for a package manager
• Support system packages
• Support prebuilt libraries
• Support building dependencies as subprojects
• Do not require any changes to my projects!
30
How to use external libraries
Always like this:
1 find_package(Foo 2.0 REQUIRED)
2 # ...
3 target_link_libraries(... Foo::Foo ...)
31
Do not require any changes to my projects!
• System packages …
32
Do not require any changes to my projects!
• System packages …
• work out of the box.
32
Do not require any changes to my projects!
• System packages …
• work out of the box.
• Prebuilt libraries …
32
Do not require any changes to my projects!
• System packages …
• work out of the box.
• Prebuilt libraries …
• need to be put into CMAKE_PREFIX_PATH.
32
Do not require any changes to my projects!
• System packages …
• work out of the box.
• Prebuilt libraries …
• need to be put into CMAKE_PREFIX_PATH.
• Subprojects …
• We need to turn find_package(Foo) into a no-op.
• What about the imported target Foo::Foo?
32
Use the your public interface
When you export Foo in namespace Foo::,
also create an alias Foo::Foo.
1 add_library(Foo::Foo ALIAS Foo)
33
When you export Foo in namespace Foo::,
also create an alias Foo::Foo.
33
The toplevel super-project
1 set(CMAKE_PREFIX_PATH "/prefix")
2 set(as_subproject Foo)
3
4 macro(find_package)
5 if(NOT "${ARG0}" IN_LIST as_subproject)
6 _find_package(${ARGV})
7 endif()
8 endmacro()
9
10 add_subdirectory(Foo)
11 add_subdirectory(App)
34
How does that work?
If Foo is a ...
• system package:
• find_package(Foo) either finds FooConfig.cmake in the system or
uses FindFoo.cmake to find the library in the system.
In either case, the target Foo::Foo is imported.
• prebuilt library:
• find_package(Foo) either finds FooConfig.cmake in the
CMAKE_PREFIX_PATH or uses FindFoo.cmake to find the library in
the CMAKE_PREFIX_PATH.
In either case, the target Foo::Foo is imported.
• subproject:
• find_package(Foo) does nothing.
The target Foo::Foo is part of the project.
35
CTest
Run with ctest -S build.cmake
1 set(CTEST_SOURCE_DIRECTORY "/source")
2 set(CTEST_BINARY_DIRECTORY "/binary")
3
4 set(ENV{CXXFLAGS} "--coverage")
5 set(CTEST_CMAKE_GENERATOR "Ninja")
6 set(CTEST_USE_LAUNCHERS 1)
7
8 set(CTEST_COVERAGE_COMMAND "gcov")
9 set(CTEST_MEMORYCHECK_COMMAND "valgrind")
10 #set(CTEST_MEMORYCHECK_TYPE "ThreadSanitizer")
11
12 ctest_start("Continuous")
13 ctest_configure()
14 ctest_build()
15 ctest_test()
16 ctest_coverage()
17 ctest_memcheck()
18 ctest_submit()
36
CTest scripts are the right place
for CI specific settings.
Keep that information out of the project.
36
Filtering tests by name
Define like this:
1 add_test(NAME Foo.Test
2 COMMAND foo_test --number 0
3 )
Run like this:
1 ctest -R 'Foo.' -j4 --output-on-failure
37
Follow a naming convention for test names.
This simplifies filtering by regex.
37
Fail to compile
1 add_library(foo_fail STATIC EXCLUDE_FROM_ALL
2 foo_fail.cpp
3 )
4 add_test(NAME Foo.Fail
5 COMMAND ${CMAKE_COMMAND}
6 --build ${CMAKE_BINARY_DIR}
7 --target foo_fail
8 )
9 set_property(TEST Foo.Fail PROPERTY
10 PASS_REGULAR_EXPRESSION "static assert message"
11 )
38
Running crosscompiled tests
• When the testing command is a build target,
the command line is prefixed with
${CMAKE_CROSSCOMPILING_EMULATOR}.
• When crosscompiling from Linux to Windows,
set CMAKE_CROSSCOMPILING_EMULATOR to wine.
• When crosscompiling to ARM,
set CMAKE_CROSSCOMPILING_EMULATOR to qemu-arm.
• To run tests on another machine,
set CMAKE_CROSSCOMPILING_EMULATOR to a script
that copies it over and executes it there.
39
Run tests on real hardware
1 #!/bin/bash
2 tester=$1
3 shift
4 # create temporary file
5 filename=$(ssh root@172.22.22.22 mktemp)
6 # copy the tester to temporary file
7 scp $tester root@172.22.22.22:$filename
8 # make test executable
9 ssh root@172.22.22.22 chmod +x $filename
10 # execute test
11 ssh root@172.22.22.22 $filename "$@"
12 # store success
13 success=$?
14 # cleanup
15 ssh root@172.22.22.22 rm $filename
16 exit $success
40
Cross Compiling
Toolchain.cmake
1 set(CMAKE_SYSTEM_NAME Windows)
2
3 set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
4 set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
5 set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
6
7 set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32)
8
9 set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
10 set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
11 set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
12
13 set(CMAKE_CROSSCOMPILING_EMULATOR wine64)
41
Don’t put logic in toolchain files.
41
Static Analysis
Treat warnings as errors?
41
How do you treat build errors?
• You fix them.
• You reject pull requests.
• You hold off releases.
42
Treat warnings as errors!
43
Treat warnings as errors!
• You fix them.
• You reject pull requests.
• You hold off releases.
43
Treat warnings as errors!
To treat warnings as errors, never pass -Werror to the
compiler. If you do, your compiler treats warnings as errors.
You can no longer treat warnings as errors, because you will
no longer get any warnings. All you get is errors.
44
-Werror causes pain
• You cannot enable -Werror unless you already reached zero
warnings.
• You cannot increase the warning level unless you already fixed
all warnings introduced by that level.
• You cannot upgrade your compiler unless you already fixed all
new warnings that the compiler reports at your warning level.
• You cannot update your dependencies unless you already
ported your code away from any symbols that are now
[[deprecated]].
• You cannot [[deprecated]] your internal code as long as it is
still used. But once it is no longer used, you can as well just
remove it…
45
Better: Treat new warnings as errors!
1. At the beginning of a development cycle (eg. sprint), allow new
warnings to be introduced.
• Increase warning level, enable new warnings explicitly.
• Update the compiler.
• Update dependencies.
• Mark symbols as [[deprecated]].
2. Then, burn down the number of warnings.
3. Repeat.
46
Pull out all the stops!
clang-tidy is a clang-based C++ “linter” tool. Its purpose is to
provide an extensible framework for diagnosing and fixing
typical programming errors, like style violations, interface
misuse, or bugs that can be deduced via static analysis.
cpplint is automated checker to make sure a C++ file follows
Google’s C++ style guide.
include-what-you-use analyzes #includes in C and C++ source files.
clazy is a clang wrapper that finds common C++/Qt antipatterns
that decrease performance.
47
Target properties for static analysis
• <lang>_CLANG_TIDY
• <lang>_CPPLINT
• <lang>_INCLUDE_WHAT_YOU_USE
• Runs the respective tool along the with compiler.
• Diagnostics are visible in your IDE.
• Diagnostics are visible on CDash.
• LINK_WHAT_YOU_USE
• links with -Wl,--no-as-needed, then runs ldd -r -u.
<lang> is either C or CXX.
Each of those properties is initialzied with CMAKE_<property>.
48
Scanning header files
• Most of those tools report diagnostics for the current source file
plus the associated header.
• Header files with no assiciated source file will not be analyzed.
• You may be able to set a custom header filter,
but then the headers may be analyzed multiple times.
49
For each header file,
there is an associated source file
that #includes this header file at the top.
Even if that source file would otherwise be empty.
49
Create associated source files
1 #!/usr/bin/env bash
2 for fn in `comm -23 
3 <(ls *.h|cut -d '.' -f 1|sort) 
4 <(ls *.c *.cpp|cut -d '.' -f 1|sort)`
5 do
6 echo "#include "$fn.h"" >> $fn.cpp
7 done
50
Enable warnings from outside the project
1 env CC=clang CXX=clazy cmake 
2 -DCMAKE_CXX_CLANG_TIDY:STRING=
3 'clang-tidy;-checks=-*,readability-*' 
4 -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE:STRING=
5 'include-what-you-use;-Xiwyu;--mapping_file=/iwyu.imp' 
6 ..
51
Supported by all IDEs
• Just setting CMAKE_CXX_CLANG_TIDY will make all clang-tidy
diagnostics appear in your normal build output.
• No special IDE support needed.
• If IDE understands fix-it hints from clang, it will also understand
the ones from clang-tidy.
52
Thank You!
52
Personal Wishlist
Personal Wishlist
• For each of the following ideas, I have started a prototype.
• Contibutions welcome!
• You can talk to me!
53
Disclaimer:
No guarantee that the following ideas
will ever be added to CMake.
53
PCH as usage requirements
PCH as usage requirements
1 target_precompile_headers(Foo
2 PUBLIC
3 "foo.h"
4 PRIVATE
5 <unordered_map>
6 )
54
PCH as usage requirements
• Calculate a list of headers per config and language
for the build specification of each target.
• Generate a header file that #includes each of those headers.
• Tell the build system to precompile this header.
• Tell the build system to force-include this header.
• Require no changes to the code (No #include "stdafx.h").
55
More Languages!
More Languages!
• CMake’s core is language-agnostic.
• Language support is scripted in modules.
• Rules how to compile object files, link them together.
• The output of the compiler must be an object file.
• CMake can be used with D by putting necessary files in
CMAKE_MODULE_PATH.1
1https://github.com/dcarp/cmake-d
56
Even more Languages!
• If we allow the output to be a source file of a known language,
we would not need special handling for Protobuf, Qt-resources,
or any other IDL.
• This would also allow using CMake for BASIC, BCX, Chapel, COBOL,
Cython, Eiffel, Genie, Haxe, Java, Julia, Lisaac, Scheme, PHP,
Python, X10, Nim, Vala.2
2https://en.wikipedia.org/wiki/Source-to-source_compiler
57
find_package(Foo PKGCONF)
find_package(Foo PKGCONF)
• find_package() has two modes: PACKAGE and CONFIG.
• Let’s add a PKGCONF mode.
• In this mode, CMake parses .pc files and generates one
IMPORTED library per package.
58
Declarative Frontend and Lua VM
Lua VM
• Execute CMake commands on Lua VM.3
• Allow CMake modules to be written in Lua.
3not the other way round. This failed before.
59
Declarative Frontend
• For directories, use a declarative language
that allows procedural subroutines.
• libucl4
is an interesting option.
4https://github.com/vstakhov/libucl
60
Tell me your ideas!
60

Weitere ähnliche Inhalte

Was ist angesagt?

Conan a C/C++ Package Manager
Conan a C/C++ Package ManagerConan a C/C++ Package Manager
Conan a C/C++ Package ManagerUilian Ries
 
Launch the First Process in Linux System
Launch the First Process in Linux SystemLaunch the First Process in Linux System
Launch the First Process in Linux SystemJian-Hong Pan
 
COSCUP2016 - LLVM框架、由淺入淺
COSCUP2016 - LLVM框架、由淺入淺COSCUP2016 - LLVM框架、由淺入淺
COSCUP2016 - LLVM框架、由淺入淺hydai
 
Consuming Libraries with CMake
Consuming Libraries with CMakeConsuming Libraries with CMake
Consuming Libraries with CMakeRichard Thomson
 
Linux kernel tracing
Linux kernel tracingLinux kernel tracing
Linux kernel tracingViller Hsiao
 
Conan.io - The C/C++ package manager for Developers
Conan.io - The C/C++ package manager for DevelopersConan.io - The C/C++ package manager for Developers
Conan.io - The C/C++ package manager for DevelopersUilian Ries
 
makefiles tutorial
makefiles tutorialmakefiles tutorial
makefiles tutorialvsubhashini
 
Blazing Performance with Flame Graphs
Blazing Performance with Flame GraphsBlazing Performance with Flame Graphs
Blazing Performance with Flame GraphsBrendan Gregg
 
Gitlab flow solo
Gitlab flow soloGitlab flow solo
Gitlab flow soloviniciusban
 
USENIX ATC 2017: Visualizing Performance with Flame Graphs
USENIX ATC 2017: Visualizing Performance with Flame GraphsUSENIX ATC 2017: Visualizing Performance with Flame Graphs
USENIX ATC 2017: Visualizing Performance with Flame GraphsBrendan Gregg
 
Introduction to GNU Make Programming Language
Introduction to GNU Make Programming LanguageIntroduction to GNU Make Programming Language
Introduction to GNU Make Programming LanguageShih-Hsiang Lin
 
Mixing C++ & Python II: Pybind11
Mixing C++ & Python II: Pybind11Mixing C++ & Python II: Pybind11
Mixing C++ & Python II: Pybind11corehard_by
 
Decompressed vmlinux: linux kernel initialization from page table configurati...
Decompressed vmlinux: linux kernel initialization from page table configurati...Decompressed vmlinux: linux kernel initialization from page table configurati...
Decompressed vmlinux: linux kernel initialization from page table configurati...Adrian Huang
 
Fuse- Filesystem in User space
Fuse- Filesystem in User space Fuse- Filesystem in User space
Fuse- Filesystem in User space Danny Tseng
 
Linux Performance Analysis: New Tools and Old Secrets
Linux Performance Analysis: New Tools and Old SecretsLinux Performance Analysis: New Tools and Old Secrets
Linux Performance Analysis: New Tools and Old SecretsBrendan Gregg
 

Was ist angesagt? (20)

Conan a C/C++ Package Manager
Conan a C/C++ Package ManagerConan a C/C++ Package Manager
Conan a C/C++ Package Manager
 
Launch the First Process in Linux System
Launch the First Process in Linux SystemLaunch the First Process in Linux System
Launch the First Process in Linux System
 
Qemu JIT Code Generator and System Emulation
Qemu JIT Code Generator and System EmulationQemu JIT Code Generator and System Emulation
Qemu JIT Code Generator and System Emulation
 
COSCUP2016 - LLVM框架、由淺入淺
COSCUP2016 - LLVM框架、由淺入淺COSCUP2016 - LLVM框架、由淺入淺
COSCUP2016 - LLVM框架、由淺入淺
 
Consuming Libraries with CMake
Consuming Libraries with CMakeConsuming Libraries with CMake
Consuming Libraries with CMake
 
CMake best practices
CMake best practicesCMake best practices
CMake best practices
 
Linux kernel tracing
Linux kernel tracingLinux kernel tracing
Linux kernel tracing
 
Conan.io - The C/C++ package manager for Developers
Conan.io - The C/C++ package manager for DevelopersConan.io - The C/C++ package manager for Developers
Conan.io - The C/C++ package manager for Developers
 
makefiles tutorial
makefiles tutorialmakefiles tutorial
makefiles tutorial
 
Blazing Performance with Flame Graphs
Blazing Performance with Flame GraphsBlazing Performance with Flame Graphs
Blazing Performance with Flame Graphs
 
Making Linux do Hard Real-time
Making Linux do Hard Real-timeMaking Linux do Hard Real-time
Making Linux do Hard Real-time
 
Gitlab flow solo
Gitlab flow soloGitlab flow solo
Gitlab flow solo
 
eBPF Basics
eBPF BasicseBPF Basics
eBPF Basics
 
USENIX ATC 2017: Visualizing Performance with Flame Graphs
USENIX ATC 2017: Visualizing Performance with Flame GraphsUSENIX ATC 2017: Visualizing Performance with Flame Graphs
USENIX ATC 2017: Visualizing Performance with Flame Graphs
 
Git Grundlagen
Git GrundlagenGit Grundlagen
Git Grundlagen
 
Introduction to GNU Make Programming Language
Introduction to GNU Make Programming LanguageIntroduction to GNU Make Programming Language
Introduction to GNU Make Programming Language
 
Mixing C++ & Python II: Pybind11
Mixing C++ & Python II: Pybind11Mixing C++ & Python II: Pybind11
Mixing C++ & Python II: Pybind11
 
Decompressed vmlinux: linux kernel initialization from page table configurati...
Decompressed vmlinux: linux kernel initialization from page table configurati...Decompressed vmlinux: linux kernel initialization from page table configurati...
Decompressed vmlinux: linux kernel initialization from page table configurati...
 
Fuse- Filesystem in User space
Fuse- Filesystem in User space Fuse- Filesystem in User space
Fuse- Filesystem in User space
 
Linux Performance Analysis: New Tools and Old Secrets
Linux Performance Analysis: New Tools and Old SecretsLinux Performance Analysis: New Tools and Old Secrets
Linux Performance Analysis: New Tools and Old Secrets
 

Ähnlich wie Effective CMake

Feature and platform testing with CMake
Feature and platform testing with CMakeFeature and platform testing with CMake
Feature and platform testing with CMakeRichard Thomson
 
Using existing language skillsets to create large-scale, cloud-based analytics
Using existing language skillsets to create large-scale, cloud-based analyticsUsing existing language skillsets to create large-scale, cloud-based analytics
Using existing language skillsets to create large-scale, cloud-based analyticsMicrosoft Tech Community
 
LOSS_C11- Programming Linux 20221006.pdf
LOSS_C11- Programming Linux 20221006.pdfLOSS_C11- Programming Linux 20221006.pdf
LOSS_C11- Programming Linux 20221006.pdfThninh2
 
Software Qualitiy with Sonar Tool 2013_4
Software Qualitiy with Sonar Tool 2013_4Software Qualitiy with Sonar Tool 2013_4
Software Qualitiy with Sonar Tool 2013_4Max Kleiner
 
Dotnetintroduce 100324201546-phpapp02
Dotnetintroduce 100324201546-phpapp02Dotnetintroduce 100324201546-phpapp02
Dotnetintroduce 100324201546-phpapp02Wei Sun
 
Python Modules, executing modules as script.pptx
Python Modules, executing modules as script.pptxPython Modules, executing modules as script.pptx
Python Modules, executing modules as script.pptxSingamvineela
 
Workshop: Symfony2 Intruduction: (Controller, Routing, Model)
Workshop: Symfony2 Intruduction: (Controller, Routing, Model)Workshop: Symfony2 Intruduction: (Controller, Routing, Model)
Workshop: Symfony2 Intruduction: (Controller, Routing, Model)Antonio Peric-Mazar
 
嵌入式Linux課程-GNU Toolchain
嵌入式Linux課程-GNU Toolchain嵌入式Linux課程-GNU Toolchain
嵌入式Linux課程-GNU Toolchain艾鍗科技
 
Fortran & Link with Library & Brief Explanation of MKL BLAS
Fortran & Link with Library & Brief Explanation of MKL BLASFortran & Link with Library & Brief Explanation of MKL BLAS
Fortran & Link with Library & Brief Explanation of MKL BLASJongsu "Liam" Kim
 
Is SQLcl the Next Generation of SQL*Plus?
Is SQLcl the Next Generation of SQL*Plus?Is SQLcl the Next Generation of SQL*Plus?
Is SQLcl the Next Generation of SQL*Plus?Zohar Elkayam
 
ExtBase workshop
ExtBase workshop ExtBase workshop
ExtBase workshop schmutt
 
Supporting Over a Thousand Custom Hive User Defined Functions
Supporting Over a Thousand Custom Hive User Defined FunctionsSupporting Over a Thousand Custom Hive User Defined Functions
Supporting Over a Thousand Custom Hive User Defined FunctionsDatabricks
 
Binding Objective-C Libraries, Miguel de Icaza
Binding Objective-C Libraries, Miguel de IcazaBinding Objective-C Libraries, Miguel de Icaza
Binding Objective-C Libraries, Miguel de IcazaXamarin
 
An introduction to maven gradle and sbt
An introduction to maven gradle and sbtAn introduction to maven gradle and sbt
An introduction to maven gradle and sbtFabio Fumarola
 
Add-On Development: EE Expects that Every Developer will do his Duty
Add-On Development: EE Expects that Every Developer will do his DutyAdd-On Development: EE Expects that Every Developer will do his Duty
Add-On Development: EE Expects that Every Developer will do his DutyLeslie Doherty
 

Ähnlich wie Effective CMake (20)

C++ Advanced Features
C++ Advanced FeaturesC++ Advanced Features
C++ Advanced Features
 
Feature and platform testing with CMake
Feature and platform testing with CMakeFeature and platform testing with CMake
Feature and platform testing with CMake
 
C++ Advanced Features
C++ Advanced FeaturesC++ Advanced Features
C++ Advanced Features
 
Using existing language skillsets to create large-scale, cloud-based analytics
Using existing language skillsets to create large-scale, cloud-based analyticsUsing existing language skillsets to create large-scale, cloud-based analytics
Using existing language skillsets to create large-scale, cloud-based analytics
 
LOSS_C11- Programming Linux 20221006.pdf
LOSS_C11- Programming Linux 20221006.pdfLOSS_C11- Programming Linux 20221006.pdf
LOSS_C11- Programming Linux 20221006.pdf
 
Software Qualitiy with Sonar Tool 2013_4
Software Qualitiy with Sonar Tool 2013_4Software Qualitiy with Sonar Tool 2013_4
Software Qualitiy with Sonar Tool 2013_4
 
Dotnetintroduce 100324201546-phpapp02
Dotnetintroduce 100324201546-phpapp02Dotnetintroduce 100324201546-phpapp02
Dotnetintroduce 100324201546-phpapp02
 
Python Modules, executing modules as script.pptx
Python Modules, executing modules as script.pptxPython Modules, executing modules as script.pptx
Python Modules, executing modules as script.pptx
 
Workshop: Symfony2 Intruduction: (Controller, Routing, Model)
Workshop: Symfony2 Intruduction: (Controller, Routing, Model)Workshop: Symfony2 Intruduction: (Controller, Routing, Model)
Workshop: Symfony2 Intruduction: (Controller, Routing, Model)
 
嵌入式Linux課程-GNU Toolchain
嵌入式Linux課程-GNU Toolchain嵌入式Linux課程-GNU Toolchain
嵌入式Linux課程-GNU Toolchain
 
Fortran & Link with Library & Brief Explanation of MKL BLAS
Fortran & Link with Library & Brief Explanation of MKL BLASFortran & Link with Library & Brief Explanation of MKL BLAS
Fortran & Link with Library & Brief Explanation of MKL BLAS
 
Is SQLcl the Next Generation of SQL*Plus?
Is SQLcl the Next Generation of SQL*Plus?Is SQLcl the Next Generation of SQL*Plus?
Is SQLcl the Next Generation of SQL*Plus?
 
ExtBase workshop
ExtBase workshop ExtBase workshop
ExtBase workshop
 
Supporting Over a Thousand Custom Hive User Defined Functions
Supporting Over a Thousand Custom Hive User Defined FunctionsSupporting Over a Thousand Custom Hive User Defined Functions
Supporting Over a Thousand Custom Hive User Defined Functions
 
Binding Objective-C Libraries, Miguel de Icaza
Binding Objective-C Libraries, Miguel de IcazaBinding Objective-C Libraries, Miguel de Icaza
Binding Objective-C Libraries, Miguel de Icaza
 
An introduction to maven gradle and sbt
An introduction to maven gradle and sbtAn introduction to maven gradle and sbt
An introduction to maven gradle and sbt
 
Gun make
Gun makeGun make
Gun make
 
presentation
presentationpresentation
presentation
 
Add-On Development: EE Expects that Every Developer will do his Duty
Add-On Development: EE Expects that Every Developer will do his DutyAdd-On Development: EE Expects that Every Developer will do his Duty
Add-On Development: EE Expects that Every Developer will do his Duty
 
Functions in c++
Functions in c++Functions in c++
Functions in c++
 

Kürzlich hochgeladen

%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park masabamasaba
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...Jittipong Loespradit
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...masabamasaba
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...masabamasaba
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyviewmasabamasaba
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Bert Jan Schrijver
 
tonesoftg
tonesoftgtonesoftg
tonesoftglanshi9
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...masabamasaba
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareJim McKeeth
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburgmasabamasaba
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 

Kürzlich hochgeladen (20)

%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaS
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security Program
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 

Effective CMake

  • 1. Effective CMake a random selection of best practices Daniel Pfeifer June 7, 2017 daniel@pfeifer-mail.de
  • 3. Why? The way you use CMake affects your users! 1
  • 4. CMake’s similarities with C++ • big userbase, industry dominance • focus on backwards compatibility • complex, feature rich, ”multi paradigm” • bad reputation, ”bloated”, ”horrible syntax” • some not very well known features 2
  • 6. CMake is code. Use the same principles for CMakeLists.txt and modules as for the rest of your codebase. 3
  • 8. Organization Directories that contain a CMakeLists.txt are the entry point for the build system generator. Subdirectories may be added with add_subdirectory() and must contain a CMakeLists.txt too. Scripts are <script>.cmake files that can be executed with cmake -P <script>.cmake. Not all commands are supported. Modules are <script>.cmake files located in the CMAKE_MODULE_PATH. Modules can be loaded with the include() command. 4
  • 9. Commands 1 command_name(space separated list of strings) • Scripting commands change state of command processor • set variables • change behavior of other commands • Project commands • create build targets • modify build targets • Command invocations are not expressions. 5
  • 10. Variables 1 set(hello world) 2 message(STATUS "hello, ${hello}") • Set with the set() command. • Expand with ${}. • Variables and values are strings. • Lists are ;-separated strings. • CMake variables are not environment variables (unlike Makefile). • Unset variable expands to empty string. 6
  • 11. Comments 1 # a single line comment 2 3 #[==[ 4 multi line comments 5 6 #[=[ 7 may be nested 8 #]=] 9 #]==] 7
  • 12. Generator expressions 1 target_compile_definitions(foo PRIVATE 2 "VERBOSITY=$<IF:$<CONFIG:Debug>,30,10>" 3 ) • Generator expressions use the $<> syntax. • Not evaluated by command interpreter. It is just a string with $<>. • Evaluated during build system generation. • Not supported in all commands (obviously). 8
  • 14. Two types of commands • Commands can be added with function() or macro(). • Difference is like in C++. • When a new command replaces an existing command, the old one can be accessed with a _ prefix. 9
  • 15. Custom command: Function 1 function(my_command input output) 2 # ... 3 set(${output} ... PARENT_SCOPE) 4 endfunction() 5 my_command(foo bar) • Variables are scoped to the function, unless set with PARENT_SCOPE. • Available variables: input, output, ARGC, ARGV, ARGN, ARG0, ARG1, ARG2, … • Example: ${output} expands to bar. 10
  • 16. Custom command: Macro 1 macro(my_command input output) 2 # ... 3 endmacro() 4 my_command(foo bar) • No extra scope. • Text replacements: ${input}, ${output}, ${ARGC}, ${ARGV}, ${ARGN}, ${ARG0}, ${ARG1}, ${ARG2}, … • Example: ${output} is replaced by bar. 11
  • 17. Create macros to wrap commands that have output parametes. Otherwise, create a function. 11
  • 19. Deprecate CMake commands 1 macro(my_command) 2 message(DEPRECATION 3 "The my_command command is deprecated!") 4 _my_command(${ARGV}) 5 endmacro() 12
  • 20. Deprecate CMake variables 1 set(hello "hello world!") 2 3 function(__deprecated_var var access) 4 if(access STREQUAL "READ_ACCESS") 5 message(DEPRECATION 6 "The variable '${var}' is deprecated!") 7 endif() 8 endfunction() 9 10 variable_watch(hello __deprecated_var) 13
  • 21. Variables are so CMake 2.8.12. Modern CMake is about Targets and Properties! 13
  • 23. Look Ma, no Variables! 1 add_library(Foo foo.cpp) 2 target_link_libraries(Foo PRIVATE Bar::Bar) 3 4 if(WIN32) 5 target_sources(Foo PRIVATE foo_win32.cpp) 6 target_link_libraries(Foo PRIVATE Bar::Win32Support) 7 endif() 14
  • 24. Avoid custom variables in the arguments of project commands. 14
  • 25. Don’t use file(GLOB) in projects. 14
  • 26. Imagine Targets as Objects • Constructors: • add_executable() • add_library() • Member variables: • Target properties (too many to list here). • Member functions: • get_target_property() • set_target_properties() • get_property(TARGET) • set_property(TARGET) • target_compile_definitions() • target_compile_features() • target_compile_options() • target_include_directories() • target_link_libraries() • target_sources() 15
  • 28. Example: 1 target_compile_features(Foo 2 PUBLIC 3 cxx_strong_enums 4 PRIVATE 5 cxx_lambdas 6 cxx_range_for 7 ) • Adds cxx_strong_enums to the target properties COMPILE_FEATURES and INTERFACE_COMPILE_FEATURES. • Adds cxx_lambdas;cxx_range_for to the target property COMPILE_FEATURES. 16
  • 29. Get your hands off CMAKE_CXX_FLAGS! 16
  • 30. Build Specification and Usage Requirements • Non-INTERFACE_ properties define the build specification of a target. • INTERFACE_ properties define the usage requirements of a target. 17
  • 31. Build Specification and Usage Requirements • PRIVATE populates the non-INTERFACE_ property. • INTERFACE populates the INTERFACE_ property. • PUBLIC populates both. 18
  • 32. Use target_link_libraries() to express direct dependencies! 18
  • 33. Example: 1 target_link_libraries(Foo 2 PUBLIC Bar::Bar 3 PRIVATE Cow::Cow 4 ) • Adds Bar::Bar to the target properties LINK_LIBRARIES and INTERFACE_LINK_LIBRARIES. • Adds Cow::Cow to the target property LINK_LIBRARIES. 19
  • 34. Example: 1 target_link_libraries(Foo 2 PUBLIC Bar::Bar 3 PRIVATE Cow::Cow 4 ) • Adds Bar::Bar to the target properties LINK_LIBRARIES and INTERFACE_LINK_LIBRARIES. • Adds Cow::Cow to the target property LINK_LIBRARIES. • Effectively adds all INTERFACE_<property> of Bar::Bar to <property> and INTERFACE_<property>. • Effectively adds all INTERFACE_<property> of Cow::Cow to <property>. 19
  • 35. Example: 1 target_link_libraries(Foo 2 PUBLIC Bar::Bar 3 PRIVATE Cow::Cow 4 ) • Adds Bar::Bar to the target properties LINK_LIBRARIES and INTERFACE_LINK_LIBRARIES. • Adds Cow::Cow to the target property LINK_LIBRARIES. • Effectively adds all INTERFACE_<property> of Bar::Bar to <property> and INTERFACE_<property>. • Effectively adds all INTERFACE_<property> of Cow::Cow to <property>. • Adds $<LINK_ONLY:Cow::Cow> to INTERFACE_LINK_LIBRARIES. 19
  • 36. Pure usage reqiurements 1 add_library(Bar INTERFACE) 2 target_compile_definitions(Bar INTERFACE BAR=1) • INTERFACE libraries have no build specification. • They only have usage requirements. 20
  • 37. Don’t abuse requirements! Eg: -Wall is not a requirement! 20
  • 39. How to use external libraries Always like this: 1 find_package(Foo 2.0 REQUIRED) 2 # ... 3 target_link_libraries(... Foo::Foo ...) 21
  • 40. FindFoo.cmake 1 find_path(Foo_INCLUDE_DIR foo.h) 2 find_library(Foo_LIBRARY foo) 3 mark_as_advanced(Foo_INCLUDE_DIR Foo_LIBRARY) 4 5 include(FindPackageHandleStandardArgs) 6 find_package_handle_standard_args(Foo 7 REQUIRED_VARS Foo_LIBRARY Foo_INCLUDE_DIR 8 ) 9 10 if(Foo_FOUND AND NOT TARGET Foo::Foo) 11 add_library(Foo::Foo UNKNOWN IMPORTED) 12 set_target_properties(Foo::Foo PROPERTIES 13 IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" 14 IMPORTED_LOCATION "${Foo_LIBRARY}" 15 INTERFACE_INCLUDE_DIRECTORIES "${Foo_INCLUDE_DIR}" 16 ) 17 endif() 22
  • 41. FindPNG.cmake if(PNG_FIND_QUIETLY) set(_FIND_ZLIB_ARG QUIET) endif() find_package(ZLIB ${_FIND_ZLIB_ARG}) if(ZLIB_FOUND) find_path(PNG_PNG_INCLUDE_DIR png.h /usr/local/include/libpng # OpenBSD ) list(APPEND PNG_NAMES png libpng) unset(PNG_NAMES_DEBUG) set(_PNG_VERSION_SUFFIXES 17 16 15 14 12) if (PNG_FIND_VERSION MATCHES "^([0-9]+).([0-9]+)(..*)?$") set(_PNG_VERSION_SUFFIX_MIN "${CMAKE_MATCH_1}${CMAKE_MATCH_2}") if (PNG_FIND_VERSION_EXACT) set(_PNG_VERSION_SUFFIXES ${_PNG_VERSION_SUFFIX_MIN}) else () string(REGEX REPLACE "${_PNG_VERSION_SUFFIX_MIN}.*" "${_PNG_VERSION_SUFFIX_MIN}" _PNG_VERSION_SUFFIXES "${_PNG_VERSION_SUFFIXES}") endif () unset(_PNG_VERSION_SUFFIX_MIN) endif () foreach(v IN LISTS _PNG_VERSION_SUFFIXES) list(APPEND PNG_NAMES png${v} libpng${v}) list(APPEND PNG_NAMES_DEBUG png${v}d libpng${v}d) endforeach() unset(_PNG_VERSION_SUFFIXES) # For compatibility with versions prior to this multi-config search, honor # any PNG_LIBRARY that is already specified and skip the search. if(NOT PNG_LIBRARY) find_library(PNG_LIBRARY_RELEASE NAMES ${PNG_NAMES}) find_library(PNG_LIBRARY_DEBUG NAMES ${PNG_NAMES_DEBUG}) include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) select_library_configurations(PNG) mark_as_advanced(PNG_LIBRARY_RELEASE PNG_LIBRARY_DEBUG) endif() unset(PNG_NAMES) unset(PNG_NAMES_DEBUG) # Set by select_library_configurations(), but we want the one from # find_package_handle_standard_args() below. unset(PNG_FOUND) if (PNG_LIBRARY AND PNG_PNG_INCLUDE_DIR) # png.h includes zlib.h. Sigh. set(PNG_INCLUDE_DIRS ${PNG_PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ) set(PNG_INCLUDE_DIR ${PNG_INCLUDE_DIRS} ) # for backward compatibility set(PNG_LIBRARIES ${PNG_LIBRARY} ${ZLIB_LIBRARY}) if (CYGWIN) if(BUILD_SHARED_LIBS) # No need to define PNG_USE_DLL here, because it's default for Cygwin. else() set (PNG_DEFINITIONS -DPNG_STATIC) endif() endif () if(NOT TARGET PNG::PNG) add_library(PNG::PNG UNKNOWN IMPORTED) set_target_properties(PNG::PNG PROPERTIES INTERFACE_COMPILE_DEFINITIONS "${PNG_DEFINITIONS}" INTERFACE_INCLUDE_DIRECTORIES "${PNG_INCLUDE_DIRS}" INTERFACE_LINK_LIBRARIES ZLIB::ZLIB) if(EXISTS "${PNG_LIBRARY}") set_target_properties(PNG::PNG PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" IMPORTED_LOCATION "${PNG_LIBRARY}") endif() if(EXISTS "${PNG_LIBRARY_RELEASE}") set_property(TARGET PNG::PNG APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) set_target_properties(PNG::PNG PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" IMPORTED_LOCATION_RELEASE "${PNG_LIBRARY_RELEASE}") endif() if(EXISTS "${PNG_LIBRARY_DEBUG}") set_property(TARGET PNG::PNG APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) set_target_properties(PNG::PNG PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C" IMPORTED_LOCATION_DEBUG "${PNG_LIBRARY_DEBUG}") endif() endif() endif () if (PNG_PNG_INCLUDE_DIR AND EXISTS "${PNG_PNG_INCLUDE_DIR}/png.h") file(STRINGS "${PNG_PNG_INCLUDE_DIR}/png.h" png_version_str REGEX "^#define[ t]+PNG_LIBPNG_VER_STRING[ t]+".+"") string(REGEX REPLACE "^#define[ t]+PNG_LIBPNG_VER_STRING[ t]+"([^"]+)".*" "1" PNG_VERSION_STRING "${png_version_str}") unset(png_version_str) endif () endif() include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) find_package_handle_standard_args(PNG REQUIRED_VARS PNG_LIBRARY PNG_PNG_INCLUDE_DIR VERSION_VAR PNG_VERSION_STRING) mark_as_advanced(PNG_PNG_INCLUDE_DIR PNG_LIBRARY ) 23
  • 42. Use a Find module for third party libraries that are not built with CMake. 23
  • 43. Use a Find module for third party libraries that are not built with CMake. that do not support clients to use CMake. 23
  • 44. Use a Find module for third party libraries that are not built with CMake. that do not support clients to use CMake. Also, report this as a bug to their authors. 23
  • 45. Export your library interface! 1 find_package(Bar 2.0 REQUIRED) 2 add_library(Foo ...) 3 target_link_libraries(Foo PRIVATE Bar::Bar) 4 5 install(TARGETS Foo EXPORT FooTargets 6 LIBRARY DESTINATION lib 7 ARCHIVE DESTINATION lib 8 RUNTIME DESTINATION bin 9 INCLUDES DESTINATION include 10 ) 11 install(EXPORT FooTargets 12 FILE FooTargets.cmake 13 NAMESPACE Foo:: 14 DESTINATION lib/cmake/Foo 15 ) 24
  • 46. Export your library interface! 1 include(CMakePackageConfigHelpers) 2 write_basic_package_version_file("FooConfigVersion.cmake" 3 VERSION ${Foo_VERSION} 4 COMPATIBILITY SameMajorVersion 5 ) 6 install(FILES "FooConfig.cmake" "FooConfigVersion.cmake" 7 DESTINATION lib/cmake/Foo 8 ) 1 include(CMakeFindDependencyMacro) 2 find_dependency(Bar 2.0) 3 include("${CMAKE_CURRENT_LIST_DIR}/FooTargets.cmake") 25
  • 47. Export the right information! Warning: The library interface may change during installation. Use the BUILD_INTERFACE and INSTALL_INTERFACE generator expressions as filters. 1 target_include_directories(Foo PUBLIC 2 $<BUILD_INTERFACE:${Foo_BINARY_DIR}/include> 3 $<BUILD_INTERFACE:${Foo_SOURCE_DIR}/include> 4 $<INSTALL_INTERFACE:include> 5 ) 26
  • 49. CPack • CPack is a packaging tool distributed with CMake. • set() variables in CPackConfig.cmake, or • set() variables in CMakeLists.txt and include(CPack). 27
  • 50. Write your own CPackConfig.cmake and include() the one that is generated by CMake. 27
  • 51. CPack secret The variable CPACK_INSTALL_CMAKE_PROJECTS is a list of quadruples: 1. Build directory 2. Project Name 3. Project Component 4. Directory 28
  • 52. Packaging multiple configurations 1. Make sure different configurations don’t collide: 1 set(CMAKE_DEBUG_POSTFIX "-d") 2. Create separate build directories for debug, release. 3. Use this CPackConfig.cmake: 1 include("release/CPackConfig.cmake") 2 set(CPACK_INSTALL_CMAKE_PROJECTS 3 "debug;Foo;ALL;/" 4 "release;Foo;ALL;/" 5 ) 29
  • 54. My requirements for a package manager • Support system packages • Support prebuilt libraries • Support building dependencies as subprojects • Do not require any changes to my projects! 30
  • 55. How to use external libraries Always like this: 1 find_package(Foo 2.0 REQUIRED) 2 # ... 3 target_link_libraries(... Foo::Foo ...) 31
  • 56. Do not require any changes to my projects! • System packages … 32
  • 57. Do not require any changes to my projects! • System packages … • work out of the box. 32
  • 58. Do not require any changes to my projects! • System packages … • work out of the box. • Prebuilt libraries … 32
  • 59. Do not require any changes to my projects! • System packages … • work out of the box. • Prebuilt libraries … • need to be put into CMAKE_PREFIX_PATH. 32
  • 60. Do not require any changes to my projects! • System packages … • work out of the box. • Prebuilt libraries … • need to be put into CMAKE_PREFIX_PATH. • Subprojects … • We need to turn find_package(Foo) into a no-op. • What about the imported target Foo::Foo? 32
  • 61. Use the your public interface When you export Foo in namespace Foo::, also create an alias Foo::Foo. 1 add_library(Foo::Foo ALIAS Foo) 33
  • 62. When you export Foo in namespace Foo::, also create an alias Foo::Foo. 33
  • 63. The toplevel super-project 1 set(CMAKE_PREFIX_PATH "/prefix") 2 set(as_subproject Foo) 3 4 macro(find_package) 5 if(NOT "${ARG0}" IN_LIST as_subproject) 6 _find_package(${ARGV}) 7 endif() 8 endmacro() 9 10 add_subdirectory(Foo) 11 add_subdirectory(App) 34
  • 64. How does that work? If Foo is a ... • system package: • find_package(Foo) either finds FooConfig.cmake in the system or uses FindFoo.cmake to find the library in the system. In either case, the target Foo::Foo is imported. • prebuilt library: • find_package(Foo) either finds FooConfig.cmake in the CMAKE_PREFIX_PATH or uses FindFoo.cmake to find the library in the CMAKE_PREFIX_PATH. In either case, the target Foo::Foo is imported. • subproject: • find_package(Foo) does nothing. The target Foo::Foo is part of the project. 35
  • 65. CTest
  • 66. Run with ctest -S build.cmake 1 set(CTEST_SOURCE_DIRECTORY "/source") 2 set(CTEST_BINARY_DIRECTORY "/binary") 3 4 set(ENV{CXXFLAGS} "--coverage") 5 set(CTEST_CMAKE_GENERATOR "Ninja") 6 set(CTEST_USE_LAUNCHERS 1) 7 8 set(CTEST_COVERAGE_COMMAND "gcov") 9 set(CTEST_MEMORYCHECK_COMMAND "valgrind") 10 #set(CTEST_MEMORYCHECK_TYPE "ThreadSanitizer") 11 12 ctest_start("Continuous") 13 ctest_configure() 14 ctest_build() 15 ctest_test() 16 ctest_coverage() 17 ctest_memcheck() 18 ctest_submit() 36
  • 67. CTest scripts are the right place for CI specific settings. Keep that information out of the project. 36
  • 68. Filtering tests by name Define like this: 1 add_test(NAME Foo.Test 2 COMMAND foo_test --number 0 3 ) Run like this: 1 ctest -R 'Foo.' -j4 --output-on-failure 37
  • 69. Follow a naming convention for test names. This simplifies filtering by regex. 37
  • 70. Fail to compile 1 add_library(foo_fail STATIC EXCLUDE_FROM_ALL 2 foo_fail.cpp 3 ) 4 add_test(NAME Foo.Fail 5 COMMAND ${CMAKE_COMMAND} 6 --build ${CMAKE_BINARY_DIR} 7 --target foo_fail 8 ) 9 set_property(TEST Foo.Fail PROPERTY 10 PASS_REGULAR_EXPRESSION "static assert message" 11 ) 38
  • 71. Running crosscompiled tests • When the testing command is a build target, the command line is prefixed with ${CMAKE_CROSSCOMPILING_EMULATOR}. • When crosscompiling from Linux to Windows, set CMAKE_CROSSCOMPILING_EMULATOR to wine. • When crosscompiling to ARM, set CMAKE_CROSSCOMPILING_EMULATOR to qemu-arm. • To run tests on another machine, set CMAKE_CROSSCOMPILING_EMULATOR to a script that copies it over and executes it there. 39
  • 72. Run tests on real hardware 1 #!/bin/bash 2 tester=$1 3 shift 4 # create temporary file 5 filename=$(ssh root@172.22.22.22 mktemp) 6 # copy the tester to temporary file 7 scp $tester root@172.22.22.22:$filename 8 # make test executable 9 ssh root@172.22.22.22 chmod +x $filename 10 # execute test 11 ssh root@172.22.22.22 $filename "$@" 12 # store success 13 success=$? 14 # cleanup 15 ssh root@172.22.22.22 rm $filename 16 exit $success 40
  • 74. Toolchain.cmake 1 set(CMAKE_SYSTEM_NAME Windows) 2 3 set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) 4 set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) 5 set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) 6 7 set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) 8 9 set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 10 set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 11 set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 12 13 set(CMAKE_CROSSCOMPILING_EMULATOR wine64) 41
  • 75. Don’t put logic in toolchain files. 41
  • 77. Treat warnings as errors? 41
  • 78. How do you treat build errors? • You fix them. • You reject pull requests. • You hold off releases. 42
  • 79. Treat warnings as errors! 43
  • 80. Treat warnings as errors! • You fix them. • You reject pull requests. • You hold off releases. 43
  • 81. Treat warnings as errors! To treat warnings as errors, never pass -Werror to the compiler. If you do, your compiler treats warnings as errors. You can no longer treat warnings as errors, because you will no longer get any warnings. All you get is errors. 44
  • 82. -Werror causes pain • You cannot enable -Werror unless you already reached zero warnings. • You cannot increase the warning level unless you already fixed all warnings introduced by that level. • You cannot upgrade your compiler unless you already fixed all new warnings that the compiler reports at your warning level. • You cannot update your dependencies unless you already ported your code away from any symbols that are now [[deprecated]]. • You cannot [[deprecated]] your internal code as long as it is still used. But once it is no longer used, you can as well just remove it… 45
  • 83. Better: Treat new warnings as errors! 1. At the beginning of a development cycle (eg. sprint), allow new warnings to be introduced. • Increase warning level, enable new warnings explicitly. • Update the compiler. • Update dependencies. • Mark symbols as [[deprecated]]. 2. Then, burn down the number of warnings. 3. Repeat. 46
  • 84. Pull out all the stops! clang-tidy is a clang-based C++ “linter” tool. Its purpose is to provide an extensible framework for diagnosing and fixing typical programming errors, like style violations, interface misuse, or bugs that can be deduced via static analysis. cpplint is automated checker to make sure a C++ file follows Google’s C++ style guide. include-what-you-use analyzes #includes in C and C++ source files. clazy is a clang wrapper that finds common C++/Qt antipatterns that decrease performance. 47
  • 85. Target properties for static analysis • <lang>_CLANG_TIDY • <lang>_CPPLINT • <lang>_INCLUDE_WHAT_YOU_USE • Runs the respective tool along the with compiler. • Diagnostics are visible in your IDE. • Diagnostics are visible on CDash. • LINK_WHAT_YOU_USE • links with -Wl,--no-as-needed, then runs ldd -r -u. <lang> is either C or CXX. Each of those properties is initialzied with CMAKE_<property>. 48
  • 86. Scanning header files • Most of those tools report diagnostics for the current source file plus the associated header. • Header files with no assiciated source file will not be analyzed. • You may be able to set a custom header filter, but then the headers may be analyzed multiple times. 49
  • 87. For each header file, there is an associated source file that #includes this header file at the top. Even if that source file would otherwise be empty. 49
  • 88. Create associated source files 1 #!/usr/bin/env bash 2 for fn in `comm -23 3 <(ls *.h|cut -d '.' -f 1|sort) 4 <(ls *.c *.cpp|cut -d '.' -f 1|sort)` 5 do 6 echo "#include "$fn.h"" >> $fn.cpp 7 done 50
  • 89. Enable warnings from outside the project 1 env CC=clang CXX=clazy cmake 2 -DCMAKE_CXX_CLANG_TIDY:STRING= 3 'clang-tidy;-checks=-*,readability-*' 4 -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE:STRING= 5 'include-what-you-use;-Xiwyu;--mapping_file=/iwyu.imp' 6 .. 51
  • 90. Supported by all IDEs • Just setting CMAKE_CXX_CLANG_TIDY will make all clang-tidy diagnostics appear in your normal build output. • No special IDE support needed. • If IDE understands fix-it hints from clang, it will also understand the ones from clang-tidy. 52
  • 93. Personal Wishlist • For each of the following ideas, I have started a prototype. • Contibutions welcome! • You can talk to me! 53
  • 94. Disclaimer: No guarantee that the following ideas will ever be added to CMake. 53
  • 95. PCH as usage requirements
  • 96. PCH as usage requirements 1 target_precompile_headers(Foo 2 PUBLIC 3 "foo.h" 4 PRIVATE 5 <unordered_map> 6 ) 54
  • 97. PCH as usage requirements • Calculate a list of headers per config and language for the build specification of each target. • Generate a header file that #includes each of those headers. • Tell the build system to precompile this header. • Tell the build system to force-include this header. • Require no changes to the code (No #include "stdafx.h"). 55
  • 99. More Languages! • CMake’s core is language-agnostic. • Language support is scripted in modules. • Rules how to compile object files, link them together. • The output of the compiler must be an object file. • CMake can be used with D by putting necessary files in CMAKE_MODULE_PATH.1 1https://github.com/dcarp/cmake-d 56
  • 100. Even more Languages! • If we allow the output to be a source file of a known language, we would not need special handling for Protobuf, Qt-resources, or any other IDL. • This would also allow using CMake for BASIC, BCX, Chapel, COBOL, Cython, Eiffel, Genie, Haxe, Java, Julia, Lisaac, Scheme, PHP, Python, X10, Nim, Vala.2 2https://en.wikipedia.org/wiki/Source-to-source_compiler 57
  • 102. find_package(Foo PKGCONF) • find_package() has two modes: PACKAGE and CONFIG. • Let’s add a PKGCONF mode. • In this mode, CMake parses .pc files and generates one IMPORTED library per package. 58
  • 104. Lua VM • Execute CMake commands on Lua VM.3 • Allow CMake modules to be written in Lua. 3not the other way round. This failed before. 59
  • 105. Declarative Frontend • For directories, use a declarative language that allows procedural subroutines. • libucl4 is an interesting option. 4https://github.com/vstakhov/libucl 60
  • 106. Tell me your ideas! 60