"slippery" Cmake variable inside of generator expression refuses concatenation

23 views Asked by At

Background

I'm trying to add proper cmake install suppport to another project.

Everything seems fine, until I attempt to do the following:

target_include_directories(my_target INTERFACE
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
        $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}>
)

I need to make the include directory when installing another directory below the base include directory (the files are properly populated in that directory) I wouldn't have designed the library to include things like this myself, but I have to maintain backward header compatibility. The problem happens after I try to install my cmake project. When I later after a cmake install attempt to query the INTERFACE_INCLUDE_DIRS from this target, I get strange results

find_package(my_target CONFIG REQUIRED)
get_target_property(MYLIB_INCLUDES my_namespace::my_target INTERFACE_INCLUDE_DIRECTORIES)
message(${MYLIB_INCLUDES })

# prints /my_targetC:/PathToRepos/MyRepo/cmake-build-release/vcpkg_installed/x64-windows-static/include
# But otherwise the install actually works if the target isn't used. 

which... is strange, considering I didn't put it at the beggining And then when I finally try to use this target in another target ie:

add_executable(my_target_exe main.cpp)
target_link_libraries(my_target_exe PRIVATE my_namespace::my_target) 

I get an error too saying:

CMake Error in CMakeLists.txt:
  Imported target "my_namespace::my_target " includes non-existent path

    "/my_target "

  in its INTERFACE_INCLUDE_DIRECTORIES.  Possible reasons include:

  * The path was deleted, renamed, or moved to another location.

  * An install or uninstall procedure did not complete successfully.

  * The installation package was faulty and references files it does not
  provide.

I also tried using PATH in generator expression, also failed ex:

$<INSTALL_INTERFACE: $<PATH:APPEND,${CMAKE_INSTALL_INCLUDEDIR},${PROJECT_NAME}>>

but with stranger result:

$<PATH:APPEND,,my_target>C:/PathToRepos/MyRepo/cmake-build-release/vcpkg_installed/x64-windows-static/include

Question

I... don't know what is going on, it's like the path refuses to be appended to, I don't appear to have this problem anywhere else, but shouldn't I just... be able to append to a path like this? Note I'm using CMake 3.27 (even with older minimum version) and I'm on windows

Sources

here's a full example of my cmakeList (header file contents don't actually matter here, this is a cmake level issue):

cmake_minimum_required(VERSION 3.9)
set(CMAKE_CXX_STANDARD 14)  

project(my_target)

add_library(my_target INTERFACE)

set_target_properties(my_target PROPERTIES
        SOVERSION 1
        VERSION 1.0.0)

target_include_directories(my_target INTERFACE
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
        $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}>
)

set_target_properties(my_target PROPERTIES EXPORT_NAME my_target)

include(CMakePackageConfigHelpers)

include(GNUInstallDirs)

install(TARGETS my_target
        EXPORT my_target_Targets
        INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
        COMPONENT cmy_target_RunTime
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT my_target_RunTIme
        NAMELINK_COMPONENT my_target_Development
        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT my_target_Development
)

set(my_target_INSTALL_CMAKEDIR
        ${CMAKE_INSTALL_DATADIR}/my_target
        CACHE STRING "Path to my_target cmake files"
)

install(EXPORT my_target_Targets
        DESTINATION ${my_target_INSTALL_CMAKEDIR}
        NAMESPACE my_namespace::
        FILE my_targetTargets.cmake
        COMPONENT my_target_Development
)

configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config.cmake.in
        "${CMAKE_CURRENT_BINARY_DIR}/my_targetConfig.cmake"
        INSTALL_DESTINATION ${my_target_INSTALL_CMAKEDIR}
)


get_target_property(my_target_VERSION my_target VERSION)

write_basic_package_version_file(my_targetConfigVersion.cmake VERSION ${my_target_VERSION} COMPATIBILITY SameMajorVersion)

install(FILES
        ${CMAKE_CURRENT_BINARY_DIR}/my_targetConfig.cmake
        ${CMAKE_CURRENT_BINARY_DIR}/my_targetConfigVersion.cmake
        DESTINATION ${my_target_INSTALL_CMAKEDIR}
)


install(FILES
        header_a.h
        header_b.h
        header_c.h
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME})

And here's my cmake.config.in

@PACKAGE_INIT@

include("${CMAKE_CURRENT_LIST_DIR}/my_targetTargets.cmake")

check_required_components(my_target)

And here's my VCPKG port/ registry file port.cmake (note my target is called my-namespace-my-target so I have to specify target path to have it differ, this is to maintain backwards compatibility, and is not really my choice).

#portfile.cmake
vcpkg_from_git(OUT_SOURCE_PATH SOURCE_PATH
        URL https://github.com/[package]
        REF [some ref]
        HEAD_REF [some branch]
)


vcpkg_configure_cmake(
        SOURCE_PATH "${SOURCE_PATH}"
        PREFER_NINJA
)

vcpkg_install_cmake()
vcpkg_fixup_cmake_targets(TARGET_PATH share/my_target)
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")

and the vcpkg.json

//vcpkg.json
{
  "name": "my-namespace-my-target",
  "version-string": "1.0.0",
  "homepage": "https://github.com/[package]",
  "dependencies": [
    {
      "name": "vcpkg-cmake",
      "host": true
    },
    {
      "name": "vcpkg-cmake-config",
      "host": true
    }
  ]
}
0

There are 0 answers