2017-03-23 62 views
1

我有一個包含兩個主要功能的項目,一個用於執行我的程序,另一個主要功能用於測試程序。我在網上搜索了這個,但幾乎找不到有關兩個可執行文件的遞歸生成文件。具有兩個可執行文件的遞歸生成文件

的Makefile

CC = clang 
CFLAGS = -g -Wall 

PROG = suggest 

OBJDIR = objects 
OBJS = $(OBJDIR)/suggest.o $(OBJDIR)/engine.o $(OBJDIR)/table.o $(OBJDIR)/levenshtein.o 

# ... link them 
$(PROG): $(OBJS) $(OBJDIR) 
    $(CC) $(CFLAGS) $(OBJS) -o $(PROG) 

$(OBJDIR)/table.o: 
    $(MAKE) -C table.c 
    cp ../file1/table.c/table.o $(OBJDIR) 

$(OBJDIR)/levenshtein.o: 
    $(MAKE) -C levenshtein.c 
    cp levenshtein.c/levenshtein.o $(OBJDIR) 

# build them all... 
$(OBJDIR)/%.o: %.c $(OBJDIR) 
    $(CC) $(CFLAGS) -c -o [email protected] $< 

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

clean: 
    rm -rf $(OBJDIR) $(PROG) 

在上面的文件,engine.c是我的程序執行情況的主要功能但是我還有一個main功能,以及被稱爲test.c,做我的文件測試。 我要的是,當我運行make命令,它應該只建立engine.cmain功能(默認),但如果我想測試我的計劃,我應該能夠通過指定這樣的運行test.cmain功能,實例make test


問題是我沒有測試文件的生成文件。我的目錄是這樣的:engine.c,suggest.c,test.c然後我有另一個名爲levenshtein.c的文件夾,並且有它自己的makefile。另外我只想使用兩個makefile。我已經寫了一個在levenshtein.c文件夾中的文件夾,而我遇到的問題是這一個,因爲此文件夾包含兩個main函數。我希望基於該命令進行條件編譯。

+0

makefiles通常只會構建(編譯)您的代碼。你確定你真的想在運行'make'命令時執行'engine.c'' main'函數嗎?或者在這種情況下「執行」是指「構建」? – anatolyg

+0

我對遞歸關鍵字有點困惑。我在這裏沒有看到任何遞歸。另一方面,你可以指定'test:'並在其中添加邏輯(例如''clean'')。 – IvRRimUm

+0

我的不好,我的意思是建立我的文件,而不是執行。 @anatolyg – Saad

回答

0

上述所有的答案是非常有益的,但我仍然無法運行我的程序。從上面的答案中得到一些提示後,我能夠想出一個簡化版的makefile。上面的那些也是準確的,取決於你的目錄的設置。這是我做到的。

(注:這可能不是最好的解決方案)

TEST = test.c engine.c levenshtein.c/levenshtein.c ../subdir1/table.c 
PROG = suggest.c engine.c levenshtein.c/levenshtein.c ../subdir1/table.c 
OBJ_TEST = $(TEST:.c=.o) 
OBJ_PROG = $(PROG:.c=.o) 

CC = clang 
CFLAGS = -g -Wall 

test: $(OBJ_TEST) 
    $(CC) $(OBJ_TEST) -o [email protected] 

suggest: $(OBJ_PROG) 
    $(CC) $(OBJ_PROG) -o [email protected] 

.SUFFIXES: .c .o 
.c.o: 
    $(CC) $< $(CFLAGS) -c -o [email protected] 

clean: 
    rm -rf *.o 

我有這包含了兩個多個文件夾父目錄。我的目錄建立是這樣的:

項目/

| _____包含我的engine.c,suggest.c和測試另一個子目錄|包含table.c

_____子目錄。 c,它還包含levenshtein.c以及這是一個單獨的文件夾。

因此,對於任何未來的讀者,如果您正在閱讀本文,請記下您的目錄,然後嘗試創建一個makefile,因爲它會減輕生活壓力。

1

