2012-10-24 27 views
2

我懷疑手冊實際上是在說我做錯了什麼,但我真的看不到解決方案;當要生成的.c文件和.o文件不在同一個目錄中時,會出現問題,並且.c文件對必須在運行中生成的.h文件具有自動依賴關係。這個問題可以通過手動設置.c和.h文件之間的依賴來解決,但我想避免這種情況。果醬對象規則和目錄

我有以下目錄結構:

weird/ 
    Jamfile 
    b.c 
    src/ 
     a.c 
     c.c 

在src/AC文件是這樣的:

#include "src/a.h" 

int main(int argc, char *argv[]) 
{ 
    return 0; 
} 

公元前文件是這樣的:

#include "src/b.h" 

int main(int argc, char *argv[]) 
{ 
    return 0; 
} 

的SRC/cc文件是這樣的:

#include "c.h" 

int main(int argc, char *argv[]) 
{ 
    return 0; 
} 

的Jamfile中是:

rule CreateHeader 
{ 
    Clean clean : $(1) ; 
} 

actions CreateHeader 
{ 
    echo "int x = 10;" > $(1) 
} 

Object a.o : src/a.c ; 
Object b.o : b.c ; 
Object c.o : src/c.c ; 

CreateHeader src/a.h ; 
CreateHeader src/b.h ; 
CreateHeader src/c.h ; 

以下命令正確地創建B.O和src/b.h:

jam b.o 

以下命令創建的src/A.H,但隨後GCC未能創建a.o;原因很明顯,在交流轉換器中的#include提到的src/A.H而實際上只應提及A.H:

jam a.o 

以下命令將完全失效,甚至不創造c.h;其原因可能是,當果醬分析CC它所產生的通道,而不是SRC/CH的依賴,並在Jamfile中有產生CH沒有規則:

jam c.o 

此命令編譯正確,如果我明確要求生成src/ch之前要求co:

jam src/c.h 
jam c.o 

在我看來,果醬src/ch應該沒有必要。這裏有什麼問題?有關更多信息,請參閱the Jam manual,特別是在標題文件掃描部分。

加入後,我接受了答案

我一直嘗試與接受答案的筆者建議構建一點點,我會在這裏發表的結果。在此設置中,您可以鍵入:

jam app 

而應用程序將在bin/app下鏈接。不幸的是,我必須在設置LOCATE_TARGET時使用UNIX路徑,我的理解是這不是一個好的做法。

目錄結構:

project/ 
    Jamfile 
    src/ 
     main.c 
    gen/ 
    bin/ 
     obj/ 

文件的Jamfile:

SubDir TOP ; 

rule CreateHeader 
{ 
    MakeLocate $(1) : $(LOCATE_SOURCE) ; 
    Clean clean : $(1) ; 
} 

actions CreateHeader 
{ 
    BUILD_DATE=`date` 
    echo "char build_date[] = \"$BUILD_DATE\";" > $(1) 
} 

SEARCH_SOURCE = src ; 
LOCATE_TARGET = bin/obj ; 
SubDirHdrs gen ; 
Object main.o : main.c ; 

LOCATE_TARGET = bin ; 
MainFromObjects app : main.o ; 

LOCATE_SOURCE = gen ; 
CreateHeader info.h ; 

文件的src/main。ç

src/main.c 
#include <stdio.h> 
#include "info.h" 

int main(int argc, char *argv[]) 
{ 
    printf("Program built with Jam on %s.\n", build_date); 

    return 0; 
} 

回答

2

更改所有#include指令省略路徑(即「#包括「啊」等)和改變的Jamfile到下面將解決你的問題:

SubDir TOP ; 

SEARCH_SOURCE += [ FDirName $(SUBDIR) src ] ; 
LOCATE_SOURCE = [ FDirName $(SUBDIR) src ] ; 

rule CreateHeader 
{ 
    MakeLocate $(1) : $(LOCATE_SOURCE) ; 
    Clean clean : $(1) ; 
} 

actions CreateHeader 
{ 
    echo "int x = 10;" > $(1) 
} 

Object a.o : a.c ; 
Object b.o : b.c ; 
Object c.o : c.c ; 

CreateHeader a.h ; 
CreateHeader b.h ; 
CreateHeader c.h ; 

我這裏還有細節:

  • 子目錄應該總是在Jamfile中被調用它設置了一些有用的(在某些情況下需要的)變量,包括SUBDIR,SEARCH_SOURCE,和在這裏使用LOCATE_SOURCE
  • 將「src」子目錄添加到SEARCH_SOURCE允許您省略Object規則調用中源文件的「src /」部分。 SEARCH_SOURCE也會自動添加到包含目錄中,這就是爲什麼可以縮短#include目錄的原因。
  • LOCATE_SOURCE是放置生成的源文件(例如生成的yacc源文件和頭文件)的目錄。爲了保持一致性,CreateHeader使用這個變量。請注意,這允許(並且需要)您省略CreateHeader調用中的「src /」部分。

所以這些改變的主要目的是從Jamfile中使用的目標名稱中省略「src /」部分。通常建議省略Jamfiles中的目錄組件(並使用grist來消除歧義)。需要注意的是,即使前者被認爲位於「。」中,Jam工作的目標名稱爲「src/a.h」和「a.h」的方式也是不同的目標。後者在「./src」中(例如通過目標SEARCH或LOCATE變量)。有了這些文件,你給下面的包括依賴關係果醬的頭掃描結果(這些都是目標名稱):

src/a.c : src/a.h 
b.c  : src/b.h 
src/c.c : c.h 

這使得顯而易見的,爲什麼干擾「合作」失敗:目標「CH」是未知的,因爲目標名稱你聲明要生成的頭文件是「src/ch」。因此,果醬忽略包含依賴。 「jam a.o」失敗的原因是您懷疑的原因。

我建議的更改需要調整源文件中的#include指令,在您的實際使用情況中這可能不是理想的/可能的。情況仍然可以挽救。例如。您可以按照建議更改Jamfile,但可以擴展CreateHeader規則:

rule CreateHeader 
{ 
    MakeLocate $(1) : $(LOCATE_SOURCE) ; 
    Clean clean : $(1) ; 
    Depends src/$(1) : $(1) ; 
    NotFile src/$(1) ; 
} 

這顯然有點破綻。它將目標「src/a.h」和朋友定義爲僞目標,每個目標取決於相應的實際目標(「a.h」等)。通過這種方式,無論是否具有「src /」前綴,Jam的標題掃描都會生成已知目標。

越少哈克的解決辦法是顯式聲明包含關係,但:

Includes a.c : a.h ; 
Includes b.c : b.h ;