移植中Makefile学习 关键字理解

 http://www.cnblogs.com/ai616818/archive/2011/06/30/2094909.html

 

CFLAGS

RPM_OPT_FLAGS

make %{?_smp_mflags} CC="%{__cc}" CFLAGS="$RPM_OPT_FLAGS -D_GNU_SOU
        RCE" LDFLAGS="" LCRYPT="-lcrypt" -C src

PATH and LDFLAGS and CFLAGS(转载) 

Linux 2010-04-20 01:39:35 阅读84 评论0    字号: 订阅

原文:http://jesserei.blog.163.com/blog/static/1214116892010314113510514/

我安装的路径不是/usr,所以遇到了一些问题。下面就讲一下解决办法。
先来看几个相关的环境变量:PATH、LDFLAGS、CFLAGS

PATH:大家应该都很熟悉。安装一个包后可能会在安装目录建立一个bin目录,里面都是些可执行程序,为了让系统能找到这些程序,就需要我们把该路径加入到PATH环境变量中。下面会讲到如何加入。

LDFLAGS:gcc 等编译器会用到的一些优化参数,也可以在里面指定库文件的位置。用法:LDFLAGS=“-L/usr/lib -L/path/to/your/lib”。每安装一个包都几乎一定的会在安装目录里建立一个lib目录。如果你明明安装了某个包,而安装另一个包时,它 愣是说找不到,那就把那个包的lib路径加入的LDFALGS中试一下吧。

CFLAGS: 和LDFLAGS类似,只不过要向里加如的是头文件(.h文件)的路径,如:CFLAGS=“-I/usr/include -I/path/to/your/include”。同样地,安装一个包时会在安装路径下建立一个include目录,当安装过程中出现问题时,试着把以 前安装的包的include目录加入到该变量中来。

那如何在那些变量中加入这些路径呢?以PATH变量为例。
一种方法是:直接在命令行下:
$ PATH="$PATH:/path/to/your/bin:/another/path/to/bin"
$ export PATH
这种方法的好处是方便,立即生效,缺点是把当前会话或shell关了之后就失效了,下次还得运行一遍。

另一种方法是:把下面的两行内容加入到~/.bashrc文件中,如果想让其影响到整个系统而不仅仅是当前用户,就把下面的内容加入到/etc/bash.bashrc(记得有的系统是/etc/bashrc这个文件)

PATH and LDFLAGS and CFLAGS - Bob - 黄宝的博客PATH="$PATH:/path/to/your/bin:/another/path/to/bin"
PATH and LDFLAGS and CFLAGS - Bob - 黄宝的博客export PATH

然后,重新启动shell即可。

需要注意的是,PATH变量的分隔符是:号,其他的是空格,
所以LDFLAGS应该是这样:
LDFLAGS=“$LDFLAGS -L/path/to/lib -L/path/to/lib”
CFLAGS应该是这样:
CFLAGS=“$CFLAGS -I/path/to/iclude -I/path/to/include”

  评论这张
转发至微博
0   分享到:         
阅读(84)| 评论(0)| 引用 (0) |举报

makefile的 LDFLAGS 选项和LIBS

1、LDFLAGS是选项,LIBS是要链接的

都是喂给ld的,只不过一个是告诉ld怎么吃,一个是吃什么

Additional flags to  the linker (LDFLAGS) 

If you want to pass flags to the linker, both in the configure step and the build step, you can do this in two ways. Either set LDFLAGS or LIBS. The difference between the two is that LIBS will be appended附加 to the command line, while LDFLAGS come earlier. LDFLAGS is pre-loaded with rpath settings for ELF machines depending on the setting of USE_IMAKE or the inclusion of mk/x11.buildlink3.mk. As with CFLAGS, if you do not wish to override these settings, use the += operator:

LDFLAGS+= -your -linkerflags

3、makefile 

 “$(CXX) –c $(CPPFLAGS) $(CFLAGS)这里的-c选择的作用是:

编译和汇编,但不链接//Compile and assemble, but do not link

4、关于makefile中链接库LIB的使用

 只是在链接生成可执行文件时用到,编译生成目标文件时并不需要用到。

比如socket编程,在编译链接时需要加上-lsocket.但生成目标文件时并不需要。

下面是一个Makefile的示例。

# +---------------------------------------------+
# |     Makefile of MoReciver(version 2)          |
# |     begin : Wen 28 April 2008                |
# +---------------------------------------------+
BINDIR=$(HOME)/bin2
BINDIR3=$(HOME)/bin3
OBJS      =   FDThread.o FDString.o MoRecvListener.o MoRecvHandler.o \
   MoRecvServer.o
TARGET    =   MoReciver
CC        = g++ 
LIBS      = -lsocket -lnsl -lpthread -lc -lclntsh -lwtc9 -liconv
#INCDIR   = -I. -I$(ORACLE_HOME)/network/public
CFLAGS    = -g -Wall -O2 -DSOLARIS 
#$(INCDIR)
CXXFLAGS = $(CFLAGS)
all:$(TARGET)
# ----------- Application --------------------------------------------------
$(TARGET): $(OBJS)
$(CC) $(CXXFLAGS) -o $@ $(OBJS) $(LIBS)
@echo "### $@ loaded ###\n"

# ----------- OBJS ---------------------------------------------------------
.cpp.o:
$(CC) ${CXXFLAGS} -c -o $@ $< #$(LIBS)
# ----------- CLEAN --------------------------------------------------------

clean:
rm -rf *.o core a.out   cxx_repository ${TARGET} SunWS_cache

为了您的安全,请只打开来源可靠的网址

打开网站    取消

 
 

  [金步国]深入理解软件包的配置、编译与安装 收藏
版权声明
本文作者是一位自由软件爱好者,所以本文虽然不是软件,但是本着 GPL 的精神发布。任何人都可以自由使用、转载、复制和再分发,但必须保留作者署名,亦不得对声明中的任何条款作任何形式的修改,也不得附加任何其它条件。您可 以自由链接、下载、传播此文档,但前提是必须保证全文完整转载,包括完整的版权信息和作译者声明。

