IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Makefile 编写教程(由简至难) -> 正文阅读

[游戏开发]Makefile 编写教程(由简至难)

一、测试代码

本文以将main.c add.c common.h三个文件编译成一个可执行文件为例,来讲解Makefile的编写。以下是每个文件的代码(很简单,测试用)

1.main.c

 #include <stdio.h>
 #include "common.h"                                                                                                                                                                                        
 int main()
 {
     int a = 1;
     int b = 2;
     printf("add(%d, %d) = %d\n",a, b, add(a,b));
     return 0;
 }

2.add.c

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

3.common.h

#ifndef __COMMON_H__                                                                                                                                                                                       
#define __COMMON_H__

extern int add(int a, int b);

#endif

二、.c 文件与Makefile同级

将.c 文件放在Makefile同级目录,然后单独建一个目录.h头文件,如图。
在这里插入图片描述
以下是 Makefile 原文:

 CC = gcc
 TARGET = prog
 OBJS = main.o add.o
 INCLUDE = -I./include
 $(TARGET):$(OBJS)
     $(CC) $(OBJS) -o $(TARGET)   
 %.o:%.c
     $(CC) $(INCLUDE) -c $^ -o $@                                                                                                                                                                           
 
 .PHONY:clean
 clean:
     rm *.o prog

逐行解释:

  • CC = gcc= 号在Makefile中是声明变量并给变量赋值的意思。这里声明了一个 自定义变量 CC,并用gcc编译器赋值。

  • TARGET = prog:声明Makefile目标文件,也就是这个Makefile最终目标是生成一个叫prog的文件。一般这种最终输出的文件都用TARGET来承载

  • INCLUDE = -I./include :用-I 选项指定自己写的头文件的路径。-I和路径之间有没有空格都行,一般没有空格

  • ** ( T A R G E T ) : (TARGET): (TARGET):(OBJS) **
    ** $(CC) $(OBJS) -o $(TARGET) **:
    格式

要生成的目标文件:生成目标文件所需要依赖的所有文件
	编译命令
  • %.o:%.c : %是Makefile的一个通配符。这句话的作用是将所有的.c文件自动编译成同名的.o文件。比如,有了这句话,那么1.c就会自动编译成1.o2.c就会自动编译成2.o

  • INCLUDE应该加在哪里
    程序在预处理时就会把头文件的内容展开,所以在调用 -c 选项 将 .c 文件编译成 .o文件时,就要指定头文件路径,否则会报错,提示找不到头文件路径

  • 通配符的作用

符号描述
$^所有依赖文件的集合,用空格分开,如果其中有重复的依赖文件,则只保留一个。比如依赖文件有三个: 1.c, 2.c, 1.c,那么$^拿到的只有 1.c 和 2.c 两个文件,舍弃了一个1.c
$<依赖文件中的第一个文件。如果依赖文件是以 “%” 定义的,那么 $< 就是依赖文件的集合。一般不会有重复的依赖文件,所以上面的 Makefile,用 $^ 替换掉 $< 也是可以的
$+与 $^ 一样,只是如果有重复的依赖文件,不会舍弃重复的依赖文件
$@目标文件的集合

三、.c文件与Makefile不同级

.c 文件放在src目录,.h文件放在include 目录,目录结构如图:
在这里插入图片描述
以下是 Makefile 原文:

 CC = gcc
 TARGET = prog
 SOURCE = $(wildcard ./src/*.c)      #获取src目录下所有.c文件
 OBJS = $(patsubst %.c, %.o, $(SOURCE))
 INCLUDE = -I./include
 $(TARGET):$(OBJS)  
     $(CC) $(OBJS) -o $(TARGET)     #另一种写法: $(CC) -o $(TARGET) $(OBJS)
 %.o:%.c
     $(CC) $(INCLUDE) -c $^ -o $@   #另一种写法:  $(CC) $(INCLUDE) -c -o $@ $^                                                                                                                                                                       
 
 .PHONY:clean
 clean:
     rm $(OBJS) $(TARGET) 

这里只有第3、4行需要注意,相当于用这两行内容可以找到指定目录下的文件

  • 第3行 wilcard是获取src目录下所有的.c文件
  • 第4行patsubst是列出 SOURCE中 .c文件对应的所有 .o 文件

四、链接静态库

在前面的基础上,新建目录lib,创建sub.c
在这里插入图片描述
sub.c编译成静态库libsub.a,代码如下:

int sub(int a, int b)
{
     return a - b;                                                                                                                                                                                          
 }

编译成静态库的命令

gcc -c sub.c -o sub.o
ar crv libsub.a sub.o
补充: 如果静态库依赖于多个源文件,则依次编译得到.o,然后将所有的.o编译成 .a 静态库。
eg. 要将1.c、2.c、3.c编译成一个静态库,则ar crv libXXX.a  1.o 2.o 3.o

当然,除了用命令编译,也可以写成在lib目录下写一个Makefile,我就是这么做的,如下。(这个Makefile只用于编译静态库)

CC = gcc
TARGET = libsub.a
OBJS = sub.o
$(TARGET):$(OBJS)
   ar crv $(TARGET) $(OBJS)
%.o:%.c
   $(CC) -c -o $@ $<
.PHONY:clean
 clean:
     rm *.o $(TARGET) 

接下来,就是修改我们最开始的那个Makefile

 CC = gcc
 TARGET = prog
 SOURCE = $(wildcard ./src/*.c) #获取src目录下所有.c文件
 OBJS = $(patsubst %.c, %.o, $(SOURCE))
 INCLUDE = -I./include
 LIBS = -lsub
 LIBPATH = -L./lib
 
 $(TARGET):$(OBJS)
     $(CC) $(OBJS) -o $(TARGET)  $(LIBPATH) $(LIBS)
 
 %.o : %.c
     $(CC) $(INCLUDE) -c -o $@ $<                                                                                                                                                                           
 
 .PHONY:clean
 clean:
     rm $(OBJS) $(TARGET)

第5、6行,编译时需要用 -L 指定静态库的路径,用 -l 指定静态库。
注意: 链接静态库是编译的最后一步链接做的事情。所以要加在第10行,而且只能加在末尾,如果直接跟在 $(CC)后面,make时会提示找不到静态库里的函数

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-05-01 16:02:57  更:2022-05-01 16:03:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/17 1:04:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码