2017-09-07 20 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