Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Library options are not exported to calling projects #275

Open
pmatalon opened this issue Sep 3, 2024 · 8 comments
Open

Library options are not exported to calling projects #275

pmatalon opened this issue Sep 3, 2024 · 8 comments

Comments

@pmatalon
Copy link

pmatalon commented Sep 3, 2024

I have a header-only library project, and I am using project_options to package it, so that it can be used as a dependency for other projects.
The library has numerous options, defined with the cmake functions option or set. What I want is to export those options, so that calling projects can configure them.
Here is the skeleton of its CMakeLists.txt, with the options WITH_OPENMP and CHECK_NAN:

project(my_lib LANGUAGES CXX)

(...) 

project_options(
  ENABLE_CACHE
  # ...other arguments
)

add_library(my_lib INTERFACE)
target_link_libraries(my_lib INTERFACE project_options project_warnings)

set(INCLUDE_DIR "include")
target_include_directories(my_lib INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${INCLUDE_DIR}>"
                          "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")

# dependencies
set(DEPENDENCIES_CONFIGURED pugixml fmt)
foreach(DEPENDENCY ${DEPENDENCIES_CONFIGURED})
  find_package(${DEPENDENCY} CONFIG REQUIRED)
endforeach()
target_link_system_libraries(my_lib INTERFACE pugixml::pugixml fmt::fmt)

# optional dependency
option(WITH_OPENMP "Enable OpenMP" OFF)
if(${WITH_OPENMP})
  find_package(OpenMP)
  target_link_libraries(my_lib INTERFACE OpenMP::OpenMP_CXX)
  target_compile_definitions(my_lib INTERFACE MYLIB_WITH_OPENMP)
endif()

# another option
option(CHECK_NAN "Check if NaN occur in computations" OFF)
if(CHECK_NAN)
  target_compile_definitions(my_lib INTERFACE MYLIB_CHECK_NAN)
endif()

(...)

# packaging of the project
package_project(
  TARGETS my_lib project_options project_warnings libdeps
  INTERFACE_DEPENDENCIES_CONFIGURED ${DEPENDENCIES_CONFIGURED}
  INTERFACE_INCLUDES ${INCLUDE_DIR}
)

Now, another project has my_lib as a dependency. Here is its CMakeLists.txt:

project(caller_project CXX)
find_package(my_lib CONFIG REQUIRED)
add_executable(caller_project main.cpp)
target_link_libraries(caller_project PRIVATE my_lib::my_lib my_lib::project_options my_lib::project_warnings my_lib::libdeps)

# How do I set the options WITH_OPENMP and CHECK_NAN of `my_lib`?

The compilation of caller_project works fine with this CMakeLists.txt. My problem is that I can't set my_lib's options.
I think the options are simply not exported, since I don't see them when I use the ccmake command. (On the other hand, if my_lib's dependencies have options themselves, I can see them in ccmake.)
I tried using dynamic_project_options with and without ENABLE_CACHE, but no luck...
Thank you for your support.

Upvote & Fund

@aminya is using Polar.sh so you can upvote and help fund this issue. The funding is received once the issue is completed & confirmed by you.

Thank you in advance for helping prioritize & fund our backlog!


Fund with Polar
@ClausKlein
Copy link
Contributor

ClausKlein commented Sep 4, 2024

If you want to change the default config values of a sub project set the options before call FetchContent_MakeAvailable() or find_package()`! i.e.:

include(FetchContent)

FetchContent_Declare(
    glfw
    GIT_REPOSITORY  https://github.com/glfw/glfw.git
    SOURCE_DIR      "${CMAKE_CURRENT_SOURCE_DIR}/glfw-src"
    GIT_TAG         "master"
    GIT_SHALLOW     TRUE
)
set(GLFW_BUILD_WAYLAND  ON)
set(GLFW_BUILD_X11      OFF)
FetchContent_MakeAvailable(glfw)

or

option(USE_BOOST "build with BOOST support" ON)
if(USE_BOOST)
  option(Boost_DEBUG "find boost at verbose mode" OFF)
  option(Boost_USE_STATIC_LIBS "use static libs only" OFF)
  option(Boost_USE_MULTITHREADED "use -mt libs only" ON)

  find_package(Boost 1.71 CONFIG REQUIRED COMPONENTS atomic chrono filesystem thread unit_test_framework)
  if(Boost_FOUND)
    add_definitions(-DBOOST_ALL_NO_LIB)
    include_directories(include)
  endif()
endif()

@pmatalon
Copy link
Author

pmatalon commented Sep 4, 2024

Thank you for your quick answer. I'll try to clarify my question.
The options are in my library project, which uses package_options for the packaging. I configured the CMakeLists.txt so that If an option is activated, other dependencies are included, compilation options are defined, etc. Now, in a caller project, I want to be able to set those options in my library, thus triggering the linking of other dependencies, compile options for my library, etc. Unfortunately, it seems that my library's options are not exported, so the caller project cannot set them. When I use the ccmake command on the caller project, I can see all available options: the options of all dependencies are present, except those of my library.

@ClausKlein
Copy link
Contributor

What do you mean with package_options?

They are not at https://github.com/aminya/project_options?tab=readme-ov-file#readme

@ClausKlein
Copy link
Contributor

@pmatalon
Copy link
Author

pmatalon commented Sep 5, 2024

What do you mean with package_options?

They are not at https://github.com/aminya/project_options?tab=readme-ov-file#readme

Sorry, I meant project_options.

@pmatalon
Copy link
Author

pmatalon commented Sep 5, 2024

I have updated the text of the issue to include a more detailed CMakeLists.txt and re-explain the problem.

@ClausKlein
Copy link
Contributor

ClausKlein commented Sep 5, 2024

Your logic is wrong!

An interface library is an header only implementation.
The find_package(OpenMP) and the resulting compile_defintions must be done by the user of your exported cmake package!

You need something like this https://github.com/ClausKlein/boost-modules-bench/blob/develop/asio-module/AsioConfig.cmake.in

And this is not supported by project_options.

@pmatalon
Copy link
Author

pmatalon commented Sep 9, 2024

I agree that the config can be done by the user, but the work that must be done if an option is activated may be complicated, and it would simplify the user's job if that work was done for him upon a simple option's activation.
Using only standard cmake functions, you indeed need a Config.cmake.in file to do that. project_options does not support it, ok.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants