当前位置: 首页 > news >正文

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的命令.经过分析编译指令改写为

::使用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文件载入,该文件内容如下:

-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.csrc/w32/compat/dirent.c
src/getopt.c
src/getopt1.clib/fnmatch.c
lib/getloadavg.c
lib/glob.c-luser32
-ladvapi32

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

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

-o ../make.exe

这个指令设置输出文件为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=

-Wall 为设置打开警告信息
-I 设置包含路径
-D 为设置一些编译常量的值

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.csrc/w32/compat/dirent.c
src/getopt.c
src/getopt1.clib/fnmatch.c
lib/getloadavg.c
lib/glob.c

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

-luser32
-ladvapi32

上面为添加两个链接库

5 编写编译指令

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

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文件
但是上面语句写起来还是很繁琐,对其进行修改如下

::设置警告信息和包含路径
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 编译和链接

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

::编译主要源码
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 编译静态链接库和动态链接库

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

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

编译动态链接库

:: 生成动态链接库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

相关文章:

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

本文以编译gmake为例讲解如何使用tcc进行复杂一点的c代码的编译 1 简介 前面主要讲解了如何编译lua解释器,lua解释器的编译很简单也很容易理解.当然大部分c语言程序编译没那么简单,下面对前面的gmake程序进行编译. 2 gmake源码结构 首先打开之前tcc-busybox-for-win32\gmak…...

公司共享网盘怎么建立

公司共享网盘的建立,关键在于明确使用需求、选择合适的网盘服务、搭建统一的文件管理规范、做好权限分级与安全防护。尤其要强调选择合适的网盘服务这一点,如果企业规模较大,且对协同办公的需求强烈,就需要考虑支持多人实时协作、…...

【高分论文密码】AI大模型和R语言的全类型科研图形绘制,从画图、标注、改图、美化、组合、排序分解科研绘图每个步骤

在科研成果竞争日益激烈的当下,「一图胜千言」已成为高水平SCI期刊的硬性门槛——数据显示很多情况的拒稿与图表质量直接相关。科研人员普遍面临的工具效率低、设计规范缺失、多维数据呈现难等痛点,因此科研绘图已成为成果撰写中的至关重要的一个环节&am…...

深入理解Java中的static关键字及其内存原理

static是Java中实现类级共享资源的核心修饰符,它突破了对象实例化的限制,使得变量和方法能够直接与类本身绑定。这种特性让static成为构建工具类、全局配置等场景的利器,但同时也带来独特的内存管理机制需要开发者关注。 static修饰成员变量…...

linux 系统 之centos安装 docker

对于 CentOS 安装 Docker 的前置条件 首先,需要安装一些必要的软件包, 对于 CentOS 7,可以使用以下命令: sudo yum install -y yum-utils device-mapper-persistent-data lvm2添加 Docker 仓库 设置 Docker 的官方仓库。对于 …...

Python语法核心架构与核心知识点:从理论到实践

一、Python的核心设计哲学 Python以“简洁优雅”为核心理念,遵循以下原则: # Zen of Python(输入 import this 可查看) >>> import this The Zen of Python, by Tim Peters ... Simple is better than complex. Readab…...

FreeRTOS(5)内核控制函数及其他函数

FreeRTOS 提供了一些用于控制内核的 API 函数,这些 API 函数主要包含了进出临界区、开关中断、启停任务调度器等一系列用于控制内核的 API 函数。本章就来学习 FreeRTOS 的内 核控制函数。 内核控制函数 1. 函数 taskYIELD() 此函数用于请求切换任务, …...

网络DNS怎么更改?

访问速度慢或某些网站无法打开?改变网络DNS设置可能会帮助解决这些问题。本文将详细介绍如何更改网络DNS,包括更改的原因、具体步骤。 一、为什么要更改DNS? 更改DNS的原因有很多,以下是一些主要的考虑因素:某些公共DNS服务器的响应速度比…...

VIC模型有哪些优势?适用哪些范围?基于QGIS的VIC模型建模;未来气候变化模型预测;基于R语言VIC参数率定和优化

VIC模型是一个大尺度的半分布式水文模型,其设计之初就是为了模拟大流域的水文过程;它能够计算陆地-大气的能量通量,考虑土壤性质和土地利用的影响,自带有简化的湖泊/湿地模块,也能够将植被状况,…...

