Are exported (installed) cmake targets distributable?
Asked Answered
C

1

0

I'm working on a project with a lot of external dependencies, which are included in the project tree. I would like to pre-build all of the dependencies and share the importable targets within the project tree.

I was planning to use cmake install with a CMAKE_INSTALL_PREFIX in the source tree, and use CMAKE_PREFIX_PATH to reference it for find_package. However, I'm beginning to wonder how maintainable this strategy is going to be? For example here's something I noticed in one of the installed cmake scripts:

${CMAKE_PREFIX_PATH}/lib/cmake/glfw3/glfw3Targets.cmake:

set_target_properties(glfw PROPERTIES
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
  INTERFACE_LINK_LIBRARIES "/usr/lib/x86_64-linux-gnu/librt.so;/usr/lib/x86_64-linux-gnu/libm.so;dl;/usr/lib/x86_64-linux-gnu/libX11.so;-lpthread"
)

It seems really suspicious to me that all of those link libraries are fully resolved to paths on the host machine.

I guess the question is: Are cmake installs to a prefix meant to be distributable and this is just a bad example, or are they meant to be tied to the machine you "install" them on? Ie. Is prefix really meant to just relocate where on the system things are supposed to be "installed", and my hope to use it as a shared package manager likely to be problematic?

Cost answered 20/6, 2018 at 6:25 Comment(6)
You shouldn't share the files cmake installs by copying them and sending them to someone else. It is fine to consume them locallyDabney
As for your question, if you want to make a fully distributable executable, the best way is still static linking.Haematic
If you are trying to package your project into something the end user can use, see CPackDabney
@Dabney technically, it's a team of people working on a product together. We're not distributing an API that end users would consume, unless you're saying my team is the end user... In which case I still don't really think I want to be "installing" anything on anyone's machine, rather having all of the dependencies as part of the project so they can all be linked to easily (even if they are all built as static libs as "Some programmer dude" pointed out.Cost
Either have everyone run cmake themselves, or enforce a common system setup, perhaps through a VM. Check out conan or vcpkg or one of the other package managersDabney
Everyone will run cmake, but I don't necessarily want everyone to rebuild all of the dependencies from source. I'd like to at least prebuild some of the dependencies and have targets that the other users can import.Cost
A
1

Yes, EXPORT'ed CMake targets can be "distributable", but the project should follow some principles for achieve that.

If you link with a (external) library, but do not want export file to contain absolute path to it, then do not pass absolute path directly to target_link_libraries.

In case a linked library is shipped with a compiler (e.g. m or rt), things are simple: just pass the library's name to the target_link_libraries.

In case a linked library YYY comes from other package and is detected by find_package(YYY), this implies several things:

  1. Script FindYYY.cmake or YYYConfig.cmake should return IMPORTED target. If this is not true, you may try to wrap its results into IMPORTED target.

  2. target_link_libraries should use this IMPORTED target.

  3. Script XXXConfig.cmake, shipped with your project, should use find_dependency(YYY) for discover a library on a user machine.

  4. For find_dependency(YYY) work, a user machine should have FindYYY.cmake or YYYConfig.cmake script. Alternatively, you may ship FindYYY.cmake with your project, and adjust CMAKE_MODULE_PATH variable before find_dependency() call (in your XXXConfig.cmake).

Algor answered 20/6, 2018 at 8:36 Comment(6)
Thanks. Though, in your second paragraph, I don't follow. Do I need to edit the third_party cmake script? In every case I can think of all of the target_libraries are other targets and not paths to libs.Cost
"Do I need to edit the third_party cmake script?" - This would be not recommended. If third-party script FindYYY.cmake doesn't provide IMPORTED target but provides variables, you may create (after call to find_package(YYY)) IMPORTED (or even INTERFACE IMPORTED) target by yourself, and set its properties according to these variables. The same should be done in your XXXConfig.cmake script after call find_dependency(YYY).Algor
No, I meant... in regards to "do not pass absolute path directly" to target_link_libraries. I can't really control what 3rd party libraries do there. For example: github.com/glfw/glfw/blob/master/CMakeLists.txt#L185 This shows the cmake that resulted in the absolute paths posted in the question.Cost
Using absolute paths in a 3d party project means just that export targets of that project are not relocatable. You still may have your own package and its export targets to be relocatable. (Assuming you use find_package(GLFW) and find_dependency(GLFW) for discover glfw libraries).Algor
The problem is almost all of the third_party libraries will use some find_package(AAA) to locate dependencies on the system, and the general FindAAA scripts (included with cmake) create non-relocatable paths. Is there a setting to tweak that? And since their dependencies are transitively consumed, it creates a nightmare of non-relocatable targets.Cost
Possibly related question: #56136285Durno

© 2022 - 2024 — McMap. All rights reserved.