tcc编译器教程6 进一步学习编译gmake源代码

本文以编译gmake为例讲解如何使用tcc进行复杂一点的c代码的编译

1 简介

前面主要讲解了如何编译lua解释器,lua解释器的编译很简单也很容易理解.当然大部分c语言程序编译没那么简单,下面对前面的gmake程序进行编译.

2 gmake源码结构

首先打开之前tcc-busybox-for-win32\gmake文件夹,具体文件如下

主要有3个文件夹和3个文件,分别为

0.tcc-主要为编译所用的信息

lib-一些相关的c代码

src-主要源码文件夹

AUTHORS-作者信息

COPYING-自述文件

README-自述文件

其中最主要的是src文件夹.

3 初次编译

在tcc-busybox-for-win32文件下有一个makebox.bat其中包含了编译gmake的命令.经过分析编译指令改写为

c 复制代码
::使用tcc 执行0.tcc/gmake.tcc.rsp文件编译内容
tcc @0.tcc/gmake.tcc.rsp

将tcc编程环境.bat复制到gmake文件夹下打开,输入上面指令,指令执行成功在上一级目录tcc-busybox-for-win32下面生成make.exe文件,其中@代表tcc编译信息从0.tcc目录下的gmake.tcc.rsp文件载入,该文件内容如下:

c 复制代码
-o ../make.exe
-Wall
-D GMAKE_FOR_BUSYBOX

-I src
-I lib
-I src/w32/include

-D WINDOWS32
-D HAVE_CONFIG_H
-D HAVE_STDINT_H
-D HAVE_STRNICMP
-D HAVE_UMASK
-D WIN32_LEAN_AND_MEAN=

-D ftruncate=_chsize
-D _cdecl=

src/ar.c
src/arscan.c
src/commands.c
src/default.c
src/dir.c
src/expand.c
src/file.c
src/function.c
src/guile.c
src/hash.c
src/implicit.c
src/job.c
src/load.c
src/main.c
src/misc.c
src/output.c
src/read.c
src/remake.c
src/remote-stub.c
src/rule.c
src/signame.c
src/strcache.c
src/variable.c
src/version.c
src/vpath.c
src/w32/pathstuff.c
src/w32/w32os.c
src/w32/compat/posixfcn.c
src/w32/subproc/misc.c
src/w32/subproc/sub_proc.c
src/w32/subproc/w32err.c

src/w32/compat/dirent.c
src/getopt.c
src/getopt1.c

lib/fnmatch.c
lib/getloadavg.c
lib/glob.c

-luser32
-ladvapi32

4 gmake.tcc.rsp文件内容分析

下面对gmake.tcc.rsp内容进行分析

c 复制代码
-o ../make.exe

这个指令设置输出文件为make.exe,位置在上一级目录

c 复制代码
-Wall
-D GMAKE_FOR_BUSYBOX

-I src
-I lib
-I src/w32/include

-D WINDOWS32
-D HAVE_CONFIG_H
-D HAVE_STDINT_H
-D HAVE_STRNICMP
-D HAVE_UMASK
-D WIN32_LEAN_AND_MEAN=

-D ftruncate=_chsize
-D _cdecl=

-Wall 为设置打开警告信息

-I 设置包含路径

-D 为设置一些编译常量的值

c 复制代码
src/ar.c
src/arscan.c
src/commands.c
src/default.c
src/dir.c
src/expand.c
src/file.c
src/function.c
src/guile.c
src/hash.c
src/implicit.c
src/job.c
src/load.c
src/main.c
src/misc.c
src/output.c
src/read.c
src/remake.c
src/remote-stub.c
src/rule.c
src/signame.c
src/strcache.c
src/variable.c
src/version.c
src/vpath.c
src/w32/pathstuff.c
src/w32/w32os.c
src/w32/compat/posixfcn.c
src/w32/subproc/misc.c
src/w32/subproc/sub_proc.c
src/w32/subproc/w32err.c

src/w32/compat/dirent.c
src/getopt.c
src/getopt1.c

lib/fnmatch.c
lib/getloadavg.c
lib/glob.c

这些为需要编译的c代码文件

c 复制代码
-luser32
-ladvapi32

上面为添加两个链接库

5 编写编译指令

将gmake.tcc.rsp文件内容改为为一行编译指令,如下