其他作品
本文作者十分愿意与他人共享劳动成果,如果你对我的其他翻译作品或者技术文章有兴趣,可以在如下位置查看现有作品的列表:

•金步国作品列表
BUG报告,切磋与探讨
由于作者水平有限,因此不能保证作品内容准确无误,请在阅读中自行鉴别。如果你发现了作品中的错误,请您来信指出,哪怕是错别字也好,任何提高作品 质量的建议我都将虚心接纳。如果你愿意就作品中的相关内容与我进行进一步切磋与探讨,也欢迎你与我联系。联系方式:Email: csfrank@citiz.net ; QQ: 70171448 ; MSN: csfrank122@hotmail.com


--------------------------------------------------------------------------------

前言
从源代码安装过软件的朋友一定对 ./configure && make && make install 安装三步曲非常熟悉了。然而究竟这个过程中的每一步幕后都发生了些什么呢?本文将带领你一探究竟。深入理解这个过程将有助于你在LFS的基础上玩出自己的 花样来。不过需要说明的是本文对 Makefile 和 make 的讲解是相当近视和粗浅的,但是对于理解安装过程来说足够了。

概述
用一句话来解释这个过程就是:

根据源码包中 Makefile.in 文件的指示,configure 脚本检查当前的系统环境和配置选项,在当前目录中生成 Makefile 文件(还有其它本文无需关心的文件),然后 make 程序就按照当前目录中的 Makefile 文件的指示将源代码编译为二进制文件,最后将这些二进制文件移动(即安装)到指定的地方(仍然按照 Makefile 文件的指示)。

由此可见 Makefile 文件是幕后的核心。要深入理解安装过程,必须首先对 Makefile 文件有充分的了解。本文将首先讲述 Makefile 与 make ,然后再讲述 configure 脚本。并且在讲述这两部分内容时,提供了尽可能详细的、可以运用于实践的参考资料。

Makefile 与 make
用一句话来概括Makefile 与 make 的关系就是:
Makefile 包含了所有的规则和目标,而 make 则是为了完成目标而去解释 Makefile 规则的工具。

make 语法
首先看看 make 的命令行语法:

make [options] [targets] [VAR=VALUE]...

[options]是命令行选项,可以用 make --help 命令查看全部,[VAR=VALUE]是在命令行上指定环境变量,这两个大家都很熟悉,将在稍后详细讲解。而[targets]是什么呢?字面的意思是" 目标",也就是希望本次 make 命令所完成的任务。凭经验猜测,这个[targets]大概可以用"ckeck","install"之类(也就是常见的测试和安装命令)。但是它到底是 个啥玩意儿?不带任何"目标"的 make 命令是什么意思?为什么在安装 LFS 工具链中的 Perl-5.8.8 软件包时会出现"make perl utilities"这样怪异的命令?要回答这些问题必须首先理解 Makefile 文件中的"规则"。

Makefile 规则
Makefile 规则包含了文件之间的依赖关系和更新此规则目标所需要的命令。

一个简单的 Makefile 规则是这样写的:

TARGET : PREREQUISITES 

              COMMAND

TARGET
规则的目标。也就是可以被 make 使用的"目标"。有些目标可以没有依赖而只有动作(命令行),比如"clean",通常仅仅定义一系列删除中间文件的命令。同样,有些目标可以没有动作而只有依赖,比如"all",通常仅仅用作"终极目标"。
PREREQUISITES
规则的依赖。通常一个目标依赖于一个或者多个文件。
COMMAND
规则的命令行。一个规则可以有零个或多个命令行。
OK! 现在你明白[targets]是什么了,原来它们来自于 Makefile 文件中一条条规则的目标(TARGET)。另外,Makefile文件中第一条规则的目标被称为"终极目标",找第一个。。。也就是你省略[targets]参数时的目标(通常为"all")。

当你查看一个实际的 Makefile 文件时,你会发现有些规则非常复杂,但是它都符合规则的基本格式。此外,Makefile 文件中通常还包含了除规则以外的其它很多东西,不过本文只关心其中的变量。

Makefile 变量
Makefile 中的"变量"更像是 C 语言中的宏,代表一个文本字符串(变量的值),可以用于规则的任何部分。变量的定义很简单:VAR=VALUE;变量的引用也很简单:$(VAR) 或者 ${VAR}。变量引用的展开过程是严格的文本替换过程,就是说变量值的字符串被精确的展开在变量被引用的地方。比如,若定义:VAR=c,那么,"$ (VAR) $(VAR)-$(VAR) VAR.$(VAR)"将被展开为"c c-c VAR.c"。

虽然在 Makefile 中可以直接使用系统的环境变量,但是也可以通过在 Makefile 中定义同名变量来"遮盖"系统的环境变量。另一方面,我们可以在调用 make 时使用 -e 参数强制使系统中的环境变量覆盖 Makefile 中的同名变量,除此之外,在调用 make 的命令行上使用 VAR=VALUE 格式指定的环境变量也可以覆盖 Makefile 中的同名变量。(setenv,然后Makefile中使用变量)

Makefile 实例
下面看一个简单的、实际的Makefile文件:

CC=gcc
CPPFLAGS=
CFLAGS=-O2 -pipe
LDFLAGS=-s
PREFIX=/usr

all : prog1 prog2

prog1 : prog1.o
$(CC) $(LDFLAGS) -o prog1 prog1.o

prog1.o : prog1.c
$(CC) -c $(CFLAGS) prog1.c

prog2 : prog2.o
$(CC) $(CFLAGS) $(LDFLAGS) -o prog2 prog2.o

prog2.o : prog2.c
$(CC) -c $(CPPFLAGS) $(CFLAGS) prog2.c

