3

SCons に基づく階層的なビルド システムがあります。共有ライブラリを構築する SConscript を呼び出してから、共有ライブラリに依存する実行可能ファイルを構築する別の SConscript を呼び出すルート SConstruct があります。

ここに私の質問があります: Linux の共有ライブラリに関する私の理解では、共有ライブラリをld使用する実行可能ファイルの最終的なリンクを行う場合ld、参照するソースとして共有ライブラリを実行可能ファイルのコマンド ラインに含める必要があります。それ(-lオプションが機能する標準的な場所にある場合を除く)。

したがって、私のSConsファイルは次のようになります。

=== rootdir/SConstruct

env=DefaultEnvironment()
shared_lib = SConscript('foolib/SConscript')
env.Append( LIBS=[shared_lib] )
executable = SConscript('barexec/SConscript')

=== rootdir/foolib/SConscript

env=DefaultEnvironment()
env.Append(CPPPATH=Glob('inc'))
penv = env.Clone()
penv.Append(CPPPATH=Glob('internal/inc'))
lib = penv.SharedLibrary( 'foo', source=['foo.c', 'morefoo.c']
Return("lib")

=== rootdir/barexec/SConscript

env=DefaultEnvironment()
exe = env.Program( 'bar', source=['main.c', 'bar.c', 'rod.c'] )
Return("exe")

したがって、ここでの問題は次の行です。

env.Append( LIBS=[shared_lib] )

これは、SCons が SConscripts を介して 2 パス実行を行っているため (最初に依存関係ツリーを生成し、次に作業を実行するため)、生成されたライブラリを必要とする他のライブラリのコマンド ラインに追加するための優れた方法です。 、rootdir/foolib/libfoo.soすべての製品のコマンドラインに表示されlibfoo.soます。

gcc -g -Wall -Werror -o libfoo.so foo.o morefoo.o libfoo.so

では、これを SCons でどのように行うのが最善でしょうか? 今のところ、私はこのハックに頼っています:

=== rootdir/SConstruct

env=DefaultEnvironment()
shared_lib = SConscript('foolib/SConscript')
env['shared_lib'] = shared_lib
executable = SConscript('barexec/SConscript')

...

=== rootdir/barexec/SConscript

env=DefaultEnvironment()
exe = env.Program( 'bar', source=['main.c', 'bar.c', 'rod.c'] + env['shared_lib'] )
Return("exe")

これを行うためのより多くの SCons-y の方法はありますか?

4

4 に答える 4

3

ビルドで共有ライブラリが見つかるようにする必要があります。

ドキュメントでLIBPATHRPATH変数を探します。これらは、生成されたオプションがライブラリを適切に検索できるSConsように検索パスを設定する「Scons-y」の方法です。-l

上記のように、 SConsの設定に基づいて実行する必要があることgccを次に示します(そうでない場合は、手動で実行する必要がある場合があります)。

この-lオプションは、コンパイラーにライブラリーの場所も指定する場合、常に共有ライブラリーを検索します。これが必要になるのは、コンパイル時(-Lオプション)と実行時(-rpath生成されたリンカーオプション)の2回です。

SConsのセットアップでは、コンパイル時の検索パスのLIBPATHように見えるものが生成されます。-L/some/directory/path

RPATHSConsのセットアップでは、検索パスを埋め込むためのリンカーオプションを生成する必要があります。たとえば-Wl,-rpath -Wl,\$ORIGIN/../lib、実行可能ファイルを相対的に検索する検索パスを埋め込んで、実行可能ファイルがインストールbinの並列ディレクトリに検索されるようにします。lib

于 2012-07-20T03:26:48.313 に答える
3

SConsctruct/SConscript ファイルを整理するためのより良い方法を次に示します。通常、階層ビルドでは、env を残りのサブディレクトリと共有する必要があります。メインの env も barexec ディレクトリに複製したことに注意してください。これにより、foolib はそのバイナリをリンクするためだけに使用されます。

=== rootdir/SConstruct

import os

env=DefaultEnvironment()

subdirs = [
    'foolib',
    'barexec'
]

# The exports attribute allows you to pass variables to the subdir SConscripts
for dir in subdirs:
    SConscript( os.path.join(dir, 'SConscript'), exports = ['env'])

=== rootdir/foolib/SConscript

# inports the env created in the root SConstruct
#
# Any changes made to 'env' here will be reflected in
# the root/SConstruct and in the barexec/SConscript
#
Import('env')

# Adding this 'inc' dir to the include path for all users of this 'env'
env.Append(CPPPATH=Glob('inc'))

penv = env.Clone()
# Adding this include only for targets built with penv
penv.Append(CPPPATH=Glob('internal/inc'))
penv.SharedLibrary( 'foo', source=['foo.c', 'morefoo.c'])

=== rootdir/barexec/SConscript

Import('env')

clonedEnv = env.Clone()

# The foo lib will only be used for targets compiled with the clonedEnv env
# Notice that specifying '#' in a path means relative to the root SConstruct
# for each [item] in LIBS, you will get -llib on the compilation line
# for each [item] in LIBPATH, you will get -Lpath on the compilation line
clonedEnv.Append(LIBS=['foo'], LIBPATH=['#foolib'])

clonedEnv.Program( 'bar', source=['main.c', 'bar.c', 'rod.c'] )
于 2012-07-20T07:33:36.877 に答える
2

ブレイディの決定に加えて、静的/グローバル変数を使用してターゲットの名前とパスを保存します。これにより、ビルドをより細かく制御できます。

# site_scons/project.py
class Project:
  APP1_NAME = "app1_name"
  APP2_NAME = "app2_name"
  MYLIB1_NAME = "mylib1_name"
  # etc
  APP_PATH = "#build/$BuildMode/bin" # BuildMode - commonly in my projects debug or release, `#` - root of project dir
  LIB_PATH = "#build/$BuildMode/lib"
  @staticmethod
  def appPath(name) :
     return os.path.join(APP_PATH, name)
  @staticmethod
  def libPath(name) :
     return os.path.join(LIB_PATH, name)

ターゲットを定義します。

from project import Project
...
env.SharedLibrary(Project.libPath(Project.MYLIB1_NAME), source=['foo.c', 'morefoo.c'])

応用:

from project import Project
...
env.Append(LIBPATH = [Project.LIB_PATH])
env.Append(LIBS = [Project.MYLIB1_NAME])
env.Program(Project.appPath(Project.MYAPP1_NAME), source=[...])

私のプロジェクトでは正常に動作し、sconsは追加のコマンドなしでライブラリに依存するものを自動的に検出します。ライブラリの名前を変更したい場合は、Projectクラスを変更するだけです。

于 2012-07-20T17:03:32.893 に答える