Linux 下源码编译相关知识
2017-08-06 14:28
183 查看
编译库代码的一般过程
./configure //configure是源代码安装的第一步,主要作用是对即将安装的软件进行配置,检查系统环境是否符合安装软件的依赖关系,然后生成Makefile,为下一步的编译做准备。执行时常用选项 –prefix=/usr 这个表明软件会安装到/usr下面,可通过./configure –help查看帮助make //执行Makefile中的编译任务,生成.o文件或者.a文件
如果是安装某个软件:一般而言执行make install;安装完之后可以执行make clean来清理中间文件
makedist:将程序和相关的档案包装成一个压缩文件以供发布,以.tar.gz结尾
有空学习下configure文件的编写
gcc 的一些常用选项
-c编译成目标文件,如gcc –c main.c //将main.c编译成main.o-I头文件的查找路径,如gcc –c main.c –I./inc //头文件的查找路径除默认的以外,还包括./inc
-L库文件的查找路径,如gcc –o main main.o –Ltest (-L./lib-ltest) //libtest.a 或者libtest.so库文件的查找路径除默认之外还包括./lib目录
-MM导出文件的依赖关系(gcc –MM main.c 找出main.c的所依赖的头文件 #include中的内容)
-o生成最终目标
-D宏定义 相当于在C中的#define 如-DPI = 3.14 就相当于在文件里面写语句 #define PI 3.14
动态库
生成:在链接时,用如下选项: -shared –fpic,如gcc–fpic –shared –o libtest.so myalib.c使用:有隐式使用和显示使用,隐式使用就是共享方式,程序一开始运行就调进去,在链接时候用 gcc –o main main.o –L./lib –ltest (像静态库的一样)
显示使用就是在程序中用语句把动态库调进来,用系统调用:dlopen、dlsym、dlerror、dlclose函数,那样在编译链接的时候,不用加上 –L编译选项。不过要加-ldl编译选项
(如果要指定程序行时在./lib目录下找库文件libtest.so,命令如下:gcc -o main main.c -L./lib -ltest -Wl,-rpath./lib
) ,其中,-Wl的意思是,后面的选项直接交给ld程序处理,-rpath选项是说更改搜索路径为后面的参数./lib
LD_LIBRARY_PATH可以指定函数库的查找路径
一些命令(与库有关的)
1、 ld是gcc的链接程序
2、 ldd是查看可执行文件中所依赖的库的程序,如ldd main 可以查看main程序用到了哪些动态库
3、 ldconfig用来更新文件/etc/ld.so.conf的修改生效,更新动态加载库的cache
4、 nm 用来查看.so库中的函数名字, 如nm /lib/libc*.so
问题:
gcc如何生成动态链接库文件?
gcc–shared –fpic –o libc.so main.c hello.c
Tips:
1、 source xxx.sh //表示在当前shell下执行.sh,shell脚本中的设置对当前窗口有效,若不加source,则表示在另一个shell执行,相当于 sh xxx.sh,这样脚本中的变量在当前不生效
2、 .a文件和.lib文件的区别(静态链接)
3、 .so文件和.dll文件的区别(动态链接)
关于问题2 3,(.a文件为静态库,可由ar文件对目标文件归档生成,例如:ar –rc libtest.a a.o b.o;采用gcc 编译工程的时候可以引入相应库文件 gcc hello.c –Ltest –o hello)
.a和.so是Linux下的静态和动态链接文件,.lib和dll是windows下的静态和动态链接文件
静态库、共享库和动态库
参考 http://www.cnblogs.com/likwo/archive/2012/05/09/2492225.html静态库为程序链接时加载,共享库为程序运行时加载(可以给多个程序共享,多个程序维护一份内存副本);动态链接可以在程序运行过程中的任何时间加载,特别适合在函数中加载一些模块和Plugin扩展模块的场合(需要时才加载,否则不需要)。 通过一个API来打开一个函数库dlopen(),寻找符号表void* dlsym(void *handle, char *symbol);,处理错误dlerror()和关闭函数表dlclose()。 例子如下:
#include
#include
#include
int main(int argc, char **argv)
{
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
cosine = dlsym(handle, "cos");
if((error = dlerror()) != NULL)
{
fputs(error, stderr);
exit(1);
}
printf ("%f ", (*cosine)(2.0));
dlclose(handle);
}
如果这个程序名字叫foo.c,那么用下面的命令来编译:
gcc -o foo foo.c -ldl
关于程序库放置的问题
文件系统层次化标准FHS(Filesystem Hierarchy Standard)(http://www.pathname.com/fhs)规定了在一个发行包中大部分的函数库文件应该安装到/usr/lib目录 下,但是如果某些库是在系统启动的时候要加载的,则放到/lib目录下,而那些不是系统本身一部分的库则放到/usr/local/lib下面。Makefile
博客链接:http://www.tuicool.com/articles/RR3Mvib#注释
标的(target):目标文件1目标文件2
<tab>gcc –o 欲建立的执行文件 目标文件1目标文件2 …-L./lib –ltest
如
#可以用变量来标识,提高效率;另外$@:代表目前的标的
main:main.ohaha.o
gcc –o main main.o haha.o –lm
clean:
rm –f main main.o haha.o
编译参数:
-Wall 生成所有警告信息
CFLAGS 表示用于 C 编译器的选项,
CXXFLAGS表示用于 C++ 编译器的选项。
这两个变量实际上涵盖了编译和汇编两个步骤。
CFLAGS: 指定头文件(.h文件)的路径,如:CFLAGS=-I/usr/include -I/path/include。同样地,安装一个包时会在安装路径下建立一个include目录,当安装过程中出现问题时,试着把以前安装的包的include目录加入到该变量中来。
LDFLAGS:gcc 等编译器会用到的一些优化参数,也可以在里面指定库文件的位置。用法:LDFLAGS=-L/usr/lib -L/path/to/your/lib。每安装一个包都几乎一定的会在安装目录里建立一个lib目录。如果明明安装了某个包,而安装另一个包时,它愣是说找不到,可以将那个包的lib路径加入的LDFALGS中试一下。
LIBS:告诉链接器要链接哪些库文件,如LIBS = -lpthread -liconv
简单地说,LDFLAGS是告诉链接器从哪里寻找库文件,而LIBS是告诉链接器要链接哪些库文件。不过使用时链接阶段这两个参数都会加上,所以你即使将这两个的值互换,也没有问题。
有时候LDFLAGS指定-L虽然能让链接器找到库进行链接,但是运行时链接器却找不到这个库,如果要让软件运行时库文件的路径也得到扩展,那么我们需要增加这两个库给"-Wl,R":
LDFLAGS= -L/var/xxx/lib -L/opt/mysql/lib -Wl,R/var/xxx/lib -Wl,R/opt/mysql/lib
如果在执行./configure以前设置环境变量export LDFLAGS="-L/var/xxx/lib -L/opt/mysql/lib-Wl,R/var/xxx/lib -Wl,R/opt/mysql/lib" ,注意设置环境变量等号两边不可以有空格,而且要加上引号(shell的用法)。那么执行configure以后,Makefile将会设置这个选项,链接时会有这个参数,编译出来的可执行程序的库文件搜索路径就得到扩展了。
makefile中经常使用的变量及含义
变量名 | 含义 | 默认值 |
AR | 生成静态库库文件的程序名称 | ar |
AS | 汇编编译器的名称 | as |
CC | C语言编译器的名称 | cc |
CPP | C语言预编译器的名称 | \$(CC) -E |
CXX | C++语言编译器的名称 | g++ |
FC | FORTRAN语言编译器的名称 | f77 |
RM | 删除文件程序的名称 | rm -f |
ARFLAGS | 生成静态库库文件程序的选项 | 无默认值 |
ASFLAGS | 汇编语言编译器的编译选项 | 无默认值 |
CFLAGS | C语言编译器的编译选项 | 无默认值 |
CPPFLAGS | C语言预编译器的编译选项 | 无默认值 |
CXXFLAGS | C++语言编译器的编译选项 | 无默认值 |
FFLAGS | FORTRAN语言编译器的编译选项 | 无默认值 |
makefile 自动化变量
变量 | 含义 |
* | 表示目标文件的名称,不包含目标文件的扩展名 |
+ | 表示所有的依赖文件,这些依赖文件之间以空格分开,按照出现的先后为顺序,其中可能包含重复的依赖文件 |
< | 表示依赖项中第一个依赖文件的名称 |
? | 依赖项中,所有目标文件时间戳晚的依赖文件,依赖文件之间以空格分开 |
@ | 目标项中目标文件的名称 |
^ | 依赖项中,所有不重复的依赖文件,这些文件之间以空格分开 |
设置搜索路径
VPATH =path1:path2:…
如下面内容:
VPATH = add:sub
add_int.o: %.o:%c
$(CC) –c –o $@ $< #第一个依赖文件为add_int.c
make 的搜索路径包含add和sub目录。add_int 规则自动扩展成以下代码
add_int.o: add/add_int.c
递归makefile
cd add &&$(MAKE)
等价于
$(MAKE) –C add
技巧
CURDIR = $(shell pwd) //获取当前目录
makefile中的函数:
获取匹配模式的文件名 wildcard
如$(wildcard *.c) #返回当前目录下所有扩展名为.c的文件列表
模式替换函数 patsubst $(patsubst pattern, replacement, text)
如,需要将c文件替换为.o 的目标文件
$(patsubst %.c, %.o, $(wildcard *.c)) #将当前目录下的所有.c文件替换为.o,作为输出字符串
循环函数foreach
原形 $foreach VAR, LIST, TEXT)
函数的功能为 foreach将 LIST字符串中一个空格分割的单词,先传给临时变量
VAR,然后执行 TEXT表达式, TEXT表达式处理结束后输出。其返回值是空格分割表达式
TEXT的计算结果。
DIRS = sub add ./ FILES = $(foreach dir, $(DIRS), $(wildcard $(dir)/*.c)) #获取目录下的所有C文件
tarball软件的安装
./configure
make clean
make
make install
相关文章推荐
- Linux下编译相关的知识
- linux 编译相关知识积累
- linux下编译make 的相关知识。
- Linux从用户层到内核层系列 - TCP/IP协议栈部分系列7: 基础知识之 - Linux内核源码目录与内核编译选项
- Linux操作系统下如何编译安装源码包软件
- linux下编译libjingle源码(android移植)
- linux下IO相关知识
- Linux 动态库相关知识整理
- 编译Linux源码导致的恐慌
- Linux 下 MySQL 5.5.8 源码编译安装记录
- Apache编译参数详解(linux下手工通过源码编译apache)
- 【Linux学习】 写一个简单的Makefile编译源码获取当前系统时间
- linux中线程的基本相关知识
- Android多线程相关知识总结——源码分析
- 第七章 Linux文件和目录相关的知识 作业题
- Linux下编译Android源码
- Linux环境下源码编译安装MySQL5.5
- Linux下" >/dev/null 2>&1 "相关知识说明
- Linux下caffe源码编译
- linux 相关知识