c 复制代码
tcc -o make.exe -Wall -D GMAKE_FOR_BUSYBOX -I src -I lib -I src/w32/include -D WINDOWS32 -D HAVE_CONFIG_H -D HAVE_STDINT_H -D HAVE_STRNICMP -D HAVE_UMASK -D WIN32_LEAN_AND_MEAN= -D ftruncate=_chsize -D _cdecl= src/ar.c src/arscan.c src/commands.c src/default.c src/dir.c src/expand.c src/file.c src/function.c src/guile.c src/hash.c src/implicit.c src/job.c src/load.c src/main.c src/misc.c src/output.c src/read.c src/remake.c src/remote-stub.c src/rule.c src/signame.c src/strcache.c src/variable.c src/version.c src/vpath.c src/w32/pathstuff.c src/w32/w32os.c src/w32/compat/posixfcn.c src/w32/subproc/misc.c src/w32/subproc/sub_proc.c src/w32/subproc/w32err.c src/w32/compat/dirent.c src/getopt.c src/getopt1.c lib/fnmatch.c lib/getloadavg.c lib/glob.c -luser32 -ladvapi32

在gmake文件夹下打开tcc编程环境.bat,输入上面指令,指令执行成功生成make.exe文件

但是上面语句写起来还是很繁琐,对其进行修改如下

c 复制代码
::设置警告信息和包含路径
set include=-Wall -I src -I lib -I src/w32/include
::设置编译常量
set define= -D GMAKE_FOR_BUSYBOX  -D WINDOWS32 -D HAVE_CONFIG_H -D HAVE_STDINT_H -D HAVE_STRNICMP -D HAVE_UMASK -D WIN32_LEAN_AND_MEAN= -D ftruncate=_chsize -D _cdecl=
::设置编译c代码路径
set src=lib\*.c src\*.c src\w32\*.c src\w32\compat\*.c src\w32\subproc\*.c
::设置链接库
set lib=-luser32 -ladvapi32
::编译指令
tcc %include% %define% %src% %lib% -o make.exe

::测试make是否能运行
.\make -v

6 编译和链接

类似的,我们也可以进行拆分成编译和链接两个部分,具体代码如下

c 复制代码
::编译主要源码
tcc -c %include% %define% src\*.c
::将main.o移动到lib目录下,主要为了后面编译静态库
move main.o lib\main.o
::将misc.o重命名为misc1.o
::这步很关键,因为后面src\w32\subproc\misc.c也会编译为misc.o,导致这个misc.o被覆盖从而无法编译
move misc.o misc1.o
::编译其他源码
tcc -c %include% %define% lib\*.c
tcc -c %include% %define% src\w32\*.c
tcc -c %include% %define% src\w32\compat\*.c
tcc -c %include% %define% src\w32\subproc\*.c
::对所有obj文件进行链接生成make.exe
tcc lib\main.o *.o %lib% -o make.exe

7 编译静态链接库和动态链接库

参照此前方法编译静态链接库和动态链接库

编译静态链接库

c 复制代码
:: 生成静态链接库libmake.a
tcc -r  *.o  -o libmake.a
::使用静态链接库进行链接生成make.exe
tcc lib\main.o libmake.a %lib% -o make.exe

编译动态链接库

c 复制代码
:: 生成动态链接库make.dll
:: 注意需包含lib\main.o
tcc -shared -rdynamic lib\main.o *.o %lib% -o make.dll
:: 只需make.def,不需要lib\main.o
tcc  make.def  -o make.exe
相关推荐
solomonzw13 分钟前
linux学习(十三)(shell编程(文字,变量,循环,条件,调试))
linux·运维·学习
是星辰吖~15 分钟前
C语言_数据结构_栈
c语言·数据结构
巧克力力克巧!35 分钟前
uni-app+vue3学习随笔
vue.js·学习·uni-app
技术干货贩卖机1 小时前
0基础 | 看懂原理图Datasheet 系列1
笔记·stm32·单片机·嵌入式硬件·学习
陈无左耳、1 小时前
HarmonyOS学习第18天:多媒体功能全解析
学习·华为·harmonyos
脏脏a1 小时前
C 语言分支与循环:构建程序逻辑的基石
c语言·开发语言
晴空对晚照2 小时前
[动手学习深度学习]13.丢弃法 Dropout
人工智能·深度学习·学习
Run_Teenage2 小时前
C语言每日一练——day_4
c语言·开发语言
汤姆和佩琦2 小时前
LLMs基础学习(一)概念、模型分类、主流开源框架介绍以及模型的预训练任务
人工智能·学习·算法·分类·数据挖掘