2013-03-14 453 views
3

我正在使用scons編譯我的項目。 在我的項目中,源文件位於不同的目錄中。 我們是否需要每個目錄中的sconscript文件來編譯這些項目源文件?我們是否需要每個源目錄中的sconscript文件

我試圖用單個sconscript文件編譯所有目錄。但是所有的目標文件都只添加到我的源代碼目錄中。

我使用這個功能:

env.Library('libs',files_list) 

如果files_list包含唯一的文件名,那麼的OBJ文件生成@ variant目錄。

如果files_list包含文件路徑名,則Obj文件正在生成@ source目錄。

你能告訴我如何做到這一點?

+0

請問您可以顯示其餘的SConstruct。 – Brady 2013-03-14 17:10:22

回答

13

我準備演示瞭如何編寫一個項目像你這樣用利用Scons VariantDir()函數只是一個SConstruct腳本(無子公司SConscripts)的例子。我決定在單獨的答案中這樣做,以便閱讀更容易。

的VariantDir()函數的心不是記錄非常好,所以你提到關於編譯的對象文件的佈局行爲心不是直接的解決。 「訣竅」是指變體目錄中的所有源文件,而不是實際的源目錄中,如下所示。

這裏是我的項目源文件的結構:

$ tree . 
. 
├── SConstruct 
├── src1 
│   ├── class1.cc 
│   └── class1.h 
├── src2 
│   ├── class2.cc 
│   └── class2.h 
└── srcMain 
    └── main.cc 

這裏是SConstruct:

env = Environment() 

# Set the include paths 
env.Append(CPPPATH = ['src1', 'src2']) 

# Notice the source files are referred to in the build dir 
# If you dont do this, the compiled objects will be in the src dirs 
src1Sources = ['build/lib1/class1.cc'] 
src2Sources = ['build/lib2/class2.cc'] 
mainSources = ['build/mainApp/main.cc'] 

env.VariantDir(variant_dir = 'build/lib1', src_dir = 'src1', duplicate = 0) 
env.VariantDir(variant_dir = 'build/lib2', src_dir = 'src2', duplicate = 0) 
env.VariantDir(variant_dir = 'build/mainApp', src_dir = 'srcMain', duplicate = 0) 

lib1 = env.Library(target = 'build/lib1/src1', source = src1Sources) 
lib2 = env.Library(target = 'build/lib1/src2', source = src2Sources) 
env.Program(target = 'build/mainApp/main', source = [mainSources, lib1, lib2]) 

以下是編譯輸出:

$ scons 
scons: Reading SConscript files ... 
scons: done reading SConscript files. 
scons: Building targets ... 
g++ -o build/lib1/class1.o -c -Isrc1 -Isrc2 src1/class1.cc 
ar rc build/lib1/libsrc1.a build/lib1/class1.o 
ranlib build/lib1/libsrc1.a 
g++ -o build/lib2/class2.o -c -Isrc1 -Isrc2 src2/class2.cc 
ar rc build/lib1/libsrc2.a build/lib2/class2.o 
ranlib build/lib1/libsrc2.a 
g++ -o build/mainApp/main.o -c -Isrc1 -Isrc2 srcMain/main.cc 
g++ -o build/mainApp/main build/mainApp/main.o build/lib1/libsrc1.a build/lib1/libsrc2.a 
scons: done building targets. 

這裏是編譯後產生的項目結構:

$ tree . 
. 
├── build 
│   ├── lib1 
│   │   ├── class1.o 
│   │   ├── libsrc1.a 
│   │   └── libsrc2.a 
│   ├── lib2 
│   │   └── class2.o 
│   └── mainApp 
│    ├── main 
│    └── main.o 
├── SConstruct 
├── src1 
│   ├── class1.cc 
│   └── class1.h 
├── src2 
│   ├── class2.cc 
│   └── class2.h 
└── srcMain 
    └── main.cc 

應該指出,更簡單的方法是使用SConscript()函數,指定variant_dir,但如果您的要求不允許您這樣做,則此示例可以工作。 SCons man page有關於VariantDir()函數的更多信息。在那裏,你還可以找到以下內容:

注意VariantDir()的作品最自然的一個子公司SConscript文件。

+0

嗨布雷迪 感謝您的回答 我有一個疑問不是在這個話題。 如果我用env.program(---)編譯程序我得到的鏈接標記爲 「鏈接/ NOLOGO /子系統:控制檯/pdb:project.pdb /OUT:program.exe d:\ build1中\ subdirA \ subdirA.lib D:\ build1 \ subdirB \ subdirB.lib main.obj「 它正在爲VC10編譯器工作。 但對於瑞薩(我的微控制器)的編譯器,我得到像 一個錯誤「無法打開文件:‘\ OUT:MAIN.EXE’鏈接時,」 它將接受「-output = start.abs」命令。 我該如何改變那個。你能告訴我 – 2013-03-24 07:17:57

+0

@SrinivasReddy,我看到你創建了一個不同的問題,所以我在那裏回答了。 – Brady 2013-03-24 19:17:46

2

要回答你的第一個問題:不,不需要在每個src子目錄中都有一個SConscript能夠編譯該目錄中的文件。一切都可以從一個單一的SConstruct完成。

話雖如此,其經常被認爲是更清潔,更好地組織有一個SConscript永遠src子目錄。通常在這種情況下,根SConstruct會設置整個項目通用的東西,並將調用編入src子目錄。然後,每個src子目錄中的SConstruct將關注該子目錄的詳細信息。我更喜歡這種方法,因爲它更模塊化。此外,這將允許您在不同的環境中調用相同的src子目錄SConstruct來編譯相同代碼的不同版本,如調試和發佈。

所有這一切都可以通過在SConstruct創造一種環境,然後將它傳遞給與SConscript()函數sudirs來完成。這裏有一個例子:

SConstruct

env = Environment() 
env.Append(CPPPATH = '/some/dir/common/to/all') 

SConscript('src/subdirA/SConscript', 
      variant_dir = 'build/subdirA', 
      duplicate = 0, 
      exports = 'env') 
SConscript('src/subdirB/SConscript', 
      variant_dir = 'build/subdirB', 
      duplicate = 0, 
      exports = 'env') 

的src/subdirA/SConscript

Import('env') 

# If you need to add specific things to the env, then you should clone it, 
# else the changes will be seen in other subdirs: clonedEnv = env.Clone() 
# No need to specify the path to the source files if all source files are in 
# the same dir as this SConscript. 
env.Library(target='subdirA', source='fileA.cc') 

的src/subdirB/SConscript

Import('env') 

# If you need to add specific things to the env, then you should clone it, 
# else the changes will be seen in other subdirs: clonedEnv = env.Clone() 
env.Library(target='subdirB', source='fileB.cc') 

至於最後的問題,我真的不明白你在找什麼,但使用我上面解釋的選項,結果編譯的目標將永遠放置在VariantDir中。

+0

嗨布雷迪 感謝您的回答 但我的要求是「我們不應該在src子目錄中有一個sconscript文件」 你能告訴我如何只有一個sconstruct文件將編譯所有源子目錄。 你能給我一個例子 謝謝 – 2013-03-20 12:40:20

+0

@SrinivasReddy,我創造了另一個答案,以免混合一切在一個答案。我在另一個答案中僅舉了一個SConstruct的例子。 – Brady 2013-03-22 15:18:24

相關問題