clean :
rm -f *.{o,a} prog{1,2}

install : prog1 prog2
if ( test ! -d $(PREFIX)/bin ) ;

    then mkdir -p $(PREFIX)/bin ;

fi
cp -f prog1 $(PREFIX)/bin/prog1
cp -f prog2 $(PREFIX)/bin/prog2

check test : prog1 prog2
prog1 < sample1.ref > sample1.rz
prog1 < sample2.ref > sample3.rz
cmp sample1.ok sample1.rz
cmp sample2.ok sample2.rz

从中可以看出,make 与 make all 以及 make prog1 prog2 三条命令其实是等价的。而常用的 make check 和 make install 也找到了归属。同时我们也看到了 Makefile 中的各种变量是如何影响编译的。针对这个特定的 Makefile ,你甚至可以省略安装三步曲中的 make 命令而直接使用 make install 进行安装。

同样,为了使用自定义的编译参数编译 prog2 ,我们可以使用 make prog2 CFLAGS="-O3 -march=athlon64" 或 CFLAGS="-O3 -march=athlon64" && make -e prog2 命令达到此目的。

Makefile 惯例
下面是Makefile中一些约定俗成的目标名称及其含义:

all
编译整个软件包,但不重建任何文档。一般此目标作为默认的终极目标。此目标一般对所有源程序的编译和连接使用"-g"选项,以使最终的可执行程序中包含调试信息。可使用 strip 程序去掉这些调试符号。
clean
清除当前目录下在 make 过程中产生的文件。它不能删除软件包的配置文件,也不能删除 build 时创建的那些文件。
distclean
类似于"clean",但增加删除当前目录下的的配置文件、build 过程产生的文件。
info
产生必要的 Info 文档。
check 或 test
完成所有的自检功能。在执行检查之前,应确保所有程序已经被创建(但可以尚未安装)。为了进行测试,需要实现在程序没有安装的情况下被执行的测试命令。
install
完成程序的编译并将最终的可执行程序、库文件等拷贝到指定的目录。此种安装一般不对可执行程序进行 strip 操作。
install-strip
和"install"类似,但是会对复制到安装目录下的可执行文件进行 strip 操作。
uninstall
删除所有由"install"安装的文件。
installcheck
执行安装检查。在执行安装检查之前,需要确保所有程序已经被创建并且被安装。
installdirs
创建安装目录及其子目录。它不能更改软件的编译目录,而仅仅是创建程序的安装目录。
下面是 Makefile 中一些约定俗成的变量名称及其含义:

这些约定俗成的变量分为三类。第一类代表可执行程序的名字,例如 CC 代表编译器这个可执行程序;第二类代表程序使用的参数(多个参数使用空格分开),例如 CFLAGS 代表编译器执行时使用的参数(一种怪异的做法是直接在 CC 中包含参数);第三类代表安装目录,例如 prefix 等等,含义简单,下面只列出它们的默认值。

AR   函数库打包程序,可创建静态库.a文档。默认是"ar"。
AS   汇编程序。默认是"as"。
CC   C编译程序。默认是"cc"。
CXX  C++编译程序。默认是"g++"。
CPP  C/C++预处理器。默认是"$(CC) -E"。
FC   Fortran编译器。默认是"f77"。
PC   Pascal语言编译器。默认是"pc"。
YACC Yacc文法分析器。默认是"yacc"。

 ARFLAGS     函数库打包程序的命令行参数。默认值是"rv"。
ASFLAGS     汇编程序的命令行参数。
CFLAGS      C编译程序的命令行参数
CXXFLAGS    C++编译程序的命令行参数。
CPPFLAGS    C/C++预处理器的命令行参数。
FFLAGS      Fortran编译器的命令行参数。
PFLAGS      Pascal编译器的命令行参数。
YFLAGS      Yacc文法分析器的命令行参数。
LDFLAGS     链接器的命令行参数

prefix前缀      /usr/local
exec_prefix $(prefix)

bindir      $(exec_prefix)/bin

sbindir     $(exec_prefix)/sbin

libexecdir  $(exec_prefix)/libexec

datadir     $(prefix)/share

sysconfdir  $(prefix)/etc

sharedstatedir $(prefix)/com

localstatedir  $(prefix)/var

libdir      $(exec_prefix)/lib

infodir     $(prefix)/info

includedir  $(prefix)/include

oldincludedir  $(prefix)/include

mandir      $(prefix)/man

srcdir      需要编译的源文件所在的目录,无默认值

最后说说 make 的命令行选项(以Make-3.81版本为准):

