如何用CMake为同一静态库设置不同编译选项适配可执行与共享库
静态库同时支持可执行程序与共享库的CMake配置方案
要满足可执行程序使用非PIC静态库、共享库使用PIC静态库的需求,核心思路是生成两个独立的静态库目标,分别配置不同的编译选项,再对应链接到可执行程序和共享库中。
配置方案(跨平台兼容版)
cmake_minimum_required(VERSION 3.26) project(mve) set(CMAKE_CXX_STANDARD 17) # 1. 生成不带位置无关代码的静态库,供可执行程序使用 add_library(staticLib STATIC library.h library.cpp) # 2. 生成带位置无关代码的静态库,供共享库使用 add_library(staticLibPIC STATIC library.h library.cpp) # 用CMake内置属性设置PIC,跨平台兼容(替代手动加-fPIC) set_target_properties(staticLibPIC PROPERTIES POSITION_INDEPENDENT_CODE ON) # 3. 可执行程序链接非PIC静态库 add_executable(exe main.cpp) target_link_libraries(exe PUBLIC staticLib) # 4. 共享库链接PIC静态库 add_library(sharedLib SHARED lib.h lib.cpp) target_link_libraries(sharedLib PUBLIC staticLibPIC)
关键说明
- 为什么要分两个静态库:共享库要求所有被链接的代码必须是位置无关的(PIC),否则会出现编译错误;而可执行程序直接链接静态库时,不需要PIC,这样能生成性能更优的可执行文件。
- 跨平台兼容性:使用
POSITION_INDEPENDENT_CODE属性而非手动添加-fPIC,CMake会自动根据目标平台生成对应的编译选项(比如Windows无需额外选项,Linux/macOS自动添加对应参数)。
优化编译速度(可选)
如果项目源文件较多,不想重复编译两次,可以用OBJECT库作为中间层,复用编译结果:
cmake_minimum_required(VERSION 3.26) project(mve) set(CMAKE_CXX_STANDARD 17) # 创建OBJECT库,仅编译源文件不生成库 add_library(staticLibObj OBJECT library.h library.cpp) add_library(staticLibObjPIC OBJECT library.h library.cpp) set_target_properties(staticLibObjPIC PROPERTIES POSITION_INDEPENDENT_CODE ON) # 基于OBJECT库生成两个静态库 add_library(staticLib STATIC $<TARGET_OBJECTS:staticLibObj>) add_library(staticLibPIC STATIC $<TARGET_OBJECTS:staticLibObjPIC>) # 后续链接逻辑和之前一致 add_executable(exe main.cpp) target_link_libraries(exe PUBLIC staticLib) add_library(sharedLib SHARED lib.h lib.cpp) target_link_libraries(sharedLib PUBLIC staticLibPIC)
内容的提问来源于stack exchange,提问作者Dimitry
相关产品推荐
相关产品推荐

