ess-dmsc / event-formation-unit

Implementation of neutron event formation pipeline for ESS
BSD 2-Clause "Simplified" License
9 stars 6 forks source link

Binaries installed via the CMake `install` target do not find all shared libraries. #732

Closed g5t closed 3 months ago

g5t commented 3 months ago

The create_executable CMake function adds the constructed target to the main CMake install target,
https://github.com/ess-dmsc/event-formation-unit/blob/64d0f21b1ab7605085bb5683d8f3968dadaa6a5b/cmake/BuildFunctions.cmake#L64 and is used to add the individual event-formation-unit modules as build targets, e.g., https://github.com/ess-dmsc/event-formation-unit/blob/64d0f21b1ab7605085bb5683d8f3968dadaa6a5b/src/modules/bifrost/CMakeLists.txt#L13

This allows a user to configure, build and install all EFUs (and ancillary binaries) with two CMake commands, e.g.,

cmake -S /path/to/event-formation-unit-repo/ -B /path/to/build-dir -DCMAKE_INSTALL_PREFIX=/path/to/efu-install
cmake --build /path/to/build-dir --target install -j

The binaries may be dependent on a number of Conan-provided shared libraries, and those at /path/to/build-dir/bin are able to load any such Conan libraries as evidenced by the output of, e.g., LD_TRACE_LOADED_OBJECTS=1 /path/to/build-dir/bin/bifrost not indicating any missing shared library files. Unfortunately the same is not true for the installed binaries, e.g. LD_TRACE_LOADED_OBJECTS=1 /path/to/efu-install/bin/bifrost likely indicates that libh5cpp.so.0.5.2 is unknown.

Solution

Fortunately Conan provides a utility to help copy files specified in the [imports] section of a conanfile.txt to a specified directory, which is already populated in the repository's Conan file. https://github.com/ess-dmsc/event-formation-unit/blob/64d0f21b1ab7605085bb5683d8f3968dadaa6a5b/conanfile.txt#L30-L35

The Conan utility is conan imports, which can be called from CMake via execute_process(COMMAND ...), and can even be defined as part of the install target via install(CODE ...)

An appropriate specification will allow the [imports] ./lib destination to be (effectively) defined relative to CMAKE_INSTALL_PREFIX, such that all specified files are copied to /path/to/efu-install/lib in this case.

Outcome

A user who wishes to move all binaries and required libraries to one location can define CMAKE_INSTALL_PREFIX and use the install CMake target. On a combined build/runtime machine, a user might set -DCMAKE_INSTALL_PREFIX=/" to place the binaries in /bin and the libraries in /lib, allowing running any EFU binary without modifying the system PATH or LD_LIBRARY_PATH.

A user that does not invoke the install target will see no difference from the current behavior. Build binaries will still appear in /path/to/build-dir/bin as before with the ability to locate the shared Conan libraries.

Alternate solution

Remove the install targets entirely, since it is not used in the 'normal' deployment.

The Conan file [imports] section already copies library files to, e.g., /path/to/build-dir/lib/.

A user can drop the --target specification from the second CMake command above, then interact directly with the binaries and libraries in the build directory.

g5t commented 3 months ago

The first proposed solution adds the line install(CODE "execute_process(COMMAND conan imports ${CMAKE_SOURCE_DIR}/conanfile.txt -imf ${CMAKE_INSTALL_PREFIX})")

While the second removes all install(...) commands and adds add_custom_target(copylibs COMMAND conan imports ${CMAKE_SOURCE_DIR}/conanfile.txt -imf ${PROJECT_BINARY_DIR}) (I was mistaken about the lib directory already existing as part of the CMake build process.