与软件编译安装有关的一些系统环境变量的说明

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和Binutils的脚本就不传递LDFLAGS),你必须手动编辑生成的 Makefile 文件,在其中寻找这些变量并修改它们的值,许多源码包在每个子文件夹中都有 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"已经启用绝大多数安全的优化选项了。

LDFLAGS
LDFLAGS 是传递给连接器的选项。这是一个常被忽视的变量,事实上它对优化的影响也是很明显的。
除了用来优化,它可以用来指定一些动态库的路径。如-L/usr/local/lib

LD_RUN_PATH
用来指定在编译时到哪些目录去寻找动态库,多个目录以冒号隔开

LD_LIBRARY_PATH
用来指定在运行时到哪些目录去寻找动态库,多个目录以冒号隔开

关于LD_RUN_PATH和LD_LIBRARY_PATH的详细说明:
http://osr507doc.sco.com/en/tools/ccs_linkedit_dynamic_dirsearch.html
Specifying directories to be searched by the dynamic linker
When you use the -l option, you must point the dynamic linker to the directories of the dynamically linked libraries that are to be linked with your program at execution. The environment variable LD_RUN_PATH lets you do that at link time. To set LD_RUN_PATH, list the absolute pathnames of the directories you want searched in the order you want them searched. Separate pathnames with a colon, as shown in the following example:
LD_RUN_PATH=/home/mylibs export LD_RUN_PATH
The command:
cc -dy -o prog -L/home/mylibs file1.c file2.c file3.c -lfoo

directs the dynamic linker to search for libfoo.so in /home/mylibs when you execute your program:
prog
The dynamic linker searches the standard place by default, after the directories you have assigned to LD_RUN_PATH. Note that as far as the dynamic linker is concerned, the standard place for libraries is /usr/lib. Any executable versions of libraries supplied by the compilation system kept in /usr/lib.
The environment variable LD_LIBRARY_PATH lets you do the same thing at run time. Suppose you have moved libfoo.so to /home/sharedobs. It is too late to replace /home/mylibs with /home/sharedobs in LD_RUN_PATH, at least without link editing your program again. You can, however, assign the new directory to LD_LIBRARY_PATH, as follows:
LD_LIBRARY_PATH=/home/sharedobs export LD_LIBRARY_PATH

Now when you execute your program
prog
the dynamic linker searches for libfoo.so first in /home/mylibs and, not finding it there, in /home/sharedobs. The directory assigned to LD_RUN_PATH is searched before the directory assigned to LD_LIBRARY_PATH. The important point is that because the pathname of libfoo.so is not hard-coded in prog, you can direct the dynamic linker to search a different directory when you execute your program. You can move a dynamically linked library without breaking your application.
You can set LD_LIBRARY_PATH without first having set LD_RUN_PATH. The main difference between them is that once you have used LD_RUN_PATH for an application, the dynamic linker searches the specified directories every time the application is executed (unless you have relinked the application in a different environment). In contrast, you can assign different directories to LD_LIBRARY_PATH each time you execute the application. LD_LIBRARY_PATH directs the dynamic linker to search the assigned directories before it searches the standard place. Directories, including those in the optional second list, are searched in the order listed. See the previous section for the syntax.
Note, finally, that when linking a set-user or set-group program, the dynamic linker ignores any directories that are not built into the dynamic linker. Currently, the only built-in directory is /usr/lib.
posted @ 2011-09-04 02:00  elwin  阅读(328)  评论(0)    收藏  举报