脏读、不可重复读,幻读的区别 mvcc及四种隔离级别

脏读:事务a还未提交更新事务b就可以看见 不可重复读:强调修改和删除,一个事务多次查询同一个表结果不同 幻读:强调新增,也是一个事务多次查询同一个表结果不同 mvcc是用来解决读写冲突的无锁并发控制 三个实现基础&…...

SpringAI介绍及本地模型使用方法

博客原文地址 前言 Spring在Java语言中一直稳居高位,与AI的洪流碰撞后也产生了一些有趣的”化学反应“,当然你要非要说碰撞属于物理反应也可以, 在经历了一系列复杂的反应方程后,Spring家族的新成员——SpringAI,就…...

numpy广播性质

一、核心规则 一维数组本质 shape (n,)的数组是无方向向量,既非严格行向量也非列向量 自动广播机制 在矩阵乘法(或np.dot())中,一维数组会自动调整维度: 前乘时视为行向量 shape (1,n)后乘时视为列向量 shape (n,1) 二、运算类型对比 假…...

Flutter_学习记录_实现列表上下拉加载 +实现加载html的数据

1. 效果图 2. 下拉加载的实现RefreshIndicator 在Flutter官方sdk中给我们提供了下拉刷新的组件RefreshIndicator。 // 显示内容列表Widget _showNewsListWidget() {if (_newsDataList.isNotEmpty) {// RefreshIndicator 来实现下拉加载的功能return RefreshIndicator(onRefr…...

基于PaddleNLP使用DeepSeek-R1搭建智能体

基于PaddleNLP使用DeepSeek-R1搭建智能体 最近在学习DeepSeek,找到了PaddleNLP星河社区大模型,跟着敲写了一遍。内容来源:DeepSeek实战训练营:从云端模型部署到应用开发 - 飞桨AI Studio星河社区-人工智能学习与实训社区 本项目基…...

『PostgreSQL』PGSQL备份与还原实操指南

📣读完这篇文章里你能收获到 了解逻辑备份与物理备份的区别及适用场景🔍。掌握全库、指定库、指定表备份还原的命令及参数📝。学会如何根据业务需求选择合适的备份策略📊。熟悉常见备份还原问题的排查与解决方法🔧。 …...

基于单片机的智慧农业大棚系统(论文+源码)

1系统整体设计 经过上述的方案分析,采用STM32单片机为核心,结合串口通信模块,温湿度传感器,光照传感器,土壤湿度传感器,LED灯等硬件设备来构成整个控制系统。系统可以实现环境的温湿度检测,土壤…...

【C语言】数组篇

目录 引言一维数组数组的定义数组的初始化完全初始化部分初始化省略数组长度 数组元素的访问 多维数组二维数组的定义二维数组的初始化完全初始化部分初始化省略第一维长度 二维数组元素的访问 遍历数组元素遍历一维数组遍历二维数组 数组作为函数参数一维数组作为函数参数二维…...

FreeRTOS概述

文章目录 核心文件头文件内存管理文件入口函数数据类型前缀 核心文件 最核心文件:task.c和list.c 文件作用tasks.c必需,任务操作list.c必须,列表queue.c基本必需,提供队列操作、信号量(semaphore)操作timer.c可选,so…...

C++ 使用红黑树的实现及迭代器完成对set和map的封装

一、红黑树的实现以及迭代器 #pragma once // 要实现完整的迭代器需要对红黑树进行改造&#xff0c;有兴趣可参考侯捷《STL源码剖析》 enum Colour {RED,BLACK };template<class T> struct RBTreeNode {RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeN…...

【Java从入门到起飞】面向对象编程(高级)

文章目录 1. 抽象类1.1 概述1.1.1 抽象类引入 1.2 abstract使用格式1.2.1 抽象方法1.2.2 抽象类1.2.3 抽象类的使用 1.3 抽象类的特征1.4 抽象类的细节1.5 抽象类存在的意义 2. 接口2.1 概述2.2 定义格式2.3 接口成分的特点2.3.1.抽象方法2.3.2 常量2.3.3 案例演示 2.4 基本的实…...

淘金币自动化脚本:3分钟完成淘宝全任务,每天节省20分钟

