搜索解决方案以创建通用Makefile来编译多个程序

时间:2019-12-01 22:00:08

标签: c makefile compilation auto-compile

到目前为止,我一直在使用以下为我的学校项目生成的makefile:

my makefile

但是现在我有一个不同的情况:我应该为一个项目编译4个程序,而部分代码应该编译为.so,以供这4个程序使用。 如此处所述:

my project's dependencies

1 -应该一起编译为一个 .so 文件的所有部分,例如:

gcc -shared -fPIC src/file1.c src/file2.c src/file3.c -o libutils.so
应该编译

3、4、5 并将其与此 .so 文件链接在一起,例如:

gcc src/file4.c -L'pwd' lutils -o file4.out

对所有3个项目采用相同的方式,对项目2进行更简单的编译。

我在网上,谷歌,您的网站等处徘徊。 试图为这种情况找到解决方案, 没有任何运气。

已经看到过这样的解决方案: solution example 您可以在其中向makefile提供整个项目结构的详细信息。

我考虑过将所有文件分成4个文件夹,位于主文件夹下,并在makefile中创建一个循环,该循环将在每个循环中编译每个程序,并根据索引使用“ if”语句进行不同的编译。但我没有运气,这似乎很复杂(也许有人可以向我展示这样的解决方案...)。

我想知道是否有一种方法可以使整个编译过程像当前文件一样通用和自动(可能少一些),

如果有办法,我想研究发现。

提前谢谢!!! 阿里

1 个答案:

答案 0 :(得分:1)

由于您拥有一幅漂亮的依存关系树,因此您只需要将其转换为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

根据源中的更改重新生成依赖文件,它也是目标,而不仅仅是目标文件。


编辑:

首先,使用目录会使Makefile更加困难。我不喜欢这样的结构,不仅因为这个原因,而且因为它们将显然彼此属于的头文件和实现文件分开。

无论如何,这是增强的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是一个很好的模式。它由三部分组成,第一部分是目标列表,第二部分是具有单个目标及其来源的通用模式。这意味着对于所有可执行文件,每个可执行文件都是从其目标文件构建的。

现在您的问题是

    新提案回答了
  1. 。我没有添加目录,但使用了VPATH

  2. 使之停止的原因不是因为exe-from-o模式错误,而是因为它没有找到构建所需目标文件的方法。新提案也解决了这一问题。要了解如果删除旧提案中的这四个食谱会发生什么:您可以尝试做,做吧!

  3. 这个点就像user3629249试图说的那样,是当前的工作目录。您在'pwd'中将它保存在Makefile中,我将其替换了。这对make并不特殊,在包括Windows在内的所有主要操作系统中都很常见。您可能知道..,它指定了父目录。

  4. 启动make时,它将读取Makefile或任何给定的文件。如果此文件包含include伪指令,则检查列出的文件是否需要重建。即使您用make进行调用,-n也会这样做!在(重新)构建要包括的所有文件之后,它们最终将被包括在内。现在make拥有所有配方,并继续其“正常”工作。