mirror of
https://github.com/Kitware/CMake.git
synced 2025-12-31 19:00:54 -06:00
Tutorial: Improve Step 10 generator expression example.
Use compiler flags and standard levels as the compelling argument for using generator expressions and interface libraries
This commit is contained in:
committed by
Brad King
parent
a1c6d7e9af
commit
fa203ee323
@@ -1,8 +1,17 @@
|
||||
cmake_minimum_required(VERSION 3.3)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(Tutorial)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
add_library(tutorial_compiler_flags INTERFACE)
|
||||
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
|
||||
|
||||
# add compiler warning flags just when building this project via
|
||||
# the BUILD_INTERFACE genex
|
||||
set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU>")
|
||||
set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
|
||||
target_compile_options(tutorial_compiler_flags INTERFACE
|
||||
"$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
|
||||
"$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
|
||||
)
|
||||
|
||||
# set the version number
|
||||
set(Tutorial_VERSION_MAJOR 1)
|
||||
|
||||
@@ -21,6 +21,7 @@ if(USE_MYMATH)
|
||||
|
||||
# first we add the executable that generates the table
|
||||
add_executable(MakeTable MakeTable.cxx)
|
||||
target_link_libraries(MakeTable tutorial_compiler_flags)
|
||||
|
||||
# add the command to generate the source code
|
||||
add_custom_command(
|
||||
@@ -44,14 +45,18 @@ if(USE_MYMATH)
|
||||
POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
|
||||
)
|
||||
|
||||
target_compile_definitions(SqrtLibrary PRIVATE
|
||||
"$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>"
|
||||
"$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>"
|
||||
)
|
||||
target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)
|
||||
|
||||
|
||||
target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
|
||||
if(HAVE_LOG AND HAVE_EXP)
|
||||
target_compile_definitions(SqrtLibrary
|
||||
PRIVATE "HAVE_LOG" "HAVE_EXP")
|
||||
endif()
|
||||
target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(MathFunctions PRIVATE "$<$<BOOL:${USE_MYMATH}>:USE_MYMATH>")
|
||||
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
|
||||
|
||||
# define the symbol stating we are using the declspec(dllexport) when
|
||||
# building on windows
|
||||
@@ -62,7 +67,7 @@ set_property(TARGET MathFunctions PROPERTY VERSION "1.0.0")
|
||||
set_property(TARGET MathFunctions PROPERTY SOVERSION "1")
|
||||
|
||||
# install rules
|
||||
install(TARGETS MathFunctions
|
||||
install(TARGETS MathFunctions tutorial_compiler_flags
|
||||
DESTINATION lib
|
||||
EXPORT MathFunctionsTargets)
|
||||
install(FILES MathFunctions.h DESTINATION include)
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
cmake_minimum_required(VERSION 3.3)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(Tutorial)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
add_library(tutorial_compiler_flags INTERFACE)
|
||||
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
|
||||
|
||||
# add compiler warning flags just when building this project via
|
||||
# the BUILD_INTERFACE genex
|
||||
set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU>")
|
||||
set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
|
||||
target_compile_options(tutorial_compiler_flags INTERFACE
|
||||
"$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
|
||||
"$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
|
||||
)
|
||||
|
||||
# set the version number
|
||||
set(Tutorial_VERSION_MAJOR 1)
|
||||
|
||||
@@ -19,6 +19,7 @@ if(USE_MYMATH)
|
||||
|
||||
# first we add the executable that generates the table
|
||||
add_executable(MakeTable MakeTable.cxx)
|
||||
target_link_libraries(MakeTable tutorial_compiler_flags)
|
||||
|
||||
# add the command to generate the source code
|
||||
add_custom_command(
|
||||
@@ -42,14 +43,17 @@ if(USE_MYMATH)
|
||||
POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
|
||||
)
|
||||
|
||||
target_compile_definitions(SqrtLibrary PRIVATE
|
||||
"$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>"
|
||||
"$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>"
|
||||
)
|
||||
target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)
|
||||
|
||||
target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
|
||||
if(HAVE_LOG AND HAVE_EXP)
|
||||
target_compile_definitions(SqrtLibrary
|
||||
PRIVATE "HAVE_LOG" "HAVE_EXP")
|
||||
endif()
|
||||
target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(MathFunctions PRIVATE "$<$<BOOL:${USE_MYMATH}>:USE_MYMATH>")
|
||||
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
|
||||
|
||||
# define the symbol stating we are using the declspec(dllexport) when
|
||||
#building on windows
|
||||
|
||||
@@ -598,27 +598,47 @@ expressions are the 0 and 1 expressions. A ``$<0:...>`` results in the empty
|
||||
string, and ``<1:...>`` results in the content of "...". They can also be
|
||||
nested.
|
||||
|
||||
For example:
|
||||
A common usage of generator expressions is to conditionally add compiler
|
||||
flags, such as those as language levels or warnings. A nice pattern is
|
||||
to associate this information to an ``INTERFACE`` target allowing this
|
||||
information to propagate. Lets start by constructing an ``INTERFACE``
|
||||
target and specifying the required C++ standard level of ``11`` instead
|
||||
of using ``CMAKE_CXX_STANDARD``.
|
||||
|
||||
.. code-block:: cmake
|
||||
So the following code:
|
||||
|
||||
if(HAVE_LOG AND HAVE_EXP)
|
||||
target_compile_definitions(SqrtLibrary
|
||||
PRIVATE "HAVE_LOG" "HAVE_EXP")
|
||||
endif()
|
||||
.. literalinclude:: Step10/CMakeLists.txt
|
||||
:language: cmake
|
||||
:start-after: project(Tutorial)
|
||||
:end-before: # Set the version number
|
||||
|
||||
Can be rewritten with generator expressions:
|
||||
Would be replaced with:
|
||||
|
||||
.. code-block:: cmake
|
||||
.. literalinclude:: Step11/CMakeLists.txt
|
||||
:language: cmake
|
||||
:start-after: project(Tutorial)
|
||||
:end-before: # add compiler warning flags just when building this project via
|
||||
|
||||
target_compile_definitions(SqrtLibrary PRIVATE
|
||||
"$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>"
|
||||
"$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>"
|
||||
)
|
||||
|
||||
Note that ``${HAVE_LOG}`` is evaluated at CMake configure time while
|
||||
``$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>`` is evaluated at build system generation
|
||||
time.
|
||||
Next we add the desired compiler warning flags that we want for our
|
||||
project. As warning flags vary based on the compiler we use
|
||||
the ``COMPILE_LANG_AND_ID`` generator expression to control which
|
||||
flags to apply given a language and a set of compiler ids as seen
|
||||
below:
|
||||
|
||||
.. literalinclude:: Step11/CMakeLists.txt
|
||||
:language: cmake
|
||||
:start-after: # the BUILD_INTERFACE genex
|
||||
:end-before: # set the version number
|
||||
|
||||
Looking at this we see that the warning flags are encapsulated inside a
|
||||
``BUILD_INTERFACE`` condition. This is done so that consumers of our installed
|
||||
project will not inherit our warning flags.
|
||||
|
||||
|
||||
**Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that
|
||||
all targets have a ``target_link_libraries()`` call to ``tutorial_compiler_flags``.
|
||||
|
||||
|
||||
Adding Export Configuration (Step 11)
|
||||
=====================================
|
||||
|
||||
Reference in New Issue
Block a user