2012-01-19 15 views
1

scons依存関係に問題があります。 バリアントディレクトリを持つ階層ビルドビルドに問題があります。バリアントディレクトリを持つ階層ビルドにおけるscons依存関係の問題

イム 2 SConscriptディレクトリの下のサブディレクトリ(moduleAとmoduleB)などで構成されて減少した環境で問題を再現することができ、以下:ここ

. 
|-- SConstruct 
|-- file.conf 
|-- moduleA 
| |-- SConscript 
| `-- conf2cc 
`-- moduleB 
    |-- SConscript 
    `-- fileB.cc 

が何をすべきかの流れです。

  1. moduleAは、シェルスクリプトを実行します。conf2cc、入力:$ projRootDir/file.conf、出力:moduleA/$ variantDir/source.cc
  2. moduleAはsource.ccをコンパイルし、moduleA/$ variantDir /李を作成しますbmoduleA.a
  3. moduleBはmoduleBはlibmoduleB.a
  4. その ライブラリにmoduleB/source.ccとmoduleB/fileB.ccをコンパイルする必要が
  5. moduleB/source.ccにmoduleA/$ variantDir/source.ccをコピーする必要があります

ここでいくつかのことを間違えている可能性があります。例えば、私は はmoduleAコマンド()で$ TARGET/$ソースを使用していないイムを知っているが、目的のthatsのは、 スクリプトは絶対パス名を必要とするため、およびsconsのは先頭の「#1」

問題を削除するdoesntの私はmoduleB(上記のステップ3)のCommand()ビルダは実行されません。ここで

SConstructとSConscriptファイルは以下のとおりです。ここ

Sconstruct

import os 

env = Environment() 
env['variantDir'] = 'linux' # for this example, just make variantDir = linux 
modules = ['moduleA', 'moduleB'] 

for dir in modules: 
    SConscript(
     os.path.join(dir, 'SConscript'), 
     variant_dir = os.path.join(dir, env['variantDir']), 
     exports = ['env'], 
     duplicate = 0) 

moduleA/Sconscript

import os 

Import('env') 

scriptInput = '#file.conf' 
sourceFile = os.path.join('#moduleA', env['variantDir'], 'source.cc') 
conf2ccScript = File('#moduleA/conf2cc').abspath 

# The script needs abspaths for input and output, not the scons '#' prepended 
# the script syntax is: script <inputFile> <outputFile> 
cmd = '%s %s %s' % (conf2ccScript, File(scriptInput).abspath, File(sourceFile).abspath) 

# Generate source.cc file based on file.conf 
conf2ccNode = env.Command(target = sourceFile, 
          source = scriptInput, 
          action = cmd) 

libNode = env.Library(target = 'moduleA', source = sourceFile) 
env.Depends(libNode, conf2ccNode) 

moduleB/Sconscript

import os 

Import('env') 

sourceFiles = ['fileB.cc', 'source.cc'] 

# Get the source.cc file 
externalSourceFile = os.path.join('#moduleA', env['variantDir'], 'source.cc') 
sourceTarget  = os.path.join('#moduleB', 'source.cc') 

cmdNode = env.Command(target = sourceTarget, 
         source = externalSourceFile, 
         action = Copy('$TARGET', '$SOURCE')) 

libNode = env.Library(target = 'moduleB', source = sourceFiles) 
env.Depends(libNode, cmdNode) 

を出力する場合であります私はsconsを実行します:

ご協力いただければ幸いです!

ブレイディ

[email protected]:~/projects/sconsTest/sconsTestHierDeps$ scons 
scons: Reading SConscript files ... 
scons: done reading SConscript files. 
scons: Building targets ... 
/home/notroot/projects/sconsTest/sconsTestHierDeps/moduleA/conf2cc /home/notroot/projects/sconsTest/sconsTestHierDeps/file.conf /home/notroot/projects/sconsTest/sconsTestHierDeps/moduleA/linux/source.cc 
g++ -o moduleA/linux/source.o -c moduleA/linux/source.cc 
ar rc moduleA/linux/libmoduleA.a moduleA/linux/source.o 
ranlib moduleA/linux/libmoduleA.a 
g++ -o moduleB/linux/fileB.o -c moduleB/fileB.cc 
scons: *** [moduleB/linux/source.o] Source `moduleB/source.cc' not found, needed by target `moduleB/linux/source.o'. 
scons: building terminated because of errors. 

答えて

0

あなたが使用するファイル名とファイル名の間に依存関係が正しくないという問題があります。

variant_dirとmoduleBのソースファイルで問題があるかもしれませんが、#/ moduleB/source.ccを生成するCommandを使用しますが、sourceFilesには 'source.cc'があります。

だから、あなたは正しいmoduleB SConscriptかもしれ支援する方法の1:

# Get the source.cc file 
externalSourceFile = os.path.join('#moduleA', env['variantDir'], 'source.cc') 
sourceTarget  = os.path.join('#moduleB', 'source.cc') 

sourceFiles = ['fileB.cc', sourceTarget] 

cmdNode = env.Command(target = sourceTarget, 
         source = externalSourceFile, 
         action = Copy('$TARGET', '$SOURCE')) 

