Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
The What, Why and How of Modern CMake
Stephen Kelly
C++ User Group, Berlin
July 2014
Who and When
● Using CMake since KDE 4.0 (December 2007)
Who and When
● Using CMake since KDE 4.0 (December 2007)● Contributor since CMake 2.8.7 (Nov 2011)
Who and When
● Using CMake since KDE 4.0 (December 2007)● Contributor since CMake 2.8.7 (Nov 2011)● Feature complete in CMake 3.0 (June 2014)
Who and When
● Using CMake since KDE 4.0 (December 2007)● Contributor since CMake 2.8.7 (Nov 2011)● (Almost) Feature complete in CMake 3.0 (June 2014)
Buildsystem Developers
Buildsystem Developers
Buildsystem Developers
Buildsystem Developers
Buildsystem Developers
Buildsystem Developers
Buildsystem Developers
Buildsystem Developers
Buildsystem Developers
Buildsystem Developers
Buildsystem Developers
Buildsystem Developers
Buildsystem Developers
include_directories("/opt/foo/bar") compile_definitions(-DUSING_BAR=1)
Buildsystem Developers
What is Modern CMake?
What is Modern CMake?
● Describes a useful model of buildsystem● Has design/direction ● Straightforward, clean syntax
What is Modern CMake?
● Describes a useful model of buildsystem● Has design/direction ● Straightforward, clean syntax● High usability, maximum speed● High level of abstraction● Declarative
What is Modern CMake?
add_library(foo foo.cpp)
add_executable(myexe main.cpp)target_link_libraries(myexe foo)
What is Modern CMake?
add_library(foo foo.cpp)target_compile_definitions(foo PRIVATE -DBUILDING_FOO=1)target_include_directories(foo PRIVATE "${srcDir}/bar")
What is Modern CMake?
add_library(foo foo.cpp)target_compile_definitions(foo INTERFACE -DUSING_FOO=1)target_include_directories(foo INTERFACE "/opt/foo/bar")
What is Modern CMake?
add_library(foo foo.cpp)target_compile_definitions(foo INTERFACE -DUSING_FOO=1)target_include_directories(foo INTERFACE "/opt/foo/bar")
add_executable(myexe main.cpp)target_link_libraries(myexe foo)
What is Modern CMake?
Describe target properties
What is Modern CMake?
Describe target dependencies
What is Modern CMake?
Transitive usage requirements
What is Modern CMake?
Exporting for downstream use
What is Modern CMake?
install(EXPORT fooTargets NAMESPACE Bar:: DESTINATION lib/cmake)
What is Modern CMake?
install(EXPORT fooTargets NAMESPACE Bar:: DESTINATION lib/cmake)
# Generates:
add_library(Bar::foo IMPORTED)set_target_properties(Bar::foo INTERFACE_COMPILE_DEFINITIONS USING_FOO=1)
What is Modern CMake?
find_package(Foo REQUIRED)
add_executable(myexe main.cpp)target_link_libraries(myexe Bar::foo)
What is Modern CMake?
Upstream provides 'CMake config packages'
No more FindFoo.cmake!
Why is this better?
# Directory-scoped. Bad!include_directories(${Foo_INCLUDES})
add_executable(myexe1 main1.cpp)target_link_libraries(myexe1 foo)
# Uses the includes too!add_executable(myexe2 main2.cpp)
How?
Less code!
target_link_libraries()
expresses target dependencies, consumes requirements
How?
target_include_directories() target_compile_definitions() target_compile_options() target_compile_features() target_sources() target_link_options() (pending) target_archive_options() (pending)
express usage requirements
How?
target_compile_definitions(tgt PRIVATE I_USE_THIS )
target_compile_definitions(tgt INTERFACE YOU_USE_THIS )
target_compile_definitions(tgt PUBLIC WE_BOTH_USE_THIS )
Compiler requirements
C++11
Compiler requirements
C++11
C++14
Compiler requirements
C++11
C++14
C++98
Compiler requirements
C++11?
C++14?
C++98?
Compiler requirements
add_library(foo SHARED foo.cpp)target_compile_features(foo INTERFACE cxx_variadic_templates)
...
add_executable(myexe main.cpp)target_link_libraries(myexe Bar::foo)
Compiler requirements
add_library(foo SHARED foo.cpp)target_compile_features(foo INTERFACE cxx_variadic_templates cxx_decltype_auto)...
add_executable(myexe main.cpp)target_link_libraries(myexe Bar::foo)
Compiler requirements
add_library(foo SHARED foo.cpp)target_compile_features(foo INTERFACE cxx_template_template_parameters)
...
add_executable(myexe main.cpp)target_link_libraries(myexe Bar::foo)
Compiler requirements
add_library(foo SHARED foo.c)target_compile_features(foo INTERFACE c_restrict c_static_assert)
...
add_executable(myexe main.c)target_link_libraries(myexe Bar::foo)
The QTestLib problem
add_executable(guitest guitest.cpp)target_link_libraries(guitest Qt5::Test Qt5::Gui)
add_executable(coretest coretest.cpp)target_link_libraries(coretest Qt5::Test Qt5::Core)
The QTestLib problem
#if defined(QT_CORE_LIB) QCoreApplication#elif defined(QT_GUI_LIB) QGuiApplication#elif defined(QT_WIDGET_LIB) QApplication#endif
Typo diagnostics
find_package(Qt5Widgets REQUIRED)
add_executable(typotest typotest.cpp)target_link_libraries(typotest Qt5::Wydjits)
Typo diagnostics
# find_package(Qt5Widgets REQUIRED)
add_executable(typotest typotest.cpp)target_link_libraries(typotest Qt5::Widgets)
Declarative
add_library(foo foo.cpp)target_include_directories(foo INTERFACE $<BUILD_INTERFACE:${srcDir}/bar> $<INSTALL_INTERFACE:${installDir}/bar>)
Declarative
add_library(foo foo.cpp)target_compile_definitions(foo INTERFACE $<$<CONFIG:Debug>:DEBUG_MODE>)
Interface compatibility
add_library(foo foo.cpp)set_target_property(foo INTERFACE_CUSTOM_STRING MULTI_THREADED)
add_library(bar bar.cpp)set_target_property(bar INTERFACE_CUSTOM_STRING NOT_MULTI_THREADED)
Interface-only libraries
add_library(boost::range INTERFACE IMPORTED)
Interface-only libraries
add_library(boost::range INTERFACE IMPORTED)set_target_properties(boost::range INTERFACE_INCLUDE_DIRECTORIES "/opt/boost_range/include")
Interface-only libraries
add_executable(myexe main.cpp)target_link_libraries(myexe boost::range boost::any boost::units)
Header-library challenges
● Find headers● Use include directories● Use correct macros (BOOST_ALL_NO_LIB etc)
Header-library challenges
● Find headers● Use include directories● Use correct macros (BOOST_ALL_NO_LIB etc)● Use correct compile flags (eg, non-broken preprocessor with Clang on Windows)● Compatibility between components● Diagnostics
Interface sources
add_library(lib_with_global_obj lib.cpp)target_sources(lib_with_global_obj INTERFACE symbol_user.cpp)
Interface sources
set(isExe "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>")add_library(lib_with_global_obj lib.cpp)target_sources(lib_with_global_obj INTERFACE "$<${isExe}:symbol_user.cpp>")
Interface sources
set(isExe "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>")add_library(lib_with_global_obj lib.cpp)target_sources(lib_with_global_obj INTERFACE "$<${isExe}:symbol_user.cpp>")
add_library(intermediate other.cpp)target_link_libraries(intermediate PUBLIC lib_with_global_obj)
Interface sources
set(isExe "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>")add_library(lib_with_global_obj lib.cpp)target_sources(lib_with_global_obj INTERFACE "$<${isExe}:symbol_user.cpp>")
add_library(intermediate other.cpp)target_link_libraries(intermediate PUBLIC lib_with_global_obj)
...
add_executable(myexe intermediate)
Batteries included
Questions
And Answers...
steveire.wordpress.comhttp://www.cmake.org/cmake/help/v3.0/