stephen kelly c++ user group, berlin july 2014 · the what, why and how of modern cmake stephen...

Post on 07-Aug-2020

1 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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/

top related