I try to create an automated build of Scram (CI yaml file, CMakeLists.txt) for Windows. The project uses CMake to create the build files. Building of the project worked already, but the runtime libraries of libxml and boost get not bundled into the package. As compiler mingw64 is used.
Libxml2 will be installed by the CI in a previous step and the install prefix is passed to the scram cmake.
In the CMakeLists.txt libxml is included as:
find_package(LibXml2 REQUIRED)
1
I tried then to install the libxmllibraries as:
install(FILES ${LIBXML2_LIBRARIES} DESTINATION bin)
The problem is that LIBXML2_LIBRARIES points to the .dll.a files in the libxml2_install_prefix/lib and not to the .dll files in the libxml2_install_prefix/bin folder. So only the .dll.a files are bundled into the exe and therefore the application does not work.
2
get_target_property(LIB_XML2_RUNTIME_OUTPUT_DIRECTORY LibXml2::LibXml2 RUNTIME_OUTPUT_DIRECTORY)
get_target_property(LIB_XML2_RUNTIME_OUTPUT_NAME LibXml2::LibXml2 RUNTIME_OUTPUT_NAME)
message(STATUS "XX LIB_XML2_RUNTIME_OUTPUT_DIRECTORY: ${LIB_XML2_RUNTIME_OUTPUT_DIRECTORY}")
message(STATUS "XX LIB_XML2_RUNTIME_OUTPUT_NAME: ${LIB_XML2_RUNTIME_OUTPUT_NAME}")
install (FILES
${LIBXML2_LIBRARIES}
"${LIB_XML2_RUNTIME_OUTPUT_DIRECTORY}/${LIB_XML2_RUNTIME_OUTPUT_NAME}"
DESTINATION bin
COMPONENT libraries)
In this case LIB_XML2_RUNTIME_OUTPUT_NAME and LIB_XML2_RUNTIME_OUTPUT_DIRECTORY are "-NOT_FOUND"
This seems to be a problem because cmake does not know the runtime directory for imported targets (
3
I tried than also install(IMPORTED_RUNTIME_ARTIFACTS LibXml2::LibXml2) which failed with: install IMPORTED_RUNTIME_ARTIFACTS given target "LibXml2::LibXml2" which is not an executable, library, or module.
Also described here: CMake Gitlab repository
4
install(TARGETS LibXml2::LibXml2 RUNTIME_DEPENDENCIES)
failed with the following message: install TARGETS given target "LibXml2::LibXml2" which does not exist.
From CMake Docu:
Note: Imported Targets are supported only if they know the location of their .dll files. An imported SHARED or MODULE library must have IMPORTED_LOCATION set to its .dll file. See the add_library imported libraries section for details. Many Find Modules produce imported targets with the UNKNOWN type and therefore will be ignored.
Probably LibXml2 is imported as unknown and therefore there is no DLL path specified. How to come around this issue and installing the dlls?
5
I tried
install(FILES $<TARGET_RUNTIME_DLLS:LibXml2::LibXml2> DESTINATION bin COMPONENT libraries)
but here I get the error message:
Objects of target "LibXml2::LibXml2" referenced but is not one of the allowed target types (EXECUTABLE, SHARED, MODULE).. Probably because the target is imported and not created by this cmake
6
get_target_property(libxml2_imported_location LibXml2::LibXml2 IMPORTED_LOCATION) points also to the .dll.a file
7 Working Hack (Ugly)
Find out where the .dll is located. For libXml2 it is in the bin folder, for boost it is in the same folder as the .dll.a Use the imported location and replace the path to match the path to the .dll
get_target_property(libxml2_imported_location LibXml2::LibXml2 IMPORTED_LOCATION)
string(REPLACE "/lib/" "/bin/" libxml2_imported_location ${libxml2_imported_location})
string(REPLACE ".dll.a" ".dll" libxml2_imported_location ${libxml2_imported_location})
message(STATUS "XX libxml2_imported_location3 ${libxml2_imported_location}")
install(FILES ${libxml2_imported_location} DESTINATION bin COMPONENT libraries)