当lib目录同时存在静态与共享C++库时,指定仅链接静态库(Conan+CMake)
Got it, let's break down how to solve this problem where you need to switch from default shared library linking to static linking for specific apps using your prebuilt Conan packages. Here are three reliable approaches, ordered by how aligned they are with Conan's best practices:
1. Add a shared Option to Your Conan Recipe (Recommended)
This is the cleanest approach because it lets you control library type directly via Conan's option system, keeping everything consistent across builds.
First, update your prebuilt library's conanfile.py to include a shared/static toggle:
class MyPrebuiltLibConan(ConanFile): name = "myprebuiltlib" version = "1.0.0" options = {"shared": [True, False]} default_options = {"shared": True} # Keep shared as default for most cases def package(self): # Copy the correct library type based on the option lib_suffix = "*.so" if self.options.shared else "*.a" self.copy(lib_suffix, dst="lib", src="path/to/your/prebuilt/lib") # Don't forget your headers self.copy("*.h", dst="include", src="path/to/your/prebuilt/include") def package_info(self): self.cpp_info.libs = ["mylib"] # If static linking, add any required system dependencies (e.g., pthread) if not self.options.shared: self.cpp_info.system_libs.append("pthread")
Then, in your application's setup, specify the static option:
- Using conanfile.txt:
[requires] myprebuiltlib/1.0.0@youruser/yourchannel [options] myprebuiltlib:shared=False - Using command line:
Runconan install . -o myprebuiltlib:shared=Falsewhen setting up dependencies. - Using conanfile.py (app side):
class MyAppConan(ConanFile): requires = "myprebuiltlib/1.0.0@youruser/yourchannel" options = {"myprebuiltlib:shared": [True, False]} default_options = {"myprebuiltlib:shared": False} def generate(self): cmake = CMakeDeps(self) cmake.generate()
Once set, Conan will package and expose only the static .a files, so your CMake target_link_libraries call will automatically link statically.
2. Force Static Library Lookup in CMake (No Recipe Changes)
If you can't modify the Conan recipe for some reason, you can tweak your app's CMakeLists.txt to prioritize static libraries.
Global override (affects all libraries)
Add this before any find_package calls for your dependencies:
# Tell CMake to look for .a files first set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ${CMAKE_FIND_LIBRARY_SUFFIXES}) find_package(myprebuiltlib REQUIRED) target_link_libraries(your_app PRIVATE myprebuiltlib::myprebuiltlib)
Target-specific override (only for your prebuilt lib)
For more control, directly locate the static library file:
# Manually find static library and headers find_path(MYPREBUILTLIB_INCLUDE_DIR NAMES mylib.h PATHS ${CONAN_INCLUDE_DIRS_MYPREBUILTLIB}) find_library(MYPREBUILTLIB_STATIC_LIB NAMES libmylib.a PATHS ${CONAN_LIB_DIRS_MYPREBUILTLIB}) add_executable(your_app main.cpp) target_include_directories(your_app PRIVATE ${MYPREBUILTLIB_INCLUDE_DIR}) target_link_libraries(your_app PRIVATE ${MYPREBUILTLIB_STATIC_LIB})
Note: This approach is less flexible than the first one, as you're hardcoding library names and paths.
3. Use Conan's default_options_overrides (App-Side Override)
If you're using a conanfile.py for your application, you can globally override the shared option for your dependency without modifying the recipe:
class MyAppConan(ConanFile): requires = "myprebuiltlib/1.0.0@youruser/yourchannel" default_options_overrides = {"myprebuiltlib:shared": False} def generate(self): cmake = CMakeDeps(self) cmake.generate()
This will automatically apply the static option every time you install dependencies for the app, no command-line flags needed.
内容的提问来源于stack exchange,提问作者Amit Jain

