`
david_je
  • 浏览: 373128 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

一个简单地Makefile入门(翻译)

 
阅读更多

         Makefile是一个简单组织代码编译的方法。这个入门只是设计到了make的一些皮毛,它主要是作为一个初学者指南来帮助你,能够快速和简单地去为中小型项目去创建自己的makefile文件。

        一个简单地例子

         这里有3个文件,hellomake.c,hellofunc.c和hellomake.h,他们能够代表一些典型的项目。

          hellomake.c

#include 

int main() {
  // call a function in another file
  myPrintHelloMake();

  return(0);
}

   hellofunc.c   

#include 

int main() {
  // call a function in another file
  myPrintHelloMake();

  return(0);
}

 hellomake.h

   

/*
example include file
*/

void myPrintHelloMake(void);
 

 

   一般情况下,你可能会使用如下命令去编译这些代码:

    gcc  -o hellomake hellomake.c hellofunc.c -I.

     

     它编译这两个C文件成可执行文件hellomake. 参数I是为了帮助gcc编译器查找当前目录下面的头文件hellomake.h.如果没有makefile文件,最典型的方法去做测试,修改和调试是在终端不断的使用上标回来上次执行难的命令重新执行。特别是一旦有增加一些C文件到工程里去。

     不幸的是,这种方法去编译代码有两个缺点。第一,如果你丢失了编译命令或更换电脑,你不得不去重新输入命令,这样就不是很高效了。第二,如果你只是修改了其中的一个C文件,重新编译所有的文件也是一件很花时间的事情,这个时候就轮到makefile上台了。

      

      下面有5个小例子来帮助我们去了解makefile:

       makefile1:

       

hellomake: hellomake.c hellofunc.c
        gcc -o hellomake hellomake.c hellofunc.c  -I.

 

     将这个命令写到文件并保存,命名为Makefile或者makefile,打开终端,输入make就可以去执行里面的命令了。注意make是没有参数去执行文件中的第一个规则的。此外,将执行命令依赖的文件列表放在:之后,make知道这个规则hellomake需要被执行,如果这些文件被改变的话。这样就解决了第一个问题,而且可以避免重复使用上标去查找你执行的上一条命令。但是,系统编译最近修改的文件时还是没有提高效率。

     注意:makefile中编辑执行的命令行是,缩进是一个tab而不是空格,否则执行makefile时会报错的。

 

      Makefile2

      

CC=gcc
CFLAGS=-I.

hellomake: hellomake.o hellofunc.o
     $(CC) -o hellomake hellomake.o hellofunc.o -I.

     

      我们在这个makefile中定义个一些常量,CC和CFLAGS. 他们是用来传递一些特殊的常量给make去编译文件hellomake.c和hellofunc.c.特别,宏CC是C语言来编译使用的.

       这个makefile基本可以满足大多数的小项目。然而,还是有一部分没有覆盖到,include文件的依赖关系。如果你修改了hellomake.h文件,make将不会重新编译,即使你真的需要重新编译。为了解决这个问题,我们需要告诉make所有的C文件依赖哪些确切的头文件。

      

      Makefile3

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.

    这个文件问新建了一个宏DEPS, 表示所有的C文件依赖的头文件。接着,我们定义了一个规则给所有以.o结尾的文件,就是说.o文件依赖.c文件和在DEPS中的头文件。参数-c表示产生目标文件,参数-o $@表示:符号左边的那些内容,参数$<是第一个依赖。

     我们来看看$@和$^,他们分别代表:的左边和右边。    

 

      Makefile4

     

CC=gcc
CFLAGS=-I.
DEPS = hellomake.h
OBJ = hellomake.o hellofunc.o 

%.o: %.c $(DEPS)
	$(CC) -c -o $@ $< $(CFLAGS)

hellomake: $(OBJ)
	gcc -o $@ $^ $(CFLAGS)

    所有的目标文件都要在OBJ中列出。

 

    Makefile5

   

IDIR =../include
CC=gcc
CFLAGS=-I$(IDIR)

ODIR=obj
LDIR =../lib

LIBS=-lm

_DEPS = hellomake.h
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)/*~ 

 

    如果想把头文件放在一个include目录,源代码都在src目录,本地库文件在lib目录该怎么办?我们能隐藏哪些烦人的.o文件吗?答案是当然的。这个makefile定义了include和lib目录,而且把目标文件放在一个obj的子目录中.。它也包括你想要包含的宏定义,例如math库-lm. 这个makefile位于src目录中。注意,它还包括clean的规则去清除所有的的代码和目标文件目录(运行make clean).

     .PHONY规则处理一些与文件名相关的清理工作。

   

     现在应该对makefile有一个基本的了解了,可以去修改makefile来管理中小型软件项目的编译工作。也可以加入一切其他的规则到makefile文件中来。更多信息可以参考http://www.gnu.org/software/make/manual/make.html 

     

分享到:
评论

相关推荐

    qt入门代码编写的第一个示范代码

    总结,"qt入门代码编写的第一个示范代码"是一个很好的起点,它让你了解了如何使用QT Designer创建简单的用户界面,并通过"Hello Qt/Embedded"展示了基本的QT编程概念。随着经验的积累,你可以进一步探索QT的高级特性...

    gnu make 手册中文版

    3. **简单示例**:展示了如何创建一个简单的Makefile,包括一个基本的编译C程序的规则。 4. **make如何工作**:详细解释了Make如何读取Makefile,分析依赖关系,以及决定何时执行命令。 5. **指定变量**:Make支持...

    QT多语言实现快速入门示例

    至此,一个简单的QT多语言应用就完成了。用户可以根据自己的需求在运行时自由切换语言,而开发者则可以通过维护`.ts`文件来轻松管理不同语言的翻译。 通过这个示例,我们可以了解到QT多语言支持的基本流程:创建`....

    CodeBlocks Manual原文加中文翻译

    `CodeBlocks Manual翻译` 文件可能是社区成员或爱好者对原版英文手册的中文译本,对于中文使用者来说,这是一个非常有价值的资源。它使得中国用户能够更方便地理解CodeBlocks的各项操作和设置,无需面对语言障碍。 ...

    预处理器,编译器,汇编器和链接器,一起构成了编译系统

    首先,我们从一个简单的 C 语言程序 "helloworld.c" 开始,这是一个常见的入门级程序。源代码文件本质上是由 0 和 1 组成的位序列,其中的字节代表了文本字符。当执行程序时,我们需要将这些高级语言指令转化为底层...

    Qt旅程——flybird

    例如,为了创建一个简单的对话框,可以按照以下步骤操作: 1. 打开`Qt Designer`。 2. 选择“Dialog without Buttons”模板。 3. 创建并保存`.ui`文件。 4. 使用`qmake`和`make`命令编译`.ui`文件生成对应的C++...

    sf4.4-website-skeleton-starter:一个简单的Symfony 4.4网站框架,具有某些功能,例如WebpackEncore,TimeContinuum,用户身份验证等。

    它展示了如何使用 , ,和其它东西(如一个Makefile,与法克尔,单元和功能测试,贝哈特,警卫,活动,实体特征,Q&A工具,翻译,命令...夹具)继建议的SensioLabs最佳做法。 安装说明 项目要求 以及。 专案检视 ...

    l4_dev_talk.pdf

    最后,文档中还提到了一个简单的L4 "Hello World" 示例,这是一个很好的入门实践,可以帮助新手快速上手L4开发。 - **编写源代码**:编写一个简单的C程序,输出"Hello World"。 - **编译程序**:使用GCC编译器将源...

    Linux程序设计权威指南_下

    系统和网络编程章节是本书的一个重点,涉及到套接字编程、并发服务器设计、网络协议的理解等。这些内容对于开发网络服务软件至关重要,例如Web服务器、FTP客户端或聊天应用。读者将学会如何利用Linux系统调用来实现...

    自己动手写操作系统(含源代码).part2

    有关操作系统的书籍资料可以找到很多,但是关注如何帮助读者实现一个试验性操作系统的书籍却不多见,本书便是从一个简单的引导扇区开始,讲述一个操作系统成长的故事,以作读者参考之用。 本书面向实践,通过具体...

    自己动手写操作系统(含源代码).part1

    有关操作系统的书籍资料可以找到很多,但是关注如何帮助读者实现一个试验性操作系统的书籍却不多见,本书便是从一个简单的引导扇区开始,讲述一个操作系统成长的故事,以作读者参考之用。 本书面向实践,通过具体...

    hello-world:Длядругихрепозитов\\

    描述中的"你好,世界"和"Длядругихрепозитов"(俄语,翻译为"为了其他仓库")可能意味着这个项目不仅限于一个简单的“Hello, World”示例,还可能包含了针对其他编程项目或仓库的基础知识。...

    Deep Learning 实战之 word2vec.pdf

    - 虽然word2vec常被视为深度学习模型,但其本身是一个层次较浅的神经网络模型。 - 深层模型通常需要在word2vec上额外添加输出层,例如Softmax层。 #### 3. word2vec的高效性 - word2vec训练速度极快,优化后的单机...

    android NDK

    综上所述,Android NDK为开发者提供了一个强大的工具集,使得他们能够在Android平台上利用C/C++开发高性能的应用程序。无论是Windows还是Linux环境下的配置与开发,都旨在帮助开发者充分利用NDK的优势,创建出更加...

    你好,世界:Éum teste

    "Éum teste meu primeiro repositório" 是葡萄牙语,翻译为 "这是一个我的第一个仓库的测试",这进一步证实了这是一个新手在学习版本控制,比如Git,时创建的初始项目。 在IT领域,"Hello, World!" 程序通常是一...

Global site tag (gtag.js) - Google Analytics