淘金币自动化脚本&#xff1a;3分钟完成淘宝全任务&#xff0c;每天节省20分钟 【免费下载链接】taojinbi 淘宝淘金币自动执行脚本&#xff0c;包含蚂蚁森林收取能量&#xff0c;芭芭农场全任务&#xff0c;解放你的双手 项目地址: https://gitcode.com/gh_mirrors/ta/taojin…...

星际软件开发:为火星殖民地编写第一批代码

一、引言&#xff1a;当测试左移到大气层之外2041年&#xff0c;第一批火星殖民者即将启程。他们携带的不仅是氧气和速食&#xff0c;还有一座预装在密封舱里的微型数据中心。在这片红色荒漠上&#xff0c;代码将比氧气更早醒来——生命维持系统的控制逻辑、通讯中继的协议栈、…...

BBDown终极指南:5分钟掌握B站视频本地化完整解决方案

BBDown终极指南&#xff1a;5分钟掌握B站视频本地化完整解决方案 【免费下载链接】BBDown Bilibili Downloader. 一个命令行式哔哩哔哩下载器. 项目地址: https://gitcode.com/gh_mirrors/bb/BBDown 在数字内容爆炸的时代&#xff0c;你是否曾为无法离线观看B站优质视频…...

STM32实战:用HAL库搞定RS485 Modbus液压传感器数据采集(附自动收发电路避坑)

STM32实战&#xff1a;HAL库驱动RS485 Modbus液压传感器全流程解析 液压系统压力监测的稳定性往往取决于传感器数据采集的可靠性。在工业现场&#xff0c;RS485总线搭配Modbus RTU协议已成为液压传感器数据传输的黄金标准。本文将深入探讨基于STM32 HAL库的完整解决方案&#x…...

AI智能体审批系统设计:从规则到价值网络的动态决策引擎

1. 项目概述&#xff1a;为什么AI需要“举手提问”&#xff1f;在AI智能体&#xff08;Agent&#xff09;日益深入业务流程自动化的今天&#xff0c;一个核心的、却常被忽视的问题浮出水面&#xff1a;这个拥有一定自主决策能力的“数字员工”&#xff0c;在什么情况下应该停下…...

半导体行业数据分析:从WSTS报告解读市场趋势与从业者应对策略

1. 从一份行业快报说起&#xff1a;如何解读半导体市场的“水温”早上刚冲好咖啡&#xff0c;习惯性地扫了一眼行业新闻&#xff0c;看到EE Times上这篇关于2013年第一季度全球半导体销售额的简报。标题很直接&#xff1a;“Chip sales up 1% through Q1”。1%的增长&#xff0…...

V2X通信:自动驾驶安全冗余与混合交通协同的关键技术

1. 项目概述&#xff1a;当自动驾驶汽车遇上“沟通障碍”如果你认为自动驾驶汽车和车与车之间的通信是两个独立的问题&#xff0c;那说明你的思考还不够“渐进式”。是时候重新审视了。自动驾驶的拥护者们常常描绘一个乌托邦式的未来&#xff1a;道路零事故。但他们很少提及那个…...

【限时公开】谷歌内部未文档化Gemini JavaScript SDK隐藏能力:流式响应中断控制、上下文压缩率提升63%实测数据

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Gemini JavaScript SDK核心能力概览 Gemini JavaScript SDK 是 Google 官方提供的轻量级客户端库&#xff0c;专为在浏览器和 Node.js 环境中无缝集成 Gemini 模型能力而设计。它抽象了底层 HTTP 请求、…...

AD导出Gerber到CAM350拼板全流程避坑指南(附文件漏导出自查清单)

AD导出Gerber到CAM350拼板全流程避坑指南&#xff08;附文件漏导出自查清单&#xff09; 在硬件产品开发中&#xff0c;PCB设计到生产的转换环节往往隐藏着诸多"暗礁"。我曾亲眼见过一个团队因为钻孔文件覆盖问题导致生产延误两周&#xff0c;损失近十万元。本文将分…...

从“意大利面”到整洁代码:我是如何用SonarQube重构遗留项目的

从“意大利面”到整洁代码&#xff1a;我是如何用SonarQube重构遗留项目的 接手一个结构混乱的遗留项目&#xff0c;就像面对一盘煮过头的意大利面——各种逻辑纠缠不清&#xff0c;随便动一处就可能引发连锁反应。去年我遇到这样一个Java项目&#xff1a;12万行代码&#xff0…...