MacOS 迅速上手 Makefile 编译 C / C++ 工程

前言

本文以实用为第一目标,将给出一个 M a c O S MacOS MacOS 编译 C / C C/C C/C++ 工程的固定模板,以便读者可以迅速上手!

文章主要如下分为三部分:

  1. 为什么需要 M a k e f i l e Makefile Makefile
  2. 如何编写 M a k e f i l e Makefile Makefile
  3. M a c O S MacOS MacOS 下编译 C / C C/C C/C++ 工程的固定模板

如果觉得文章对你有帮助,请点个赞再走!(•̀ᴗ•́)و ̑̑


为什么需要 M a k e f i l e Makefile Makefile

M a k e f i l e Makefile Makefile 的出现主要是由于在大型的 C / C C/C C/C++ 工程中,经常会出现文件相互依赖的情况。举个例子, A A A 文件调用了 B B B 文件中的 类 / 函数,因此我们需要将 A , B A,B A,B 文件统一链接在一起形成最终的可执行文件。

正是由于上述情况的存在,使得我们必须将工程中所有文件链接在一起,而手工一条一条命令敲又非常费时,因此我们需要 M a k e f i l e Makefile Makefile,在我们给定编译顺序后自动帮助我们完成编译。

我们将以下面的三份代码为例来介绍在 M a c O S MacOS MacOS 下使用 M a k e f i l e Makefile Makefile 的方法。

  • A . c p p A.cpp A.cpp
#include <iostream>
#include "B.h"
using namespace std;

int main() {
    cout << add(1, 2) << endl;
    return 0;
}
  • B . h B.h B.h
#ifndef B_H
#define B_H
    int add(int a, int b);
#endif
  • B . c p p B.cpp B.cpp
#include <iostream>
#include "B.h"

int add(int a, int b) {
    return a + b;
}

由此不难发现,想要让 A . c p p A.cpp A.cpp 文件能够正确执行,我们需要将这三个文件统一链接在一起!如果一条一条命令输的话,我们需要依次执行下述命令。

g++ -c A.c
g++ -c B.c
g++ -o main A.o B.o

显然一条一条命令输非常麻烦,因此我们需要 M a k e f i l e Makefile Makefile 来简化这个过程!


如何编写 M a k e f i l e Makefile Makefile

我们以上述的例子为例,简要介绍我们的固定模板!

  • 文件结构
    • 两个大文件夹: b u i l d build build s r c src src
    • b u i l d : build: build: 分为两个小文件夹, b i n bin bin o b j e c t s objects objects
      • b i n : bin: bin: 放最终的可执行文件
      • o b j e c t s : objects: objects: s r c src src 中的文件所生成的 . o .o .o 文件
    • s r c : src: src: 工程文件
    • 最外层: M a k e f i l e Makefile Makefile m a i n main main(最终可执行文件的链接文件)
      在这里插入图片描述
  • M a k e f i l e Makefile Makefile 语法规则
    • $@: 目标文件
    • $^: 所有依赖文件
    • $< 第一个依赖文件
    • 编译语法规则
      • targets: 文件名,以空格分开,可以使用通配符
      • command: 命令行,如果其不与 targets:prerequisites \text{targets:prerequisites} targets:prerequisites 在一行,则必须以 T a b Tab Tab 键卡头,如果和 targets:prerequisites \text{targets:prerequisites} targets:prerequisites 在一行,则可以用分号作为分隔
      • prerequisites: 目标所依赖的文件,如果其中某个文件要比目标文件要新,则目标就被认为是 “过时的”,被认为是需要重新生成的
      • r e f : ref: ref: 《跟我一起写 Makefile \text{Makefile} Makefile
targets: prerequisites
	command
  • 定义变量
    • 文件路径
    • 编译命令参数
    • 最终目标文件
dest_dir = build
src_dir = src
obj_dir = $(dest_dir)/objects
bin_dir = $(dest_dir)/bin

CC = g++
RESULT = main
CFLAGS = -Wall -O3 -std=c++14
CFILES = A.cpp B.cpp
ofiles = $(CFILES:%.cpp=$(obj_dir)/%.o)

program = $(bin_dir)/$(RESULT)
$(program): $(ofiles)
  • 产生 . o .o .o 文件
    • 第一句:输出编译信息
    • 第二句:如果不存在路径上的文件夹,则创建文件夹
    • 第三句:执行 g++ -c xxx.c 命令
