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

本文提供了一套适用于MacOS系统的C/C++工程Makefile模板,旨在简化编译流程。通过构建固定的目录结构和Makefile规则,实现了自动化编译与链接,适合初学者快速上手。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

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

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

  1. 为什么需要 MakefileMakefileMakefile
  2. 如何编写 MakefileMakefileMakefile
  3. MacOSMacOSMacOS 下编译 C/CC/CC/C++ 工程的固定模板

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


为什么需要 MakefileMakefileMakefile

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

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

我们将以下面的三份代码为例来介绍在 MacOSMacOSMacOS 下使用 MakefileMakefileMakefile 的方法。

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

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

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

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

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

显然一条一条命令输非常麻烦,因此我们需要 MakefileMakefileMakefile 来简化这个过程!


如何编写 MakefileMakefileMakefile

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

  • 文件结构
    • 两个大文件夹:buildbuildbuildsrcsrcsrc
    • build:build:build: 分为两个小文件夹,binbinbinobjectsobjectsobjects
      • bin:bin:bin: 放最终的可执行文件
      • objects:objects:objects:srcsrcsrc 中的文件所生成的 .o.o.o 文件
    • src:src:src: 工程文件
    • 最外层:MakefileMakefileMakefilemainmainmain(最终可执行文件的链接文件)
      在这里插入图片描述
  • MakefileMakefileMakefile 语法规则
    • $@: 目标文件
    • $^: 所有依赖文件
    • $< 第一个依赖文件
    • 编译语法规则
      • targets: 文件名,以空格分开,可以使用通配符
      • command: 命令行,如果其不与 targets:prerequisites\text{targets:prerequisites}targets:prerequisites 在一行,则必须以 TabTabTab 键卡头,如果和 targets:prerequisites\text{targets:prerequisites}targets:prerequisites 在一行,则可以用分号作为分隔
      • prerequisites: 目标所依赖的文件,如果其中某个文件要比目标文件要新,则目标就被认为是 “过时的”,被认为是需要重新生成的
      • ref: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 $@)
  • makemakemake cleancleanclean 命令
    • 当我们需要重新编译时,我们想要快速地删除上一次编译所产生的文件
    • 我们可以自定义 makemakemake cleancleanclean 命令,实现对上一次编译生成文件的快速清理
.PHONY: clean
clean:
	rm -rf $(dest_dir)
	rm -f $(RESULT)

MacOSMacOSMacOS 下编译 C/CC/CC/C++ 工程的固定模板

至此,我们实现了一个简易的编译 C/CC/CC/C++ 工程的 MakefileMakefileMakefile 的固定模板。

每次需要编译,则先执行 makemakemake cleancleanclean,再执行 makemakemake

CCC 工程: gccgccgccCCC++ 工程: ggg++

增加需要编译的文件: 在 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)

后记

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Gene_INNOCENT

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

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

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

打赏作者

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

抵扣说明:

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

余额充值