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
)


构建和链接静态库和动态库

1.3 构建和链接静态库和动态库

# 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的区别

posted @ 2024-07-11 17:25  guanyubo  阅读(23)  评论(0编辑  收藏  举报