Skip to content

Export targets under custom namespaces (Dune:: by default)

Santiago Ospina De Los Ríos requested to merge feature/cmake-namespaces into master

Description

This MR changes the behavior of dune_add_library to export targets under a namespace. The new signature is:

    dune_add_library(<target> [INTERFACE|[STATIC|SHARED|MODULE]]
      [EXPORT_NAME <exportname>] 
      [NAMESPACE <namespace>]
      ...
    )

This signature will create a mutable target <target>, but additionally, this will create an aliased target and setup an exported target with the name <namespace><exportname> (i.e. concatenation of namespace and export name).

Expected Usage

In other words, the idea is to allow the following usage:

# dune-foo/CMakeLists.txt
dune_add_library(dunefoo EXPORT_NAME Foo)

# dune-foo/test/CMakeLists.txt (maybe run independently of dune-foo to check build-system correctness)
if("${CMAKE_SOURCE_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}")
  find_package(dune-foo REQUIRED IMPORTED)
endif()
target_link_librarty(my_test_target PRIVATE Dune::Foo) # consumed target: maybe an alias or maybe an imported [build|install] target

# dune-boo/CMakeLists.txt
find_package(dune-foo REQUIRED IMPORTED)
target_link_library(my_target PRIVATE Dune::Foo) # consumed target: imported [build|install] target

# dune-zee/CMakeLists.txt
FetchContent_Declare(dunefoo GIT_REPOSITORY https://gitlab.dune-project.org/foo/dune-foo.git)
FetchContent_MakeAvailable(dunefoo)
target_link_library(my_target PRIVATE Dune::Foo) # consumed target: aliased target

Reasoning and Details

Namespace scopes is CMake best practice and we want to follow that. Additionally, the exported target usually needs to be exposed as an alias so that the target consumers see always the same name. This makes CMake scripts that consume the target independent whether the target was generated within the module, consumed as an build target, or as an installed target (see https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#alias-targets). The common theme here is that the scoped targets (e.g. Dune::Foo) are non-mutable. For discussion about custom namespaces see !1257 (closed) and !1260 (merged).

This MR does:

  • Export targets under the requested namespace.
  • Deprecate usage of dune_add_library without export specification.
  • dune_add_library now creates an alias with the same name as the exported target for non-mutable usage.
  • dune_add_library and project_finalize now distinguish between exported libraries ${ProjecName}_INTERFACE_LIBRARIES and non-exported libraries ${ProjecName}_LIBRARIES (see #337 (closed)).
  • Write a unique targets file for each namespace and load all of them in only one targets file ${PrjectName}-targets.cmake.
  • ${ProjectName}-targets.cmake also creates an alias with the old unscoped names in the downstream project so that we have backwards compatibility.
  • ${ProjectName}-targets.cmake also sets up deprecation of old names for future releases (see Migration Path).

Migration Path

In this MR a timeline for incremental changes and deprecation is proposed:

  1. The function dune_add_library(<lib> ...) now requires to provide NO_EXPORT or EXPORT_NAME. Calls to dune_add_library(<lib> ...) without export specification will be supported until Dune 2.11
  2. Consumption of unscoped targets <lib> (without the Dune:: prefix) will be supported until Dune 2.12

In order to integrate this change in our workflow some changes are needed:

  1. Test this MR and report any strange behavior.
  2. After this MR is merged (DUNE 2.10-git), adapt your CMakeLists.txt files by adding the EXPORT_NAME or NO_EXPORT property to your dune_add_library calls. A warning will be issued if this is not done.
  3. If you currently consume the dune targets explicitly (e.g. linking against dunecommon without help of the dune build system), follow the next recommendations:
    • Applications: In application code where there is no more downstream libraries, you may use the new exported targets right away (e.g. link against Dune::Common instead of dunecommon).
    • Libraries: Wait and do not consume the new targets for one or two releases. This is because older versions (DUNE <=2.9) don't export the new names (e.g., Dune::Common), and linking against them will make your library strictly not compatible with those older versions. For DUNE >=2.11 we have scheduled a warning for old target name usage (e.g. linking against dunecommon) so that they can be updated to the correct names when support for DUNE <=2.9 is entirely dropped (i.e, scoped target names like Dune::Common is mandatory).
  4. Ask any questions what is unclear to you.

Is this MR Ready?

Edited by Simon Praetorius

Merge request reports