懒人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

 1# lazy build C project Makefiles by impressionyang
 2# user config values
 3CC="/usr/bin/gcc"
 4# CC="E:\\impressionyang\\scoop\\apps\\mingw\\12.2.0\\bin\\gcc.exe"
 5PROJECT=test
 6
 7# check operating system type
 8ifeq ($(OS), Windows_NT)
 9	OS_TYPE := WINDOWS
10	SHELL := cmd
11else
12	UNAME_S := $(shell uname -s)
13    ifeq ($(UNAME_S),Linux)
14        OS_TYPE := LINUX
15    endif
16    ifeq ($(UNAME_S),Darwin)
17        OS_TYPE := OSX
18    endif
19endif
20
21$(info OS type = $(OS_TYPE))
22
23# patern config
24FILES_PATH  := ./
25SRC_FILES_SUFFIX := %.c
26HDR_FILES_SUFFIX := %.h
27
28# define func to remove_same_str for debug: $(info get seen ${seen})
29define remove_same_str =
30  $(eval seen :=)
31  $(foreach _,$1,$(if $(filter $_,${seen}),,$(if $_, $(eval seen += $_)))) 
32  ${seen}
33endef
34
35# find recursive all files
36rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
37
38# get source file and header file
39FIND_ALL_FILES := $(foreach files_path,$(FILES_PATH), $(call rwildcard,$(files_path),*.*) ) 
40SOURCES  := $(filter $(SRC_FILES_SUFFIX),$(FIND_ALL_FILES)) 
41SOURCES  := $(SOURCES:$(LOCAL_PATH)/%=%)
42HEADERS  := $(filter $(HDR_FILES_SUFFIX),$(FIND_ALL_FILES)) 
43HEADERS  := $(HEADERS:$(LOCAL_PATH)/%=%)
44
45# fillter out all include path
46FIND_ALL_FILES_DIR := $(dir $(foreach files_path,$(FILES_PATH), $(call rwildcard,$(files_path),*/) ) )
47GET_INC_DIRS := $(call remove_same_str,$(FIND_ALL_FILES_DIR))
48INC_DIRS :=
49INC_DIRS += $(foreach v, $(GET_INC_DIRS), $(if $(filter %/,$v) , $(eval INC_DIRS+=$v), ))
50INC_DIRS := $(subst ./, -I./, $(INC_DIRS))
51INC_DIRS := $(wordlist 1, $(words $(INC_DIRS)), $(INC_DIRS))
52
53# debug print info, no need to be change
54# $(info "INC_DIRS")
55# $(info $(INC_DIRS))
56# $(info "HEADERS")
57# $(info $(HEADERS))
58# $(info "SOURCES")
59# $(info $(SOURCES))
60
61# compile job
62all : 
63	$(CC) -fdiagnostics-color=always -g $(SOURCES) $(HEADERS) $(INC_DIRS) -o $(PROJECT)
64
65# virtual clean job
66.PHONY : clean
67clean:
68ifeq ($(OS_TYPE), WINDOWS)
69	del $(PROJECT).exe
70endif
71ifeq ($(OS_TYPE), LINUX)
72	rm $(PROJECT)
73endif
74ifeq ($(OS_TYPE), OSX)
75	rm $(PROJECT)
76endif
77	

如何使用

基本上,只要如下几步就可以进行项目开发:

  1. 创建一个文件夹,命名为项目名称
  2. 然后把这个Makfile创建好,修改Makefile中的CC(编译器的路径,推荐使用MinGW)和PROJECT(项目名)字段就行
  3. 写C代码
  4. make就行啦

如果还想要使用VSCode的调试功能的话,就加上调试的luanch.json就行啦,具体的话以后有需要再增加文章说明。

总结

总之,这个Makefile就突出一个懒,所以它很多过程自动完成,所以他的缺点也很明显,目前没有自动连接库,这个以后会继续优化的。


impressionyang