-B, --always-make
无条件的重建所有规则的目标,而不是根据规则的依赖关系决定是否重建某些目标文件。
-C DIR, --directory=DIR
在做任何动作之前先切换工作目录到 DIR ,然后再执行 make 程序。
-d
在 make 执行过程中打印出所有的调试信息。包括:make 认为那些文件需要重建;那些文件需要比较它们的最后修改时间、比较的结果;重建目标所要执行的命令;使用的隐含规则等。使用该选项我们可以看到 make 构造依赖关系链、重建目标过程的所有信息,它等效于"-debug=a"。
--debug=FLAGS
在 make 执行过程中打印出调试信息。FLAGS 用于控制调试信息级别:
a
输出所有类型的调试信息
b
输出基本调试信息。包括:那些目标过期、是否重建成功过期目标文件。
v
除 b 级别以外还包括:解析的 makefile 文件名,不需要重建文件等。
i
除 b 级别以外还包括:所有使用到的隐含规则描述。
j
输出所有执行命令的子进程,包括命令执行的 PID 等。
m
输出 make 读取、更新、执行 makefile 的信息。
-e, --environment-overrides
使用系统环境变量的定义覆盖 Makefile 中的同名变量定义
-f FILE, --file=FILE, --makefile=FILE
将 FILE 指定为 Makefile 文件。
-h, --help
打印帮助信息。
-i, --ignore-errors
忽略规则命令执行过程中的错误。
-I DIR, --include-dir=DIR
指定包含 Makefile 文件的搜索目录。使用多个"-I"指定目录时,搜索目录按照指定顺序进行。
-j [N], --jobs[=N]
指定并行执行的命令数目。在没有指定"-j"参数的情况下,执行的命令数目将是系统允许的最大可能数目。
-k, --keep-going
遇见命令执行错误时不终止 make 的执行,也就是尽可能执行所有的命令,直到出现致命错误才终止。
-l [N], --load-average[=N], --max-load[=N]
如果系统负荷超过 LOAD(浮点数),不再启动新任务。
-L, --check-symlink-times
同时考察符号连接的时间戳和它所指向的目标文件的时间戳,以两者中较晚的时间戳为准。
-n, --just-print, --dry-run, --recon
只打印出所要执行的命令,但并不实际执行命令。
-o FILE, --old-file=FILE, --assume-old=FILE
即使相对于它的依赖已经过期也不重建 FILE 文件;同时也不重建依赖于此文件任何文件。
-p, --print-data-base
命令执行之前,打印出 make 读取的 Makefile 的所有数据(包括规则和变量的值),同时打印出 make 的版本信息。如果只需要打印这些数据信息,可以使用 make -qp 命令。查看 make 执行前的预设规则和变量,可使用命令 make -p -f /dev/null 。
-q, --question
"询问模式"。不运行任何命令,并且无输出,只是返回一个查询状态。返回状态为 0 表示没有目标需要重建,1 表示存在需要重建的目标,2 表示有错误发生。
-r, --no-builtin-rules
取消所有内嵌的隐含规则,不过你可以在 Makefile 中使用模式规则来定义规则。同时还会取消所有支持后追规则的隐含后缀列表,同样我们也可以在 Makefile 中使用".SUFFIXES"定义我们自己的后缀规则。此选项不会取消 make 内嵌的隐含变量。
-R, --no-builtin-variables
取消 make 内嵌的隐含变量,不过我们可以在 Makefile 中明确定义某些变量。注意,此选项同时打开了"-r"选项。因为隐含规则是以内嵌的隐含变量为基础的。
-s, --silent, --quiet
不显示所执行的命令。
-S, --no-keep-going, --stop
取消"-k"选项。在递归的 make 过程中子 make 通过 MAKEFLAGS 变量继承了上层的命令行选项。我们可以在子 make 中使用"-S"选项取消上层传递的"-k"选项,或者取消系统环境变量 MAKEFLAGS 中的"-k"选项。
-t, --touch
更新所有目标文件的时间戳到当前系统时间。防止 make 对所有过时目标文件的重建。
-v, --version
打印版本信息。
-w, --print-directory
在 make 进入一个目录之前打印工作目录。使用"-C"选项时默认打开这个选项。
--no-print-directory
取消"-w"选项。可以是用在递归的 make 调用过程中,取消"-C"参数将默认打开"-w"。
-W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE
设定 FILE 文件的时间戳为当前时间,但不改变文件实际的最后修改时间。此选项主要是为实现了对所有依赖于 FILE 文件的目标的强制重建。
--warn-undefined-variables
在发现 Makefile 中存在对未定义的变量进行引用时给出告警信息。此功能可以帮助我们调试一个存在多级套嵌变量引用的复杂 Makefile 。但是:我们建议在书写 Makefile 时尽量避免超过三级以上的变量套嵌引用。
configure
此阶段的主要目的是生成 Makefile 文件,是最关键的运筹帷幄阶段,基本上所有可以对安装过程进行的个性化调整都集中在这一步。

configure 脚本能够对 Makefile 中的哪些内容产生影响呢?基本上可以这么说:所有内容,包括本文最关心的 Makefile 规则与 Makefile 变量。那么又是哪些因素影响着最终生成的 Makefile 文件呢?答曰:系统环境和配置选项。

配置选项的影响是显而易见的。但是"系统环境"的概念却很宽泛,包含很多方面内容,不过我们这里只关心环境变量,具体说来就是将来会在 Makefile 中使用到的环境变量以及与 Makefile 中的变量同名的环境变量。

通用 configure 语法
在进一步讲述之前,先看看 configure 脚本的语法,一般有两种:

configure [OPTIONS] [VAR=VALUE]...

configure [OPTIONS] [HOST]

不管是哪种语法,我们都可以用 configure --help 查看所有可用的[OPTIONS],并且通常在结尾部分还能看到这个脚本所关心的环境变量有哪些。在本文中将对这两种语法进行合并,使用下面这种简化的语法:

configure [OPTIONS]

这种语法能够被所有的 configure 脚本所识别,同时也能通过设置环境变量和使用特定的[OPTIONS]完成上述两种语法的一切功能。

通用 configure 选项
虽然每个软件包的 configure 脚本千差万别,但是它们却都有一些共同的选项,也基本上都遵守相同的选项语法。

