Simplify add_library and installation for convential layouts
Extracted from #16414 (comment 679294)
IMO this could lead to a great simplification of CMake itself. Having read about the build tool/package manager "dds" I think we could make it even better:
I propose project(name WITH_NAMESPACE)
and an optional keyword arg NAMESPACE <name>
which defaults to PROJECT_NAME and make PROJECT_NAMESPACE set. This namespace would be used by install commands as the default argument for NAMESPACE
and every library without a namespace will have that namespace added.
To be conservative (problem: target_link_libraries(... foo)
-> Is foo
a package or external dependency?) I'll let any add_library/add_executable
implicitly create an ALIAS target with the namespaced name (just as is already common practice). Additionally I'd allow operations on namespaced targets of the current namespace, i.e. target_link_libraries(${PROJECT_NAMESPACE}::foo ...)
is allowed and affects the underlying target.
We probably need something like INTERNAL
for libraries that should not have such a namespaced alias and hence not be "exported".
Combining this with your proposal to have namespaced targets global leads to a solution where existing CMakes continue to work and CMakes written for this proposal have significantly reduced work.
I'm also for borrowing other ideas from dds
to reduce the amount of boilerplate code required for simple projects. Example: add_library(foo DIRECTORY <dir>)
would look for folders src
and include
in directory <dir>
. If an include
folder is found it is used as the PUBLIC
include directory and src
as a private one. Else (only src found) src
is used as a PUBLIC include folder. It will also add all sources according to the current language(s) to the library sources, i.e. extensions cpp, cxx, h, hpp
for C++, c, h
for C and so on. Combined with a unified install
command (combination of install(EXPORT
(superflous due to namespace), configuring version and config file and installation of the artefacts + headers) would allow to create simple projects following a useful convention to be configured by CMake with only 3(4) commands:
cmake_minimum_version(3.20)
project(foo VERSION 1.0.0 WITH_NAMESPACE)
add_library(bar DIRECTORY .)
install_project(VERSION_COMPATIBILITY SAME_MAJOR) # Runtime, include, ... default to values of GNUInstallDirs implicitly included