由于您有一个绘制得很好的依赖树,因此您“只需”将其转换为Makefile
.
你可能想从这个开始:
.PHONY: all
all: reloader.exe block_finder.exe formatter.exe printdb.exe
MODULES = reloader block_finder formatter printdb linked_list bitcoin file_handler
SRCS = $(MODULES:%=%.c)
reloader.exe block_finder.exe formatter.exe printdb.exe: libbitcoin_manager.so
reloader.exe: reloader.o
block_finder.exe: block_finder.o
formatter.exe: formatter.o
printdb.exe: printdb.o
libbitcoin_manager.so: linked_list.o bitcoin.o file_handler.o
gcc -shared -fPIC $^ -o $@
%.exe: %.o
gcc $< -L. -lbitcoin_manager -o $@
%.o: %.c
gcc -c $< -o $@
%.d: %.c
gcc -MM -MT $@ -MT $*.o -MF $@ $<
include $(SRCS:%.c=%.d)
因为图表中没有循环,所以Makefile
. 相反,您将所有依赖文件放在冒号的左侧,将它们依赖的文件放在右侧。
您可能希望在变量中收集更多“对象”,例如要构建的程序、库中的模块等等。
我还使用了一种通用模式从头文件生成依赖项。所示方式只是其中一种方式。它使用带有“ .d
”扩展名的文件来表示“依赖”。GCC 可以选择构建这些文件,它会扫描源代码并收集所有包含的头文件,即使是“堆叠的”。
例如,“ bitcoin.d
”看起来像这样:
bitcoin.d bitcoin.o: bitcoin.c bitcoin.h linked_list.h definitions.h \
file_handler.h
重新生成对源更改的依赖文件,它也是一个目标,而不仅仅是目标文件。
编辑:
首先,使用目录使 Makefiles 更加困难。我不喜欢这样的结构不仅是因为这个原因,还因为它们将明显属于彼此的头文件和实现文件分开。
无论如何,这是一个增强的Makefile
:
.PHONY: all
SRCDIR = src
INCDIR = include
BLDDIR = build
APPS = reloader block_finder formatter printdb
MODULES = reloader block_finder formatter printdb linked_list bitcoin file_handler
LIBNAME = bitcoin_manager
LIBMODULES = linked_list bitcoin file_handler
VPATH = $(SRCDIR)
SRCS = $(MODULES:%=%.c)
LIB = $(LIBNAME:%=lib%.so)
#win LIB = $(LIBNAME:%=%.lib)
EXES = $(APPS:%=%.exe)
all: $(BLDDIR) $(EXES)
$(BLDDIR):
mkdir $@
$(LIB): $(LIBMODULES:%=$(BLDDIR)/%.o)
gcc -shared -fPIC $^ -o $@
$(EXES): $(LIB)
$(EXES): %.exe: $(BLDDIR)/%.o
gcc $< -L. -l$(LIBNAME) -o $@
$(BLDDIR)/%.o: %.c
gcc -I$(INCDIR) -c $< -o $@
$(SRCDIR)/%.d: %.c
gcc -I$(INCDIR) -MM -MT $@ -MT $(BLDDIR)/$*.o -MF $@ $<
include $(SRCS:%.c=$(SRCDIR)/%.d)
它使用更多变量来简化重命名和管理不断增长的库和应用程序。
一个重要的问题是使用VPATH
. 这使得make
在分配给它的路径列表中搜索源。确保您完全理解它,搜索文章和文档。很容易用错。
图案$(EXES): %.exe: $(BLDDIR)/%.o
很好看。它由三部分组成,首先是目标列表,其次是具有单个目标及其源的通用模式。这意味着对于所有可执行文件,它们中的每一个都是从其目标文件构建的。
现在回答你的问题:
由新提案回答。我没有添加目录,而是使用VPATH
.
Make 停止不是因为 exe-from-o 模式错误,而是因为它没有找到构建所需目标文件的方法。新提案也解决了这个问题。想知道如果你删除旧提案中的这 4 个食谱会发生什么:你可以做实验,那就去做吧!
就像 user3629249 试图说的那样,这个点是当前的工作目录。你在你的 Makefile 中有它'pwd'
,我替换了它。这对 来说并不特殊make
,它在所有主要操作系统中都很常见,包括 Windows。您可能知道..
哪个指定父目录。
启动时make
,它会读取该Makefile
文件或任何给定文件。如果此文件包含include
指令,则检查列出的文件是否需要重建。make
即使你用-n
! 在(重新)构建所有要包含的文件之后,它们最终被包含在内。现在make
拥有所有配方并继续其“正常”工作。