2011-06-01 19 views
25

假設我有一個SConstruct文件看起來像這樣:如何解決「scons的:警告:兩種不同的環境中對目標指定爲」

env = Environment() 

env.Program("a", ["a.c", "util.c"]) 
env.Program("b", ["b.c", "util.c"]) 

此版本工作正常,沒有SCons的警告消息。但是,如果我修改這個指定不同庫每個Program版本(實際庫不相關):

env.Program("a", ["a.c", "util.c"], LIBS="m") 
env.Program("b", ["b.c", "util.c"], LIBS="c") 

然後我得到警告:

 
scons: warning: Two different environments were specified for target util.o, 
     but they appear to have the same action: $CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES 

這似乎引起由Program建設者自動創建一個新的環境來構建,儘管它只是LIBS變量是不同的(所以只有鏈接步驟需要有不同的環境)。我可以解決這個做類似:

util = env.Object("util.c") 
env.Program("a", ["a.c"] + util, LIBS="m") 
env.Program("b", ["b.c"] + util, LIBS="c") 

它使用一個單一的Object建設者建設util.c,然後使用預編譯的目標文件中的每個Program構建,從而避免了警告。但是,這不應該是必要的。有沒有更好的方法來解決這個問題?或者這實際上是一個應該修復的SCons中的錯誤?

上下文:我有將近2000個C源文件編譯到大約20個庫和120個可執行文件中,這些文件有很多共享源。我使用我寫的轉換腳本創建了以前專有構建系統中的SConstruct文件。 SCons使用我目前的SConstruct有大約450個「兩種不同環境」的警告信息。

回答

19

我找到了一個解決辦法,不涉及建立額外的變量來保存的目標文件的節點:

env.Program("a", ["a.c", env.Object("util.c")], LIBS="m") 
env.Program("b", ["b.c", env.Object("util.c")], LIBS="c") 

這種隔離的util.c在單一環境中構建。雖然它被指定了兩次,每次一次Program,SCons並不會對此提出警告,因爲它是使用相同env對象構建的同一個源。當然SCons在這種情況下只編譯一次。

0

我在代碼中發現的一個問題是我沒有正確使用目標對象路徑。或者換句話說,我有一個變體dir指令,但不是使用BUILDPATH,而是使用我的原始源代碼路徑。這樣Scons就會找到在目標BUILDPATH和源路徑中生成的對象。

9

您可以使用Split函數和一個自定義幫助簡化構建過程爲大型項目:

def create_objs(SRCS, path=""): 
    return [env.Object(path+src+".cpp") for src in SRCS] 

prg1 = Split("file_1 file_2 file_N") 
prg2 = Split("file_2 file_5 file_8") 

env.Program("a", create_objs(prg1), LIBS="x") 
env.Program("b", create_objs(prg2), LIBS="y") 

目標文件被創建一次,並且可多次使用的基礎之上。希望這有助於...

+0

我投了這個解決方案,因爲它不需要我記住每個對象編譯到哪個環境。所有的都被編譯成一個單一的環境。它還允許SConscript文件乾淨。我修改了create_obj函數來不自動追加.cpp後綴 – 2013-02-17 17:29:10

1

從第一組文件中創建一個靜態庫並將該庫鏈接到下一組文件(與第一組文件有相同的文件)以創建一個目標。

env.StaticLibrary ("a", ["a.c","util.c"], LIBS = "m") 
env.Program ("b", ["b.c","util.c"], LIBS = ["c","a"]) 
相關問題