Linux下(软件)标准编译安装原理

1、为什么要编译安装

  包管理系统是绝大多数发行版的必备组件,也是一个发行版区别于其它发行版的主要特征。但是有些软件,并不能通过包管理系统安装,这就需要下载源码编译安装。

  一个软件可能有许多功能,但是发行版中提供的安装包,通常只具有一些常见的功能。如果提供所有功能,那么无疑会占用更多的资源,而这些功能,大多数用户不会用到;[1]而你会用到的功能,可能安装包中刚好没有。编译安装可以灵活地定制软件,选择自己需要的,取消自己不需要的。

  编译安装还可以针对特定的硬件进行优化,以获得更好的性能表现。[2]

2、编译环境

编译环境包括多个工具,它们环环相扣,称作编译工具链。主要包括以下工具:

工具

简介

binutils

连接器、汇编器和其他用于目标文件和档案的工具

gcc

编译器,将源代码转换为机器代码

glibc

C库,提供标准例程(C函数)

还有一些工具,能够调用工具链,实现自动化编译:

autoconf

自动生成 Makefile 文件

automake

make

按照 Makefile 文件中的规则编译程序

在后面的部分将分别介绍这些工具

标准编译安装

首先,下载源代码,通常是压缩包,如:xxx.tar.gz 或者 xxx.tar.bz2,解包:

压缩包格式

命令

.tar.gz

tar zxvf xxx.tgz

.tgz

.tar.bz2

tar jxvf xxx.tar.bz2

通常解包后会在当前位置得到一个 xxx/ 目录,进入这个目录

cd xxx/

使用下列命令编译安装:

./configure[1]     --prefix=/opt/xxx [2]    make[3]     sudo make install[4]    make clean[5] 

[1]  配置软件特性,检查编译环境,生成 Makefile文件

[2]  最常用配置选项:指定软件的安装路径

[3]  根据 Makefile 编译源代码

[4]  将编译完成的程序安装到系统中。通常需要 root权限

[5]  清除源代码目录中的编译结果

[1] Windows 系统下的一些经典软件,如 ACDseeNeroWinamp 等,集成了越来越多的功能,使它们越来越臃肿。而且不能够只选择自己喜欢的功能,要么全盘接收,要么改寻它途

[2] 通常发行版提供的安装包,已经进行了优化。自己编译的软件,性能未必更好

 3、编译过程

将下面代码保存为 Hello.c

#include <stdio.h>

int main(void)

{

printf("Hello World!\n") [1];

return 0;

}

[1]printf() 函数

  执行命令 cc Hello.c[3],得到一个可执行文件 a.out,执行它 ./a.out

可以看到,C的源代码(Hello.c)是纯文本,不能够直接执行。可执行代码是计算机的本机语言或机器语言表示的代码,这种语言是由数字代码表示的详细指令组成,不同的计算机具有不同的机器语言。

  编译器是一个程序,其工作是将源代码转换为可执行代码。

·         编译器用来将 C语言 转换成特定的机器语言。

·          编译器还从C的库中向最终程序加入代码。[4]

·           

·         编译器还检查源代码是否为有效的C语言程序。如果编译器发现错误,将报告错误,而且不生成可执行文件。编译器分三步完成这个工作:

预处理

调用预处理器 cpp 对源代码文件中的文件包含(include)、预编译语句(如宏定义 define ) 进行分析

编译

调用编译器 cc 将源代码转换为中间代码

链接

调用链接器 ld 将中间代码与其它代码结合起来生成可执行文件

·         这种方法使用程序便于模块化。分别编译各个模块,然后使用链接器将编译过的模块结合起来。这样,如果需要改变一个模块,则不必重新编译所有其它模块。

  可执行文件包含目标文件库例程启动代码

  编译器将源代码转换为机器语言代码(中间代码),将结果放置在目标文件(*.o)中。虽然目标文件包含机器代码,但该文件还不能运行,它还不是一个完整的程序。

  启动代码(start-up code)相当于程序和操作系统之间的接口。[5]

  库例程为函数的实现。几乎所有C程序都利用标准C库中所包含的例程,目标代码文件不包含这一函数的代码,它只包含调用函数的指令。实际代码存储在一个称为“库”的文件中。库文件中包含许多函数的目标代码

链接器的作用是将这3个元素(目标代码、系统的标准启动代码和库代码[6])结合在一起,并将它们存放在可执行文件中。

 

