gcc 、makefile 编译小项目示例--了解makefile、gcc指令

本文章的背景:

因为最近想每天上Leetcode 刷每日一题,同时又想练习一下vim的使用(立志成为一个vimer),因此打算在云服务器上做算法编程。
刷了几天题后,发现每次使用gcc 来编译并执行我的算法稍微有点麻烦。而且,经过几天的编程,我也积攒了一些通用的api,为了方便在之后的刷题过程中能够丝滑地使用这些api方法,我新建了一个目录 “api” 来存放它们.
好了,现在因为涉及到多文件编译,更没有理由不使用makefile来解放自己了。于是就有了接下来的尝试。

任务背景:

每日一题管理目录结构如下:
顶层目录: everyday
顶层目录下的文件与子目录:

  • 2023xxxx.c (每日一题算法实现)
  • api目录
  • srcs目录(存放往日的算法实现.c文件)
  • outs目录(存放往日算法的可执行文件.out)

api目录下的文件与子目录:

  • incs目录(存放实用api方法的.h文件)
  • srcs目录(存放实用api方法的.c文件)
    在这里插入图片描述

为什么手动 gcc 来编译会很困扰?

情景介绍:
每日一题源文件20231229.c 中调用了api方法 “scanf_int_array()” 因此 include 了 api 文件 “input_datas.h” 。如下:

#include<stdio.h>
#include<stdlib.h>
#include"input_datas.h"
int buyChoco(int* prices, int pricesSize, int money);
int main()
{
	int * int_array = NULL;
	int arraySize = 0;
	//scanf_int_array方法 来自 input_datas.h
	//scanf_int_array 封装了获取一个一维整数数组过程
	int_array = scanf_int_array();
	
	arraySize = int_array[0];
	int ans = buyChoco(int_array+1,arraySize,10);
	printf("剩余金额 = %d\n",ans);
	free(int_array);
	return 0;
}
int buyChoco(int* prices, int pricesSize, int money)
{
	/*
	** 这里具体实现不重要...
	*/
}

此时如果要让 20231229.c 正常编译生成可执行文件,其编译指令应该这样写:

gcc -I api/incs -o 20231229.out 20231229.c api/srcs/*.c
# -I api/incs 告诉编译器要去 api/incs 目录下搜索头文件。不指定的话会找不到方法 scanf_int_array 的
# 依赖的.c 文件也要同时编译

这条指令已经有点长了,而且大部分内容是固定的,不会随日期的改变而改变。如果一直手动gcc,不得不说会做很多无用功。

makefile 的实现
makefile 可以代替我们执行一系列的编译指令,并生成目标文件。makefile的语法并不复杂,但是要了解一下makefile的基本规则。这方面可以阅读《gnu makefile手册》。(英文版,慎入!)

先澄清下我们想要的最终效果:
我们希望 在往后编译每日一题的.c文件时,我只需要输入不固定的部分——算法.c文件名,其他部分可以通过简单的make 指令代替。
这也意味着,我们在执行make指令时,必然是有一个入参变量的。为了方便,我们取名为 T (target的缩写)

这上述的情景中,我最终书写的makefile规则如下:

  1 INCDIR=api/incs #api头文件位置
  2 SRCDIR=api/srcs #api源文件位置
  3 TARGET=$(subst .c,.out,$(T))  #subst 可以将字符串 $(T) 的一部分替换为另一字串,这里是把.c 替换为了 .out,相当于改了后缀名
  4 all:$(TARGET)
  5 $(TARGET):$(T) $(SRCDIR)/*.c
  6     @echo "目标文件为:$(TARGET)"
  7     gcc -I $(INCDIR) -o $@ $^ # $@ 表示目标部分, $^ 表示所有的依赖部分
  8     @echo "编译完成"
  9 
 10 .PHONY:clean
 11 clean:
 12     rm -f ./*.out
 13     @echo "删除.out文件"

此后,我只需要输入如下指令:

make T=20231229.c 

就可以完成对 每日一题的编译,生成 .out文件。

结尾

文章附件中有 GNU make中文手册v3.80.rar
承认自己的无知,乃是开启智慧的大门。慢慢学习,慢慢进步吧。

  • 23
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值