0

Through that, I link private libraries with BUILD_INTERFACE genexpr and they wouldn't be in the exported targets, but the libraries' linked libraries will be and unfortunately when we run the install rule they will be installed. And i don't have access to those libraries' code to change. How can I remove those targets from being installed?

For testing:

TestingExports.text

cmake_minimum_required(VERSION 3.20 FATAL_ERROR)
project(TestinExports CXX)

add_subdirectory(ThatThing)

file(WRITE main.cc "int main() { }")
add_executable(${PROJECT_NAME} main.cc)
target_link_libraries(${PROJECT_NAME} PRIVATE $<BUILD_INTERFACE:ThatThing>)

install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Config)
install(EXPORT ${PROJECT_NAME}Config DESTINATION lib/cmake)

ThatThing/CMakeLists.txt

cmake_minimum_required(VERSION 3.20 FATAL_ERROR)
project(ThatThing CXX)

add_subdirectory(ThoseLibraries)

file(WRITE that_thing.cc "void Function() { }")
add_library(${PROJECT_NAME} STATIC that_thing.cc)
target_link_libraries(${PROJECT_NAME} PRIVATE ThoseLibraries)

ThatThing/ThoseLibraries/CMakeLists.txt

cmake_minimum_required(VERSION 3.20 FATAL_ERROR)
project(ThoseLibraries CXX)

file(WRITE those_libraries.cc "void AnotherFunction() { }")
add_library(${PROJECT_NAME} STATIC those_libraries.cc)

install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Config)
install(EXPORT ${PROJECT_NAME}Config DESTINATION lib/cmake)

After we build and install we can see that ThoseLibraries is also installed:

$ cmake -B build -DCMAKE_INSTALL_PREFIX=$PWD/install
$ cmake --build build
$ cmake --install build
-- Install configuration: ""
-- Installing: /tmp/export_set/install/lib/libThoseLibraries.a
-- Installing: /tmp/export_set/install/lib/cmake/ThoseLibrariesConfig.cmake
-- Installing: /tmp/export_set/install/lib/cmake/ThoseLibrariesConfig-noconfig.cmake
-- Installing: /tmp/export_set/install/bin/TestinExports
-- Installing: /tmp/export_set/install/lib/cmake/TestinExportsConfig.cmake
-- Installing: /tmp/export_set/install/lib/cmake/TestinExportsConfig-noconfig.cmake

EDIT:

  • Obviously using EXCLUDE_FROM_ALL is completely useless from what I wrote as an example above. I don't want completely that target to be removed from ALL. Also, I needed enough information for my IDE. Mentioned here: https://stackoverflow.com/a/64900982/9248466

  • And overwriting install() is a workaround that doesn't work for me because I also have some rules and options to install the private section of the project. Mentioned here: https://stackoverflow.com/a/43043052/9248466

    • The overwriting install() macro didn't work and cause CMake ignore all the installation rules:
macro(install)
endmacro()

add_subdirectory(ThatThing)

macro(install)
  _install(${ARGV})
endmacro(install)

Ghasem Ramezani
  • 2,683
  • 1
  • 13
  • 32
  • For disable installation commands in the subdirectory use EXCLUDE_FROM_ALL: `add_subdirectory(ThatThing EXCLUDE_FROM_ALL)`. – Tsyvarev Apr 01 '23 at 21:20
  • @Tsyvarev, this is not a duplicate question, unfortunately. Using that useless `EXCLUDE_FROM_ALL` or overwriting the `install` isn't the answer. I will consider this problem as a bug, It should be fixed from CMake. – Ghasem Ramezani Apr 02 '23 at 07:43
  • "I will consider this problem as a bug" - Why do you think that this is a **bug**? In script `ThatThing/ThoseLibraries/CMakeLists.txt` there are `install` commands, and CMake installs thing noted in these commands. That installation is absolutely **not related** with `BUILD_INTERFACE` generator expression, PRIVATE linkage and other things you noted in your question post. The installation is driven purely because of presence of `install` commands. – Tsyvarev Apr 02 '23 at 08:13
  • @Tsyvarev: The problem is here that CMake will just blindly pick all the installation commands even if they don't need them. `PRIVATE` linkage through `BUILD_INTERFACE` should avoid adding installation rules for the linked target. – Ghasem Ramezani Apr 02 '23 at 08:22
  • 1
    You have wrong understanding of installation in CMake. Binaries are installed not because something in the project depends on them. E.g. nothing in your project depends on `TestinExports` executable but it is installed (and you expect it to be installed). Using `BUILD_INTERFACE` affects only on the **content** of the **config file**, which you install with `install(EXPORT)`. It doesn't affect on what files are installed. The `PRIVATE` linkage affects on the config file too, but also affects on the targets which are used in your project. – Tsyvarev Apr 02 '23 at 08:33
  • @Tsyvarev: I tried to use that overwriting approach but it completely ignores all the installation, is that hack still valid for CMake 3.20? I will edit the question for what I have done. – Ghasem Ramezani Apr 02 '23 at 10:53
  • 1
    "is that hack still valid for CMake 3.20?" - Probably, not, the hack with **double** `install` redefinition no longer works. (In the the second redifinition `_install` refers to the first redifinition, not to the original function). However, the approach with `EXCLUDE_FROM_ALL` should work. Not sure why you bother about "I don't want completely that target to be removed from ALL" - The target `ThoseLibraries` will still be built during ALL, because the target `ThatThing` is built during ALL and depends on `ThoseLibraries`. – Tsyvarev Apr 02 '23 at 11:03
  • You may bother about `EXCLUDE_FROM_ALL` making Visual Studio subprojects to be broken. This just means that none of suggested solutions are suitable for you, but your question still not doesn't differentiate itself from the [duplicate](https://stackoverflow.com/questions/35344132). You may put a *bounty* to the duplicate question, so the question could attract more attention from someone who knows more solutions. – Tsyvarev Apr 02 '23 at 11:17
  • 1
    I have redesigned [my approach](https://stackoverflow.com/a/35345933/3440745) with `install` redefinition, so it should work with today's CMake (works for me with CMake 3.22). So you may re-evaluate it for your purposes. – Tsyvarev Apr 02 '23 at 12:39

0 Answers0