試試這個;添加新的目標TEST並有條件地鏈接到engine.o或test.o.這隻有在你的測試程序不需要引擎中的任何功能或數據的情況下才能起作用。如果有,你可能需要使用類似於-DTEST_PROGRAM

有條件編譯這兩個主要功能因爲你使用其他函數和來自engine.o的數據,你應該在engine.c的main(...)函數週圍添加像#if USE_TEST_PROGRAM #endif這樣的內容,並在makefile中定義USE_TEST_PROGRAM標誌,如下所示。這會產生兩次編譯engine.c的副作用(一次到您的OBJDIR程序中,一次在您的測試程序的頂部目錄中)。

CC = clang 
CFLAGS = -g -Wall 

PROG = suggest 
TEST = test 

OBJDIR = objects 
OBJS = $(OBJDIR)/suggest.o $(OBJDIR)/table.o $(OBJDIR)/levenshtein.o 

# ... link them 
$(PROG): $(OBJS) $(OBJDIR) 
    $(CC) $(CFLAGS) $(OBJS) $(OBJDIR)/engine.o -o $(PROG) 

$(TEST): $(OBJS) $(OBJDIR) 
    $(CC) $(CFLAGS) -DUSE_TEST_PROGRAM=1 engine.c $(OBJS) $(OBJDIR)/test.o -o $(PROG) 

$(OBJDIR)/table.o: 
    $(MAKE) -C table.c 
    cp ../file1/table.c/table.o $(OBJDIR) 

$(OBJDIR)/levenshtein.o: 
    $(MAKE) -C levenshtein.c 
    cp levenshtein.c/levenshtein.o $(OBJDIR) 

# build them all... 
$(OBJDIR)/%.o: %.c $(OBJDIR) 
    $(CC) $(CFLAGS) -c -o [email protected] $< 

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

clean: 
    rm -rf $(OBJDIR) $(PROG) 
+0

沒有解釋的代碼是沒有用的。如果代碼無法正常工作,則需要解釋以改進它。 – anatolyg

+0

@anatolyg這足夠的解釋了嗎? – cleblanc

+0

我正在使用engine.o的函數,請你介紹一下關於條件編譯的第二部分? – Saad

1

你不想爲你正在做的事情使用遞歸。

通過描述的聲音,您希望有一個生成文件,它生成兩個最終目標之一:testengine。對於test,它應該編譯並鏈接test.c。對於engine,它應該編譯並鏈接engine.c

如果這是正確的,你可以建立兩個目標的生成文件爲這樣:

test engine: $(PROG) 

.PHONY: test engine 

所以每個目標depnds上$(PROG)。然後,修改makefile有對象的正確列表建設:

OBJS := .... 

ifneq ($(filter test,$(MAKECMDGOALS)),) 
    #test was a command goal, add test.o to the targets: 
    OBJS+=$(OBJDIR)/test.o 
else ifneq ($(filter engine,$(MAKECMDGOALS)),) 
    #engine was a command goal, add test.o to the targets: 
    OBJS+=$(OBJDIR)/engine.o 
else 
    #neither were command goals. set default: 
    OBJS+=$(OBJDIR)/engine.o 
fi 

$(PROG): $(OBJS) 
    @$(CC) $(CFLAGS) $? -o [email protected] 

現在當你運行make test,它將test.o添加到$(OBJS),建立和鏈接($?將包含所有.o文件),否則會將engine.o添加到$(OBJS)。 Make將編譯所有$(OBJS)並構建您的目標。

另一件事。您有:

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

(這是很好的,但不是那麼好,你有:

$(PROG): $(OBJS) $(OBJDIR) 

首先,它會嘗試構建的對象是創建對象目錄之前(可導致構建失敗)。另外,如果objdir由時間提前,並彙編作品,每次上$(OBJDIR)時間戳更新該目錄的變化中的文件......所以,它可能比$(PROG)更新,使它在不需要時經常重建。正確的方法是:

$(OBJS): | $(OBJDIR) 

通知|,這意味着訂單隻依賴,這意味着它不會重建$(OBJS)如果$(OBJDIR)有一個較新的時間戳,但它之前的任何對象建立目錄。

相關問題