SCons入門(1)

SConsとは?

Python製のMake代替ツール。
中でPythonコードを書けるので、複雑なMake処理を簡単に書ける。
C言語の依存関係などを自動に調べる機能などがあるらしいが、使った事はないので詳しい事はわからない。


自分の場合はプログラムのビルドではなく、ゲームデータのビルドに使用した。
(プログラムのビルドならVisualCやEclipseなどの専用ツールに任せた方が楽だったりする)


C言語などのビルドでは依存関係を調べる関係上、大規模開発では速度が出ないという意見もある。
しかし、自分が使っている限りでは、ゲームデータなどのコンバートであればかなりの数のデータを処をしているが、実用十分な速度が出ていると思う。


■SCons公式
http://www.scons.org/

使い方

ビルドしたいプロジェクトディレクトリに「SConstruct」というファイルを作成する。
SConstructにビルドコマンドを記述していくが、もちろんPythonコードをそのまま書ける。
以下、簡単なSConstructの例。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
print "hello scons: %s" % os.getcwd()

コマンドライン上で「scons」と打つと、ビルドが始まる。

> scons
scons: Reading SConscript files ...
hello scons /home/xxxx
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.

-cコマンドを付けると、クリーンアップされる。

> scons -c

独自のコマンドを実行する「Command」

自前で作ったコンバートプログラムを実行するには「Command」を使用する。
以下、自前のコンバートプログラム「my_convert.py」で、ルートディレクトリ配下のtxtファイルをコンバートする例。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import glob

#環境設定 システムパスの設定など
env = Environment(ENV = os.environ)

for input_name in glob.glob("*.txt"):
    output_name = os.path.splitext(input_name)[0]+".out"
    env.Command(
        output_name, input_name, "python my_convert.py $SOURCE $TARGET"
    )

「Command」は、出力したファイル名を返す。

env = Environment(ENV = os.environ)

print env.Command("a.out", "a.in", "python my_convert.py $SOURCE $TARGET")
# -> "a.out"

第2引数の出力ファイルをNoneにすると、出力ファイルがないタスクを作ることができる。
ファイルの更新チェックは行われずに、毎回必ず実行されるタスクとなる。

env = Environment(ENV = os.environ)

#出力ファイルがない場合、毎回実行されるタスクとなる
env.Command(None, "a.in", "python my_convert.py $SOURCE")

また、第3引数のactionにはPython関数も指定する事が可能。

def my_action(target, source, env):
    print target[0], len(target)
    print source[0], len(source)
    return None

env.Command("a.out", "a.in", my_action)

独自のビルダーを定義する「Builder」もあるが、「Command」で十分な場合が多い。

独自のビルダーを実行する「Builder」

独自のビルダーを登録する事も可能、こちらは拡張子などを自動で変換してくれる。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import glob

#独自ビルダー
bld = Builder(
    action = "python my_convert.py $SOURCE $TARGET",
    suffix = '.out',
    src_suffix = '.txt',
)

#独自ビルダーを登録
env = Environment(ENV = os.environ, BUILDERS = {'MyBuilder' : bld})

for input_name in glob.glob("*.txt"):
    env.MyBuilder(input_name)

引数の解析

sconsに引数を設定する事ができる。
以下、引数「project_dir」を渡すコマンドライン

> scons project_dir=/home/prj

「arg=value」の形で書かないと、ターゲットオブジェクトの認識されてしまうので注意。
SConstructでは、「ARGUMENTS」という辞書に引数が格納される。

#引数 project_pathを取得
project_path = ARGUMENTS.get("project_path", "./")
# -> project_path = /home/prj

まとめ

自分がよく使う機能を備忘録としてのメモ。
自分の場合、ゲームデータのビルダーとして使っているので「Program」などの基本的なタスクは説明しない。しかし、Googleで「SCons」で調べれば、基本的な使い方はたくさん出てくるのでここでは割愛する。


たったこれだけ覚えるだけで、かなりの事が出来るようになる。
Pythonコードを書けるので、Pythonさえ覚えていればいちいち機能を調べる必要がないので、とても楽になる。
惜しむべきは日本語の資料が少ない事か。


SCons入門(2) - Pashango’s Blog