# src 中所有 cpp 文件
$(obj_dir)/%.o: $(src_dir)/%.cpp
	@echo ">>> Compiling" $< "<<<"
	@if [ ! -d $(obj_dir) ]; then mkdir -p $(obj_dir); fi;
	$(CC) $(CFLAGS) -c $< -o $@

# src 所有子文件夹中 cpp 文件
$(obj_dir)/%.o: $(src_dir)/*/%.cpp
	@echo ">>> Compiling" $< "<<<"
	@if [ ! -d $(obj_dir) ]; then mkdir -p $(obj_dir); fi;
	$(CC) $(CFLAGS) -c $< -o $@
  • 将所有 . o .o .o 文件链接在一起生成可执行文件,并在最外层生成可执行文件的链接文件
    • 第一句:输出编译信息
    • 第二句:如果不存在路径上的文件夹,则创建文件夹
    • 第三句:执行 g++ -o 目标可执行文件 xxx1.o xxx2.o ... 命令
    • 第四句:将目标可执行文件链接到最外层
$(bin_dir)/%:
	@echo ">>> Linking" $@ "<<<"
	@if [ ! -d $(bin_dir) ]; then mkdir -p $(bin_dir); fi;
	$(CC) -o $@ $^
	ln -sf $@ $(notdir $@)
  • m a k e make make c l e a n clean clean 命令
    • 当我们需要重新编译时,我们想要快速地删除上一次编译所产生的文件
    • 我们可以自定义 m a k e make make c l e a n clean clean 命令,实现对上一次编译生成文件的快速清理
.PHONY: clean
clean:
	rm -rf $(dest_dir)
	rm -f $(RESULT)

M a c O S MacOS MacOS 下编译 C / C C/C C/C++ 工程的固定模板

至此,我们实现了一个简易的编译 C / C C/C C/C++ 工程的 M a k e f i l e Makefile Makefile 的固定模板。

每次需要编译,则先执行 m a k e make make c l e a n clean clean,再执行 m a k e make make

C C C 工程: g c c gcc gcc C C C++ 工程: g g g++

增加需要编译的文件: 在 CFILES \text{CFILES} CFILES 变量后面继续添加即可

# $@: 目标文件, $^: 所有依赖文件, $<: 第一个依赖文件
# 语法规则:
# 	targets: prerequisites
# 		command
dest_dir = build
src_dir = src
obj_dir = $(dest_dir)/objects
bin_dir = $(dest_dir)/bin

CC = g++
RESULT = main
CFLAGS = -Wall -O3 -std=c++14
CFILES = A.cpp B.cpp
ofiles = $(CFILES:%.cpp=$(obj_dir)/%.o)

program = $(bin_dir)/$(RESULT)
$(program): $(ofiles)

$(bin_dir)/%:
	@echo ">>> Linking" $@ "<<<"
	@if [ ! -d $(bin_dir) ]; then mkdir -p $(bin_dir); fi;
	$(CC) -o $@ $^
	ln -sf $@ $(notdir $@)

$(obj_dir)/%.o: $(src_dir)/%.cpp
	@echo ">>> Compiling" $< "<<<"
	@if [ ! -d $(obj_dir) ]; then mkdir -p $(obj_dir); fi;
	$(CC) $(CFLAGS) -c $< -o $@

$(obj_dir)/%.o: $(src_dir)/*/%.cpp
	@echo ">>> Compiling" $< "<<<"
	@if [ ! -d $(obj_dir) ]; then mkdir -p $(obj_dir); fi;
	$(CC) $(CFLAGS) -c $< -o $@

.PHONY: clean
clean:
	rm -rf $(dest_dir)
	rm -f $(RESULT)

后记

本文的主要目标就是帮助读者快速迅速上手 M a c O S MacOS MacOS C / C C/C C/C++ 工程的 M a k e f i l e Makefile Makefile 文件编写,因此并没有太多涉及 M a k e f i l e Makefile Makefile 的高阶用法,有兴趣的朋友可以仔细研读陈皓所写的《跟我一起写 Makefile \text{Makefile} Makefile》!

技术水平的不断提高在于不断实践,不断记录,持续精进!💪💪💪

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gene_INNOCENT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值