make命令

用 make 进行巨集编译

在本章一开始我们提到过 make 的功能是可以简化编译过程里面所下达的命令,同时还具有很多很方便的功能!那么底下咱们就来试看看使用make 简化下达编译命令的流程吧!


小标题的图示 为什么要用 make

先来想像一个案例,假设我的运行档里面包含了四个原始码文件,分别是 main.c haha.c sin_value.c cos_value.c 这四个文件,这四个文件的目的是:

  • main.c :主要的目的是让使用者输入角度数据与呼叫其他三支副程序;
  • haha.c :输出一堆有的没有的信息而已;
  • sin_value.c :计算使用者输入的角度(360) sin 数值;
  • cos_value.c :计算使用者输入的角度(360) cos 数值。

这四个文件你可以到 http://vbird.dic.ksu.edu.tw/linux_basic/0520source/main.tgz来下载。由於这四个文件里面包含了相关性,并且还用到数学函式在里面,所以如果你想要让这个程序可以跑,那么就需要这样编译:

# 1. 先进行目标档的编译,最终会有四个 *.o 的档名出现:
[root@www ~]# gcc -c main.c
[root@www ~]# gcc -c haha.c
[root@www ~]# gcc -c sin_value.c
[root@www ~]# gcc -c cos_value.c

# 2. 再进行连结成为运行档,并加入 libm 的数学函式,以产生 main 运行档:
[root@www ~]# gcc -o main main.o haha.o sin_value.o cos_value.o \
> -lm -L/usr/lib -L/lib

# 3. 本程序的运行结果,必须输入姓名、360 度角的角度值来计算:
[root@www ~]# ./main 
Please input your name: VBird  <==这里先输入名字
Please enter the degree angle (ex> 90): 30   <==输入以 360 度角为主的角度
Hi, Dear VBird, nice to meet you.    <==这三行为输出的结果喔!
The Sin is:  0.50
The Cos is:  0.87

编译的过程需要进行好多动作啊!而且如果要重新编译,则上述的流程得要重新来一遍,光是找出这些命令就够烦人的了!如果可以的话,能不能一个步骤就给他完成上面所有的动作呢?那就利用 make 这个工具吧!先试看看在这个目录下创建一个名为 makefile 的文件,内容如下:

# 1. 先编辑 makefile 这个守则档,内容只要作出 main 这个运行档
[root@www ~]# vim makefile
main: main.o haha.o sin_value.o cos_value.o
	gcc -o main main.o haha.o sin_value.o cos_value.o -lm
# 注意:第二行的 gcc 之前是 <tab> 按键产生的空格喔!

# 2. 尝试使用 makefile 制订的守则进行编译的行为:
[root@www ~]# rm -f main *.o   <==先将之前的目标档去除
[root@www ~]# make
cc    -c -o main.o main.c
cc    -c -o haha.o haha.c
cc    -c -o sin_value.o sin_value.c
cc    -c -o cos_value.o cos_value.c
gcc -o main main.o haha.o sin_value.o cos_value.o -lm
# 此时 make 会去读取 makefile 的内容,并根据内容直接去给他编译相关的文件罗!

