当前位置:网站首页>gcc与makefile
gcc与makefile
2022-06-29 09:10:00 【水似冰】
前言
自接触C语言以来,小demo直接gcc,大项目的Makefile都是框架里自带的,一般都是按需修修补补,具体的规则总是摸不清搞不懂!当自己搭个小项目,手搓一个Makefile真是费劲,根本写不出来,因此书此博客,以后来ctrl+c。
本文不会详细展开如何编写一个Makefile。如想了解种种细节,请参考下面这个非常详细的教程,包含几乎GNU make的Makefile的所有细节:
而本文包含以下内容:
- makefile小模板
- gcc指令
Makefile小模板
适用于纯 C 语言
# 指令编译器和选项
CC=gcc
CFLAGS=-Wall -std=gnu99
# 目标文件
TARGET=main
SRCS = main1.c \
main2.c \
main3.c
INC = -I./
OBJS = $(SRCS:.c=.o)
$(TARGET):$(OBJS)
$(CC) -o [email protected] $^
clean:
rm -rf $(TARGET) $(OBJS)
%.o:%.c
$(CC) $(CFLAGS) $(INC) -o [email protected] -c $<
注意:Makefile有个规则就是命令行是以tab键开头,4个空格或其他则会报错:Makefile:2: *** missing separator。stop
- 相比于单个文件和多个文件的makefile,通过变量
INC制定了头文件路径。头文件路径之间通过空格隔开。 - 编译规则
%.o:%.c中加入了头文件参数$(CC) $(CFLAGS) $(INC) -o [email protected] -c $<, - 单个文件和多个文件的makefile相比增加了头文件路径参数。
SRCS变量中,文件较多时可通过“\”符号续行。[email protected]--代表目标文件$^--代表所有的依赖文件$<--代表第一个依赖文件(最左边的那个)。
适用于 C/C++ 混合编译
目录结构如下:
httpserver
│ main.cpp
│ Makefile
└─────inc
│ │ mongoose.h
│ │ http_server.h
│
──────src
│ │ http_server.cpp
│ │ mongoose.c
│ │ ...
Makefile 如下:
CC=gcc
CXX=g++
# 编译器在编译时的参数设置,包含头文件路径设置
CFLAGS:=-Wall -O2 -g
CFLAGS+=-I $(shell pwd)/inc
CXXFLAGS:=-Wall -O2 -g -std=c++11
CXXFLAGS+=-I $(shell pwd)/inc
# 库文件添加
LDFLAGS:=
LDFLAGS+=
# 指定源程序存放位置
SRCDIRS:=.
SRCDIRS+=src
# 设置程序中使用文件类型
SRCEXTS:=.c .cpp
# 设置运行程序名
PROGRAM:=httpserver
SOURCES=$(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))
OBJS=$(foreach x,$(SRCEXTS),$(patsubst %$(x),%.o,$(filter %$(x),$(SOURCES))))
.PHONY: all clean distclean install
%.o: %.c
$(CC) -c $(CFLAGS) -o [email protected] $<
%.o: %.cxx
$(CXX) -c $(CXXFLAGS) -o [email protected] $<
$(PROGRAM): $(OBJS)
ifeq ($(strip $(SRCEXTS)),.c)
$(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)
else
$(CXX) -o $(PROGRAM) $(OBJS) $(LDFLAGS)
endif
install:
install -m 755 -D -p $(PROGRAM) ./bin
clean:
rm -f $(shell find -name "*.o")
rm -f $(PROGRAM)
distclean:
rm -f $(shell find -name "*.o")
rm -f $(shell find -name "*.d")
rm -f $(PROGRAM)
all:
@echo $(OBJS)
gcc指令
一步到位
gcc main.c -o main
多个程序文件的编译
gcc main1.c main2.c -o main
预处理
gcc -E main.c -o main.i
或gcc -E main.c
gcc的-E选项,可以让编译器在预处理后停止,并输出预处理结果。
编译为汇编代码
预处理之后,可直接对生成的test.i文件编译,生成汇编代码:gcc -S main.i -o main.s
gcc的-S选项,表示在程序编译期间,在生成汇编代码后,停止,-o输出汇编代码文件。
汇编
对于上文中生成的汇编代码文件test.s,gas汇编器负责将其编译为目标文件,如下:gcc -c main.s -o main.o
连接
gcc连接器是gas提供的,负责将程序的目标文件与所需的所有附加的目标文件连接起来,最终生成可执行文件。附加的目标文件包括静态连接库和动态连接库。
对于上一小节中生成的main.o,将其与C标准输入输出库进行连接,最终生成可执行程序main。
检错
参数-Wall,使用它能够使GCC产生尽可能多的警告信息。gcc -Wall main.c -o main
在编译程序时带上-Werror选项,那么GCC会在所有产生警告的地方停止编译,迫使程序员对自己的代码进行修改,如下:gcc -Werrormain.c -o main
创建动态链接库
生成生成o文件gcc -c -fPIC add.c //这里一定要加上-fPIC选项,目的使库不必关心文件内函数位置
再编译gcc -shared -fPIC -o libadd.so add.o
库文件连接
开发软件时,完全不使用第三方函数库的情况是比较少见的,通常来讲都需要借助许多函数库的支持才能够完成相应的功能。从程序员的角度看,函数库实际上就是一些头文件(.h)和库文件(so、或lib、dll)的集合。虽然Linux下的大多数函数都默认将头文件放到/usr/include/目录下,而库文件则放到/usr/lib/目录下;但也有的时候,我们要用的库不在这些目录下,所以GCC在编译时必须用自己的办法来查找所需要的头文件和库文件。
额外补充:Linux需要连接so库文件(带软连接),可以完完整整的复制到/usr/include/或/usr/lib/目录下,使用 cp -d * /usr/lib/ 命令,然后别忘记再运行 ldconfig。
其中inclulde文件夹的路径是/home/test/include,lib文件夹是/home/test/lib,lib文件夹中里面包含二进制so文件libtest.so
首先要进行编译main.c为目标文件,这个时候需要执行:gcc –c –I /home/test/include main.c –o main.o
最后把所有目标文件链接成可执行文件:gcc –L /home/test/lib -ltest main.o –o main
默认情况下, GCC在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑使用静态链接库,如果需要的话可以在编译时加上-static选项,强制使用静态链接库。gcc –L /home/test/lib -static -ltest main.o –o main
静态库链接时搜索路径顺序:
ld会去找GCC命令中的参数-L- 再找gcc的环境变量
LIBRARY_PATH - 再找内定目录
/lib、/usr/lib、/usr/local/lib这是当初compile gcc时写在程序内的
动态链接时、执行时搜索路径顺序:
- 编译目标代码时指定的动态库搜索路径
- 环境变量
LD_LIBRARY_PATH指定的动态库搜索路径 - 配置文件
/etc/ld.so.conf中指定的动态库搜索路径 - 默认的动态库搜索路径
/lib - 默认的动态库搜索路径
/usr/lib
相关环境变量:LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径
边栏推荐
- Yotact real-time instance segmentation
- Wechat applet realizes store function
- Lc236. nearest common ancestor of binary tree
- 微信小程序实现store功能
- Please use the learned knowledge to write a program to find out the password hidden in the long string below. The burial point of the password conforms to the following rules:
- Visual assist plug-in settings for UE4 vs
- 2020-09-29 非商品模板化代码层次 rapidjson库
- 【华为认证】HCIA-DATACOM史上最全精选题库(附答案解析)
- The 23 most useful elasticsearch search techniques you must know
- 官方stm32芯片包下载地址 stm32f10x stm32f40x下载
猜你喜欢

