Optional Code, Approach 2: Pushing Optionality Down In Module Interface¶
Remove Too Much CMake Optionality¶
Remove optional descending from toplevel
CMakeLists.txt
Remove optional dependency from
libhello
Remove
DEMO_USE_BLACKLIST
fromDemoConfig.h.in
Test (⟶ macro not defined)
$ cmake -DUSE_BLACKLIST=ON ~/work/jfasch-home/trainings/material/soup/cmake/code/ $ make greeter-name.h:8:3: error: #error DEMO_USE_BLACKLIST not defined 8 | # error DEMO_USE_BLACKLIST not defined | ^~~~~
How to solve? Where to define macro?
TARGET_COMPILE_DEFINITIONS()
(backlist
Availablility)¶
Let
blacklist
announce its availability to its dependers⟶
TARGET_COMPILE_DEFINITIONS()
TARGET_COMPILE_DEFINITIONS(blacklist PUBLIC DEMO_USE_BLACKLIST=1)
Test
cmake -DUSE_BLACKLIST=ON ...
⟶ workscmake -DUSE_BLACKLIST=OFF ...
⟶ blacklist still used (obviously, because we always announce is as1
)
⟶ put optionality in
blacklist
Push Optionality Down In blacklist
(⟶ INTERFACE
Targets)¶
Naive approach
IF (${USE_BLACKLIST}) ADD_LIBRARY(blacklist blacklist.cpp) TARGET_INCLUDE_DIRECTORIES(blacklist PUBLIC .) TARGET_COMPILE_DEFINITIONS(blacklist PUBLIC DEMO_USE_BLACKLIST=1) ELSE() TARGET_COMPILE_DEFINITIONS(blacklist PUBLIC DEMO_USE_BLACKLIST=0) ENDIF()
$ cmake -DUSE_BLACKLIST=OFF ~/work/jfasch-home/trainings/material/soup/cmake/code/ CMake Error at blacklist/CMakeLists.txt:7 (TARGET_COMPILE_DEFINITIONS): Cannot specify compile definitions for target "blacklist" which is not built by this project. -- Configuring incomplete, errors occurred!
INTERFACE
targets: dependency nodes, but without anything that’s builtCan have dependencies itself (
TARGET_LINK_LIBRARIES()
)Ours has
TARGET_COMPILE_DEFINITIONS()
IF (${USE_BLACKLIST}) ADD_LIBRARY(blacklist blacklist.cpp) TARGET_INCLUDE_DIRECTORIES(blacklist PUBLIC .) TARGET_COMPILE_DEFINITIONS( blacklist INTERFACE DEMO_USE_BLACKLIST=1) # <--- INTERFACE: propagate-only ELSE() ADD_LIBRARY(blacklist INTERFACE) # <--- INTERFACE: there is no library here TARGET_COMPILE_DEFINITIONS( blacklist INTERFACE DEMO_USE_BLACKLIST=0) # <--- INTERFACE: propagate-only ENDIF()
Good Or Bad?¶
Is this better than the other approach?
It is more flexible
Optionality is local, between provider (
blacklist
) and consumer (libhello
)Is it simpler? Probably not!