# 3. 在不删除任何文件的情况下,重新运行一次编译的动作:
[root@www ~]# make
make: `main' is up to date.
# 看到了吧!是否很方便呢!只会进行升级 (update) 的动作而已。

或许你会说:『如果我创建一个 shell script 来将上面的所有动作都集结在一起,不是具有同样的效果吗?』呵呵!效果当然不一样,以上面的测试为例,我们仅写出 main 需要的目标档,结果 make 会主动的去判断每个目标档相关的原始码文件,并直接予以编译,最后再直接进行连结的动作!真的是很方便啊!此外,如果我们更动过某些原始码文件,则 make 也可以主动的判断哪一个原始码与相关的目标档文件有升级过,并仅升级该文件,如此一来,将可大大的节省很多编译的时间呢!要知道,某些程序在进行编译的行为时,会消耗很多的CPU 资源呢!所以说, make 有这些好处:

  • 简化编译时所需要下达的命令;
  • 若在编译完成之后,修改了某个原始码文件,则 make 仅会针对被修改了的文件进行编译,其他的object file 不会被更动;
  • 最后可以依照相依性来升级 (update) 运行档。

既然 make 有这么多的优点,那么我们当然就得好好的了解一下 make 这个令人关心的家伙啦!而 make 里面最需要注意的大概就是那个守则文件,也就是 makefile 这个文件的语法啦!所以底下我们就针对 makefile 的语法来加以介绍罗。


小标题的图示 makefile 的基本语法与变量

make 的语法可是相当的多而复杂的,有兴趣的话可以到 GNU (注1)去查阅相关的说明,鸟哥这里仅列出一些基本的守则,重点在於让读者们未来在接触原始码时,不会太紧张啊!好了,基本的 makefile 守则是这样的:

标的(target): 目标档1 目标档2
<tab>   gcc -o 欲创建的运行档 目标档1 目标档2

那个标的 (target) 就是我们想要创建的资讯,而目标档就是具有相关性的 object files ,那创建运行档的语法就是以 <tab> 按键开头的那一行!特别给他留意喔,『命令列必须要以 tab 按键作为开头』才行!他的守则基本上是这样的:

  • 在 makefile 当中的 # 代表注解;
  • <tab> 需要在命令行 (例如 gcc 这个编译器命令) 的第一个字节;
  • 标的 (target) 与相依文件(就是目标档)之间需以『:』隔开。

同样的,我们以刚刚上一个小节的范例进一步说明,如果我想要有两个以上的运行动作时,例如下达一个命令就直接清除掉所有的目标档与运行档,该如何制作呢?

# 1. 先编辑 makefile 来创建新的守则,此守则的标的名称为 clean :
[root@www ~]# vi makefile
main: main.o haha.o sin_value.o cos_value.o
	gcc -o main main.o haha.o sin_value.o cos_value.o -lm
clean:
	rm -f main main.o haha.o sin_value.o cos_value.o

# 2. 以新的标的 (clean) 测试看看运行 make 的结果:
[root@www ~]# make clean  <==就是这里!透过 make 以 clean 为标的
rm -rf main main.o haha.o sin_value.o cos_value.o

如此一来,我们的 makefile 里面就具有至少两个标的,分别是 main 与 clean ,如果我们想要创建 main 的话,输入『make main』,如果想要清除有的没的,输入『makeclean』即可啊!而如果想要先清除目标档再编译 main 这个程序的话,就可以这样输入:『make clean main』,如下所示:

[root@www ~]# make clean main
rm -rf main main.o haha.o sin_value.o cos_value.o
cc    -c -o main.o main.c
cc    -c -o haha.o haha.c
cc    -c -o sin_value.o sin_value.c
cc    -c -o cos_value.o cos_value.c
gcc -o main main.o haha.o sin_value.o cos_value.o -lm

这样就很清楚了吧!但是,你是否会觉得,咦! makefile 里面怎么重复的数据这么多啊!没错!所以我们可以再藉由 shellscript 那时学到的『变量』来更简化 makefile 喔:

[root@www ~]# vi makefile
LIBS = -lm
OBJS = main.o haha.o sin_value.o cos_value.o
main: ${OBJS}
        gcc -o main ${OBJS} ${LIBS}
clean:
        rm -f main ${OBJS}

bash shell script 的语法有点不太相同,变量的基本语法为:

  1. 变量与变量内容以『=』隔开,同时两边可以具有空格;
  2. 变量左边不可以有 <tab> ,例如上面范例的第一行 LIBS 左边不可以是 <tab>;
  3. 变量与变量内容在『=』两边不能具有『:』;
  4. 在习惯上,变量最好是以『大写字母』为主;
  5. 运用变量时,以 ${变量} 或 $(变量) 使用;
  6. 在该 shell 的环境变量是可以被套用的,例如提到的 CFLAGS 这个变量!
  7. 在命令列模式也可以给予变量。

由於 gcc 在进行编译的行为时,会主动的去读取 CFLAGS这个环境变量,所以,你可以直接在 shell 定义出这个环境变量,也可以在makefile 文件里面去定义,更可以在命令列当中给予这个咚咚呢!例如:

[root@www ~]# CFLAGS="-Wall" make clean main
# 这个动作在上 make 进行编译时,会去取用 CFLAGS 的变量内容!

也可以这样:

[root@www ~]# vi makefile
LIBS = -lm
OBJS = main.o haha.o sin_value.o cos_value.o
CFLAGS = -Wall
main: ${OBJS}
	gcc -o main ${OBJS} ${LIBS}
clean:
	rm -f main ${OBJS}

咦!我可以利用命令列进行环境变量的输入,也可以在文件内直接指定环境变量,那万一这个CFLAGS 的内容在命令列与 makefile 里面并不相同时,以那个方式输入的为主?呵呵!问了个好问题啊!环境变量取用的守则是这样的:

  1. make 命令列后面加上的环境变量为优先;
  2. makefile 里面指定的环境变量第二;
  3. shell 原本具有的环境变量第三。

此外,还有一些特殊的变量需要了解的喔:

  • $@:代表目前的标的(target)

所以我也可以将 makefile 改成:

[root@www ~]# vi makefile
LIBS = -lm
OBJS = main.o haha.o sin_value.o cos_value.o
CFLAGS = -Wall
main: ${OBJS}
	gcc -o $@ ${OBJS} ${LIBS}   <==那个 $@ 就是 main !
clean:
	rm -f main ${OBJS}

这样是否稍微了解了 makefile (也可能是 Makefile) 的基本语法?这对於你未来自行修改原始码的编译守则时,是很有帮助的喔!^_^!




###################################################################

例解 Linux 下 Make 命令

Linux 下 make 命令是系统管理员和程序员用的最频繁的命令之一。管理员用它通过命令行来编译和安装很多开源的工具,程序员用它来管理他们大型复杂的项目编译问题。本文我们将用一些实例来讨论 make 命令背后的工作机制。

Make 如何工作的

对于不知道背后机理的人来说,make 命令像命令行参数一样接收目标。这些目标通常存放在以 “Makefile” 来命名的特殊文件中,同时文件也包含与目标相对应的操作。更多信息,阅读关于 Makefiles 如何工作的系列文章。

当 make 命令第一次执行时,它扫描 Makefile 找到目标以及其依赖。如果这些依赖自身也是目标,继续为这些依赖扫描 Makefile 建立其依赖关系,然后编译它们。一旦主依赖编译之后,然后就编译主目标(这是通过 make 命令传入的)。

现在,假设你对某个源文件进行了修改,你再次执行 make 命令,它将只编译与该源文件相关的目标文件,因此,编译完最终的可执行文件节省了大量的时间。

Make 命令实例

下面是本文所使用的测试环境:

OS —— Ubunut 13.04
Shell —— Bash 4.2.45
Application —— GNU Make 3.81

下面是工程的内容:

$ ls 
anotherTest.c Makefile test.c test.h

下面是 Makefile 的内容:

all: test 

test: test.o anotherTest.o 
    gcc -Wall test.o anotherTest.o -o test

test.o: test.c 
    gcc -c -Wall test.c 

anotherTest.o: anotherTest.c 
    gcc -c -Wall anotherTest.c 

clean: 
    rm -rf *.o test

现在我们来看 Linux 下一些 make 命令应用的实例:

1. 一个简单的例子

为了编译整个工程,你可以简单的使用 make 或者在 make 命令后带上目标 all

$ make 
gcc -c -Wall test.c 
gcc -c -Wall anotherTest.c 
gcc -Wall test.o anotherTest.o -o test

你能看到 make 命令第一次创建的依赖以及实际的目标。

如果你再次查看目录内容,里面多了一些 .o 文件和执行文件:

$ ls 
anotherTest.c anotherTest.o Makefile test test.c test.h test.o

现在,假设你对 test.c 文件做了一些修改,重新使用 make 编译工程:

$ make 
gcc -c -Wall test.c 
gcc -Wall test.o anotherTest.o -o test

你可以看到只有 test.o 重新编译了,然而另一个 Test.o 没有重新编译。

现在清理所有的目标文件和可执行文件 test,你可以使用目标 clean:

$ make clean
rm -rf *.o test

$ ls
anotherTest.c Makefile test.c test.h

你可以看到所有的 .o 文件和执行文件 test 都被删除了。

2. 通过 -B 选项让所有目标总是重新建立

到目前为止,你可能注意到 make 命令不会编译那些自从上次编译之后就没有更改的文件,但是,如果你想覆盖 make 这种默认的行为,你可以使用 -B 选项。

下面是个例子:

$ make
make: Nothing to be done for `all’.

