gcc生成静态链接库
gcc -c file1.c
gcc -c file2.c
ar crv my_library.a file1.o file2.o
注意,用gcc链接静态库的时候。-l要放在xxx.c后面
-I -l -L
系统头文件路径是:/usr/include。假设引用的头文件不在系统路径下,那么须要用-Ipath来指明头文件的文件夹。
静态链接库的系统路径是:/lib, /usr/lib, /usr/local/lib,引用系统路径下的库文件仅仅要加上-lxxx就可以(假设库名是libxxx.a。那么为-lxxx)。
假设保存静态库的路径不是系统路径,那么须要使用-Lpath来指明库的路径
静态库链接时搜索路径:
1) ld会去找GCC命令中的參数-L
2) 再找gcc的环境变量LIBRARY_PATH
3) 再找内定文件夹 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的
gcc生成动态链接库
gcc -fPIC -shared file1.c file2.c -o my_library.so
动态库假设没有保存在系统库的路径下,那么应用程序在执行时须要通过export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:path来指定动态库的路径
动态库链接时搜索路径:
1) 编译目标代码时指定的动态库搜索路径
2) 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
3) 配置文件/etc/ld.so.conf中指定的动态库搜索路径
4) 默认的动态库搜索路径/lib
5) 默认的动态库搜索路径/usr/lib
有关环境变量:
LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径
LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径
LIBRARY_PATH和LD_LIBRARY_PATH是在链接的时候gcc查找的库文件路径,当程序在执行时查找库文件需通过LD_LIBRARY_PATH或RUN_LIBRARY_PATH指定
强制链接时使用静态链接库
默认情况下,gcc在链接时优先使用动态链接库。仅仅有当动态链接库不存在时才考虑使用静态链接库。假设须要的话。能够在编译时加上-static选项来强制使用静态链接库。
如:gcc -L/path/lib -static -lxxx test.c -o test
gcc參数
warn选项
-Werror
make all warning into errors
-Wall(打开大部分检查。不是所有)
This enables all the warnings about constructions that some users consider questionable, and that are easy to avoid
(or modify to prevent the warning), even in conjunction with macros. This also enables some language-specific warnings
described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options.
-Wall turns on the following warning flags:
-Waddress -Warray-bounds (only with -O2) -Wc++0x-compat -Wchar-subscripts -Wimplicit-int -Wimplicit-function-declaration -Wcomment -Wformat -Wmain (only for C/ObjC and unless -ffreestanding)
-Wmissing-braces -Wnonnull -Wparentheses -Wpointer-sign -Wreorder -Wreturn-type -Wsequence-point -Wsign-compare (only in C++) -Wstrict-aliasing -Wstrict-overflow=1 -Wswitch -Wtrigraphs
-Wuninitialized -Wunknown-pragmas -Wunused-function -Wunused-label -Wunused-value -Wunused-variable -Wvolatile-register-var
-Wextra
This enables some extra warning flags that are not enabled by -Wall.
(This option used to be called -W. The older name is still supported, but
the newer name is more descriptive.)
-g
生成可执行文件里包括gdb调试信息,发生异常时会产生core文件。
-O[level]
指定优化等级,level数字越大优化程序越高。须要的编译时间也越长。默认是-O0,很多程序猿喜欢用-O2,由于他在优化长度,编译时间和代码之间取得一个比較理想的平衡点。
-DMACRO
以字符串”1”定义MACRO宏
假设在源码中使用
#ifdef MACRO
…
#endif
则源码会依据gcc编译选项编译
使用方法參考:http://blog.csdn.net/luckywang1103/article/details/31821857
-DMACRO=DEFN
以字符串”DEFN”定义MACRO宏
-fPIC
-fPIC作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,所有使用相对地址。故而代码能够被载入器载入到内存的不论什么位置。都能够正确的执行。这正是共享库所要求的。共享库被载入时。在内存的位置不是固定的。
-shared
编译源码为动态链接库,如gcc -fPIC -shared test.c -o libtest.so
-E -S -c -o
-E 仅预处理 gcc -E test.c -o test.i
-S 仅预处理和编译 gcc -S test.c -o test.s
-c 预处理、编译和汇编 gcc -c test1.c test2.c生成各自的目标文件test1.o test2.o
-o output_filename 生成指定文件。假设没有指定,生成a.out
-Lpath -Ipath -l
假设代码中仅仅使用c的标准库(libc.a libc.so),不须要指定选项
假设使用了非标准库。且该库文件及库的头文件位于默认文件夹,须要使用-lxxx,比如使用了libm.a或libm.so,须要指定-lm
假设使用了非标准库,且该库文件及库的头文件不在默认文件夹,须要使用-Ipath指定库的头文件所在文件夹,-Lpath指定库文件所在位置,-lxxx指定使用的库
gcc编译属性
unused
它用于函数和变量。表示该函数或变量可能不使用,能够在编译时防止编译器产生“变量未使用”这种警告信息
pack
不进行对齐
align
使用指定的字节数对齐
force
# define force __attribute((force))
表示所定义的变量类型是能够做强制类型转换的,在进行Sparse分析的时候,是不用报告警信息的。
预编译
预编译又称预处理。主要做些代码替换的工作。
虽然在眼下绝大多数编译器都包括了预处理程序,但通常觉得它们是独立于编译器的。预处理过程读入源码,检查包括预处理指令的语句和宏定义,并对源码进行对应的转换。预处理过程还会删除程序中的凝视和多余的空白字符。
预处理指令是以#号开头的代码行。#号必须是该行除了不论什么空白字符外的第一个字符。
#后是指令keyword,在keyword和#号之间同意存在随意个数的空白字符。
以下是部分预处理指令:
# 空指令。无不论什么效果
#include 包括一个源码文件
#define 定义宏
#undef 取消已定义的宏
#if 假设给定条件为真,则编译以下代码
#ifdef 假设宏已经定义。则编译以下代码
#ifndef 假设宏未定义,则编译以下代码
#elif 假设前面的#if给定条件不为真,当前条件为真。则编译以下代码。相当于#elseif
#endif 结束一个#if……#else条件编译块
#error 停止编译并显示错误信息
文件包括
‘#include’预处理指令的作用是在指令处展开被包括的文件。包括能够是多重的,也就是说一个被包括的文件里还能够包括其它文件。
在程序中包括头文件有两种格式:
#include <my.h>
#include "my.h"
为了避免那些仅仅包括一次的头文件被包括多次,能够在头文件里用编译条件来进行控制
#ifndef MY_H
#define MY_H
...
#endif
宏
宏最常见的使用方法是定义代表某个值的全局符号。宏的另外一种使用方法是定义带參数的宏,这种宏能够象函数一样被调用。但它是在调用语句处展开宏,并用调用时的实际參数来取代定义中的形式參数。
#define指令
#运算符
‘#’运算符把跟在其后的參数转换成一个字符串。有时把这种使用方法的#称为字符串化运算符。比如:
#define PASTE(n) "adhfkj"#n
main()
{
printf("%s\n",PASTE(15));
}
输出应该是adhfkj15
##运算符
‘##’运算符用于把參数连接到一起。
预处理程序把出如今##两側的參数合并成一个符号
#define NUM(a,b,c) a##b##c
#define STR(a,b,c) a##b##c
main()
{
printf("%d\n",NUM(1,2,3));
printf("%s\n",STR("aa","bb","cc"));
}
最后程序的输出为:
123
aabbcc\
条件编译指令
条件编译指令将决定那些代码被编译,而哪些是不被编译的。能够依据表达式的值或者某个特定的宏是否被定义来确定编译条件
#if
#endif
#ifdef和#ifndef
#else
#elif
其它一些标准指令
#error指令将使编译器显示一条错误信息,然后停止编译。
#line指令能够改变编译器用来指出警告和错误信息的文件号和行号。
#pragma指令没有正式的定义。编译器能够自己定义其用途。典型的使用方法是禁止或同意某些烦人的警告信息