Makefile-gcc 使用小结
# gcc
## gcc编译器的可选参数。
-c表示只编译(compile)源文件但不链接,会把.c或.cc的c源程序编译成目标文件,一般是.o文件。
-o用于指定输出(out)文件名。不用-o的话,一般会在当前文件夹下生成默认的a.out文件作为可执行程序。
例如:
gcc -c test.c将生成test.o的目标文件
gcc -o app test.c将生成可执行程序app
gcc -c a.c -o a.o表示把源文件a.c编译成指定文件名a.o的中间目标文件(其实在这里,把-o a.o省掉,效果是一样的,因为中间文件默认与源文件同名,只是后缀变化)。
1、如果GCC不带-C参数,编译一个源代码文件(test.c)。那么会自动将编译和链接一步完成,并生成可执行文件。可执行文件可以有-o参数指定(test.o)
2、如果是多个文件,则需要先编译成中间目标文件(一般是.o文件),在链接成可执行文件,一般习惯目标文件都是以.o后缀,也没有硬性规定可执行文件不能用.o文件
加个-g 是为了gdb 用,不然gdb用不到
-W: 关闭编译警告
-Wall: 打开编译警告
-lpthread:l指link,链接pthread库
# makefile
- makefile老是报“recipe for target xxx”错误,不妨先看看makefile文件的编码是否正确
如果你的makefile是直接从网上复制来的,先在window下,用写字板看看是否有乱码,“空格”的乱码很有可能就是你错误的罪魁祸首。
- 在函数‘_start’中:对‘main’未定义的引用
这是因为,编译的文件中,找不到main()这个函数.
确认一下,是不是注释了,或者ifdef没了.或者包含main的.cpp文件未被包含生成.o文件
## 相关教程、示例资料
《跟我一起写Makefile》
链接:https://pan.baidu.com/s/1OT-Hk3bzo070hjuWo39ASg
提取码:sjfy
一个Makefile示例; 采用了很多高级功能,大大简化了makefile文件的编写
https://www.jianshu.com/p/3c13d915dcb0
完整的示例工程和 makefile 文件可以到如下路径取:
https://github.com/Lingminzou/code/tree/master/makefile/example
make的使用和Makefile的编写
https://blog.youkuaiyun.com/u012510204/article/details/53926399
跟我一起写Makefile
https://seisman.github.io/how-to-write-makefile/overview.html
自动生成项目的Makefile文件(待研究)
https://www.cnblogs.com/yejinru/p/4983209.html
vs code 配置.json文件引入makefile文件实现多文件编译
https://blog.youkuaiyun.com/m0_37433067/article/details/80145679
# *************** 一般工程makefile模板 ******************
# 输出标目名称
BINNAME = UnderdriveHand
# 设置 .o 文件输出路径
OBJDIR = ./obj
# 配置工具链 CC
CC = g++
# 配置编译选项
CC_OPTS := -std=c++11 # -Wall -Werror 编译过程中输出控制
# 配置链接选项
LD_OPTS := -lpthread
# 指定编译时依赖的头文件目录,然后放进编译选项
INC_DIR := ./EigenArduino_Eigen30 # ./serial ./driver ./kinematic ./control 如何连续包含??
CC_OPTS += -I$(INC_DIR)
CC_OPTS += -I ./drive
CC_OPTS += -I ./kinematic
CC_OPTS += -I ./control
CC_OPTS += -I ./main
# 指出源文件存放路径
SRC_DIR := ./EigenArduino_Eigen30
SRC_DIR += ./drive ./kinematic ./control ./main
# 指定依赖文件搜索路径,即我们的源文件路径
VPATH = $(SRC_DIR)
# 找出所有需要编译的 cpp 类型文件,注意 find 默认是会循环找子目录的,
# 由于我们子目录的路径也需要写进 VPATH 所以这里把 find 的查找深度设置为了 1
SRC = $(shell find $(SRC_DIR) -maxdepth 1 -name '*.cpp') # -maxdepth 1
# 生成需要输出的 .o 文件名
OBJ_0 = $(notdir $(patsubst %.cpp, %.o, $(SRC)))
# 加上 .o 文件存放路径前缀
OBJ = $(foreach file, $(OBJ_0), $(OBJDIR)/$(file))
.PHONY: all setup bin clean
all: setup bin
setup:
@echo $(SRC)
@echo $(OBJ_0)
@echo $(OBJ)
mkdir -p $(OBJDIR)
bin: $(OBJ)
$(CC) $(OBJ) $(LD_OPTS) -o $(BINNAME)
$(OBJ): $(OBJDIR)/%.o : %.cpp
$(CC) $(CC_OPTS) -o $@ -c $<
clean:
rm -rf $(OBJDIR)
rm -rf $(BINNAME)
# 一个基础示例 makefile_test
main.cpp
#include "print.h"
int main()
{
printhello();
return 0;
}
print.h
#include<stdio.h>
void printhello();
print.cpp
#include"print.h"
void printhello()
{
printf("Hello, world\n");
}
Makefile
# #*********基础版
# helloworld:main.o print.o
# gcc -o helloworld main.o print.o
# mian.o:mian.c print.h
# gcc -c main.c
# print.o:print.c print.h
# gcc -c print.c
# clean:
# rm helloworld main.o print.o
# #*********简化版
obj := main.o print.o # 变量;宏定义
helloworld:$(obj)
gcc -o helloworld $(obj)
$(obj):print.h # 都依赖print.h
mian.o:mian.c #去掉了gcc -c main.c 让gcc make自动推导
print.o:print.c
clean:
rm helloworld $(obj)
# 报错、异常处理
- makefile老是报“recipe for target xxx”错误,不妨先看看makefile文件的编码是否正确
如果你的makefile是直接从网上复制来的,先在window下,用写字板看看是否有乱码,“空格”的乱码很有可能就是你错误的罪魁祸首。
- 在函数‘_start’中:对‘main’未定义的引用
这是因为,编译的文件中,找不到main()这个函数.
确认一下,是不是注释了,或者ifdef没了.或者包含main的.cpp文件未被包含生成.o文件
# 相关教程、示例资料
《跟我一起写Makefile》
链接:https://pan.baidu.com/s/1OT-Hk3bzo070hjuWo39ASg
提取码:sjfy
一个Makefile示例; 采用了很多高级功能,大大简化了makefile文件的编写
https://www.jianshu.com/p/3c13d915dcb0
完整的示例工程和 makefile 文件可以到如下路径取:
https://github.com/Lingminzou/code/tree/master/makefile/example
make的使用和Makefile的编写
https://blog.youkuaiyun.com/u012510204/article/details/53926399
跟我一起写Makefile
https://seisman.github.io/how-to-write-makefile/overview.html
自动生成项目的Makefile文件(待研究)
https://www.cnblogs.com/yejinru/p/4983209.html
vs code 配置.json文件引入makefile文件实现多文件编译
https://blog.youkuaiyun.com/m0_37433067/article/details/80145679
# 一个较通用模板
Makefile
# //*** 根据具体工程需要,更改BINNAME、LD_OPTS、SRC_DIR 、CC_OPTS等宏变量即可 ***//
# 输出标目名称
BINNAME = UnderdriveHand
# 设置 .o 文件输出路径
OBJDIR = ./obj
# 配置工具链 CC
CC = g++
# 配置编译选项
CC_OPTS := -std=c++11 # -Wall -Werror 编译过程中输出控制
# 配置链接选项
LD_OPTS := -lpthread
# 指定编译时依赖的头文件目录,然后放进编译选项
INC_DIR := ./EigenArduino_Eigen30 # ./serial ./driver ./kinematic ./control 如何连续包含??
CC_OPTS += -I$(INC_DIR)
CC_OPTS += -I ./drive
CC_OPTS += -I ./kinematic
CC_OPTS += -I ./control
CC_OPTS += -I ./main
# 指出源文件存放路径
SRC_DIR := ./EigenArduino_Eigen30
SRC_DIR += ./drive ./kinematic ./control ./main
# 指定依赖文件搜索路径,即我们的源文件路径
VPATH = $(SRC_DIR)
# 找出所有需要编译的 cpp 类型文件,注意 find 默认是会循环找子目录的,
# 由于我们子目录的路径也需要写进 VPATH 所以这里把 find 的查找深度设置为了 1
SRC = $(shell find $(SRC_DIR) -maxdepth 1 -name '*.cpp') # -maxdepth 1
# 生成需要输出的 .o 文件名
OBJ_0 = $(notdir $(patsubst %.cpp, %.o, $(SRC)))
# 加上 .o 文件存放路径前缀
OBJ = $(foreach file, $(OBJ_0), $(OBJDIR)/$(file))
.PHONY: all setup bin clean
all: setup bin
setup:
@echo $(SRC)
@echo $(OBJ_0)
@echo $(OBJ)
mkdir -p $(OBJDIR)
bin: $(OBJ)
$(CC) $(OBJ) $(LD_OPTS) -o $(BINNAME)
$(OBJ): $(OBJDIR)/%.o : %.cpp
$(CC) $(CC_OPTS) -o $@ -c $<
clean:
rm -rf $(OBJDIR)
rm -rf $(BINNAME)
根据具体工程需要,更改BINNAME、LD_OPTS、SRC_DIR 、CC_OPTS等宏变量即可.