Linux环境下CMake中为无SONAME的共享库创建导入库目标并实现安装后正确链接的方案
Let's break down how to properly set up the imported foo library target so your bar executable works both during development and after installation. The core issues with your previous attempts were missing library installation steps, incorrect path handling, and not configuring runtime search paths (RPATH).
Step 1: Create the Imported Library Target Correctly
First, define the imported foo target with its absolute path, and mark it as global so it's visible across your project:
add_library(foo SHARED IMPORTED GLOBAL) set_target_properties(foo PROPERTIES # Use the absolute path to avoid CMake converting it to a relative path in internal builds IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/foo.so" )
This avoids the relative path problem from your first attempt because we're explicitly using an absolute path for the source library.
Step 2: Install the Precompiled foo.so
Your original install command only handles the bar executable—you need to copy foo.so to the installation's lib directory too, so it's available where bar expects it:
install(FILES "${CMAKE_SOURCE_DIR}/foo.so" DESTINATION lib PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ )
Step 3: Configure Runtime Search Path (RPATH) for bar
To ensure bar can find foo.so both during development (in your build directory) and after installation, set both build and install RPATH properties:
set_target_properties(bar PROPERTIES # For running bar directly from the build directory: point to the original foo.so location BUILD_RPATH "${CMAKE_SOURCE_DIR}" # For installed bar: use a relative RPATH to find the lib directory (assuming bar is in bin/ and foo.so in lib/) INSTALL_RPATH "$ORIGIN/../lib" # Ensure CMake uses the specified INSTALL_RPATH instead of relying on system paths INSTALL_RPATH_USE_LINK_PATH TRUE )
The $ORIGIN variable is a special token understood by the dynamic linker—it refers to the directory where the bar executable is located. So $ORIGIN/../lib tells the linker to look in the lib directory one level above bar's install location (perfect if you're installing bar to bin/ and foo.so to lib/).
Step 4: Link bar to the foo Target
Finally, link your executable to the imported target as intended:
target_link_libraries(bar PRIVATE foo)
Why Your Previous Attempts Failed
- Method 1: CMake converts absolute paths to relative paths in internal builds, which breaks runtime linking after installation (the relative path no longer points to
foo.so). You also didn't installfoo.soto the target location. - Method 2:
IMPORTED_NO_SONAME ONtells CMake to use-lfoofor linking, but the linker expects libraries namedlibfoo.sowhen using-lflags—your library is namedfoo.so, so this fails. - Method 3: Setting
IMPORTED_SONAMEdoesn't fix the root issue because your library doesn't have an embedded SONAME, and you still didn't handle installation offoo.soor configure RPATH for the installed executable.
Testing the Setup
- Build in
${CMAKE_SOURCE_DIR}/buildas usual:
Runningcd build cmake .. make./barfrom the build directory should work, thanks to theBUILD_RPATHpointing to the originalfoo.so. - Install to an external location:
Runningmake install DESTDIR=/path/to/installation/path/to/installation/bin/barshould now find/path/to/installation/lib/foo.sovia the configuredINSTALL_RPATH.
内容的提问来源于stack exchange,提问作者gnaggnoyil

