cmake target属性POSITION_INDEPENDENT_CODE
-fPIC
-fPIC是gcc编译器的编译参数,以下是-fPIC参数的作用
- 在GCC编译器中, -fPIC 参数是指生成位置无关代码(Position Independent Code,PIC)。位置无关代码是一种可在内存中的任何位置加载和执行的代码。它通常用于动态链接库(shared library)的编译。
- 使用 -fPIC 参数编译代码时,生成的目标文件中的代码和数据引用都使用相对地址,而不是绝对地址。这样,当目标文件被加载到内存中时,它可以被放置在任何可用的内存地址上,而不会发生地址冲突。
- 通过使用位置无关代码,可以使得动态链接库在不同的内存地址空间中被加载和共享,提供更高的灵活性和可移植性。这对于操作系统和应用程序来说是非常重要的,因为它们可以在不同的环境中加载和使用这些动态链接库,而无需担心地址冲突和重新编译的问题。
总结来说, -fPIC 参数的作用是生成位置无关代码,用于编译动态链接库,以提供更高的灵活性和可移植性。
POSITION_INDEPENDENT_CODE
定义 -fPIC 参数最直接的方式是通过CMAKE_CXX_FLAGS或CMAKE_C_FLAGS参数定义,
示例如下,因为它只是clang和gcc才有的参数所以在设置-fPIC参数的时候需要判断编译器
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
endif()
但这样在跨平台项目编译时需要更多的维护工作量,为了让CMakeLists.txt脚本更简洁,减少编译器无关性,通过POSITION_INDEPENDENT_CODE属性来定义-fPIC参数是推荐的方式:
POSITION_INDEPENDENT_CODE是cmake为target定义的属性
可以通过set_property,set_target_properties函数来定义POSITION_INDEPENDENT_CODE属性
## set_property示例
set_property(TARGET my_target
PROPERTY
POSITION_INDEPENDENT_CODE ON
)
## set_target_properties 示例
set_target_properties (my_target
PROPERTIES
POSITION_INDEPENDENT_CODE ON
)
构建和链接静态库和动态库
# set minimum cmake version
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
# project name and language
project(recipe-03 LANGUAGES CXX)
# generate an object library from sources
# OBJECT: 可将给定add_library的列表中的源码编译到目标文件,不将它们归档到静态库中,也不能将它们链接到共享对象中。
# 如果需要一次性创建 静态库和动态库, 那么使用对象库尤其有用
add_library(message-objs
OBJECT
Message.hpp
Message.cpp
)
# this is only needed for older compilers
# but doesn't hurt either to have it
# 设置目标的一些属性来改变它们构建的方式, 保证编译的目标文件与生成位置无关
set_target_properties(message-objs
PROPERTIES
POSITION_INDEPENDENT_CODE 1 # 在GCC编译器中, -fPIC 参数是指生成位置无关代码(Position Independent Code,PIC)
)
# 注意引用对象库的生成器表达式语法: $<TARGET_OBJECTS:message-objs>
add_library(message-shared
SHARED
$<TARGET_OBJECTS:message-objs>
)
set_target_properties(message-shared
PROPERTIES
OUTPUT_NAME "message"
)
# 注意引用对象库的生成器表达式语法: $<TARGET_OBJECTS:message-objs>
add_library(message-static
STATIC
$<TARGET_OBJECTS:message-objs>
)
set_target_properties(message-static
PROPERTIES
OUTPUT_NAME "message"
)
add_executable(hello-world hello-world.cpp)
target_link_libraries(hello-world message-static)
cmake:target属性POSITION_INDEPENDENT_CODE和INTERFACE_POSITION_INDEPENDENT_CODE的区别
多用组合、少用继承
基于接口而非实现进行编程