Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cmake usefulness of aliases

Tags:

alias

cmake

I dont quite get the application of alias expressions. I understand that I can write something like this

cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR)
project(myLibs)
add_library(${PROJECT_NAME} src/test.cpp)
add_library(myLibs::myLibs ALIAS ${PROJECT_NAME})
...

and then use

  target_link_libraries(${TARGET_NAME}
  myLibs::myLibs

in another file to link the library to some executable, etc.

but why would I do that? I might as well skip the alias definition and just use the targetname of the built library directly

target_link_libraries(${TARGET_NAME}
myLibs
  • Can anyone explain to me why aliases exist
  • why do they employ the :: syntax? is the alias not completely arbitrary?
like image 502
CD86 Avatar asked Oct 04 '17 14:10

CD86


People also ask

What is alias target Cmake?

ALIAS target is just another name for original one. So the requirement for ALIAS target to be non-modifiable - you cannot adjust its properties, install it, etc.

What are targets in Cmake?

In general, targets comprise executables or libraries which are defined by calling add_executable or add_library and which can have many properties set. They can have dependencies on one another, which for targets such as these just means that dependent ones will be built after their dependencies.


1 Answers

TLDR: It gives other projects consuming yours more flexibility.

To me, the primary motivation for adding an ALIAS is related to installing/packaging and how other projects might use yours. When a project is installed, it can have its targets exported. The two relevant forms of the install() command are these:

install(TARGETS target... EXPORT exportName ...)
install(EXPORT exportName ... NAMESPACE myNS:: ...)

The first is what installs your actual target (i.e. the binaries), but it also includes the EXPORT keyword. This tells CMake that this target install is part of the exportName export set. The second of the above commands then installs a file for the exportName export set which contains CMake code that creates imported targets for each target in the set. It will prepend myNS:: to all the targets in that set (this is a crucial point for your question). This exported file will be included by the config package file for your project (this is a fairly involved topic, you can get further details on it here). Other projects can then build against your installed project by first doing a find_package(), which will recreate all your exported targets, except they will now all be prefixed with myNS::. It then links against these namespaced targets as though they were part of its own build. I'm skipping over a fair bit of detail, but those are the most relevant points to your question.

Now, it may be that the consuming project doesn't want to use find_package(), but instead it might want to bring your project directly into its build with add_subdirectory(). This would be a way to build your project from source rather than against a pre-built binary package. It is becoming a much more popular approach since the addition of the FetchContent module in CMake 3.11. If your project has provided ALIAS targets with names that match the exported target name, then the consuming project doesn't have to change any of its target_link_libraries() commands. Whether it builds against the pre-built binary package or brings in your project via add_subdirectory(), it links against the namespaced target name (i.e. myLibs::myLibs in your question) in either case and it all Just Works.

As for what the :: does, when a name containing :: appears in a target_link_libraries() command, it will only ever be interpreted as a CMake target (assuming policy CMP0028 is set to NEW, which it really always should be now). If no such target exists, CMake will fail with an error rather than assume it is the name of a library provided by the system.

like image 168
Craig Scott Avatar answered Oct 10 '22 11:10

Craig Scott