脚本自身选项
--help
显示帮助信息。
--version
显示版本信息。
--cache-file=FILE
在FILE文件中缓存测试结果(默认禁用)。
--no-create
configure脚本运行结束后不输出结果文件,常用于正式编译前的测试。
--quiet, --silent
不显示脚本工作期间输出的"checking ..."消息。
目录选项
--srcdir=DIR
源代码文件所在目录,默认为configure脚本所在目录或其父目录。
--prefix=PREFIX
体系无关文件的顶级安装目录PREFIX ,默认值一般是 /usr/local 或 /usr/local/pkgName
--exec-prefix=EPREFIX
体系相关文件的顶级安装目录EPREFIX ,默认值一般是 PREFIX
--bindir=DIR
用户可执行文件的存放目录DIR ,默认值一般是 EPREFIX/bin
--sbindir=DIR
系统管理员可执行目录DIR ,默认值一般是 EPREFIX/sbin
--libexecdir=DIR
程序可执行目录DIR ,默认值一般是 EPREFIX/libexec
--datadir=DIR
通用数据文件的安装目录DIR ,默认值一般是 PREFIX/share
--sysconfdir=DIR
只读的单一机器数据目录DIR ,默认值一般是 PREFIX/etc
--sharedstatedir=DIR
可写的体系无关数据目录DIR ,默认值一般是 PREFIX/com
--localstatedir=DIR
可写的单一机器数据目录DIR ,默认值一般是 PREFIX/var
--libdir=DIR
库文件的安装目录DIR ,默认值一般是 EPREFIX/lib
--includedir=DIR
C头文件目录DIR ,默认值一般是 PREFIX/include
--oldincludedir=DIR
非gcc的C头文件目录DIR ,默认值一般是 /usr/include
--infodir=DIR
Info文档的安装目录DIR ,默认值一般是 PREFIX/info
--mandir=DIR
Man文档的安装目录DIR ,默认值一般是 PREFIX/man
体系结构选项
玩交叉编译的朋友对这些选项已经很熟悉了,并且对于通常的交叉编译情况而言,HOST == BUILD != TARGET 。但是对于不使用交叉编译的朋友也不必担心,将它们三个都设为相同即可。

--host=HOST
运行工具链的机器,默认是 config.guess 脚本的输出结果。
--build=BUILD
用来建立工具链的机器,默认值是 HOST
--target=TARGET
工具链所生成的二进制代码最终运行的机器,默认值是 HOST
特性选项
--enable-FEATURE
启用FEATURE特性
--disable-FEATURE
禁用FEATURE特性
--with-PACKAGE[=DIR]
启用附加软件包PACKAGE,亦可同时指定PACKAGE所在目录DIR
--without-PACKAGE
禁用附加软件包PACKAGE
通用环境变量
除了上述通用的选项外,下列环境变量影响着最终生成的 Makefile 文件:

CPP
C预处理器命令
CXXCPP
C++预处理器命令
CPPFLAGS
C/C++预处理器命令行参数
CC
C编译器命令
CFLAGS
C编译器命令行参数
CXX
C++编译器命令
CXXFLAGS
C++编译器命令行参数
LDFLAGS
连接器命令行参数
至于设置这些环境变量的方法,你可以将它们 export 为全局变量在全局范围内使用,也可以在命令行上使用 [VAR=VALUE]... configure [OPTIONS] 的语法局部使用。此处就不详细描述了。


--------------------------------------------------------------------------------

看完上述内容以后,不用多说你应当自然而然的明白该进行如何对自己的软件包进行定制安装了。祝你好运!


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/hanyu1980/archive/2008/05/16/2452509.aspx

 

 

编译选项 CC 与 CXX CPPFLAGS CFLAGS 与 CXXFLAGS LDFLAGS

编译选项

让我们先看看 Makefile 规则中的编译命令通常是怎么写的。

大多数软件包遵守如下约定俗成的规范:

#1,首先从源代码生成目标文件(预处理,编译,汇编),"-c"选项表示不执行链接步骤。
$(CC) $(CPPFLAGS) $(CFLAGS) example.c   -c   -o example.o
#2,然后将目标文件连接为最终的结果(连接),"-o"选项用于指定输出文件的名字。
$(CC) $(LDFLAGS) example.o   -o example
#有一些软件包一次完成四个步骤:
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) example.c   -o example
当然也有少数软件包不遵守这些约定俗成的规范,比如:
#1,有些在命令行中漏掉应有的Makefile变量(注意:有些遗漏是故意的)
$(CC) $(CFLAGS) example.c    -c   -o example.o
$(CC) $(CPPFLAGS) example.c  -c   -o example.o
$(CC) example.o   -o example
$(CC) example.c   -o example
#2,有些在命令行中增加了不必要的Makefile变量
$(CC) $(CFLAGS) $(LDFLAGS) example.o   -o example
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) example.c   -c   -o example.o
当然还有极个别软件包完全是"胡来":乱用变量(增加不必要的又漏掉了应有的)者有之,不用$(CC)者有之,不一而足.....

尽管将源代码编译为二进制文件的四个步骤由不同的程序(cpp,gcc/g++,as,ld)完成,但是事实上 cpp, as, ld 都是由 gcc/g++ 进行间接调用的。换句话说,控制了 gcc/g++ 就等于控制了所有四个步骤。从 Makefile 规则中的编译命令可以看出,编译工具的行为全靠 CC/CXX CPPFLAGS CFLAGS/CXXFLAGS LDFLAGS 这几个变量在控制。当然理论上控制编译工具行为的还应当有 AS ASFLAGS ARFLAGS 等变量,但是实践中基本上没有软件包使用它们。

那么我们如何控制这些变量呢?一种简易的做法是首先设置与这些 Makefile 变量同名的环境变量并将它们 export 为全局,然后运行 configure 脚本,大多数 configure 脚本会使用这同名的环境变量代替 Makefile 中的值。但是少数 configure 脚本并不这样做(比如GCC-3.4.6和Binutils-2.16.1的脚本就不传递LDFLAGS),你必须手动编辑生成的 Makefile 文件,在其中寻找这些变量并修改它们的值,许多源码包在每个子文件夹中都有 Makefile 文件,真是一件很累人的事!

CC 与 CXX

这是 C 与 C++ 编译器命令。默认值一般是 "gcc" 与 "g++"。这个变量本来与优化没有关系,但是有些人因为担心软件包不遵守那些约定俗成的规范,害怕自己苦心设置的 CFLAGS/CXXFLAGS/LDFLAGS 之类的变量被忽略了,而索性将原本应当放置在其它变量中的选项一股老儿塞到 CC 或 CXX 中,比如:CC="gcc -march=k8 -O2 -s"。这是一种怪异的用法,本文不提倡这种做法,而是提倡按照变量本来的含义使用变量。

CPPFLAGS