[3]  Linux 系统中,编译器为gcccc为它的链接

[4] 库中包含许多标准例程供您使用,例如printf()。更准确的说,是一个被称为链接器(linker)的程序将库例程引入的,但在多数系统上,编译器为您运行链接器。

[5] 硬件相同的情况下,在 DOS  Linux 下可以使用同样的目标代码,但 DOC  Linux 要使用不同的启动代码,因为这两种系统处理程序的方式是不同的。

[6] 程序有两种方法来使用这些库函数,如果静态连接一个程序,这些函数就会被复制到可执行程序中,这就是lib*.a函数库的作用。

 

   如果你动态的连接一个程序(默认),那么当程序运行时需要库中的代码,它就会调用lib*.so中的内容。

 

4gcc 编译器

  gcc  GNU 推出的功能强大、性能优越的多平台编译器,是 GNU 的代表作品之一。它能将CC++语言源程序、汇编语言源程序和目标程序编译、链接成可执行文件,如果没有给出可执行文件的名字,gcc 将生成一个名为 a.out 的文件。

  gcc 通过后缀来区分输入文件的类型:

后缀

类型

.c

C语言源代码文件

.a

由目标文件构成的档案库文件

.C|.cc|.cxx

C++源代码文件

.h

程序所包含的头文件

.i

预处理过的C源代码文件

.ii

预处理过的C++源代码文件

.m

Objective-C源代码文件

.o

编译后的目标文件

.s

汇编语言源代码文件

.S

预编译的汇编语言源代码文件

  前面我们已经使用 gcc 编译了一个程序:cc Hello.c

gcc 还有许多选项:

-c

只编译,不链接成为可执行文件

-o 文件名

设定输出文件名。默认为a.out

-g

加入调试符号(默认)[1]

-O

编译、链接时进行优化,耗时比较多,但产生的可执行文件执行效率更高

-O2

更高的优化级别,耗时更多

  [1] 可以使用 gdb 进行调试

  使用下面的命令去掉调试符号:

  strip --strip-unneeded a.out strip --strip-debug a.out

  不要在库文件上使用 --strip-unneeded

5、自动化编译

  在前面的标准编译安装中,第一步是./configure[7],它会根据Makefile.in生成Makefile文件,然后make根据Makefile自动编译软件。

  通常在一个源码包中,已经包含了configure脚本和Makefile文件,作为课外知识,我们大致了解一下怎么生成这两个文件。

  autoconf

  autoconf用来生成configure脚本,它可以检查系统特性、编译环境、环境变量、软件参数、依赖关系等。

autoconf需要用到 m4

1.       autoscan描源代码目录生成configure.scan文件;

2.       configure.scan改名为configure.in

3.       aclocal根据configure.in文件的内容,自动生成aclocal.m4文件;

4.       使用autoconf,根据configure.inaclocal.m4来产生configure文件;

   automake

  automake可以从Makefile.am文件自动生成Makefile.in,它主要用来配置源代码。

automake需用到perl

·         手工写Makefile.am

·         使用automake,根据configure.inMakefile.am来产生Makefile.in

 Makefile

 使用configure脚本,配合Makefile.in可以生成Makefile文件,然后用make自动化的编译软件。

这里有一张生成Makefile的流程图:

Linux下(软件)标准编译安装原理介绍

  Makefile的用途不只是编译软件,还可以利用它完成一些琐碎的工作,只要最后输出一个文件,都可以用make来完成

这是一个最简单的Makefile

filelist [1][2]*[3]     [4] ls -lF > filelist  [5]

[1]  输出的目标文件,不能省略。如果有多个文件,可以使用all

[2]  分隔符,不能省略

 [3] 输入文件,可以省略

 [4] 这一行必须以TAB字符起始,不能使用空格代替

 [5] make的命令

可以使用变量代替命令,便于维护

TARGET = filelist[1]   SOURCE = * ARG = -lF APPLICATION = ls $(TARGET):$(SOURCE)[2]$(APPLICATION) $(ARG) $(SOURCE) > $(TARGET)

[1]  定义变量,传统上用大写

[2]  使用变量写Makefile

  Makefile可以有多个目标文件,我们前面提到,gcc编译时先生成目标文件,再把目标文件链接成可执行文件,Makefile应该是这样的:

