2015-01-14 124 views
1

我有,我想我的Makefile編譯的文件列表,一個列表中爲每個源語言:makefile編譯源列表中的文件

CFILES= Src/Application/main.c Src/Core/data.c Lib/routines.c 
ASFILES= Src/Application/startup.s Lib/sqrt.s 

我希望所有的輸出在一個目錄:

OBJDIR= output 

我該怎麼做等價的:

output/main.o  : Src/Application/main.c 
    cc -c -o output/main.o Src/Application/main.c 

output/data.o  : Src/Core/data.c 
    cc -c -o output/data.o Src/Core/data.c 

output/routines.o : Lib/routines.c 
    cc -c -o output/routines.o Lib/routines.c 

output/startup.o : Src/Application/startup.s 
    as -o output/startup.o Src/Application/startup.s 

output/sqrt.o  : Lib/sqrt.s 
    as -o output/sqrt.o Lib/sqrt.s 

的食譜是在其列表中的每個文件相同。

輸入文件有各種不同的目錄,僅僅列出它們的文件名並使用搜索路徑找到它們是不可接受的,它們的顯式路徑必須被使用。

輸出文件名是源文件名的基名,擴展名變爲o。不同源語言的列表之間沒有重複的基名。

我不想列出目標文件,這應該從源列表派生。

我正在使用gnu make,但爲便攜式解決方案提供了獎勵點數。

回答

1

類似下面可以做:

all : 

OBJDIR := output 
CFILES := Src/Application/main.c Src/Core/data.c Lib/routines.c 
ASFILES := Src/Application/startup.s Lib/sqrt.s 

target = ${OBJDIR}/$(patsubst %.s,%.o,$(notdir ${1})) 
obj.c := 
obj.s := 
define obj 
    $(call target,${1}) : ${1} | ${OBJDIR} 
    obj$(suffix ${1}) += $(call target,${1}) 
    ${1} : ; mkdir -p `dirname [email protected]` && touch [email protected] # Create the source for testing. Remove this. 
endef 

define SOURCES 
    $(foreach src,${1},$(eval $(call obj,${src}))) 
endef 

$(eval $(call SOURCES,${CFILES})) 
$(eval $(call SOURCES,${ASFILES})) 

all : ${obj.c} ${obj.s} 

${obj.c} : % : 
    @echo cc -c -o [email protected] $^; touch [email protected] # echo and touch are for testing. Remove these. 

${obj.s} : % : 
    @echo as -o [email protected] $^; touch [email protected] # echo and touch are for testing. Remove these. 

${OBJDIR} : 
    mkdir [email protected] 

.PHONY: all 

輸出:

$ make 
make: Entering directory '/home/max/tmp' 
mkdir -p `dirname Src/Application/main.c` && touch Src/Application/main.C# Create the source for testing. Remove this. 
mkdir output 
cc -c -o output/main.c Src/Application/main.c 
mkdir -p `dirname Src/Core/data.c` && touch Src/Core/data.C# Create the source for testing. Remove this. 
cc -c -o output/data.c Src/Core/data.c 
mkdir -p `dirname Lib/routines.c` && touch Lib/routines.C# Create the source for testing. Remove this. 
cc -c -o output/routines.c Lib/routines.c 
mkdir -p `dirname Src/Application/startup.s` && touch Src/Application/startup.s # Create the source for testing. Remove this. 
as -o output/startup.o Src/Application/startup.s 
mkdir -p `dirname Lib/sqrt.s` && touch Lib/sqrt.s # Create the source for testing. Remove this. 
as -o output/sqrt.o Lib/sqrt.s 
make: Leaving directory '/home/max/tmp' 
0

我在編寫makefile時經驗不足,所以這只是一個嘗試。在我的例子中,我在幾個目錄中有C和C++文件,並構建一個由這些文件組成的程序。

$ cat Makefile 
.PHONY : clean all 

CC=gcc 
CXX=g++ 

CFILES = c/f.c c/g.c 
CPPFILES = cpp/main.cpp 

OUTPUT = ./output 

SOURCE_DIRS := $(dir $(CFILES)) 
SOURCE_DIRS += $(dir $(CPPFILES)) 

VPATH = $(sort $(SOURCE_DIRS)) 

C_FILENAMES := $(notdir $(CFILES)) 
CPP_FILENAMES += $(notdir $(CPPFILES)) 

OBJ_FILES := $(patsubst %.c, $(OUTPUT)/%.o, $(C_FILENAMES)) 
OBJ_FILES += $(patsubst %.cpp, $(OUTPUT)/%.o, $(CPP_FILENAMES)) 

all : $(OUTPUT)/program 

$(OUTPUT)/program : $(OBJ_FILES) 
    g++ -o [email protected] $^ 

$(OUTPUT)/%.o : %.cpp 
    $(shell mkdir -p $(OUTPUT)) 
    $(CXX) $(CXXFLAGS) -c $< -o [email protected] 

$(OUTPUT)/%.o : %.c 
    $(shell mkdir -p $(OUTPUT)) 
    $(CC) $(CFLAGS) -c $< -o [email protected] 

clean: 
    rm -fr $(OUTPUT) 

這是用我的makefile的例子:

$ make 
gcc -c c/f.c -o output/f.o 
gcc -c c/g.c -o output/g.o 
g++ -c cpp/main.cpp -o output/main.o 
g++ -o output/program output/f.o output/g.o output/main.o 
+0

感謝您嘗試。不幸的是,這並不能幫助我,因爲它使用VPATH。正如我在問題中所說的,我需要使用每個文件明確給定的路徑。 – Tom

0

下面的方法應該做你想要的東西:編譯所有您指定的源文件,並把目標目錄中的文件./自動輸出。當然,您需要提供編譯器選項,鏈接所需的適當庫,等等。

OBJDIR =./output 
SRCDIR1 =./Src/Application 
SRCDIR2 =./Src/Core 
SRCDIR3 =./Lib 
SRC1 =$(SRCDIR1)/main.c 
SRC2 =$(SRCDIR2)/data.c 
SRC3 =$(SRCDIR3)/routines.c 
SRC4 =$(SRCDIR1)/startup.s 
SRC5 =$(SRCDIR3)/sqrt.s 
OBJ1 =$(patsubst $(SRCDIR1)/%.c,$(OBJDIR)/%.o,$(SRC1)) 
OBJ2 =$(patsubst $(SRCDIR2)/%.c,$(OBJDIR)/%.o,$(SRC2)) 
OBJ3 =$(patsubst $(SRCDIR3)/%.c,$(OBJDIR)/%.o,$(SRC3)) 
OBJ4 =$(patsubst $(SRCDIR1)/%.s,$(OBJDIR)/%.o,$(SRC4)) 
OBJ5 =$(patsubst $(SRCDIR3)/%.s,$(OBJDIR)/%.o,$(SRC5)) 

vpath %.c $(SRCDIR1): $(SRCDIR2): $(SRCDIR3) 
vpath %.s $(SRCDIR1): $(SRCDIR3) 

all: $(OBJ1) $(OBJ2) $(OBJ3) $(OBJ4) $(OBJ5) 
     cc $^ -o executable 

$(OBJDIR)/%.o: %.c | $(OBJDIR) 
     cc -c $< -o [email protected] 
$(OBJDIR)/%.o: %.s | $(OBJDIR) 
     cc -c $< -o [email protected] 

$(OBJDIR): 
     mkdir -p $(OBJDIR) 
+0

這個問題非常清楚地表明「僅僅列出文件名並使用搜索路徑是不可接受的」。 – Tom