はじめに
GitHubに具体例のリポジトリを上げてあります:ishioka0222/scons-execute-python-example
背景
SConsにはCommandという機能があり、ビルド時にコマンドを呼び出すことができます。
例えば、SConstructファイルに以下のように記述してscons
コマンドを実行すると、echo hello, world! > output.txt
が実行されます:
Command(
target="output.txt",
source=None,
action="echo hello, world! > $TARGET"
)
しかし、デフォルトの設定では、action
の中でどのコマンドでも呼び出せるわけではないようです。
例えば、Pythonがインストール済みでPATHを通していても、以下のようにaction
の中でpython
コマンドを実行しようとするとエラーが出ます:
Command(
target="output.txt",
source=None,
action="python script.py --out $TARGET"
)
import argparse
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--out')
args = parser.parse_args()
with open(args.out, 'w') as f:
f.write('hello, world!')
if __name__ == "__main__":
main()
> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
python script.py --out output.txt
'python' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
scons: *** [output.txt] Error 1
scons: building terminated because of errors.
> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
python script.py --out output.txt
'python' is not recognized as an internal or external command,
operable program or batch file
scons: *** [output.txt] Error 1
scons: building terminated because of errors.
このようなエラーが出る理由ですが、デフォルトではSConsはシステム環境変数の値(PATHなど)を読み込まず、python
コマンドを見つけることができないためのようです。
なぜこうなっているかという理由については、公式ドキュメント内のENVの項目に詳しく書かれています。
要約すると、SConsの実行時に設定されている環境変数と関係なく、ビルドの再現性が保証されるようにするためだそうです。
SConsからpythonなど外部のコマンドを呼び出す方法
python
コマンドはシステム環境変数のPATHに定義されているので、SConstructファイルの中で、以下のようにしてPATHの値を明示的にSConsに読み込ませる必要があります。
import os
env = Environment(ENV={'PATH': os.environ['PATH']})
env.Command(
...
)
公式ドキュメントには "it is usually not recommended" と前置きしたうえで、以下のように、PATH以外の環境変数もすべて読み込ませる方法も紹介されています:
import os
env = Environment(ENV=os.environ.copy())
env.Command(
...
)