1
votes

I've got a project with two subdirectory projects (added with add_subdirectory), each with their own libraries, binaries and install/uninstall targets. So:

main_project
|
|--CMakeLists.txt
|--src/
   |--CMakeLists.txt (with binary target, install()
|
|--project_a
   |--CMakeLists.txt
   |--src/
      |--CMakeLists.txt (with library, install())
|
|--project_b
   |--CMakeLists.txt
   |--src/
      |--CMakeLists.txt (with library, install())

I'd like for the top-level project (main_project) to automatically install the libraries a and b (included in main_project from target_link_libraries()). So, I'd like to be able to go:

cd main_project/build
cmake ..
make
sudo make install

and have the main_project binary and project_a/b libraries installed automatically. I've tried this:

main_project/src/CMakeLists.txt
...
install(FILES main project_a project_b DESTINATION bin
        LIBRARY DESTINATION lib)

but a cmake .. results in

install TARGETS given target "project_a" which does not exist in this directory.

as expected.

I've also tried specifying a path:

main_project/src/CMakeLists.txt
...
install(FILES main ${CMAKE_SOURCE_DIR}/project_a/ ${CMAKE_SOURCE_DIR}/project_b DESTINATION bin
        LIBRARY DESTINATION lib)

which also complains that project_a/b are not in this directory (also expected, I guess?)

I've also tried installing the libraries "manually" with the FILES option in install(), and that works just fine, but that seems very kludgy considering there are perfectly good install()s in the subprojects.

One additional issue: since project_a and project_b also have uninstall() custom targets, I can't add an uninstall target to the main_project without CMake complaining about the custom target already existing. When I try adding an uninstall directive to the top dir CMakeLists:

add_custom_target(uninstall
    COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)

But, since my project_a has an uninstall directive, I get:

CMake Error at CMakeLists.txt:37 (add_custom_target):
  add_custom_target cannot create target "uninstall" because another
  target with the same name already exists.  The existing target is a
  custom target created in source directory "/main_project/project_a".
  See documentation for policy CMP0002 for more details.

So, how do I install and uninstall the necessary library files from my subproject alongside my main_project?

1
It is not clear what you have and what you want. Show us the code you have tried.Tsyvarev
Edited to include what I've tried. Thanks for the help.Allan
As subproject's CMakeLists.txt already issue install() command, then main project doesn't need to do anything more about installing it. As for "uninstall", as subprojects already have given target, you may not create it in the main project. BTW, in case of 3d-party subprojects, when you cannot (or don't want to) change their code, preferrable way is to use ExternalProject_Add for configure and build them. For install subprojects with the main project, you may use install(SCRIPT) or install(CODE).Tsyvarev
Hmm, when make install is called from top-level build directory, every install() command issued in subdirectory (added with add_subdirectory()) shoul have an effect. If this is not true in your case, try to create minimal reproducible example which triggers that behaviour. As for overriding custom targets, I don't know the way for doing that.Tsyvarev
I found the problem. I am adding the subdirectory I want to install with EXCLUDE_FROM_ALL such that it doesn't build everything in the subdirectory, only the library I need. That flag seems to prevent the subdirectory install() from happening. Perhaps ExternalProject_Add is indeed the best way to go here...Allan

1 Answers

2
votes

I found the problem. I am adding the subdirectory I want to install with EXCLUDE_FROM_ALL such that it doesn't build everything in the subdirectory, only the library I need. That flag seems to prevent the subdirectory install() from happening. Perhaps ExternalProject_Add is indeed the best way to go here...

Also, RE overriding custom targets, this worked for me: http://public.kitware.com/pipermail/cmake/2011-July/045269.html