这是用于预处理阶段的选项。不过能够用于此变量的选项,看不出有哪个与优化相关。如果你实在想设一个,那就使用下面这两个吧:

-DNDEBUG

"NDEBUG"是一个标准的 ANSI 宏,表示不进行调试编译。

-D_FILE_OFFSET_BITS=64

大多数包使用这个来提供大文件(>2G)支持。

CFLAGS 与 CXXFLAGS

CFLAGS 表示用于 C 编译器的选项,CXXFLAGS 表示用于 C++ 编译器的选项。这两个变量实际上涵盖了编译和汇编两个步骤。大多数程序和库在编译时默认的优化级别是"2"(使用"-O2"选项)并且带有调试符号来编译,也就是 CFLAGS="-O2 -g", CXXFLAGS=$CFLAGS 。事实上,"-O2"已经启用绝大多数安全的优化选项了。另一方面,由于大部分选项可以同时用于这两个变量,所以仅在最后讲述只能用于其中一个变量的选项。[提醒]下面所列选项皆为非默认选项,你只要按需添加即可。

先说说"-O3"在"-O2"基础上增加的几项:

-finline-functions

允许编译器选择某些简单的函数在其被调用处展开,比较安全的选项,特别是在CPU二级缓存较大时建议使用。

-funswitch-loops

将循环体中不改变值的变量移动到循环体之外。

-fgcse-after-reload

为了清除多余的溢出,在重载之后执行一个额外的载入消除步骤。

另外:

-fomit-frame-pointer

对于不需要栈指针的函数就不在寄存器中保存指针,因此可以忽略存储和检索地址的代码,同时对许多函数提供一个额外的寄存器。所有"-O"级别都打开它,但仅在调试器可以不依靠栈指针运行时才有效。在AMD64平台上此选项默认打开,但是在x86平台上则默认关闭。建议显式的设置它。

-falign-functions=N
-falign-jumps=N
-falign-loops=N
-falign-labels=N

这四个对齐选项在"-O2"中打开,其中的根据不同的平台N使用不同的默认值。如果你想指定不同于默认值的N,也可以单独指定。比如,对于L2-cache>=1M的cpu而言,指定 -falign-functions=64 可能会获得更好的性能。建议在指定了 -march 的时候不明确指定这里的值。

调试选项:

-fprofile-arcs

在使用这一选项编译程序并运行它以创建包含每个代码块的执行次数的文件后,程序可以再次使用 -fbranch-probabilities 编译,文件中的信息可以用来优化那些经常选取的分支。如果没有这些信息,gcc将猜测哪个分支将被经常运行以进行优化。这类优化信息将会存放在一个以源文件为名字的并以".da"为后缀的文件中。

全局选项:

-pipe

在编译过程的不同阶段之间使用管道而非临时文件进行通信,可以加快编译速度。建议使用。

目录选项:

--sysroot=dir

将dir作为逻辑根目录。比如编译器通常会在 /usr/include 和 /usr/lib 中搜索头文件和库,使用这个选项后将在 dir/usr/include 和 dir/usr/lib 目录中搜索。如果使用这个选项的同时又使用了 -isysroot 选项,则此选项仅作用于库文件的搜索路径,而 -isysroot 选项将作用于头文件的搜索路径。这个选项与优化无关,但是在 CLFS 中有着神奇的作用。

代码生成选项:

-fno-bounds-check

关闭所有对数组访问的边界检查。该选项将提高数组索引的性能,但当超出数组边界时,可能会造成不可接受的行为。

-freg-struct-return

如果struct和union足够小就通过寄存器返回,这将提高较小结构的效率。如果不够小,无法容纳在一个寄存器中,将使用内存返回。建议仅在完全使用GCC编译的系统上才使用。

-fpic

生成可用于共享库的位置独立代码。所有的内部寻址均通过全局偏移表完成。要确定一个地址,需要将代码自身的内存位置作为表中一项插入。该选项产生可以在共享库中存放并从中加载的目标模块。

-fstack-check

为防止程序栈溢出而进行必要的检测,仅在多线程环境中运行时才可能需要它。

-fvisibility=hidden

设置默认的ELF镜像中符号的可见性为隐藏。使用这个特性可以非常充分的提高连接和加载共享库的性能,生成更加优化的代码,提供近乎完美的API输出和防止符号碰撞。我们强烈建议你在编译任何共享库的时候使用该选项。参见 -fvisibility-inlines-hidden 选项。

硬件体系结构相关选项[仅仅针对x86与x86_64]:

-march=cpu-type

为特定的cpu-type编译二进制代码(不能在更低级别的cpu上运行)。Intel可以用:pentium2, pentium3(=pentium3m), pentium4(=pentium4m), pentium-m, prescott, nocona, core2(GCC-4.3新增) 。AMD可以用:k6-2(=k6-3), athlon(=athlon-tbird), athlon-xp(=athlon-mp), k8(=opteron=athlon64=athlon-fx)

-mfpmath=sse

P3和athlon-xp级别及以上的cpu支持"sse"标量浮点指令。仅建议在P4和K8以上级别的处理器上使用该选项。

-malign-double

将double, long double, long long对齐于双字节边界上;有助于生成更高速的代码,但是程序的尺寸会变大,并且不能与未使用该选项编译的程序一起工作。

-m128bit-long-double

指定long double为128位,pentium以上的cpu更喜欢这种标准,并且符合x86-64的ABI标准,但是却不附合i386的ABI标准。

-mregparm=N

指定用于传递整数参数的寄存器数目(默认不使用寄存器)。0<=N<=3 ;注意:当N>0时你必须使用同一参数重新构建所有的模块,包括所有的库。

-msseregparm

使用SSE寄存器传递float和double参数和返回值。注意:当你使用了这个选项以后,你必须使用同一参数重新构建所有的模块,包括所有的库。

