./configure //configure是源代码安装的第一步,主要作用是对即将安装的软件进行配置,检查系统环境是否符合安装软件的依赖关系,然后生成Makefile,为下一步的编译做准备。执行时常用选项 –prefix=/usr 这个表明软件会安装到/usr下面,可通过./configure –help查看帮助
make //执行Makefile中的编译任务,生成.o文件或者.a文件
如果是安装某个软件:一般而言执行make install;安装完之后可以执行make clean来清理中间文件
makedist:将程序和相关的档案包装成一个压缩文件以供发布,以.tar.gz结尾
有空学习下configure文件的编写
-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下面。
博客链接:http://www.tuicool.com/articles/RR3Mvib
#注释
标的(target):目标文件1目标文件2
如
#可以用变量来标识,提高效率;另外$@:代表目前的标的
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