【问题标题】:Forcing Orders in Makefile DependenciesMakefile 依赖项中的强制顺序
【发布时间】:2017-09-07 04:35:38
【问题描述】:

我需要一些帮助来编写 GNU makefile。我有一个 C 程序“main.c”,它取决于文件“constants.h”中定义的“CONSTANT”的值。

“main.c”

#include <stdio.h>
#include "constants.h"

void work(void)
{
    int array[CONSTANT];
    for (int i = 0; i < CONSTANT; i++) {
        printf("%d\n", i);
    }
}

int main(int argc, char const* argv[])
{
    printf("constant=%d\n", CONSTANT);
    work();
    return 0;
}

“常数.h”

#ifndef CONSTANTS_H
#define CONSTANTS_H

#define CONSTANT 4
#endif

我在这里要做的是用不同的“CONSTANT”值来编译程序。例如,“out1”用“CONSTANT=1”和“make all”编译,我应该能够产生所有的变体(“out1”、“out2”和“out4”)。

问题是“main.c”所需的“a.o”也取决于“CONSTANT”的值。所以“a.o”必须在“sed%”之后编译。但是,据我了解,“make”中没有办法强制依赖项中的命令(我想这是使用 makefile 的全部意义)。

解决这种情况的推荐方法是什么?

“生成文件”

CC= gcc
CFLAGS  = -std=c99 -Wall

CONSTANTS = 1 2 4
targets = $(addprefix out, $(CONSTANTS))
seds = $(addprefix sed, $(CONSTANTS))

.PHONY: $(seds)
$(seds): sed%:
  sed -i 's/define CONSTANT [0-9]*/define CONSTANT $*/g' constants.h

$(targets): out%: main.c sed% a.o
  $(CC) $(CFLAGS) $< a.o -o $@

a.o: a.c constant.h
  $(CC) $(CFLAGS) $< a.o -o $@

 .PHONY: all
 all : $(targets)

请注意,我知道我可以重写“main.c”,以便它从命令行获取一个参数。实际上,“main.c”以外的许多其他文件都依赖于“CONSTANT”,所以我想避免重写所有这些文件。我也知道我可以执行“gcc -DCONSTANT=n main.c”之类的操作,但也必须重新编译依赖于“CONSTANT”的每个文件。

相关问题

【问题讨论】:

  • Make 假定一旦它构建了一个文件 (a.o),它就是最新的并且在同一次运行期间不需要重新编译。因此,您必须做其他事情。一种选择是从a.cconstants.h 和合适的sed-work 创建a1.oa2.oa4.o。如果只有一个常量,请考虑在命令行上使用-DCONSTANT=1,因为您从a.c 等创建a1.o,根本不使用constants.h。但是,我怀疑这是对 SO 的最小化问题,并且您拥有的值不仅仅是要设置的值。我仍然倾向于创建不同名称的目标文件。
  • 请提供minimal reproducible example 进行测试。 IE。定义改变的情况(constant.h)或调用makefile的某种方式)和期望的结果,即文件的输出或结果内容。
  • @JonathanLeffler 我按照您和 Mike 的建议生成了单独的目标文件(a1.o、a2.o、....)。我的程序只有一个常量要配置,所以你的解决方案对我有用。谢谢。
  • 欢迎来到 Stack Overflow。请注意,在这里说“谢谢”的首选方式是投票赞成好的问题和有用的答案(一旦你有足够的声誉这样做),并接受对你提出的任何问题最有帮助的答案(这也给出了你的声誉小幅提升)。请参阅About 页面以及How do I ask questions here?What do I do when someone answers my question?

标签: c sed makefile


【解决方案1】:

我知道我可以做一些类似“gcc -DCONSTANT=n main.c”的事情, 但是每个依赖于“CONSTANT”的文件也必须重新编译。

如果你有你的 makefile 生成,这不一定是一个障碍 每个编译配方中正确的 -DCONSTANT=n 和不同的目标文件。

这是一个插图:

constants.h

#ifndef CONSTANTS_H
#define CONSTANTS_H

#ifndef CONSTANT
#define CONSTANT 4
#endif

#endif

foo.c

#include "constants.h"

int foo = CONSTANT;

ma​​in.c

#include <stdio.h>
#include "constants.h"

extern int foo;

int main()
{
    printf("%d\n",CONSTANT + foo);
    return 0;
}

生成文件

CC := gcc
CFLAGS := -std=c99 -Wall

CONSTANTS = 1 2 4
TARGETS = $(addprefix out, $(CONSTANTS))
SRCS := main.c foo.c

define compile =
$(basename $(1))$(2).o: $(1) constants.h
    $$(CC) -c -DCONSTANT=$(2) $$(CFLAGS) $$< -o $$@
endef

.PHONY: all clean

all : $(TARGETS)

$(foreach src,$(SRCS),\
    $(foreach const,$(CONSTANTS),$(eval $(call compile,$(src),$(const))))) 

out%: main%.o foo%.o 
    $(CC) $^ -o $@


clean:
    rm -f $(TARGETS) *.o

运行如下:

$ make
gcc -c -DCONSTANT=1 -std=c99 -Wall main.c -o main1.o
gcc -c -DCONSTANT=1 -std=c99 -Wall foo.c -o foo1.o
gcc main1.o foo1.o -o out1
gcc -c -DCONSTANT=2 -std=c99 -Wall main.c -o main2.o
gcc -c -DCONSTANT=2 -std=c99 -Wall foo.c -o foo2.o
gcc main2.o foo2.o -o out2
gcc -c -DCONSTANT=4 -std=c99 -Wall main.c -o main4.o
gcc -c -DCONSTANT=4 -std=c99 -Wall foo.c -o foo4.o
gcc main4.o foo4.o -o out4

生成的程序运行如下:

$ for i in 1 2 4; do ./out$i; done
2
4
8

【讨论】:

  • 单独的目标文件是有意义的。我的事情开始了。谢谢。
猜你喜欢
  • 2022-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多