-mmmx
-msse
-msse2
-msse3
-m3dnow
-mssse3(没写错!GCC-4.3新增)
-msse4.1(GCC-4.3新增)
-msse4.2(GCC-4.3新增)
-msse4(含4.1和4.2,GCC-4.3新增)

是否使用相应的扩展指令集以及内置函数,按照自己的cpu选择吧!

-maccumulate-outgoing-args

指定在函数引导段中计算输出参数所需最大空间,这在大部分现代cpu中是较快的方法;缺点是会明显增加二进制文件尺寸。

-mthreads

支持Mingw32的线程安全异常处理。对于依赖于线程安全异常处理的程序,必须启用这个选项。使用这个选项时会定义"-D_MT",它将包含使用选项"-lmingwthrd"连接的一个特殊的线程辅助库,用于为每个线程清理异常处理数据。

-minline-all-stringops

默认时GCC只将确定目的地会被对齐在至少4字节边界的字符串操作内联进程序代码。该选项启用更多的内联并且增加二进制文件的体积,但是可以提升依赖于高速 memcpy, strlen, memset 操作的程序的性能。

-minline-stringops-dynamically

GCC-4.3新增。对未知尺寸字符串的小块操作使用内联代码,而对大块操作仍然调用库函数,这是比"-minline-all-stringops"更聪明的策略。决定策略的算法可以通过"-mstringop-strategy"控制。

-momit-leaf-frame-pointer

不为叶子函数在寄存器中保存栈指针,这样可以节省寄存器,但是将会使调试变的困难。注意:不要与 -fomit-frame-pointer 同时使用,因为会造成代码效率低下。

-m64

生成专门运行于64位环境的代码,不能运行于32位环境,仅用于x86_64[含EMT64]环境。

-mcmodel=small

[默认值]程序和它的符号必须位于2GB以下的地址空间。指针仍然是64位。程序可以静态连接也可以动态连接。仅用于x86_64[含EMT64]环境。

-mcmodel=kernel

内核运行于2GB地址空间之外。在编译linux内核时必须使用该选项!仅用于x86_64[含EMT64]环境。

-mcmodel=medium

程序必须位于2GB以下的地址空间,但是它的符号可以位于任何地址空间。程序可以静态连接也可以动态连接。注意:共享库不能使用这个选项编译!仅用于x86_64[含EMT64]环境。

其它优化选项:

-fforce-addr

必须将地址复制到寄存器中才能对他们进行运算。由于所需地址通常在前面已经加载到寄存器中了,所以这个选项可以改进代码。

-finline-limit=n

对伪指令数超过n的函数,编译程序将不进行内联展开,默认为600。增大此值将增加编译时间和编译内存用量并且生成的二进制文件体积也会变大,此值不宜太大。

-fmerge-all-constants

试图将跨编译单元的所有常量值和数组合并在一个副本中。但是标准C/C++要求每个变量都必须有不同的存储位置,所以该选项可能会导致某些不兼容的行为。

-fgcse-sm

在全局公共子表达式消除之后运行存储移动,以试图将存储移出循环。gcc-3.4中曾属于"-O2"级别的选项。

-fgcse-las

在全局公共子表达式消除之后消除多余的在存储到同一存储区域之后的加载操作。gcc-3.4中曾属于"-O2"级别的选项。

-floop-optimize

已废除(GCC-4.1曾包含在"-O1"中)。

-floop-optimize2

使用改进版本的循环优化器代替原来"-floop-optimize"。该优化器将使用不同的选项(-funroll-loops, -fpeel-loops, -funswitch-loops, -ftree-loop-im)分别控制循环优化的不同方面。目前这个新版本的优化器尚在开发中,并且生成的代码质量并不比以前的版本高。已废除,仅存在于GCC-4.1之前的版本中。

-funsafe-loop-optimizations

假定循环不会溢出,并且循环的退出条件不是无穷。这将可以在一个比较广的范围内进行循环优化,即使优化器自己也不能断定这样做是否正确。

-fsched-spec-load

允许一些装载指令执行一些投机性的动作。

-ftree-loop-linear

在trees上进行线型循环转换。它能够改进缓冲性能并且允许进行更进一步的循环优化。

-fivopts

在trees上执行归纳变量优化。

-ftree-vectorize

在trees上执行循环向量化。

-ftracer

执行尾部复制以扩大超级块的尺寸,它简化了函数控制流,从而允许其它的优化措施做的更好。据说挺有效。

-funroll-loops

仅对循环次数能够在编译时或运行时确定的循环进行展开,生成的代码尺寸将变大,执行速度可能变快也可能变慢。

-fprefetch-loop-arrays

生成数组预读取指令,对于使用巨大数组的程序可以加快代码执行速度,适合数据库相关的大型软件等。具体效果如何取决于代码。

-fweb

建立经常使用的缓存器网络,提供更佳的缓存器使用率。gcc-3.4中曾属于"-O3"级别的选项。

-ffast-math

违反IEEE/ANSI标准以提高浮点数计算速度,是个危险的选项,仅在编译不需要严格遵守IEEE规范且浮点计算密集的程序考虑采用。

-fsingle-precision-constant

将浮点常量作为单精度常量对待,而不是隐式地将其转换为双精度。

-fbranch-probabilities

在使用 -fprofile-arcs 选项编译程序并执行它来创建包含每个代码块执行次数的文件之后,程序可以利用这一选项再次编译,文件中所产生的信息将被用来优化那些经常发生的分支代码。如果没有这些信息,gcc将猜测那一分支可能经常发生并进行优化。这类优化信息将会存放在一个以源文件为名字的并以".da"为后缀的文件中。

-frename-registers

试图驱除代码中的假依赖关系,这个选项对具有大量寄存器的机器很有效。gcc-3.4中曾属于"-O3"级别的选项。

-fbranch-target-load-optimize
-fbranch-target-load-optimize2

在执行序启动以及结尾之前执行分支目标缓存器加载最佳化。

-fstack-protector