$ make -B
gcc -c -Wall test.c
gcc -c -Wall anotherTest.c
gcc -Wall test.o anotherTest.o -o test

你可以看到尽管 make 命令不会编译任何文件,然而 make -B 会强制编译所有的目标文件以及最终的执行文件。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: linuxmake命令是一个在Linux系统中用于编译和构建软件的命令。它可以根据源代码生成可执行文件或库文件,并且可以根据不同的编译选项进行定制化的编译。使用linuxmake命令可以方便地管理和构建大型软件项目,提高开发效率和代码质量。 ### 回答2: linux中的make命令是一个用于自动化编译和链接程序的工具。它可以根据源代码文件的修改情况,智能地判断哪些文件需要重新编译,从而避免不必要的编译过程,提高程序的编译效率。 make命令通过读取Makefile文件中的规则来执行编译和链接过程。Makefile是一个文本文件,定义了各个源文件之间的依赖关系和编译链接规则。通过编写Makefile文件,可以实现程序的模块化编译和管理。 make命令的基本用法如下: make [选项] [目标] 常用的选项包括: - -f:指定Makefile文件的路径,默认为当前目录下的Makefile文件。 - -n:显示make命令执行的过程,但不实际执行。 - -j n:指定并行编译的任务数,加快编译速度。 常用的目标包括: - all:编译并链接整个程序。 - clean:删除编译生成的目标文件和可执行文件。 - install:将可执行文件安装到指定的目录。 在执行make命令时,它会根据Makefile文件中定义的规则进行编译和链接。如果某个源文件或依赖的头文件被修改,make会重新编译相应的文件。这样可以避免不必要的编译过程,提高编译效率。 Makefile文件中的规则由目标、依赖和命令三部分组成。目标是生成的文件,依赖是生成目标所需要的文件,命令是生成目标的具体操作。通过定义合理的规则,可以实现源文件的自动编译、模块的自动链接等功能,简化了编译过程。 总之,make命令是一个非常实用的工具,在Linux系统中广泛应用于程序的编译和管理中,它能够提高编译效率,简化编译过程,是开发者的得力助手。 ### 回答3: Linux中的make命令是一个构建工具,主要用于自动化编译和链接程序。它基于Makefile文件来描述构建关系和规则,并根据这些规则来生成目标文件、可执行文件或库文件。 make命令通过检查文件的修改时间来确定哪些文件需要重新编译,从而提高了编译的效率。通过定义依赖关系和编译规则,make命令可以自动化地进行增量编译,只编译发生改变的文件,大大节省了编译时间。 Makefile是make命令的配置文件,它通常包含了工程中各个源文件的编译规则、依赖关系和链接参数。在Makefile中,可以定义目标及其依赖关系,并指定相应的编译命令。 使用make命令,可以简化复杂的编译操作,尤其适用于大型工程或包含多个源文件的项目。通过简单的命令make命令可以自动完成编译、连接和生成可执行文件。 make命令还提供了一些常用的功能,例如清理编译生成的中间文件、执行程序等。 总之,make命令是一个强大的构建工具,它可以自动化编译和链接程序,提高编译效率,简化编译操作,尤其适用于大型工程或包含多个源文件的项目。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值