gcc编译选项fpic/fPIC, fpie/fPIE的说明

-shared; Create a shared library /* 创建共享库时需要添加的编译选项 */
因为共享库的代码都是位置无关的,所以通常还需要添加编译选项-fPIC。

-fPIC; Generate position-independent code if possible (large mode)
-fpic; Generate position-independent code if possible (small mode)
编译共享库时使用;

-fPIE; Generate position-independent code for executables if possible (large mode)
-fpie; Generate position-independent code for executables if possible (small mode)
编译可执行程序时使用
还需要在ld时增加-pie选项才能产生这种代码。即gcc -fpie -pie来编译程序。单独使用哪一个都无法达到效果。

-pie; Create a position independent executable

================================================================================================
关于large mode和small mode

“mcmodel=” Use given x86-64 code model [仅适用于x86_64环境]
-mcmodel=small
Generate code for the small code model: the program and its symbols must be linked in the lower 2 GB of the address space. Pointers are 64 bits. Programs can be statically or dynamically linked. This is the default code model.
[默认值]程序和它的符号必须位于2GB以下的地址空间。指针仍然是64位。程序可以静态连接也可以动态连接。

-mcmodel=kernel
Generate code for the kernel code model. The kernel runs in the negative 2 GB of the address space. This model has to be used for Linux kernel code.
内核运行于2GB地址空间之外。在编译linux内核时必须使用该选项!

-mcmodel=medium
Generate code for the medium model: The program is linked in the lower 2 GB of the address space. Small symbols are also placed there. Symbols with sizes larger than ‘-mlarge-data-threshold’ are put into large data or bss sections and can be located above 2GB. Programs can be statically or dynamically linked.
程序必须位于2GB以下的地址空间,但是它的符号可以位于任何地址空间。程序可以静态连接也可以动态连接。
注意:共享库不能使用这个选项编译!

-mcmodel=large
Generate code for the large model: This model makes no assumptions about addresses and sizes of sections.
对地址空间没有任何限制。

