首页 > 其他分享 >Make和Makefile

Make和Makefile

时间:2023-08-29 11:41:40浏览次数:39  
标签:src sub2 .. sub1 ++ Make Makefile cpp



文章目录

  • 一、demo的目录结构
  • 二、使用Makefile生成可执行文件
  • 1、简单版本的Makefile
  • 2、使用变量改进Makefile
  • 3、使用自动变量继续改进Makefile
  • 4、使用 %.o:%.c 样式继续改进Makefile
  • 5、使用模块化继续改进Makefile
  • 三、Makefile中一些关键语法
  • 1、wildcard
  • 2、notdir
  • 3、patsubst
  • 4、`@、$@、$^、$<`
  • 四、一个实例详解


Makefile是一个神奇的东西,有了它只需一个make命令就可以让源文件按你的规则编译成你所想要的程序。非常简单,方便。对于Keil,VS等IDE,一般只需点一下绿色的三角按钮,就可以完成编译。但具体内部是怎么实现编译的?改动文件后如何只编译改动的文件?学完makefile就可以掌握这些东西,从而对系统编程会有更深层次的理解。

Make和Makefile_g++


Make和Makefile_可执行文件_02

一、demo的目录结构

Make和Makefile_可执行文件_03

二、使用Makefile生成可执行文件

1、简单版本的Makefile

//例行公式,表示在bin目录下生成可执行文件
all : ../bin/make_test 

//可执行文件(make_test)的生成依赖于多个目标文件(.o),'\'表示转义字符
../bin/make_test : ./main.o ./sub1/dummy1.o \
					./sub1/dummy2.o ./sub2/dummy3.o \
					./sub2/dummy4.o

//生成目标文件(.o)
	g++ -o ../bin/make_test ./main.o ./sub1/dummy1.o \
					./sub1/dummy2.o ./sub2/dummy3.o \
					./sub2/dummy4.o

//目标文件(.o)的生成依赖于源文件(.cpp)
./main.o : ../src/main.cpp
	g++ -o ./main.o -c ../src/main.cpp -I ../inc

./sub1/dummy1.o : ../src/sub1/dummy1.cpp
	g++ -o ./sub1/dummy1.o -c ../src/sub1/dummy1.cpp -I ../inc

./sub1/dummy2.o : ../src/sub1/dummy2.cpp
	g++ -o ./sub1/dummy2.o -c ../src/sub1/dummy2.cpp -I ../inc

./sub2/dummy3.o : ../src/sub2/dummy3.cpp
	g++ -o ./sub2/dummy3.o -c ../src/sub2/dummy3.cpp -I ../inc

./sub2/dummy4.o : ../src/sub2/dummy4.cpp
	g++ -o ./sub2/dummy4.o -c ../src/sub2/dummy4.cpp -I ../inc