OBJECTS = main.o kbd.o command.o display.o \[1] insert.o search.o files.o utils.o exe : $(OBJECTS) cc -o exe $(OBJECTS) main.o : main.c defs.h  [2]  cc -c main.c kbd.o : kbd.c defs.h command.h cc -c kbd.c command.o : command.c defs.h command.h cc -c command.c display.o : display.c defs.h buffer.h cc -c display.c insert.o : insert.c defs.h buffer.h cc -c insert.c search.o : search.c defs.h buffer.h cc -c search.c files.o : files.c defs.h buffer.h command.h cc -c files.c utils.o : utils.c defs.h cc -c utils.c clean : [3]  rm exe $(OBJECTS)

[1]  如果写在多行,要用脱字符换行

[2]   如何生成中间文件

[3] 伪目标文件,make clean并不生成clean文件,而是清理编译结果

  Makefile还有很多强大的机制,这里就不详细介绍了

 

[7] 执行当前目录下的configure脚本

6、使用 make

利用 configure所产生的Makefile文件有几个预先设定的目标可供使用:

目标

用途

make all

产生预设的目标,只敲入make也可以

make clean

清除编译结果

make distclean

除了清除编译结果,也把configure所产生的 Makefile 清除掉

make install

将程序安装到系统中

make dist

将程序和相关的文档打包为一个压缩文档以供发布

make distcheck

打包并检验

7emerge

  虽然我们能够使用autoconfautomakemake等工具实现自动化编译,但这种针对单个软件包的编译系统,在编译多个软件时仍然十分繁琐。

  假设需要编译emacsvim,使用 xft字体、图形界面支持,并去掉调试符号,需要分别作如下配置:

  emacs ./configure --prefix=/usr/local/ \ --no-debug \ --with-xft --with-x-toolkit=gtk \ --with-freetypevim ./configure --prefix=/usr/local/ \ --no-debug \ --with-xft --with-x-toolkit=gtk

  这就像点菜时,你必须告诉厨师:鱼香肉丝(多放辣椒、不放蒜)、宫保鸡丁(多放辣椒、不放蒜)、麻婆豆腐(多放辣椒、不放蒜)……

  实际上,大多数人这样点菜:鱼香肉丝、宫保鸡丁、麻婆豆腐……多放辣椒、不放蒜

emerge就是这样一种点菜方式,它是gentoo的包管理系统,提供了更为现代化的编译方式。

  可以通过指定USE标记xftgtk-debug来确定所有软件的编译方式。

  设置 USE标记:

  以下方法按优先级由低到高排列:

  /etc/make.profile/目录是一个符号链接,里面包含一些make.defaults文件,放置开发者设置的 USE标记[8]

  /usr/portage/profile/base/make.defaults /usr/portage/profile/default-linux/make.defaults /usr/portage/profile/default-linux/x86/make.defaults /usr/portage/profile/default-linux/x86/2008.0/make.defaults

  在/etc/make.conf文件中声明永久 USE标记(推荐)

  USE="nptl nptlonly nls cjk php mysql -kde -qt3 -qt4"

·         - USE标记,表示排除

  在/etc/portage/package.use文件中为单个包声明 USE标记

  app-editors/emacs-cvs xft www-servers/lighttpd fastcgi dev-lang/php mysqli cgi gd ctype pcre session unicode pic posix dev-db/phpmyadmin vhosts app-shells/zsh doc net-ftp/pure-ftpd -ldap mysql pam ssl vchroot

  使用环境变量声明临时 USE标记

  USE="-java" emerge seamonkey

  查看使用的 USE标记:

  merge --pretend --verbose seamonkey Calculating dependencies ...done! [ebuild R ] www-client/seamonkey-1.0.7 USE="crypt gnome java -debug -ipv6 -ldap -mozcalendar -mozdevelop -moznocompose -moznoirc -moznomail -moznopango -moznoroaming -postgres -xinerama -xprint" 0 kB

  编译选项

  /etc/make.conf

CFLAGS="-O2 -march=i686 -pipe"  [1]  CXXFLAGS="-O2 -march=i686 -pipe"   [2] CHOST="i686-pc-linux-gnu"   [3] MAKEOPTS="-j2"  [4]   FEATURES="parallel-fetch ccache"  [5] CCACHE_DIR="/var/tmp/ccache"    [6] CCACHE_SIZE="2G"  [7] ACCEPT_KEYWORDS="x86"   [8]USE="nptl nptlonly nls cjk php mysql"   [9] FETCHCOMMAND="/usr/bin/axel -a -n4 \${URI} -o \${DISTDIR}"  [10] RESUMECOMMAND="/usr/bin/axel -a -n4 \${URI} -o \${DISTDIR}"

