Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何区分不同配置的Makefile生成输出?_C++_C_Makefile_Continuous Integration_Gnu Make - Fatal编程技术网

C++ 如何区分不同配置的Makefile生成输出?

C++ 如何区分不同配置的Makefile生成输出?,c++,c,makefile,continuous-integration,gnu-make,C++,C,Makefile,Continuous Integration,Gnu Make,假设我有一个项目,有一个简单的Makefile,如下所示: all: foobar foobar: foo.o bar.o 我可以针对不同的体系结构构建: $ CC=clang make # or $ CC=x86_64-w64-mingw32-gcc make # or $ CC=arm-linux-gnueabihf-gcc make 这是可行的,但我希望能够同时维护多个配置的输出,例如在构建服务器上 什么是一个好的,干净的方式去做这件事?我考虑

假设我有一个项目,有一个简单的Makefile,如下所示:

all: foobar
foobar: foo.o bar.o
我可以针对不同的体系结构构建:

$ CC=clang make                    # or
$ CC=x86_64-w64-mingw32-gcc  make  # or
$ CC=arm-linux-gnueabihf-gcc make
这是可行的,但我希望能够同时维护多个配置的输出,例如在构建服务器上

什么是一个好的,干净的方式去做这件事?我考虑了以下几点:

  • 使用自动工具或其他构建工具,但我想看看没有自动工具有什么可能
  • 创建包含Makefile的生成目录,其中包含设置VPATH并包含根Makefile的Makefile
  • 编写一个脚本,在构建每个体系结构后移动输出
  • 修改Makefile以生成多个配置。我不喜欢这个解决方案,因为您最终会得到一种元生成文件,它非常复杂,并且与特定的构建环境紧密耦合
  • 向Makefile添加一个变量以设置输出目录。这可能有效,但这意味着我不能使用隐式Makefile规则。模式规则也会变得混乱

我会说这样的话:

# User configuration
BINARY  := hello
SOURCES := main.c

# Create the output paths
out     ?= out
outdir  := $(out)/$(CC)
outbin  := $(outdir)/$(BINARY)
objects := $(outdir)/$(SOURCES:.c=.o)

# Default target
all: $(outbin)

# Binary target
$(outbin): $(objects)
    $(CC) -o $@ $^

# Objects target
$(objects): $(outdir)/%.o: %.c
    mkdir -p $(@D)
    $(CC) -o $@ -c $<

# The cleanning targets
clean:
    $(RM) -r $(outdir)

mrproper:
    $(RM) -r $(out)

# Declare phony targets
.PHONY: all clean mrproper

当您说要保存输出时,是指对象,还是仅指最终的可执行文件?通常的做法是将
$(OBJDIR)
设置为对象的输出目录,您可以根据构建配置有条件地进行设置。隐式规则重写起来非常简单,不过您首先必须创建一个规则来创建$(OBJDIR)。说
arm/foo
x86_64/foo
main/foo
。我建议尽量简单:)我想我会使用@John提到的
$(OBJDIR)
解决方案。我真的希望像
make-f../Makefile VPATH=…
这样的东西成为可能,但我想它不是@uzsoft我不认为Makefile应该了解这些不同的环境,相反,它应该具有适应性。因此我的“meta Makefile”是这样说的。您可以在命令行上轻松地配置
OBJDIR
make OBJDIR=/foo/bar
,然后在Makefile中执行
OBJDIR?=/foo/obj default
,以防用户没有指定它。如果你不介意难看的目录名,你甚至可以做一些类似于
OBJDIR?=/foo/obj-$(CC)
的事情……谢谢你的详细回答。我想这就是我要走的方向。如果在此期间没有其他新的想法出现,我会在一段时间内将此标记为答案。但有一个后续问题:是否可以使用经典后缀语法执行
obj/%.o:%.c
规则?@SijmenMulder是的,我相信你可以。我更喜欢这种表示法,因为它只对您指定的目标有效。一个快速注释,不要在配方中为每个对象运行
mkdir-p
。而是添加行
$(对象):|$(outdir)
$(outdir):;mkdir-p$@
,它将只运行mkdir一次。@John只有当所有源文件都在同一目录中时,您的解决方案才能正常工作。否则您可以每次运行
mkdir-p
,或者如果您想要更干净的东西,您可以检查。