How to set option to a library but only when used by examples

I have a CMake project that is a library that also adds an example. Something like this

/example/
 -> myexample.cpp
 -> CMakeLists.txt
/include/
 -> mylib.h
/src/
 -> mylib.cpp
/CMakeLists.txt

My /CMakeLists.txt looks like this:

cmake_minimum_required (VERSION 3.16)
set(BOOST_VERSION 1.72)

option(ASIO_SEPARATE_COMPILATION "Compile Asio separately" ON)

project(mylib)

add_library(mylib STATIC "src/mylib.cpp")
target_include_directories(mylib PUBLIC "include")

if(ASIO_SEPARATE_COMPILATION)
  target_compile_definitions(mylib PUBLIC -DBOOST_ASIO_SEPARATE_COMPILATION)
endif()

add_subdirectory(example)

The /example/CMakeLists.txt is as simple as it can get:

add_executable(myexample "myexample.cpp")
target_link_libraries(myexample mylib)

Note the ASIO_SEPARATE_COMPILATION option: it is there to optionally add the BOOST_ASIO_SEPARATE_COMPILATION definition. The details of what that does aren’t important in context of this question, but more can be found here for anyone interested.

Now, for whoever is using mylib, it is a good default to set ASIO_SEPARATE_COMPILATION option to ON. But for very simple executables such as myexample.cpp, it can be set to OFF for convenience. My problem is that I don’t know how to set that option only for myexample while leaving it on OFF by default for anyone else using mylib.

In other words, when mylib is used by myexample, I want mylib to be compiled with ASIO_SEPARATE_COMPILATION OFF. And when mylib is used by anyone else, I want that option to be ON by default, but configurable.

As a side note: it feels backwards that myexample is “added” from /CMakeLists.txt defining mainly the mylib library (though by looking at other projects this seems to be the standard approach). Ideally, (IMO) myexample should also showcase how an application “adds” mylibrary (not vice versa). I think doing it this other way would also solve my problem quite nicely, though I would prefer not to change the directory structure if possible.

Did you read that topic: Is target specific stuff transitive to dependencies?
AFAIU you seem to pursue a similar functional goal: compiling a library depending on its usage.

Thanks, I think that’s a step in the right direction. Unfortunately I’m having problems using your solution for my case where I have a more elaborate project structure. Here is a minimal example I came up with (I’m a new cmake forum user, so I can’t upload the file here directly).

In the example you’ll find three targets: mylib, myexample and myapp. Both myexample and myapp use mylib. The run.sh script compiles myexample twice, once from mylib and once from myapp.

I tried two different cases:

#1

  • Set target_compile_definitions(myexample PRIVATE SEPARATE_COMPILATION=0) in mylib/myexample/CMakeLists.txt
  • Set target_compile_definitions(myapp PRIVATE SEPARATE_COMPILATION=1) in myapp/CMakeLists.txt

This results in everything being compiled without SEPARATE_COMPILATION even being defined when mylib.cpp is being compiled. And by everything I mean myexample when compiled from mylib and both myexample and myapp when compiled from myapp.

#2 (this is the one more akin to what I’m looking for as I’d like SEPARATE_COMPILATION to be 1 by default)

  • Set target_compile_definitions(mylib PRIVATE SEPARATE_COMPILATION=1) in mylib/CMakeLists.txt
  • Set target_compile_definitions(myexample PRIVATE SEPARATE_COMPILATION=0) in mylib/myexample/CMakeLists.txt

This results in everything being compiled with SEPARATE_COMPILATION=1.

This is getting hairy, so I’ll just reiterate that the goal is to compile

  • myexample with SEPARATE_COMPILATION=0 for both cases: where its compiled from mylib as well as from myapp
  • myapp with SEPARATE_COMPILATION=1