基于keil5自动配置stm32f103标准库的官网freertos移植

In the era of data processing, data quality construction is the way for enterprises to survive

长安链数据存储介绍及Mysql存储环境搭建

Automatic Multi-Organ SegmVentation on Abdominal CT With Dense V-Networks

阿里云服务器安装配置redis,无法远程访问

CROSSFORMER: A VERSATILE VISION TRANSFORMER BASED ON CROSS-SCALE ATTENTION

How to do unit test well

Fully Automated Gross Tumor Volume Delineation From PET in Head and Neck Cancer Using Deep Learning

你知道BFD是什么吗?一文详解BFD协议原理及使用场景

Self cultivation (XXI) servlet life cycle, service method source code analysis, thread safety issues
随机推荐
Factory mode
Leetcode skimming -- teponacci sequence
证券账号开户安全吗?是靠谱的吗?
基於PyQt5和Qt Designer的簡易加法計算器的制作
Fabrication d'une calculatrice d'addition simple basée sur pyqt5 et Qt Designer
Chang'an chain go language smart contract writing and compilation
How to set Google Chrome as the default browser
Deep Learning-based Automated Delineation of Head and Neck Malignant Lesions from PET Images
JS obtain mobile phone model and system version
第十二章 信号(二)- 生产者消费者示例
Making of simple addition calculator based on pyqt5 and QT Designer
通识篇:原型设计的认知,设计及最佳实践
云管理平台:9大开源云管理平台(CMP)
In the future of Business Intelligence BI, how do you view the ai+bi model?
Cloud management platform: openstack architecture design and detailed interpretation
Gd32f4xx Ethernet chip (ENC28J60) driver migration
Please use the learned knowledge to write a program to find out the password hidden in the long string below. The burial point of the password conforms to the following rules:
In the era of data processing, data quality construction is the way for enterprises to survive
zabbix4.4配置监控服务器指标,以及图形页乱码解决
KDevelop new project