自建工程makefile文件

自建工程makefile文件

前言:本人是linux开发C++工程师,最近心血来潮从0学习了Makefile。在网上搜索了N篇资料。终于写了一个符合自己需求的Makefile

需求:

自建一个工程,工程目录树:

.
├── bin
│   └── libPubClass.so
├── Makefile
├── objs
│   ├── pubclass
│   │   └── deamon
│   └── util
│       └── deamon
│           ├── deamon.d
│           └── deamon.o
├── shell
│   └── home
└── src
    ├── business
    ├── pubclass
    ├── startApp.cpp
    ├── test
    │   └── deamon
    ├── third-part
    └── util
        └── deamon
            ├── deamon.cpp
            └── deamon.h

代码主要放在src目录。objs目录 用来保存编译目录文件,bin目录存放生成的可执行文件及动态库。其中src/business用于业务相关目录,src/third-part用于第三 方代码,如boost,src/util用于公共代码,pubclass用于公共类。

正式动手之前应该了解下下面的知识。

1、makefile中的三个重要函数

wildcard

在目录下根据正则表达式遍历文件。

用法:wildcard $(dir).cpp

在dir目录下遍历所有cpp后缀文件,并以空格作为分割返回。

foreach

用法:foreach dir $(DIRS) action

将DIRS的依次赋于dir(不一定是目录),并执行action动作。action可以根据dir运行表达式得到想要的结果。

patsubst

用法:patsubst %.cpp, %.o $(FILES)

将FILES所有以cpp结尾的字符串替换成以o结尾。

根据上面三个函数,可以得到我们要的东西,如:

FILES=$(foreach
dir, $(DIRS),$(wildcard $(dir).cpp)

可以得到DIRS定义目录下的所有cpp文件,以目录+文件的形式赋值给FILES

OBJS=$(patsubst
src%, objs%, $(patsubst %.cpp, %.o, $(FILES)))

得到objs文件

DEPS=$(patsubst
%.o, %.d, $(OBJS))

得到DEPS文件

思路:

src
下的代码app文件先用g++
-MM
生成DEPS文件(放到objs对应目录,一个文件一个独立DEPS文件),后利用include加载到Makefile中,则可编译生成对应
obj
文件,放到objs目录下。后根据规则将目标文件统一编译生成可执行文件及动态库到bin目录下

思路分解:

将上面思路分解,先生成DEPS,将DEPS加载到makefile中,根据makefile规则生成obj文件,再将obj编译成动态库,最后将主文件链接动态库生成最终可执行文件。

思路清析了,下面正式动手:

1、生成DEPS

$(DEPS):$(FILES)

  g++
-MM $< -o [email protected] |\

sed
"$ s+$(patsubst %.d,%.o, $(notdir [email protected]))+$(patsubst %.d,%.o,[email protected])+g"
|\

sed
‘$$ a\\tg++ -fPIC -shared -c -o $(patsubst %.d, %.o, [email protected]) $<‘ >
[email protected]

这里因为g++
-MM $< -o [email protected]
将如下结果输出到屏幕。

deamon.o:
src/util/deamon/deamon.cpp src/util/deamon/deamon.h

所以我们要作一些处理,并重定向。刚加了两个sed命令。最终结果为:

objs/util/deamon/deamon.o:
src/util/deamon/deamon.cpp src/util/deamon/deamon.h
       
g++ -fPIC -shared -c -o  objs/util/deamon/deamon.o
src/util/deamon/deamon.cpp

这就是我们想要的。

2、将DEPS加载到makefile中。

这个很简单,只要用include命令就可以了,看下面代码

-include
$(DEPS)

这跟c中的#include效果是一样的。相当于在makefile中增加了一行代码

3、现在已经将DEPS加载到makefile,但怎样利用这段代码呢?

只需要在makefile加如下依赖关系就可以了:

$(TARGET):$(OBJS)

  g++
-o $(TARGET) $^

这样,所有的objs目标文件就编译生成了我们想要的APP文件了。

如果想生成动态库,则加上-shared和-fPIC选项就可以了。

$(LIB):$(OBJS)  

  g++
-shared -fPIC -o $(LIB) $^

如果生成可执行文件时要加上动态库

$(TARGET):$(OBJS)

  g++
-o $(TARGET) $^ -LLIBPATH -lyourlibname

4、你以为只是这样吗?

makefile文件执行时,是以第一个目标为入口的。也就是说我们要把之前生成的依赖关系通过第一个目标建立依赖关系。

现在我们理一理我们生成的文件。

1、DEPS文件,要加载到makefile

2、objs文件,用来生成动态库或可执行文件

3、可执行文件或动态库

首先要生成的是DEPS文件,然后通过DEPS加载到makefile中的命令生成objs,最后生成可执行文件或库文件当然库文件要先于可执行文件生成

所以所有的关系总结如下:

可执行是最终的产物,依赖于库文件和objs文件,库文件依赖objs文件,objs依赖include也就是DEPS要最先生成。

all:$(DEPS)
$(OBJS) $(LIB) $(TARGET)

  #这里可以什么都不用写

$(DEPS):$(FILES)

  g++命令

-include
$(DEPS)  #
这里建立了objs的依赖关系,是自动加载进makefile中的

$(LIB):$(OBJS)

  g++命令

$(TARGET):$(OBJS)
$(LIB)

  g++命令

如此,当有一个cpp文件,或h头文件有修改时,则依赖它的所有文件都会重新编译生成,最终也就更新了可执行文件及库文件。

一个完整的makefile文件就大功告成了

  

时间: 2024-08-27 05:25:13

自建工程makefile文件的相关文章

工程管理之makefile与自动创建makefile文件过程

(风雪之隅 http://www.laruence.com/2009/11/18/1154.html) Linux Makefile自动编译和链接使用的环境 想知道到Linux Makefile系统的真相么,想知道Linux Makefile系统中藏有的内在奥义么,只有我来给大家全面讲解介绍Linux Makefile系统作为Linux下的程序开发人员,大家一定都遇到过Linux Makefile,用make命令来编译自己写的程序确实是很方便.一般情况下,大家都是手工写一个简单Linux Mak

eclipse自己写makefile 建工程

新建工程,makefile project with existing code 选择目录,在目录下新建makefile文件,makefile文件中要有all :  这样的字样

linux中Makefile文件相关内容

第一章.概述什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional(专业)的程序员,makefile还是要懂.这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义.特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力.因为,makefile关系到了整个

嵌入式 Linux开发Kernel移植(三)——Kernel工程Makefile分析

嵌入式 Linux开发Kernel移植(三)--Kernel工程Makefile分析 本文选择三星发布的基于SMDKV210开发板的linux 2.6.35.7版本kernel. 一.Kernel Makefle体系简介 1.Kernel Makefile体系组成 Kernel Makefile体系包含Kconfig和Kbuild两个系统. Kconfig系统 Kconfig 对应的是内核配置阶段,make xxconfig就是在使用Kconfig系统.Kconfig由三部分组成: script

makefile文件操作大全

 Makefile的规则 -- 转自 :http://blog.csdn.net/ruglcc/article/details/7814546/ 在讲述这个Makefile之前,还是让我们先来粗略地看一看Makefile的规则.  target... : prerequisites ...           command           ...           ...         --------------------------------------------------

QT基础(五)QT工程pro文件模板变量 使用

QT工程pro文件模板变量(TEMPLATE)模板变量告诉qmake为这个应用程序生成哪种makefile.下面是可供使用的选择: app - 建立一个应用程序的makefile.这是默认值,所以如果模板没有被指定,这个将被使用. lib - 建立一个库的makefile. vcapp - 建立一个应用程序的Visual Studio项目文件. vclib - 建立一个库的Visual Studio项目文件. subdirs - 这是一个特殊的模板,它可以创建一个能够进入特定目录并且为一个项目文

linux中make命令的简单使用以及Makefile文件的书写

Makefile 会不会写makele,从一个侧面说明了一个是否具备完成大型工程的能力. 一个工程中的源件不计数,其按类型.功能.模块分别放在若干个目录中,makele定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makele就像一个Shell脚本一样,其中也可以执行操作系统的命令.makele带来的好处就是"自动化编译",一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率. ma

nixyx —— 一个小巧的项目工程/编译文件生成器(构建系统?)

恩..nixyx确实算不上是一个构建系统. 所谓构建系统,比如GNU的Autotools,那是一套很完整的构建体系,包括了程序的配置,编译和安装三大部分. 类似的软件还有:google的gyp.腾讯的Blade等.它们最大的好处在于,可以不考虑平台之间的差别,使用统一的配置文件和命令,做到跨平台部署. 它们往往还支持很多很高端的功能,比如集成自动测试,代码检查(Blade).. 可是我暂时不需要这些复杂的功能.我正在编写的nixy库是一个跨平台/编译器的C++库,它非常小,没必要使用大型的(或者

Contiki 2.7 Makefile 文件(一)

一.主控Makefile 这里以hello-world例子为主线,从其工程Makefile开始,解析整个build过程. (1)CONTIKI_PROJECT = hello-world 定义变量CONTIKI_PROJECT为 hello-world (2)all:  $(CONTIKI_PROJECT) all是第一个目标,也就是默认目标,其为伪目标,依赖于CONTIKI_PROJECT变量定义的文件. 由于默认目标的特性是,总是被执行(除非显式定义了目标),但由于all是伪目标,只是一个标