2017-09-07 18 views
2

我需要一些编写GNU makefile的帮助。我有一个C程序“main.c”,它取决于文件“constants.h”中定义的“CONSTANT”的值。在Makefile相关性中强制执行订单

“的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; 
} 

“constant.h”

#ifndef CONSTANTS_H 
#define CONSTANTS_H 

#define CONSTANT 4 
#endif 

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

问题是“main.c”要求的“a.o”也取决于“CONSTANT”的值。所以“a.o”必须在“sed%”之后编译。然而,据我所知,“make”无法在依赖中强制执行命令(我想这是使用makefile的全部要点)。

解决这种情况的建议方法是什么?

“的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 [email protected] 

a.o: a.c constant.h 
    $(CC) $(CFLAGS) $< a.o -o [email protected] 

.PHONY: all 
all : $(targets) 

注意,我知道,我可以改写“main.c中”,因此,它需要从comman线的参数。实际上,“main.c”以外的其他许多文件依赖于“CONSTANT”,所以我想避免重写所有这些文件。我也知道我可以像“gcc -DCONSTANT = n main.c”那样做,但是每个依赖于“CONSTANT”的文件也必须重新编译。

相关问题

+1

制作假定次它立即建立了一个文件('a.o'),它是最新的,并且不需要在同一次运行中重新编译。因此,你必须做其他事情。一种选择是从'a.c'和'constants.h'和适当的sed-work创建'a1.o','a2.o'和'a4.o'。如果只有一个常量,那么当你从'a.c'等创建'a1.o'时,在命令行中考虑'-DCONSTANT = 1',而不使用'constants.h'。但是,我怀疑这是SO的最小化问题,你有更多的价值而不仅仅是设定的价值。我仍倾向于创建不同名称的对象文件。 –

+0

请提供[mcve]测试。即定义改变的情况(constant.h)或调用makefile的某种方式)和期望的结果,即文件的输出或结果内容。 – Yunnosch

+0

@JonathanLeffler我和你和Mike建议一起生成单独的目标文件(a1.o,a2.o,....)。我的程序只有一个常量来配置,所以你的解决方案为我工作。谢谢。 – user3127171

回答

3

我......知道我可以这样做“GCC -DCONSTANT = N为主。 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; 

为主。ç

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

extern int foo; 

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

的Makefile

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 [email protected] 
endef 

.PHONY: all clean 

all : $(TARGETS) 

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

out%: main%.o foo%.o 
    $(CC) $^ -o [email protected] 


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 
+0

单独的目标文件是有意义的。我有我的事情工作。谢谢。 – user3127171