在关键函数的堆栈中设置保护值。在返回地址和返回值之前,都将验证这个保护值。如果出现了缓冲区溢出,保护值不再匹配,程序就会退出。程序每次运行,保护值都是随机的,因此不会被远程猜出。

-fstack-protector-all

同上,但是在所有函数的堆栈中设置保护值。

--param max-gcse-memory=xxM

执行GCSE优化使用的最大内存量(xxM),太小将使该优化无法进行,默认为50M。

--param max-gcse-passes=n

执行GCSE优化的最大迭代次数,默认为 1。

传递给汇编器的选项:

-Wa,options

options是一个或多个由逗号分隔的可以传递给汇编器的选项列表。其中的每一个均可作为命令行选项传递给汇编器。

-Wa,--strip-local-absolute

从输出符号表中移除局部绝对符号。

-Wa,-R

合并数据段和正文段,因为不必在数据段和代码段之间转移,所以它可能会产生更短的地址移动。

-Wa,--64

设置字长为64bit,仅用于x86_64,并且仅对ELF格式的目标文件有效。此外,还需要使用"--enable-64-bit-bfd"选项编译的BFD支持。

-Wa,-march=CPU

按照特定的CPU进行优化:pentiumiii, pentium4, prescott, nocona, core, core2; athlon, sledgehammer, opteron, k8 。

仅可用于 CFLAGS 的选项:

-fhosted

按宿主环境编译,其中需要有完整的标准库,入口必须是main()函数且具有int型的返回值。内核以外几乎所有的程序都是如此。该选项隐含设置了 -fbuiltin,且与 -fno-freestanding 等价。

-ffreestanding

按独立环境编译,该环境可以没有标准库,且对main()函数没有要求。最典型的例子就是操作系统内核。该选项隐含设置了 -fno-builtin,且与 -fno-hosted 等价。

仅可用于 CXXFLAGS 的选项:

-fno-enforce-eh-specs

C++标准要求强制检查异常违例,但是该选项可以关闭违例检查,从而减小生成代码的体积。该选项类似于定义了"NDEBUG"宏。

-fno-rtti

如果没有使用'dynamic_cast'和'typeid',可以使用这个选项禁止为包含虚方法的类生成运行时表示代码,从而节约空间。此选项对于异常处理无效(仍然按需生成rtti代码)。

-ftemplate-depth-n

将最大模版实例化深度设为'n',符合标准的程序不能超过17,默认值为500。

-fno-optional-diags

禁止输出诊断消息,C++标准并不需要这些消息。

-fno-threadsafe-statics

GCC自动在访问C++局部静态变量的代码上加锁,以保证线程安全。如果你不需要线程安全,可以使用这个选项。

-fvisibility-inlines-hidden

默认隐藏所有内联函数,从而减小导出符号表的大小,既能缩减文件的大小,还能提高运行性能,我们强烈建议你在编译任何共享库的时候使用该选项。参见 -fvisibility=hidden 选项。

LDFLAGS

LDFLAGS 是传递给连接器的选项。这是一个常被忽视的变量,事实上它对优化的影响也是很明显的。

[提示]以下选项是在完整的阅读了ld-2.18文档之后挑选出来的选项。http://blog.chinaunix.net/u1/41220/showart_354602.html 有2.14版本的中文手册。

-s

删除可执行程序中的所有符号表和所有重定位信息。其结果与运行命令 strip 所达到的效果相同,这个选项是比较安全的。

-Wl,options

options是由一个或多个逗号分隔的传递给链接器的选项列表。其中的每一个选项均会作为命令行选项提供给链接器。

-Wl,-On

当n>0时将会优化输出,但是会明显增加连接操作的时间,这个选项是比较安全的。

-Wl,--exclude-libs=ALL

不自动导出库中的符号,也就是默认将库中的符号隐藏。

-Wl,-m<emulation>

仿真<emulation>连接器,当前ld所有可用的仿真可以通过"ld -V"命令获取。默认值取决于ld的编译时配置。

-Wl,--sort-common

把全局公共符号按照大小排序后放到适当的输出节,以防止符号间因为排布限制而出现间隙。

-Wl,-x

删除所有的本地符号。

-Wl,-X

删除所有的临时本地符号。对于大多数目标平台,就是所有的名字以'L'开头的本地符号。

-Wl,-zcomberloc

组合多个重定位节并重新排布它们,以便让动态符号可以被缓存。

-Wl,--enable-new-dtags

在ELF中创建新式的"dynamic tags",但在老式的ELF系统上无法识别。

-Wl,--as-needed

移除不必要的符号引用,仅在实际需要的时候才连接,可以生成更高效的代码。

-Wl,--no-define-common

限制对普通符号的地址分配。该选项允许那些从共享库中引用的普通符号只在主程序中被分配地址。这会消除在共享库中的无用的副本的空间,同时也防止了在有多个指定了搜索路径的动态模块在进行运行时符号解析时引起的混乱。

-Wl,--hash-style=gnu

使用gnu风格的符号散列表格式。它的动态链接性能比传统的sysv风格(默认)有较大提升,但是它生成的可执行程序和库与旧的Glibc以及动态链接器不兼容。


最后说两个与优化无关的系统环境变量,因为会影响GCC编译程序的方式,下面两个是咱中国人比较关心的:

LANG

指定编译程序使用的字符集,可用于创建宽字符文件、串文字、注释;默认为英文。[目前只支持日文"C-JIS,C-SJIS,C-EUCJP",不支持中文]

LC_ALL

指定多字节字符的字符分类,主要用于确定字符串的字符边界以及编译程序使用何种语言发出诊断消息;默认设置与LANG相同。中文相关的几项:"zh_CN.GB2312 , zh_CN.GB18030 , zh_CN.GBK , zh_CN.UTF-8 , zh_TW.BIG5"。

posted @ 2012-03-11 17:37  wdliming  阅读(214)  评论(0编辑  收藏  举报