<think>我们正在讨论如何在CMake中添加`-fPIE`编译选项。根据之前的引用内容,我们知道在CMake中可以通过设置`CMAKE_CXX_FLAGS`或`CMAKE_C_FLAGS`来添加编译选项。同时,我们注意到引用[2]中有一个例子,其中包含了`-fPIC`选项,而我们要添加的是`-fPIE`,两者类似。在CMake中,我们可以通过以下方式添加`-fPIE`选项:1.通过直接设置`CMAKE_CXX_FLAGS`和`CMAKE_C_FLAGS`变量来添加,这会影响所有后续的目标(可执行文件和库)。2.如果只想对特定目标添加,可以使用`target_compile_options`命令。另外,需要注意的是,链接时也需要对应的选项(`-pie`或`-no-pie`)。在CMake中,链接选项可以通过`CMAKE_EXE_LINKER_FLAGS`来设置。根据引用[2]中的例子,他们使用了`-no-pie`,所以我们也要注意,如果我们要生成位置无关的可执行文件(PIE),我们需要设置链接器选项`-pie`。但是,现代CMake版本(3.14及以上)提供了更好的方式来处理PIE。###方法1:全局设置(适用于所有目标)在CMakeLists.txt的顶层设置:```cmake#对于C和C++编译器都添加-fPIEset(CMAKE_C_FLAGS"${CMAKE_C_FLAGS}-fPIE")set(CMAKE_CXX_FLAGS"${CMAKE_CXX_FLAGS}-fPIE")#链接时添加-pie选项set(CMAKE_EXE_LINKER_FLAGS"${CMAKE_EXE_LINKER_FLAGS}-pie")```注意:这样设置会影响到该CMakeLists.txt及其子目录中的所有目标。###方法2:针对特定目标设置对于可执行文件目标,我们可以这样设置:```cmakeadd_executable(my_target...)#为该目标添加编译选项target_compile_options(my_targetPRIVATE-fPIE)#设置链接选项target_link_options(my_targetPRIVATE-pie)```或者,为了兼容性,也可以使用老版本的`target_link_libraries`命令来添加链接选项(虽然不推荐):```cmaketarget_link_libraries(my_targetPRIVATE-pie)```###方法3:使用CMake内置功能(推荐)CMake3.14及以上版本支持通过设置`CMAKE_POSITION_INDEPENDENT_CODE`变量来开启位置无关代码(PIC或PIE)。默认情况下,此变量用于设置库的位置无关代码(即PIC),但对于可执行文件,我们可以显式设置PIE。然而,需要注意的是,`CMAKE_POSITION_INDEPENDENT_CODE`默认只影响库(SHARED和MODULE库),不会影响可执行文件。所以对于可执行文件的PIE,我们需要单独设置。在CMake3.14之后,我们可以通过设置目标的`POSITION_INDEPENDENT_CODE`属性来为可执行文件启用PIE:```cmakeadd_executable(my_target...)set_property(TARGETmy_targetPROPERTYPOSITION_INDEPENDENT_CODEON)```这样,CMake会自动添加编译选项(如`-fPIE`)和链接选项(如`-pie`),而且这是跨编译器的(对于GNU编译器是`-fPIE-pie`,对于Clang也是类似的选项,其他编译器会有对应的选项)。###总结推荐使用CMake3.14及以上版本,并设置目标的`POSITION_INDEPENDENT_CODE`属性,这样最简单且跨编译器。如果使用较老的CMake版本,则可以采用全局设置或针对特定目标设置编译和链接选项。注意:如果同时有库和可执行文件,我们通常只为可执行文件开启PIE,库则开启PIC(位置无关代码)即可。但库的PIC可以通过设置`CMAKE_POSITION_INDEPENDENT_CODE`为ON来全局开启,或对每个库设置。###相关问题1.如何在CMake中为静态库添加编译选项?2.CMake中的`target_compile_options`和`CMAKE_CXX_FLAGS`有什么区别?3.如何在CMake中检测编译器是否支持`-fPIE`选项?</think> ### 在 CMake 中添加 `-fPIE` 编译选项的方法 在 CMake 中添加 `-fPIE` 选项有两种主要方式,根据项目需求选择合适的方法: #### 1. 全局设置(推荐) ```cmake # 在项目主 CMakeLists.txt 的 project() 声明后添加 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") # 链接时需添加对应的 -pie 选项 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") ``` #### 2. 特定目标设置 ```cmake add_executable(my_app main.cpp) # 只为该目标添加 -fPIE target_compile_options(my_app PRIVATE -fPIE) # 链接时添加 -pie target_link_options(my_app PRIVATE -pie) ``` #### 3. 条件性添加(跨平台安全) ```cmake if(UNIX AND NOT APPLE) # 适用于 Linux 系统 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") endif() ``` #### 完整示例 CMakeLists.txt ```cmake cmake_minimum_required(VERSION 3.10) project(MyProject) # 添加 -fPIE 选项 (位置无关可执行文件) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") # 添加其他必要选项 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall") add_executable(my_app main.cpp) ``` ### ⚠️ 重要注意事项 1. **与 `-fPIC` 的互斥性**: - `-fPIE` 用于可执行文件 - `-fPIC` 用于共享库 - 同时使用会导致冲突,请确保不同目标使用正确的选项 2. **编译器兼容性**: - GCC 4.5+ 完全支持 `-fPIE` - Clang 3.2+ 支持 - 老版本编译器可改用 `-pie`(但功能不如 `-fPIE` 完整) 3. **现代 CMake 最佳实践**: ```cmake # CMake 3.14+ 可以使用更简洁的方法 set(CMAKE_POSITION_INDEPENDENT_CODE ON) # 自动添加 -fPIE/-fPIC ``` ### 验证方法 构建后检查编译命令: ```bash $ cmake --build . --verbose # 输出中应包含 -fPIE-pie 参数 ``` 使用 `readelf` 验证可执行文件: ```bash $ readelf -d my_app | grep PIE 0x000000000000001e (FLAGS) BIND_NOW, PIE ``` 此方法能确保生成位置无关可执行文件,增强系统安全防护能力,同时保持兼容 ASLR 等现代安全特性[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值