如何让CMake生成的Makefile在Windows下生成.so后缀共享库
如何让CMake在Windows下生成.so后缀的共享库而非.dll?
现有跨平台项目,主程序通过dlopen()动态加载硬编码文件名libfunc.so的共享库。原手写Makefile可在Linux和Windows平台统一生成libfunc.so,但迁移到CMake构建后,Windows下默认生成libfunc.dll,导致程序因找不到指定文件运行失败(手动重命名.dll为.so后可正常运行)。以下是两种可行的CMake配置方案:
方案1:直接指定输出文件名(推荐)
通过设置共享库目标的属性,强制输出文件名为libfunc.so,跨平台生效:
修改后的CMakeLists.txt:
cmake_minimum_required(VERSION 3.5) project(hello_world) add_library(func SHARED func.c) # 强制设置库的输出名称和后缀 set_target_properties(func PROPERTIES OUTPUT_NAME "libfunc" # 覆盖默认的"func",设置基础名为libfunc SUFFIX ".so" # 强制使用.so后缀,替代Windows默认的.dll ) add_executable(a.out main.c) if(CMAKE_SYSTEM_NAME STREQUAL "Windows") include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}) endif()
说明
- Linux下CMake原本就会生成
libfunc.so,此配置对Linux无影响,仅修改Windows平台的输出规则 - 生成的Windows导入库会变为
libfunc.lib,不影响主程序动态加载逻辑
方案2:构建后重命名文件
若不想修改库的原生生成规则,可添加自定义命令,在构建完成后自动将.dll复制并重命名为.so:
修改后的CMakeLists.txt:
cmake_minimum_required(VERSION 3.5) project(hello_world) add_library(func SHARED func.c) add_executable(a.out main.c) if(CMAKE_SYSTEM_NAME STREQUAL "Windows") include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}) # 构建完成后将dll复制并重命名为so add_custom_command(TARGET func POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:func> # 源文件:生成的func.dll $<TARGET_FILE_DIR:func>/libfunc.so # 目标文件:同目录下的libfunc.so ) endif()
说明
POST_BUILD确保命令在共享库构建完成后执行$<TARGET_FILE:func>和$<TARGET_FILE_DIR:func>是CMake的生成器表达式,自动适配Debug/Release等不同构建目录- 仅在Windows平台执行重命名操作,Linux下保持原有输出
验证效果
两种方案均实现:
- Linux平台:生成
libfunc.so和a.out - Windows平台:生成
libfunc.so(同时保留原生func.dll和func.lib,不干扰运行)和a.exe - 主程序无需修改代码,可直接通过
dlopen("libfunc.so")成功加载共享库
内容的提问来源于stack exchange,提问作者StoneThrow
相关产品推荐
相关产品推荐

