A Simple Makefile Tutorial
A Simple Makefile Tutorial A Simple Makefile Tutorial: http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/ Makefiles are a simple way to organize code compilation. This tutorial does not even scratch the surface of what is possible using make, but is intended as a starters guide so that you can quickly and easily create your own makefiles for small to medium-sized projects.
Makefile是一种以简单的方式来组织代码进行编译的文件。本教程并不对make使用深入研究,而是旨在为初学者指南,让您可以快速,轻松地为小、中等规模的项目创建自己的makefile文件。 A Simple Example
一个简单的示例 Let's start off with the following three files, hellomake.c, hellofunc.c, and hellomake.h, which would represent a typical main program, some functional code in a separate file, and an include file, respectively.
让我们由以下三个文件开始:hellomake.c、hellofunc.c、hellomake.h,分别是:一个典型的主程序、一个单独的文件包含一些功能程序、一个头文件。
+--------------------------------------+---------------------------------+------------------------------+
| hellomake.c | hellofunc.c | hellomake.h |
+--------------------------------------+---------------------------------+------------------------------+
| #include <hellomake.h> | #include <stdio.h> | /* |
| | #include <hellomake.h> | example include file |
| int main() { | void myPrintHelloMake(void) { | */ |
| // call a function in another file | | |
| myPrintHelloMake(); | printf("Hello makefiles!\n"); | void myPrintHelloMake(void); |
| | | |
| return(); | return; | |
| } | } | |
+--------------------------------------+---------------------------------+------------------------------+ Normally, you would compile this collection of code by executing the following command:
通常情况下,你会通过执行以下命令来编译所有的代码: gcc -o hellomake hellomake.c hellofunc.c -I. This compiles the two .c files and names the executable hellomake. The -I. is included so that gcc will look in the current directory (.) for the include file hellomake.h. Without a makefile, the typical approach to the test/modify/debug cycle is to use the up arrow in a terminal to go back to your last compile command so you don't have to type it each time, especially once you've added a few more .c files to the mix.
编译两个.c文件并输出可执行文件名称为hellomake 。-I 表示gcc会查看在当前目录(.)的头文件hellomake.h 。如果没有makefile文件,在典型的软件编写流程中的测试、修改、调试周期中,使用向上箭头在终端中找到你最后的使用编译命令(最近成功编译的那条命令),尤其是当你组合了比较多的.c文件时,这样你就不必每次都输入它,反正你肯定不愿意每次都输入一串很长的编译命令,而且每次都是同样的编译命令。 Unfortunately, this approach to compilation has two downfalls. First, if you lose the compile command or switch computers you have to retype it from scratch, which is inefficient at best. Second, if you are only making changes to one .c file, recompiling all of them every time is also time-consuming and inefficient. So, it's time to see what we can do with a makefile.
不幸的是,这种方法汇编有两个弱点。首先,如果你丢失、忘记了编译命令或者换了台电脑,你必须从头开始,这充其量是低效率的重新输入。其次,如果你只更改一个.c文件,每次重新编译所有的文件也费时,效率低下。那么,是时候看看,当我们有了makefile文件之后,我们能做什么。 The simplest makefile you could create would look something like:
您可以创建的最简单的Makefile应该是这个样子: Makefile
hellomake: hellomake.c hellofunc.c
gcc -o hellomake hellomake.c hellofunc.c -I.
If you put this rule into a file called Makefile or makefile and then type make on the command line it will execute the compile command as you have written it in the makefile. Note that make with no arguments executes the first rule in the file. Furthermore, by putting the list of files on which the command depends on the first line after the :, make knows that the rule hellomake needs to be executed if any of those files change. Immediately, you have solved problem # and can avoid using the up arrow repeatedly, looking for your last compile command. However, the system is still not being efficient in terms of compiling only the latest changes.
如果你把这个规则写到一个名为Makefile的文件或Makefile的文件里,然后输入make命令行会执行您在makefile文件写的编译命令。需要注意的是,不带参数默认执行文件中的第一条规则。此外,将命令依赖的文件列表放在第一行冒号(:)后面,如果任何文件发生改变,make知道hellomake规则需要重新执行。这样,你已经解决了第一个问题,避免反复使用向上箭头,寻找你的最后编译命令。但是,该系统仍没有被有效地满足只编译的最新变化的.c文件这个需求。 One very important thing to note is that there is a tab before the gcc command in the makefile. There must be a tab at the beginning of any command, and make will not be happy if it's not there.
需要注意的一个非常重要的事情是,在makefile gcc的命令前一个tab键。必须在任何命令的开头一个tab键,如果它不存在,make将会很不爽。 :) In order to be a bit more efficient, let's try the following:
为了更有效一点,让我们尝试以下操作: Makefile
CC=gcc
CFLAGS=-I. hellomake: hellomake.o hellofunc.o
$(CC) -o hellomake hellomake.o hellofunc.o -I.
So now we've defined some constants CC and CFLAGS. It turns out these are special constants that communicate to make how we want to compile the files hellomake.c and hellofunc.c. In particular, the macro CC is the C compiler to use, and CFLAGS is the list of flags to pass to the compilation command. By putting the object files--hellomake.o and hellofunc.o--in the dependency list and in the rule, make knows it must first compile the .c versions individually, and then build the executable hellomake.
所以,现在我们已经定义了一些常量CC和CFLAGS。这些特殊的常量用于告知make,我们想要如何编译hellomake.c、hellofunc.c。特别是,宏CC是给C编译器使用,而CFLAGS是标志列表,传递给编译器的参数。通过将目标文件hellomake.o、hellofunc.o放在规则的依赖列表中,使make知道它必须首先编译.C单独版本,然后生成可执行的hellomake 。 Using this form of makefile is sufficient for most small scale projects. However, there is one thing missing: dependency on the include files. If you were to make a change to hellomake.h, for example, make would not recompile the .c files, even though they needed to be. In order to fix this, we need to tell make that all .c files depend on certain .h files. We can do this by writing a simple rule and adding it to the makefile.
使用这种形式的makefile足以满足大多数小规模项目。然而,有一件事会发生:依赖发生的改变内容在.h文件中。如果仅仅对hellomake.h进行修改,即使这样需要重新编译.c文件,make也不会重新编译.c文件。为了解决这个问题,我们需要告诉make,所有.c文件取决于某些.h文件。我们可以通过编写一个简单的规则,并将其添加到生成文件中做到这一点。 Makefile
CC=gcc
CFLAGS=-I.
DEPS = hellomake.h %.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS) hellomake: hellomake.o hellofunc.o
gcc -o hellomake hellomake.o hellofunc.o -I.
This addition first creates the macro DEPS, which is the set of .h files on which the .c files depend. Then we define a rule that applies to all files ending in the .o suffix. The rule says that the .o file depends upon the .c version of the file and the .h files included in the DEPS macro. The rule then says that to generate the .o file, make needs to compile the .c file using the compiler defined in the CC macro. The -c flag says to generate the object file, the -o $@ says to put the output of the compilation in the file named on the left side of the :, the $< is the first item in the dependencies list, and the CFLAGS macro is defined as above.
这除了首先创建宏DEPS,并且将.h文件设置成为.c文件的依赖。然后,我们定义适用于所有.o后缀结尾的文件的规则。规则说,.o文件将取决于文件的.C版本和DEPS宏定义的.h文件。然后,规则说,生成的.o文件,使用CC宏定义的编译器来编译.c文件。-c标志说,生成目标文件,-o $@说把编译输出到冒号(:)左边的文件名中,$ <在依赖列表中的第一项,和CFLAGS宏被定义如前面所述。 As a final simplification, let's use the special macros $@ and $^, which are the left and right sides of the :, respectively, to make the overall compilation rule more general. In the example below, all of the include files should be listed as part of the macro DEPS, and all of the object files should be listed as part of the macro OBJ.
作为最终简化版本,让我们用特殊的宏$@和$^,他们分别代表冒号(:)左侧和右侧,让使整个编制规则更具有通用性。在下面的例子中,所有的.h文件应该被列为宏DEPS的一部分,并且所有的目标文件的应列为宏OBJ的一部分。 Makefile
CC=gcc
CFLAGS=-I.
DEPS = hellomake.h
OBJ = hellomake.o hellofunc.o %.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS) hellomake: $(OBJ)
gcc -o $@ $^ $(CFLAGS)
So what if we want to start putting our .h files in an include directory, our source code in a src directory, and some local libraries in a lib directory? Also, can we somehow hide those annoying .o files that hang around all over the place? The answer, of course, is yes. The following makefile defines paths to the include and lib directories, and places the object files in an obj subdirectory within the src directory. It also has a macro defined for any libraries you want to include, such as the math library -lm. This makefile should be located in the src directory. Note that it also includes a rule for cleaning up your source and object directories if you type make clean. The .PHONY rule keeps make from doing something with a file named clean.
那么,如果我们要把我们的.h文件放在include目录,在src目录下存放源代码,并在lib目录下存放了一些本地库,该怎么办?此外,我们可以以某种方式隐藏那些烦人的.o文件?当然,答案是肯定的。下面的makefile定义include和lib目录路径,并将OBJ作为src目录的子目录,将目标文件存放于OBJ目录。当然也定义了一个宏用于包含你想要的任何库,如数学库-lm。这个makefile应位于src目录。请注意,这还包括一条规则,如果你输入make clean会清理你的源代码和目标目录的规则。.PHONY规则防止make将clean识别为一个文件而不是一条规则。 Makefile
IDIR =../include
CC=gcc
CFLAGS=-I$(IDIR) ODIR=obj
LDIR =../lib LIBS=-lm _DEPS = hellomake.h
# 在$(patsubst %.c,%.o,$(dir) )中,patsubst把$(dir)中的变量符合后缀是.c的全部替换成.o,
# 在$(patsubst %,$(IDIR)/%,$(_DEPS))中,patsubst把$(_DEPS)目标前面加入一个路径前缀
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS)) _OBJ = hellomake.o hellofunc.o
# 同上
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) $(ODIR)/%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS) hellomake: $(OBJ)
gcc -o $@ $^ $(CFLAGS) $(LIBS) .PHONY: clean
clean:
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
So now you have a perfectly good makefile that you can modify to manage small and medium-sized software projects. You can add multiple rules to a makefile; you can even create rules that call other rules. For more information on makefiles and the make function, check out the GNU Make Manual, which will tell you more than you ever wanted to know (really).
所以,现在你有一个完美的makefile文件,您可以修改管理小型、中型的软件项目。您可以添加多个规则到makefile文件;你甚至可以创建规则来调用其他规则。有关makefile文件的更多信息,以及功能,请查阅GNU Make使用手册,它会告诉你,比你曾经想知道(真的)的更多 。
A Simple Makefile Tutorial的更多相关文章
- 简明awk教程(Simple awk tutorial)
整理翻译.原文地址:http://www.hcs.harvard.edu/~dholland/computers/awk.html 简明awk教程 为什么选awk? awk小巧.快速.简单.awk语言 ...
- [mk] 喝一杯咖啡, 写一写 Makefile
Makefile 是 Linux 下组织程序的一个工具,它的命令是 make. (首字母M/m都可以) [Makefile] Makefile 编写的主旋律: target: [dependency] ...
- [GNU] 喝一杯咖啡, 写一写 Makefile
Makefile 是 Linux 下组织程序的一个工具,它的命令是 make. (首字母M/m都可以) [Makefile] Makefile 编写的主旋律: target: [dependency] ...
- C/C++笔记 #035# Makefile
相关资料: Understanding roles of CMake, make and GCC GCC and Make ( A simple tutorial, teaches u how to ...
- 操作系统(5)实验0——makefile的写法
之前GCC那部分我提到过,gcc啥啥啥啥傻傻的那个指令只能够编译简单的代码,如果要干大事(例如突然心血来潮写个c开头的神经网络库之类的),还是要写Makefile来编译.其实在Windows下通常用I ...
- Makefile 简要辅导 【转载】
A Simple Makefile Tutorial Makefiles are a simple way to organize code compilation. This tutorial do ...
- [c++] Collection of key and difficult points
Operator Overload 1. 在重载下标运算符时(数组符号):不可重载为友元函数,必须是非static类的成员函数. why 2. overload ++ 时,如果是: int a; ...
- Debugging Under Unix: gdb Tutorial (https://www.cs.cmu.edu/~gilpin/tutorial/)
//注释掉 #include <iostream.h> //替换为 #include <iostream> using namespace std; Contents Intr ...
- 迷宫问题&MakeFile
先看一个有意思的问题, 我们定义一个二维数组表示迷宫. 它表示一个迷宫, 其中的1表示墙壁,0表示可以走的路, 只能横着走或竖着走,不能斜着走, 我们要编程序找出从左上角到右下角的路线.其实这个问题可 ...
随机推荐
- PAT 1129 Recommendation System[比较]
1129 Recommendation System(25 分) Recommendation system predicts the preference that a user would giv ...
- 【Cocos2dx3.x Lua】图片异步加载
一.说明 异步加载就是把消耗程序时间比较大的加载操作放到其他线程中,待加载完毕后通过回调函数的方式通知主线程. addImageAsync函数实现(Cocos2dx 3.3) Link: ...
- 【转】Deep Learning(深度学习)学习笔记整理系列之(六)
9.3.Restricted Boltzmann Machine (RBM)限制波尔兹曼机 假设有一个二部图,每一层的节点之间没有链接,一层是可视层,即输入数据层(v),一层是隐藏层(h),如果假设所 ...
- NodeJS学习笔记二
类声明和类表达式 ES6 中的类实际上就是个函数,而且正如函数的定义方式有函数声明和函数表达式两种一样,类的定义方式也有两种,分别是:类声明.类表达式. 类声明 类声明是定义类的一种方式,就像下面这样 ...
- CCPC-Wannafly Winter Camp Day7 (Div2, onsite)
Replay Dup4: 啥都不会? 只能看着两位聚聚A题? X: 模拟题不会写, 日常摔锅 u, v分不清, 日常演员 又是自己没理清楚就抢键盘上机导致送了一万个罚时, 日常背锅 A:迷宫 Solv ...
- HCNP学习笔记之史上最全华为路由器交换机配置命令大合集
先来一张思科和华为命令的对照表: 史上最全华为路由器交换机配置命令大合集,熟练掌握下面的华为路由器交换机配置知识点,你只需花几分钟的时间就能明白华为路由器交换机配置.交换机的配置命令等等. 华为路由器 ...
- 205315Java实验二实验报告
实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验步骤 (一)单元测试 用程序解决问题时,要会写三种码: ...
- git clone,push,pull,fetch命令详解
源自 Git是目前最流行的版本管理系统,学会Git几乎成了开发者的必备技能. Git有很多优势,其中之一就是远程操作非常简便.本文详细介绍5个Git命令,它们的概念和用法,理解了这些内容,你就会完全掌 ...
- autofac &web api 切换数据库
https://stackoverflow.com/questions/24188025/is-there-another-way-of-changing-database-instance-in-a ...
- 【bzoj5170】Fable(树状数组)
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=5170 我们会发现,经过一轮冒泡后,若a[i]的前面有比它大的数,就一定会有一个被丢到后 ...