C语言—Linux环境下CMake设置库(动态/静态)
1. Yesterday Once More
由于昨日我们在VSCode设置了如何使用CMake构建与编译c语言项目,如有疑问,请看以下链接,今日根据昨天的配置来进一步完成项目的构建。
c语言- 如何构建CMake项目(Linux/VSCode)-CSDN博客
2. 动态静态lib的区别
1. 静态库与动态库对比表
特性 静态库(.a / .lib) 动态库(.so / .dll) 文件扩展名 Linux: .a
Windows:.lib
Linux: .so
Windows:.dll
链接时机 编译时完整链接到可执行文件 运行时动态加载 可执行文件体积 较大(库代码被复制到可执行文件中) 较小(仅记录库的引用) 运行时依赖 无需依赖库文件 必须存在对应的动态库文件 内存占用 每个程序独立占用库的内存 多个程序共享同一份库的内存 更新维护 需重新编译程序 替换库文件即可生效 兼容性 与编译时的库版本完全绑定 需保证接口兼容性(版本管理重要) 性能 略快(无运行时加载开销) 略慢(首次加载需额外时间) 跨平台支持 依赖编译平台 需为不同平台编译对应的动态库 典型应用场景 小型项目、嵌入式系统(无动态加载环境) 大型项目、插件系统、多程序共享库 2. 核心区别详解
1. 链接方式与内存管理
静态库:
在编译时,库的代码会被完整地复制(copy)到最终的可执行文件中。
优点:程序独立运行,无需外部依赖。
缺点:可执行文件体积大,多进程运行时内存占用高(库代码被多次加载)。
动态库:
编译时仅记录库的符号(函数名、变量名等),运行时由操作系统动态加载。
优点:节省磁盘和内存空间,支持热更新(替换库文件无需重新编译程序)。
缺点:部署时需确保目标系统存在正确的库版本。
2. 更新与维护
静态库:
修改库代码后,必须重新编译链接程序才能生效。# 重新编译静态库和程序
gcc -c Exampile.c -o Exampile.o ar rcs libExampile.a Exampile.o gcc main.c -L. -lExampile -o main
动态库:
更新库文件后,只需替换旧库文件,所有依赖该库的程序会自动使用新版本(需接口兼容)。
# 编译动态库gcc -shared -fPIC Exampile.c -o libExampile.so
# 编译程序时链接动态库gcc main.c -L. -lExampile -o main
3. 跨平台与兼容性
静态库:
不同操作系统(如 Linux 和 Windows)需分别编译静态库,且格式不兼容。动态库:
需为每个平台编译对应的动态库(如 Linux 的.so
和 Windows 的.dll
),且需注意符号版本控制(如使用soname
)。1
1
1
3. 在linux环境下设置库与编译文件
主要是更改CMakeLists.txt文件,分五部分
1. 更改source,指定路径下的文件
# 2.需要的依赖库 现在没有 set(SOURCESsrc/foo.csrc/bar.csrc/you.c )
2. 用获取到的路径变量,创建动/静库
# 创建静态库 source获取路径 add_library(mylib_static STATIC ${SOURCES})# 创建动态库,source获取路径 add_library(mylib_shared SHARED ${SOURCES})
3. 对动态库设置rpath
set_target_properties(mylib_shared PROPERTIES# 插入路径为INSTALL_RPATH "\$ORIGIN"BUILD_WITH_INSTALL_RPATH TRUE )
4. 连接动/静库(此时为动态库)
# 链接共享库 target_link_libraries(main mylib_shared)
5. 把之前扫描src下的c文件注释掉
# 扫描src目录下的所有C文件 # aux_source_directory(src SRC_FILES) # add_executable(main ${SRC_FILES})
CMakeLists.txt文件
cmake_minimum_required(VERSION 3.10.0) # CMake版本
project(t1 VERSION 0.1.0 LANGUAGES C) # 项目版本# debug模式
SET(CMAKE_BUILD_TYPE Debug) # debug模式# SET(CMAKE_BUILD_TYPE Release) #Release严格测试模式# 暂时不管,测试
include(CTest)
enable_testing()# 2.需要的依赖库 现在没有
set(SOURCESsrc/foo.csrc/bar.csrc/you.c
)# 3.设置可执行文件与链接库保存的路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)# 4.设置头文件目录使得系统可以找到对应的头文件
include_directories(${PROJECT_SOURCE_DIR}/inc/inner # 自己目录的头文件${EIGEN3_INCLUDE_DIR} # 其他系统目录的头文件 也可以直接写路径/usr/include/eigen3${Pangolin_INCLUDE_DIRS}
)# 5.编译动态库并链接库文件
# 创建静态库 source获取路径
add_library(mylib_static STATIC ${SOURCES})# 创建动态库,source获取路径
add_library(mylib_shared SHARED ${SOURCES})# 设置rpath仅对共享库生效
set_target_properties(mylib_shared PROPERTIES# 插入路径为INSTALL_RPATH "\$ORIGIN"BUILD_WITH_INSTALL_RPATH TRUE
)# 6.生成可执行文件
# 选择需要编译的源文件,有几个文件写几个
add_executable(main src/main.c)# add_executable(my src/main.c src/test.c)
# 扫描src目录下的所有C文件
# aux_source_directory(src SRC_FILES)
# add_executable(main ${SRC_FILES})# 链接共享库
target_link_libraries(main mylib_shared)# 链接静态库
# target_link_libraries(main mylib_static)# 配置cmake项目名称
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})# 配置cmake项目c语言的版本 11
set(CMAKE_C_STANDARD 11)# 设置交叉编译器的位置
set(CMAKE_C_COMPILER gcc)
include(CPack)
点击ctrl+shift+b编译后,执行bin下的mian二进制文件