My project has a core library that is generated using GraalVM’s native-image
tool from Java sources. Around this we wrap some C++ classes and other convenience functionality. The core is built out of CMake’s control, and the C++ layer is a project with a CMakeLists.txt that looks something like this (simplified to remove clutter):
cmake_minimum_required(VERSION 3.27)
project(MyProject)
enable_testing()
set(fullVersion "12.4.0" CACHE STRING "full version X.Y.Z")
set(majorVersion "12" CACHE STRING "major version X")
set(coreLibPath "${CMAKE_CURRENT_SOURCE_DIR}/../cpp/build/Release" CACHE PATH "Path to Graal native-image output")
set(coreIncludePath "${CMAKE_CURRENT_SOURCE_DIR}/../cpp/build/Release" CACHE PATH "Path to Graal native-image output")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN YES)
add_library(mine SHARED
src/lib/mine.cpp
)
set_target_properties(mine PROPERTIES
SOVERSION ${majorVersion}
VERSION ${version}
)
target_sources(mine
PUBLIC
FILE_SET mine_headers
TYPE HEADERS
BASE_DIRS
src/include
FILES
src/include/mine.h
)
include(GenerateExportHeader)
generate_export_header(mine)
target_sources(${saxonc}
PUBLIC
FILE_SET export_header
TYPE HEADERS
BASE_DIRS
${CMAKE_CURRENT_BINARY_DIR}
FILES
${CMAKE_CURRENT_BINARY_DIR}/mine_export.h
)
find_library(CORE_LIB_FILE mine-core
NAMES mine-core
PATHS "${coreLibPath}"
NO_DEFAULT_PATH
)
find_path(CORE_INCLUDE_DIR
NAMES graal_isolate.h mine-core.h
HINTS "${coreIncludePath}"
)
cmake_path(GET CORE_LIB_FILE PARENT_PATH CORE_LIB_DIR)
add_library(MineCore SHARED IMPORTED)
set_target_properties(MineCore PROPERTIES
IMPORTED_LOCATION "${CORE_LIB_FILE}"
)
target_include_directories(MineCore INTERFACE
$<BUILD_INTERFACE:${CORE_INCLUDE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_link_libraries(mine PUBLIC MineCore)
include(GNUInstallDirs)
install(TARGETS mine
EXPORT "MineLib"
FILE_SET common_headers
FILE_SET edition_headers
FILE_SET export_header
)
install(IMPORTED_RUNTIME_ARTIFACTS MineCore)
install(EXPORT "MineLib"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mine
NAMESPACE "MineLib::"
)
This builds fine, but when I install it I end up with just the NAMELINK symlink file from the core lib installed, like this:
lib/libmine.so.12.4.0 # 'real', SONAME is 'libmine.so.12'
lib/libmine.so.12 # symlink to './libmine.so.12.4.0'
lib/libmine.so # symlink to './libmine.so.12'
lib/libmine-core.so # symlink to './libmine-core.so.12'
This is an annoyance. This isn’t one of those situations where we should be importing the generated library file by full filename: we control both the core and the main API libraries, and would like to preserve the ABI claims made by using the SONAME, so that clients could upgrade our library pair without having to recompile when that’s possible.
I know I can use install(DIRECTORY...)
to copy the right files over to CMAKE_INSTALL_LIBDIR
, but that seems like I’m missing something about runtime dependency sets. I’m also pretty sure the generated export config module is not doing the right thing, but I expect that’s for another day…
Has anyone got recommendations for the ‘right’ way to do this?