[1] 针对C语言的优化选项,-march=设置目标架构

[2]  针对C++语言的优化选项

[3]  进行编译工作的机器架构

[4]  编译选项

[5]  emerge 特性。并行下载、使用 ccache 缓冲编译结果

[6]  ccache 缓存目录

[7]  ccache 缓存大小

[8]  通过关键字选择分支。x86表示 x86 架构的稳定分支,~x86表示 x86 架构的不稳定分支

[9]  USE标记

[10] 使用axel加速下载

  gentoo支持多种架构:x86 sparc amd64 ppc ppc64 alpha hppa mips ia64 arm,我们使用的PC 多为 x86 架构。

  假设你主要使用 x86 稳定分支,但少数软件要使用最新版本,在/etc/portage/package.keywords文件中为单个包设置关键字。

  app-editors/emacs-cvs ~x86 x11-misc/emacs-desktop ~x86 app-i18n/fcitx ~x86 app-editors/vim x86 app-editors/vim-core x86 media-video/mplayer ~x86 media-libs/win32codecs ~x86 app-i18n/man-pages-zh_CN ~x86

微调

  在/etc/portage/目标下包含一些文件,可以在软件包级别上进行调节。前面已经介绍了package.usepackage.keywords

  package.keywords

  还未被确认适合你的系统或架构,但是你希望能安装的软件包。

  package.use

  特定软件包而不是整个系统使用的 USE标记。

  package.provided

  屏蔽的软件包(需要指明版本号)

  package.mask

  永远不希望 Portage 安装的软件包。

  package.unmask

  被 Gentoo 开发者屏蔽的软件包,但是你希望能安装的软件包。

软件包可能由于以下原因被屏蔽:

~架构 keyword

意味着这个软件没有经过充分的测试,不能进入稳定分支,请等待一段时间后在尝试使用它

-架构 keyword  -* keyword

意味着这个软件不能工作在您机器的体系结构中

missing keyword

意味着这个软件还没有在您机器的体系结构中进行过测试

package.mask

意味着这个软件被认为是损坏的,不稳定的或者有更严重的问题,它被故意标识为不应使用

profile

意味着这个软件不适用于您的 profile。安装这样的应用软件可能会破坏您的系统,或者只是不能与您使用的 profile 相兼容

例如:

gnome-base/gnome-2.8.0_pre1 (masked by: ~x86 keyword) lm-sensors/lm-sensors-2.8.7 (masked by: -sparc keyword) sys-libs/glibc-2.3.4.20040808 (masked by: -* keyword) dev-util/cvsd-1.0.2 (masked by: missing keyword) games-fps/unreal-tournament-451 (masked by: package.mask) sys-libs/glibc-2.3.2-r11 (masked by: profile)

使用 emerge

注意  本部分内容来源于gentoo 中文手册

查找.

查找名字包含 pdf 的软件包

emerge --search pdf

查找与 pdf 相关的软件包

emerge --searchdesc pdf emerge -S pdf

查看软件拥有的 USE标记

emerge -vp 软件包名称

管理.

安装软件包

emerge 软件包名称

模拟安装软件包

emerge --pretend 软件包名称

下载软件包的源代码包

emerge --fetchonly 软件包名称

从系统中删除软件包

emerge --unmerge 软件包名称

更新.

更新系统

emerge --update --ask world emerge -ua world

更新整个系统

emerge --update --deep world emerge -uD world

使用新的 USE标记 重新构建系统

emerge --update --deep --newuse world emerge -uDN world

移除孤立依赖的软件包

emerge --update --deep --newuse world[1]  emerge –depclean[2]  revdep-rebuild [3]

 [1]  重新构建系统

 [2]  清除孤立依赖包

 [3]  重新构建依赖关系

revdep-rebuild工具由gentoolkit包提供;使用前别忘了首先 emerge 它:

emerge gentoolkit

 

[8] 在升级 Portage 的时候,这些文件将会被覆盖,请不要在这里设置

 

原文地址:http://blog.chinaunix.net/uid-12372814-id-2626304.html

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值