//清理目标文件(.o)和可执行文件
clean:
	rm -rf ./*.o ./sub1/* ./sub2/* ../bin/*

2、使用变量改进Makefile

Make和Makefile_Makefile_04

all : ../bin/make_test

//':='表示不跟踪变量,一般用于固定格式的命令或变量
RM := rm -rf

//'='表示跟踪变量,可以追加和修改,类似于C++中的引用
OBJS = ./main.o ./sub1/dummy1.o \
		./sub1/dummy2.o ./sub2/dummy3.o \
		./sub2/dummy4.o

//$(val)表示使用变量
../bin/make_test : $(OBJS)
	g++ -o ../bin/make_test $(OBJS)

./main.o : ../src/main.cpp
	g++ -o ./main.o -c ../src/main.cpp -I ../inc

./sub1/dummy1.o : ../src/sub1/dummy1.cpp
	g++ -o ./sub1/dummy1.o -c ../src/sub1/dummy1.cpp -I ../inc

./sub1/dummy2.o : ../src/sub1/dummy2.cpp
	g++ -o ./sub1/dummy2.o -c ../src/sub1/dummy2.cpp -I ../inc

./sub2/dummy3.o : ../src/sub2/dummy3.cpp
	g++ -o ./sub2/dummy3.o -c ../src/sub2/dummy3.cpp -I ../inc

./sub2/dummy4.o : ../src/sub2/dummy4.cpp
	g++ -o ./sub2/dummy4.o -c ../src/sub2/dummy4.cpp -I ../inc

clean:
	$(RM) $(OBJS) ../bin/*

3、使用自动变量继续改进Makefile

Make和Makefile_Makefile_05

all : ../bin/make_test

RM := rm -rf

OBJS = ./main.o ./sub1/dummy1.o \
		./sub1/dummy2.o ./sub2/dummy3.o \
		./sub2/dummy4.o

../bin/make_test : $(OBJS)
	g++ -o $(@) $(^)

./main.o : ../src/main.cpp
	g++ -o $(@) -c $(<) -I ../inc

./sub1/dummy1.o : ../src/sub1/dummy1.cpp
	g++ -o $(@) -c $(<) -I ../inc

./sub1/dummy2.o : ../src/sub1/dummy2.cpp
	g++ -o $(@) -c $(<) -I ../inc

./sub2/dummy3.o : ../src/sub2/dummy3.cpp
	g++ -o $(@) -c $(<) -I ../inc

./sub2/dummy4.o : ../src/sub2/dummy4.cpp
	g++ -o $(@) -c $(<) -I ../inc

clean:
	$(RM) $(OBJS) ../bin/*

4、使用 %.o:%.c 样式继续改进Makefile

Make和Makefile_可执行文件_06

all : ../bin/make_test

RM := rm -rf

OBJS = ./main.o ./sub1/dummy1.o \
		./sub1/dummy2.o ./sub2/dummy3.o \
		./sub2/dummy4.o

../bin/make_test : $(OBJS)
	g++ -o $(@) $(^)

./%.o : ../src/%.cpp
	g++ -o $(@) -c $(<) -I ../inc

./sub1/%.o : ../src/sub1/%.cpp
	g++ -o $(@) -c $(<) -I ../inc

./sub2/%.o : ../src/sub2/%.cpp
	g++ -o $(@) -c $(<) -I ../inc

clean:
	$(RM) $(OBJS) ../bin/*

5、使用模块化继续改进Makefile

Make和Makefile_Makefile_07

// ./sub1/sub.mk

OBJS += ./sub1/dummy1.o ./sub1/dummy2.o

./sub1/%.o : ../src/sub1/%.cpp
	g++ -o $(@) -c $(<) -I ../inc
// ./sub2/sub.mk

OBJS += ./sub2/dummy3.o ./sub2/dummy4.o

./sub2/%.o : ../src/sub2/%.cpp
	g++ -o $(@) -c $(<) -I ../inc
// ./sub.mk

OBJS += ./main.o \

./%.o : ../src/%.cpp
	g++ -o $(@) -c $(<) -I ../inc
// Makefile终极版本

RM := rm -rf

-include ./sub.mk
-include ./sub1/sub.mk
-include ./sub2/sub.mk

all : ../bin/make_test

../bin/make_test : $(OBJS)
	@echo 'Building target : $@'
	@echo 'Invoking : GCC C++ Linker'
	g++ -o $(@) $(^)
	@echo 'Finishing building target: $@'
	@echo ' '

//显式指定某个目标为伪目标 ,表明不论是否有 clean 这个文件, make clean 中 make 都会将 clean 当作伪目标。
.PHONY : clean 

clean:
	-$(RM) $(OBJS) ../bin/*

三、Makefile中一些关键语法

Makefile里的函数使用,和取变量的值类似,是以一个‘$’开始,然后是一个括号里面是函数名和需要的参数列表,多个变量用逗号隔开,像这样:

return = $(functionname  arg1,arg2,arg3...)。

1、wildcard

SRC = $(wildcard *.c ./foo/*.c)

搜索当前目录及./foo/下所有以.c结尾的文件,生成一个以空格间隔的文件名列表,并赋值给SRC.当前目录文件只有文件名,子目录下的文件名包含路径信息,比如./foor/bar.c。

2、notdir

SRC = $(notdir wildcard)

去除所有的目录信息,SRC里的文件名列表将只有文件名

3、patsubst

OBJ = $(patsubst %.c %.o $(SRC))

patsubst是patten substitude的缩写,匹配替代的意思。这句是在SRC中找到所有.c 结尾的文件,然后把所有的.c换成.o

4、@、$@、$^、$<

// target:表示我们的目标,components:表示依赖对象,rule:表示规则
target:components
	rule

@:表示不显示命令本身

$@:代表目标文件(target)

$^:代表所有的依赖文件(components)

$<:代表第一个依赖文件(components中最左边的那个)。

四、一个实例详解

# 定义一些变量
DIR_BIN = .
DIR_OBJ = ./obj
DIR_SRC = ./src

# 把DIR_SRC目录下所有的.CPP文件展开
SRC = $(wildcard $(DIR_SRC)/*.cpp)
# 把DIR_SRC目录下所有的.CPP替换为.o文件
OBJ = $(patsubst %.cpp,$(DIR_OBJ)/%.o,$(notdir $(SRC)))

#  -g表示调试,-Wall表示让所有编译警告都显示出来,
# -std=c++11表示使用C++11版本,-pthread表示使用多线程库,
# -O3表示产生更高级别的优化
CXX_FLAG = -g -Wall -std=c++11 -pthread -O3
CC = g++

TARGET = exec

# 生成可执行文件
$(DIR_BIN)/$(TARGET) : $(OBJ)
	$(CC) $(CXX_FLAG) -o $@ $^

# 表示把DIR_SRC目录下所有的.cpp文件编译成.o文件。
$(DIR_OBJ)/%.o : $(DIR_SRC)/%.cpp
	if [ ! -d $(DIR_OBJ) ];	then mkdir -p $(DIR_OBJ); fi;
	$(CC) $(CXX_FLAG) -c $< -o $@

# 清空所有目标文件
.PHONY : clean
clean : 
	-rm -rf $(DIR_OBJ)

  

标签:src,sub2,..,sub1,++,Make,Makefile,cpp
From: https://blog.51cto.com/u_6526235/7273742

相关文章

  • Windows10 环境下使用 Cmake 和 MinGW-w64 编译安装 OpenCV 4.0.1
    Windows10环境下使用Cmake和MinGW-w64编译安装OpenCV4.0.1翻译搜索复制......
  • makefile实操准备
    (目录)一、系统变量系统变量描述$*不包括扩展名的目标文件名称$+所有的依赖文件,以空格分隔$<表示规则中的第一个依赖项$?所有时间戳比目标文件晚的依赖文件,以空格分隔$@目标Target的完整名称$^所有不重复的依赖文件,以空格分隔$%如果目标是归......
  • cmake学习方法+CHI独占+ctags编写+C/C++语言原子的序+单核比多核快的C代码
    cmake学习方法主要是cmake这个东西好像有点抽象,而我想要的是完完全全的控制,虽然是花里胡哨的;但是在高手看来,这些东西有点过家家,而不是真正意义上的技术,甚至经常被怼,净是花拳绣腿,不容易阅读,控制效果不好,有时候还有语法错误云云。因此我还是用的Makefile,但是想必cmake是更好的,因......
  • Makefile练习1:静态库/动态库的生成和使用
    自己动手写下Makefile,并记录备忘。工程目录如下一、生成静态库libAdd.a1、头文件add.h#include<stdio.h>intadd(inta,intb);2、源文件add.c#include"add.h"intadd(inta,intb){ return(a+b);}3、Makefile(1)入门版libAdd.a:add.o ar-rlibAdd.aad......
  • 【转载】CMake从头开始学习-上
    这篇文章写的太好了非常适合新手入门,原文链接是https://subingwen.cn/cmake/CMake-primer/index.html......
  • Makefile学习笔记
    规则:每条规则由三个部分组成分别是目标(target),依赖(depend)和命令(command)。#示例#规则1app:a.ob.oc.ogcca.ob.oc.o-oapp#规则2a.o:a.cgcc-ca.c#规则3b.o:b.cgcc-cb.c#规则4c.o:c.cgcc-cc.c makefile有自动推导功能,有时漏......
  • cmake定义宏
    比如在打印日志信息的时候定义宏test.cpp#include<stdio.h>#defineNUMBER3intmain(){inta=10;#ifdefDEBUGprintf("我是一个程序猿,我不会爬树...\n");#endiffor(inti=0;i<NUMBER;++i){printf("hello,GCC!!!\n");......
  • cmake中list,set的对字符串操作
    cmake中所有的对象都是string,所以我们对这些的操作就是对字符串的操作,里面提供追加和删除的方法 CMakeLists.txtcmake_minimum_required(VERSION3.15)project(test)#方式二file(GLOBSRC${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)message("=========================")m......
  • cmake动态库
    动态库有传递性,但是通过修饰符修饰public可传递,因为需要用到动态链接库,而且动态链接库只不过是一个文件,只能生成的可执行文件后面,因为只有有了可执行文件才需要链接动态库CMakeLists.txtcmake_minimum_required(VERSION3.15)project(test)#添加头文件aux_source_director......
  • cmake生成动静态库文件及目录
    CMakeLists.txtcmake_minimum_required(VERSION3.15)project(test)#set(SRCadd.cpp;div.cpp;mult.cpp;main.cpp;sub.cpp)#${PROJECT_SOURCE_DIR}指定的就是cmakelists所在的路径aux_source_directory(搜索路径)方式一#aux_source_directory(${PROJECT_SOURCE_DIR}/sr......