libNode = env.Library(target = 'moduleB', source = sourceFiles) 

とソースファイルのようなコマンドを使用してみてください。代わりにfilename。より正確に見えます。 moduleA:

conf2ccNode = env.Command(target = sourceFile, 
          source = scriptInput, 
          action = cmd) 
libNode = env.Library(target = 'moduleA', source = conf2ccNode) 

moduleB:

cmdNode = env.Command(target = sourceTarget, 
         source = externalSourceFile, 
         action = Copy('$TARGET', '$SOURCE')) 

libNode = env.Library(target = 'moduleB', source = ['fileB.cc', cmdNode]) 
+0

素晴らしいです!それは期待どおりに動作します。 SConsは暗黙の依存関係を明示的にDepends()関数でリストするのではなく、私が好むのが好きです。どうもありがとう! – Brady

+0

しかし、1つの注意点:moduleB/source.ccのオブジェクトファイルはmoduleBに配置され、moduleBのvariant_dirには配置されませんが、fileB.oは実際にvariant_dirに配置されます。何故ですか?どうすればsource.oをvariant_dirに置くことができますか? – Brady

+0

モジュールBのsource.ccファイルを次のように指定して見つけました。 'sourceTarget = os.path.join( '#moduleB'、env ['variantDir']、 'source.cc')' .ccとsource.oファイルはvariant_dirに配置されます。 – Brady

0

私は問題の解決策を見つけたが、私はそれが動作する理由本当に理解していけません。

env.Default()への呼び出しを追加して、必要なターゲットを追加すると動作します。だから、SConscriptファイルは次のようになります。

moduleA/Sconscript

import os 

Import('env') 

scriptInput = '#file.conf' 
sourceFile = os.path.join('#moduleA', env['variantDir'], 'source.cc') 
conf2ccScript = File('#moduleA/conf2cc').abspath 

# The script needs abspaths for input and output, not the scons '#' prepended 
# the script syntax is: script <inputFile> <outputFile> 
cmd = '%s %s %s' % (conf2ccScript, File(scriptInput).abspath, File(sourceFile).abspath) 

# Generate source.cc file based on file.conf 
conf2ccNode = env.Command(target = sourceFile, 
          source = scriptInput, 
          action = cmd) 

libNode = env.Library(target = 'moduleA', source = sourceFile) 
env.Depends(libNode, conf2ccNode) 
env.Default([conf2ccNode, libNode]) 

moduleB/Sconscript

import os 

Import('env') 

sourceFiles = ['fileB.cc', 'source.cc'] 

# Get the source.cc file 
externalSourceFile = os.path.join('#moduleA', env['variantDir'], 'source.cc') 
sourceTarget  = os.path.join('#moduleB', 'source.cc') 

cmdNode = env.Command(target = sourceTarget, 
         source = externalSourceFile, 
         action = Copy('$TARGET', '$SOURCE')) 

libNode = env.Library(target = 'moduleB', source = sourceFiles) 
env.Depends(libNode, cmdNode) 
env.Default(cmdNode, libNode) 

をだから、質問につながる:私はデフォルト()のターゲットを指定してはいけない場合とターゲットが複数ある場合、スコーンはどのターゲットをビルドするのですか?

また、sconsがなぜmoduleNodeのcmdNodeにあるmoduleB/SConscriptの依存関係を解決していないのかまだ分かりません。

0

私の解決策:使用の

def CreateLibrary(env, name, sources, shared=True): 

    def GetObjectFile(sourceFileName): 

     def GetFileNameWithoutExtension(path): 
      return os.path.splitext(os.path.basename(path))[0] 

     def IsFileNameExist(newFileName): 
      return fileNames.count(newFileName) > 0 

     sourceAbsPath = os.path.abspath(sourceFileName) 
     fileNameWithoutExtension = GetFileNameWithoutExtension(sourceAbsPath) 
     destFileName = fileNameWithoutExtension 
     attemptNumber = 0 
     while IsFileNameExist(destFileName): 
      attemptNumber += 1 
      destFileName = fileNameWithoutExtension + str(attemptNumber) 
     fileNames.append(destFileName) 
     destFilePath = os.path.join(compilationDirRoot, destFileName) 
     if shared: 
      return env.SharedObject(destFilePath, sourceAbsPath) 
     else: 
      return env.StaticObject(destFilePath, sourceAbsPath) 

    objFiles = [] 
    fileNames = [] 
    compilationDirRoot = Dir('.').abspath 
    for src in sources: 
     if isinstance(src,str): 
      objFiles.append(GetObjectFile(src)) 
     elif isinstance(src, SCons.Node.FS.File): 
      objFiles.append(GetObjectFile(SCons.Node.FS.File.rstr(src))) 
     else: 
      for f in src: 
       objFiles.append(GetObjectFile(str(f))) 
    if shared: 
     return env.SharedLibrary(name, objFiles, no_import_lib=True) 
    else: 
     return env.StaticLibrary(name, objFiles) 

例:

theora = CreateLibrary(env, 'theora', sources) 
関連する問題