makefileeval - 代码构建工具教程

发布时间:2023-05-20

一、什么是makefileeval?

makefileeval是一个工具库,可以帮助我们轻松构建C/C++代码的编译和安装流程。它基于Makefile文件,提供了方便的API接口,允许我们在代码库中定义自己的编译、安装规则,并且可以跨平台使用。see example:

.PHONY: all clean install
.DEFAULT_GOAL := all
CC := g++
CFLAGS := -Wall -std=c++17
ALL_OBJS := obj/a.o obj/b.o obj/c.o
all: $(ALL_OBJS)
	$(CC) $(ALL_OBJS) -o main
obj/%.o: src/%.cc
	$(CC) $(CFLAGS) -o $@ -c $<
install:
	install main /usr/local/bin
clean:
	rm -rf obj/*.o main

在这个例子中,我们定义了三个目标,all、clean和install。其中,all目标是makefileeval中默认的目标,因此不需要手动指定执行。它将依赖obj目录下所有的.o文件,并将它们链接成一个二进制文件main。我们还定义了一个规则,指定了将src目录下的.cc文件编译并生成对应.o文件的方法。最后,我们实现了一个安装目标,将生成的二进制文件main安装到系统路径中。通过这些定义,我们可以通过运行make来完成编译、链接和安装。

二、如何使用makefileeval?

使用makefileeval可以分为两个部分,一是在代码库中定义Makefile文件,二是在命令行中调用make工具。在Makefile文件的编写中,我们需要定义好我们的编译规则、依赖关系以及目标操作。然后在命令行中,通过执行make命令,可以根据Makefile文件定义的规则来自动编译源代码,生成可执行程序、动态库、静态库等。see example:

all: bin/foo
bin/foo: obj/main.o obj/foo.o obj/helper.o
	mkdir -p bin
	g++ -o $@ $^
obj/main.o: src/main.cpp inc/foo.h inc/helper.h
	mkdir -p obj
	g++ -c -o $@ -Iinc src/main.cpp
obj/foo.o: src/foo.cpp inc/foo.h
	mkdir -p obj
	g++ -c -o $@ -Iinc src/foo.cpp
obj/helper.o: src/helper.cpp inc/helper.h
	mkdir -p obj
	g++ -c -o $@ -Iinc src/helper.cpp
.PHONY: clean
clean:
	rm -rf bin/foo obj/*.o

在这个例子中,我们定义了一个名为all的目标操作,它依赖于名为bin/foo的目标文件。同时bin/foo依赖obj目录下的三个.o文件。在每一个.o文件构建规则中,我们都实现了将源文件编译成.o文件的步骤,并在目标文件构建规则中执行链接操作,将所有的.o文件链接为最终的可执行文件。最后,clean规则用于清除编译生成的目录和文件。

三、如何定制makefileeval?

makefileeval允许我们在代码库中定义自己的编译规则和依赖关系,帮助我们处理各种常见的编译问题。我们可以通过修改Makefile文件中的路径、编译选项、依赖项、目标输出路径等来达到特定需求。see example:

# 使用C++20标准编译
CXXFLAGS = -std=c++20
# 源文件目录
SRC_DIR = src
# 对象文件目录
BUILD = build
# 应用程序名称和目录
APPNAME = app
DEPLOY_DIR ?= /usr/bin
# 依赖的库文件目录
LIB_DIR = -L../lib
# 需要引入的第三方库
LIBS = -lpthread -lcrypto -lssl
# 根据源文件生成.o文件
%.o: $(SRC_DIR)/%.cpp
	$(CXX) $(CXXFLAGS) -c $< -o $(BUILD)/$@
# 编译链接最终应用程序
$(APPNAME): main.o common.o tools.o
	$(CXX) $(CXXFLAGS) -o $(APPNAME) $(BUILD)/main.o $(BUILD)/common.o $(BUILD)/tools.o $(LIBS) $(LIB_DIR)
# 依赖文件更新时间戳
DEPS := $(shell find $(SRC_DIR) -name '*.h' -or -name '*.hpp' | sed 's/^/--include=/' | tr '\n' ' ')
# 向量清空
OBJ = 
OBJ += $(patsubst %.cpp, %.o, $(shell find $(SRC_DIR) -name '*.cpp'))
all: $(APPNAME)
clean:
	rm -rf $(BUILD)
	rm -rf $(APPNAME)
install: all
	install -d $(DEPLOY_DIR)
	install $(APPNAME) $(DEPLOY_DIR)

在这个例子中,我们使用了C++20标准编译我们的代码。定义了源文件目录、对象文件目录,以及应用程序名称和目录,依赖库文件目录和需引入的第三方库。我们也重新定义了生成.o文件的规则,并定义了最终应用程序链接的规则。对于依赖文件,我们使用shell命令查找源文件目录中所有的.h和.hpp文件作为依赖项,并将查找到的结果用于update的依赖项中,以保证更新和编译的正确性。clean规则用于清除编译生成的目录和文件,install规则用于安装可执行文件。