2014-10-21 47 views
2

我已經搜索並嘗試了幾個使用非遞歸makefile來完成簡單項目的示例。在過去,我用了簡單的單一代碼庫的目錄,但現在我放在一起的環境多名工程師:-)簡單的非遞歸Makefile與目標文件在單獨的目錄中

+--app 
| +-- obj/ 
| +-- Makefile 
| +-- first.c 
| +-- second.c 
| 
+--lib1 
| +-- obj/ 
| +-- Makefile 
| +-- foo.c 
| +-- bar.c 
| 
+--lib2 
| +-- obj/ 
| +-- Makefile 
| +-- sample.c 

沒什麼fancy-只是兩個目錄(也許第三個版本)和庫代碼和多個應用程序都在「應用程序」目錄中。我想將.o和.d文件保存在一個單獨的obj /目錄中以保持清潔。

  1. 我希望能夠在每個子目錄(如lib1和lib2)中執行「make」來驗證庫。他們將分別生成libabc.a和libxyz.a。
  2. 我寫了一些簡單的Makefile,但我的規則不起作用,我試圖理解GNU make手冊,但是迷路了。

LIB1/Makefile文件:

lib_src = foo.c bar.c 
lib_obj = $(patsubst %.c,obj/%.o,$(lib_src)) 
libabc.a: $(lib_obj) 
    @echo [Archive... $(@F)] 
    @$(AR) -cr libabc.a $^ 
obj/%.c : %.c 
    $(CC) $(CFLAGS) -c -o [email protected] $< 

應用程序/ Makefile文件:

ALL_APP = first second 
% : %.c libabc.a libxyz.a 
    $(CC) $(CLFAGS) $^ -o [email protected] 
include ../lib1/Makefile 
include ../lib2/Makefile 

現在,我已經定義在每個Makefile文件(顯然)對同一目標的麻煩。就像我無法在lib1/Makefile和app/Makefile中定義一個clean,因爲lib1包含在那裏。雖然我希望我可以在lib1中單獨做一個清理,但這是有道理的。

現在,當我在「應用程序」中進行製作時,沒有制定obj/foo.o的規則。我猜是因爲路徑都是假的。 「obj /」指的是lib1/obj /,但是隨着Makefile的包含,這些都丟失了。

我在做什麼錯了,我可以用我真正簡單的Makefiles構建項目嗎?網上的大多數例子都相當複雜,因爲他們試圖獲得更多(我相信)。

在此先感謝(對於已經討論過很多次的話題感到抱歉)。如果我能避免它,我現在寧願不學習automake和cmake。我希望我的項目很簡單,不能保證使用這些強大的工具。

最好的問候,

+0

我不認爲在您的應用程序makefile中包含庫makefiles是這裏的正確解決方案。這就是我要做的:爲每個目錄編寫一個完全正常運行的獨立makefile。然後爲您的應用程序編寫一個簡單的構建腳本,爲每個庫調用make,最後再調用make for your app。您也可以讓構建腳本將構建的庫複製到您的應用程序目錄中。 – 2014-10-21 22:54:57

+1

@BrandonYates這是或多或少的遞歸,但更多的刪除了一步,因爲你甚至不讓make做遞歸構建。 – 2014-10-21 23:30:30

+0

謝謝布蘭登。我認爲調用make並不是一個好主意,並且包含Makefile是一種更好的方法。彼得米勒寫了一篇文章解釋爲什麼。通過獨立調用每個Makefile,依賴性更難管理。 – guraaf 2014-10-21 23:32:01

回答

3

讓我們先從lib1/Makefile

lib_src = foo.c bar.c 
lib_obj = $(patsubst %.c,obj/%.o,$(lib_src)) 

libabc.a: $(lib_obj) 
    @echo [Archive... $(@F)] 
    @$(AR) -cr libabc.a $^ 

obj/%.c : %.c 
    $(CC) $(CFLAGS) -c -o [email protected] $< 

我們引入變量HERE,使一對夫婦的小變化:

HERE := ../lib1 

lib_src := foo.c bar.c 
lib_obj := $(patsubst %.c,$(HERE)/obj/%.o,$(lib_src)) 

$(HERE)/libabc.a: $(lib_obj) 
    @echo [Archive... $(@F)] 
    @$(AR) -cr [email protected] $^ 

$(HERE)/obj/%.c : $(HERE)/%.c 
    $(CC) $(CFLAGS) -c -o [email protected] $< 

這個Makefile仍然會工作得如之前從lib1/內調用。爲clean規則

ALL_APP = first second 
% : %.c ../lib1/libabc.a ../lib2/libxyz.a 
    $(CC) $(CLFAGS) $^ -o [email protected] 

include ../lib1/Makefile 
include ../lib2/Makefile 

現在:但是,一旦我們做出相應的改動lib2/Makefile,我們可以改變app/Makefile我們重命名lib1/Makefile =>lib1/lib1.maklib2/Makefile =>lib2/lib2.mak,譜寫新的lib1/Makefile

include lib1.mak 

clean: 
    @rm -f lib*.a obj/* 

做相同的lib2/,並修改app/Makefile

... 

include ../lib1/lib1.mak 
include ../lib1/lib1.mak 

clean: 
    @rm -f $(ALL_APP) 
    @$(MAKE) -C ../lib1 clean 
    @$(MAKE) -C ../lib2 clean 

(我們可以做到這一點沒有遞歸,但它會更復雜,並且以這種方式使用遞歸Make確實沒有錯。)

一些進一步的改進是可能的。例如,以這種方式將路徑硬編碼到lib1/lib1.maklib2/lib2.mak並不好,這可以修復。但這足夠一天。