懒人C工程Makefile
懒人C工程Makefile
引言
在工作的一段时间里面, 因为平时写项目的时候有一些功能需要紧急调试,但是调试的代码呢又想单独的分出来进行归档,然后又不想使用IDE进行创建,同时还想跨平台使用(windows/Linux),所以还是继续折腾Makdfile吧。
需求
首先因为是懒人需求,也就是不想老是每次都编辑Makefile文件进行项目文件的管理,所以就想整个项目只有一个Makefile文件,然后仅需要修改项目名称和编译器的路径(甚至编译器路径仅需要自己配一次,以后直接复制该Makefile文件修改项目名称即可),也就是修改有限的两行代码。
Makefile的功能需求很简单,使用Makefile来进行C项目的编译工作,自动收集.c文件和.h文件按,并且自动完成头文件目录的包含,最后进行编译和清除生成的文件。
环境上,目前使用的是VSCode作为文本编辑器,所以需要使用VSCode的调试功能工作进行内存查看,所以需要编译出来的可执行文件可以被追溯源代码(如果使用Makefile的自动推导功能一般不能被MinGW的GDB进行追溯)。然后因为想快平台,环境就是用MinGW即可。
Makefile文件内容
既然需求已经明确,所以直接给出第一版代码,未来的代码更新会在GitHub上同步,传送门https://github.com/impressionyang/lazy_single_makefile_for_c_project。
# lazy build C project Makefiles by impressionyang
# user config values
CC="/usr/bin/gcc"
# CC="E:\\impressionyang\\scoop\\apps\\mingw\\12.2.0\\bin\\gcc.exe"
PROJECT=test
# check operating system type
ifeq ($(OS), Windows_NT)
OS_TYPE := WINDOWS
SHELL := cmd
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
OS_TYPE := LINUX
endif
ifeq ($(UNAME_S),Darwin)
OS_TYPE := OSX
endif
endif
$(info OS type = $(OS_TYPE))
# patern config
FILES_PATH := ./
SRC_FILES_SUFFIX := %.c
HDR_FILES_SUFFIX := %.h
# define func to remove_same_str for debug: $(info get seen ${seen})
define remove_same_str =
$(eval seen :=)
$(foreach _,$1,$(if $(filter $_,${seen}),,$(if $_, $(eval seen += $_))))
${seen}
endef
# find recursive all files
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
# get source file and header file
FIND_ALL_FILES := $(foreach files_path,$(FILES_PATH), $(call rwildcard,$(files_path),*.*) )
SOURCES := $(filter $(SRC_FILES_SUFFIX),$(FIND_ALL_FILES))
SOURCES := $(SOURCES:$(LOCAL_PATH)/%=%)
HEADERS := $(filter $(HDR_FILES_SUFFIX),$(FIND_ALL_FILES))
HEADERS := $(HEADERS:$(LOCAL_PATH)/%=%)
# fillter out all include path
FIND_ALL_FILES_DIR := $(dir $(foreach files_path,$(FILES_PATH), $(call rwildcard,$(files_path),*/) ) )
GET_INC_DIRS := $(call remove_same_str,$(FIND_ALL_FILES_DIR))
INC_DIRS :=
INC_DIRS += $(foreach v, $(GET_INC_DIRS), $(if $(filter %/,$v) , $(eval INC_DIRS+=$v), ))
INC_DIRS := $(subst ./, -I./, $(INC_DIRS))
INC_DIRS := $(wordlist 1, $(words $(INC_DIRS)), $(INC_DIRS))
# debug print info, no need to be change
# $(info "INC_DIRS")
# $(info $(INC_DIRS))
# $(info "HEADERS")
# $(info $(HEADERS))
# $(info "SOURCES")
# $(info $(SOURCES))
# compile job
all :
$(CC) -fdiagnostics-color=always -g $(SOURCES) $(HEADERS) $(INC_DIRS) -o $(PROJECT)
# virtual clean job
.PHONY : clean
clean:
ifeq ($(OS_TYPE), WINDOWS)
del $(PROJECT).exe
endif
ifeq ($(OS_TYPE), LINUX)
rm $(PROJECT)
endif
ifeq ($(OS_TYPE), OSX)
rm $(PROJECT)
endif
如何使用
基本上,只要如下几步就可以进行项目开发:
- 创建一个文件夹,命名为项目名称
- 然后把这个Makfile创建好,修改Makefile中的
CC
(编译器的路径,推荐使用MinGW)和PROJECT
(项目名)字段就行 - 写C代码
make
就行啦
如果还想要使用VSCode的调试功能的话,就加上调试的luanch.json
就行啦,具体的话以后有需要再增加文章说明。
总结
总之,这个Makefile就突出一个懒,所以它很多过程自动完成,所以他的缺点也很明显,目前没有自动连接库,这个以后会继续优化的。