cmake:POSITION_INDEPENDENT_CODE

set(POSITION_INDEPENDENT_CODE True)

position-independent code (PIC) 编译动态库 .so

position-independent code (PIC):用于生成位置无关代码。位置无关代码,可以理解为代码无绝对跳转,跳转都为相对跳转。生成动态库时,需要加上-fPIC选项。

在 Linux 系统中,动态链接文件称为动态共享对象 (Dynamic Shared Objects,DSO),一般是以.so为扩展名的文件。在 Windows 系统中,动态链接文件称为动态链接库 (Dynamic Linking Library),一般是以 .dll为扩展名。

一般的编译链接命令行为:

gcc -fPIC -shared func.c -o libfunc.so

或者:

gcc -fPIC -c func.c -o func.o
gcc -shared func.o -o libfunc.so

-fPIC选项作用于编译阶段,告诉编译器产生与位置无关代码 (Position-Independent Code)。

-fPIC选项

不添加fPIC也可以生成.so文件,但是对于源文件有要求。因为不加fPIC编译的.so必须要在加载到用户程序的地址空间时重定向到所有表目。所以在它里面不能引用其他代码

编译错误

/*
 ============================================================================
 Name        : function_validation.c
 Author      : Foreverstrong Cheng
 Version     :
 Copyright   : Copyright 2019 ForeverStrong License
 Description : function_validation in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>

int function_validation(int num)
{
    
    
	puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
	num += 1;
	return num;
}


编译通过

/*
 ============================================================================
 Name        : function_validation.c
 Author      : Foreverstrong Cheng
 Version     :
 Copyright   : Copyright 2019 ForeverStrong License
 Description : function_validation in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>

int function_validation(int num)
{
    
    
	// puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
	num += 1;
	return num;
}


不添加fPIC生成的动态库,生产时假定它被加载在地址0处,加载时它会被加载到一个地址(base),需要进行一次重定位(relocation),代码、数据段中所有地址加上这个base的值。这时代码运行时就能使用正确的地址了

-fPIC选项

添加fPIC选项生成的动态库,是位置无关。这样的代码本身就能被放到线性地址空间的任意位置,无需修改就能运行。通常的方法是获取指令指针的值,加上一个偏移得到全局变量/函数的地址。添加 -fPIC选项的源文件对于它引用的函数头文件编写有较宽松的尺度。比如只需要包含声明的函数的头文件,即使没有相应的 C 文件来实现,编译成 .so 库照样可以通过。

添加 -fPIC 选项实现真正意义上的多个进程共享.so 库。多个进程引用同一个-fPIC 动态库时,可以共用内存。这一个库在不同进程中的虚拟地址不同,操作系统会把它们映射到同一块物理内存上。

不添加-fPIC 选项,加载 .so 库时,需要对代码段引用的数据对象重定位,重定位会修改代码段的内容,造成每个使用这个.so 文件代码段的进程在内核里都会生成这个.so 文件代码段的copy,每个 copy 都不一样,取决于这个 .so 文件代码段和数据段内存映射的位置。不添加-fPIC 选项,消耗内存,编译的.so文件的优点是加载速度快。

不能使用 .so 库来静态编译 (-static) 一个可执行程序,会出现错误提示:
attempted static link of dynamic object

/*
 ============================================================================
 Name        : function_validation.c
 Author      : Foreverstrong Cheng
 Version     :
 Copyright   : Copyright 2019 ForeverStrong License
 Description : function_validation in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>

int function_validation(int num)
{
    
    
	puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
	num += 1;
	return num;
}


strong@foreverstrong:~/dbscan_work/fPIC_validation$ pwd
/home/strong/dbscan_work/fPIC_validation
strong@foreverstrong:~/dbscan_work/fPIC_validation$ 
strong@foreverstrong:~/dbscan_work/fPIC_validation$ ll
total 12
drwxrwxr-x  2 strong strong 4096 Feb 27 10:11 ./
drwxrwxr-x 14 strong strong 4096 Feb 27 09:18 ../
-rw-rw-r--  1 strong strong  492 Feb 27 10:11 function_validation.c
strong@foreverstrong:~/dbscan_work/fPIC_validation$ 
strong@foreverstrong:~/dbscan_work/fPIC_validation$ gcc -fPIC -shared function_validation.c -o validation.so
strong@foreverstrong:~/dbscan_work/fPIC_validation$ 
strong@foreverstrong:~/dbscan_work/fPIC_validation$ ls -l
total 12
-rw-rw-r-- 1 strong strong  492 Feb 27 10:11 function_validation.c
-rwxrwxr-x 1 strong strong 8144 Feb 27 10:12 validation.so
strong@foreverstrong:~/dbscan_work/fPIC_validation$

猜你喜欢

转载自blog.csdn.net/zhizhengguan/article/details/115323750