惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Y
Y Combinator Blog
博客园_首页
量子位
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
H
Help Net Security
The Cloudflare Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
A
About on SuperTechFans
腾讯CDC
H
Hackread – Cybersecurity News, Data Breaches, AI and More
D
DataBreaches.Net
L
LangChain Blog
Stack Overflow Blog
Stack Overflow Blog
Jina AI
Jina AI
月光博客
月光博客
云风的 BLOG
云风的 BLOG
博客园 - 聂微东
Hugging Face - Blog
Hugging Face - Blog
雷峰网
雷峰网
C
Check Point Blog
V
V2EX
T
Tailwind CSS Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Microsoft Security Blog
Microsoft Security Blog

h-jr.me

Tinymist 的 Typst 无用声明检测 一路顺风 经验贴|末九17%上岸南大计院 Frama-C WP Tutorial | 函数契约 SOP 和 POS Verilog 打砖块游戏 Verilog 基础语法 Wasm 二进制结构 我和 Typst 的 2024 计算机网络 TCP 大实验 2024 年冬天吃的第一个亏从换电脑开始 我学编程原神 Rust 记三天数模国赛
C 编译体系
2024-04-26 · via h-jr.me

video

gcc 的常用编译选项

gcc 的参数组合比较随意,比如-Wall 其实就是-W all ,有时候空格等号和粘连的写法都是等价的,但像-O1 就不能分开写。

-E 预处理

-v 打印输出信息(默认 quiet)

- 从 stdio 中读取输入

多文件编译和第三方库

用 makefile 举例。先生成目标文件(.o)再链接成可执行文件,相较于直接使用两个源文件编译成可执行文件,能够避免未修改的文件也要重新编译的开销。

main: main.o a.o

gcc $^ -o $@

%.o: %.c

gcc -c $^ -o $@

makefile 能够简化成上面这么写,而不需要展开写所有的文件。$^ 就代表上面所有的依赖,$@ 指的就是冒号前面这个要输出的文件,% 是个模式的匹配。

更好地,还可以提取出所有的变量。

CC = gcc

SRC = main.c a.c

OBJ = $(SRC:.c=.o)

main: $(OBJ)

$(CC) $^ -o $@

%.o: %.c

$(CC) -c $^ -o $@

有时,文件目录嵌套了非常多层,要包含头文件时就需要写很多次的".." ,既不简洁也不优雅。gcc 中可以使用-I 这个编译选项来指定 include 目录,而不需要相对引用。

CC = gcc

SRC = main.c a.c

OBJ = $(SRC:.c=.o)

INCLUDE_PATH = -Ifolder/ -Iinclude1 -I include2

main: $(OBJ)

$(CC) $^ -o $@

%.o: %.c

$(CC) -c $(INCLUDE_PATH) $^ -o $@

使用第三方库的时候,在 Linux 上apt 安装后只需要加入几个-l 选项就可以使用了。如果说修改了源码,想要用修改后的自己的库,那就要自己引入INCLUDE_PATHLIBRARY_PATH ,通常情况下程序会优先使用动态链接库(.a.la 结尾)以减小体积。apt 安装库时,把可执行文件放在/usr/bin ,头文件放在/usr/include ,库文件放在/usr/lib ,gcc 就能默认从这几个路径下搜索包含。

CC = gcc

SRC = main.c a.c

OBJ = $(SRC:.c=.o)

INCLUDE_PATH =

LDFLAGS = -lgvs -lcgraph -lcdt

main: $(OBJ)

$(CC) $^ $(LDFLAGS) -o $@

%.o: %.c

$(CC) -c $(INCLUDE_PATH) $^ -o $@

pkg-config 是一个能根据 package 自动补全 include 和 library 路径的工具,这样只需要提供 CFLAGS 和 LDFLAGS 就可以了。下面使用的``` 在 shell 中会先执行,然后用返回的值替代。

CC = gcc

SRC = main.c a.c

OBJ = $(SRC:.c=.o)

CFLAGS = `pkg-config libgvc --cflags`

# -I/usr/include/graphviz

LDFLAGS = `pkg-config libgvc --libs`

# -lgvs -lcgraph -lcdt

main: $(OBJ)

$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@

%.o: %.c

$(CC) -c $(CFLAGS) $^ -o $@

crl 和 triplet

跨平台和交叉编译

编译出来的文件会有一个可执行的configure 文件,这和 gnu 的构建三件套 GNU build system(automake,autoconf 和 libtools)有关。主要目的就是简化跨平台软件的构建过程。但最好用 cmake 来构建跨平台应用。

API 是应用程序接口,ABI 指的是应用程序二进制接口,和硬件、操作系统、编译器等等有关系。

出现一个新架构之后,如何将已有的编译器引入新架构?使用加拿大编译。

Canadian Cross

3 阶段实现自举。