wafでdebugとreleaseの設定を記述する(variant) wafでdebug版とrelease版の出力を分けるにはvariantなる機能を使う。 +hello +hello.cpp +waf +wscript

と前回と同様のプロジェクト。 wscriptを以下のように記述する。

coding: utf-8

APPNAME='hello' VERSION='1.0.0'

def configure(conf): # config 'debug'を作る conf.setenv('debug') # debugの設定 conf.env['MSVC_TARGETS'] = ['x86'] conf.load('msvc') conf.env.CXXFLAGS = ['/nologo', '/EHsc'] # PDBやNDEBUG等の設定をきっちり書く必要がある

# config 'release'を作る。debugの設定は引き継がない
conf.setenv('release')
# releaseの設定
conf.env['MSVC_TARGETS'] = ['x86']
conf.load('msvc')
conf.env.CXXFLAGS = ['/nologo', '/EHsc']

BuildContextの設定

def build(bld): bld.program( source='hello.cpp', target=APPNAME )

from waflib.Build import BuildContext

BuildContextを使うコマンド

class BuildDebug(BuildContext): # config 'debug' を使うvariant # 出力ディレクトリがbuild/debugに変わる variant = "debug" # 呼び出しコマンドはbuild_debug cmd = "build_debug"

BuildContextを使うコマンド

class BuildRelease(BuildContext): # config 'release' を使うvariant # 出力ディレクトリがbuild/releaseに変わる variant = "release" # 呼び出しコマンドはbuild_release cmd = "build_release"

variantという概念を使う。 http://docs.waf.googlecode.com/git/book_17/single.html の 6.2.2. Changing the output directory Configuration sets for variants に記述がある。 使う

unknown: blockquote => {"type":"blockquote","children":[{"type":"paragraph","children":[{"type":"text","value":"python waf --help\nwaf [commands] [options]","position":{"start":{"line":64,"column":3,"offset":1339},"end":{"line":65,"column":25,"offset":1381}}}],"position":{"start":{"line":64,"column":3,"offset":1339},"end":{"line":65,"column":25,"offset":1381}}}],"position":{"start":{"line":64,"column":1,"offset":1337},"end":{"line":65,"column":25,"offset":1381}}}

Main commands (example: ./waf build -j4) build : executes the build build_debug : build_release: : : 省略

という感じでbuild_debug, build_releaseが増える。

unknown: blockquote => {"type":"blockquote","children":[{"type":"paragraph","children":[{"type":"text","value":"python waf build_debug\nWaf: Entering directory ","position":{"start":{"line":76,"column":3,"offset":1542},"end":{"line":77,"column":25,"offset":1589}}},{"type":"inlineCode","value":"C:\\work\\_waf\\debug_release\\build\\debug'\n[1/2] cxx: hello.cpp -> build\\debug\\hello.cpp.1.o\nhello.cpp\n[2/2] cxxprogram: build\\debug\\hello.cpp.1.o -> build\\debug\\hello.exe build\\debug\\hello.exe.manifest\nWaf: Leaving directory ","position":{"start":{"line":77,"column":25,"offset":1589},"end":{"line":81,"column":25,"offset":1814}}},{"type":"text","value":"C:\\work_waf\\debug_release\\build\\debug'\n'build_debug' finished successfully (0.487s)","position":{"start":{"line":81,"column":25,"offset":1814},"end":{"line":82,"column":45,"offset":1898}}}],"position":{"start":{"line":76,"column":3,"offset":1542},"end":{"line":82,"column":45,"offset":1898}}}],"position":{"start":{"line":76,"column":1,"offset":1540},"end":{"line":82,"column":45,"offset":1898}}}

素のビルドはエラーになった。たぶん対象になる名無しのconfigが存在しないため。

unknown: blockquote => {"type":"blockquote","children":[{"type":"paragraph","children":[{"type":"text","value":"python waf build\nWaf: Entering directory ","position":{"start":{"line":85,"column":3,"offset":1944},"end":{"line":86,"column":25,"offset":1985}}},{"type":"inlineCode","value":"C:\\work\\_waf\\debug_release\\build'\n[1/2] cxx: hello.cpp -> build\\hello.cpp.1.o\nWaf: Leaving directory ","position":{"start":{"line":86,"column":25,"offset":1985},"end":{"line":88,"column":25,"offset":2088}}},{"type":"text","value":"C:\\work_waf\\debug_release\\build'\nBuild failed\n:\n:\n省略","position":{"start":{"line":88,"column":25,"offset":2088},"end":{"line":92,"column":3,"offset":2141}}}],"position":{"start":{"line":85,"column":3,"offset":1944},"end":{"line":92,"column":3,"offset":2141}}}],"position":{"start":{"line":85,"column":1,"offset":1942},"end":{"line":92,"column":3,"offset":2141}}}

ということで素のビルドの時にメッセージを表示して止めるようにする。 buildメソッドの先頭にwaf book通りの記述を入れる。

BuildContextの設定

def build(bld): if not bld.variant: bld.fatal('call "waf build_debug" or "waf build_release", and try "waf --help"') bld.program( source='hello.cpp', target=APPNAME )

unknown: blockquote => {"type":"blockquote","children":[{"type":"paragraph","children":[{"type":"text","value":"python waf build\nWaf: Entering directory `C:\\work_waf\\debug_release\\build'\ncall \"waf build_debug\" or \"waf build_release\", and try \"waf --help\"\npython waf clean\ncall \"waf build_debug\" or \"waf build_release\", and try \"waf --help\"","position":{"start":{"line":105,"column":3,"offset":2450},"end":{"line":109,"column":68,"offset":2680}}}],"position":{"start":{"line":105,"column":3,"offset":2450},"end":{"line":109,"column":68,"offset":2680}}}],"position":{"start":{"line":105,"column":1,"offset":2448},"end":{"line":109,"column":68,"offset":2680}}}

build以外にもbuildメソッド(BuildContext)を使うコマンドがあって、 http://docs.waf.googlecode.com/git/book_17/single.html の 12.1.2. Context classes のクラス図によると ListContext, CleanContext, StepContext, InstallContext, UninstallContext がBuildContextを継承しているのでこれに対応するコマンド それぞれにdebug版、release版を定義してやる必要がある。 waf bookに書いてあるようにコマンドclassの記述を変える。 from waflib.Build import BuildContext, ListContext, CleanContext, StepContext, InstallContext, UninstallContext

CONTEXTS=[BuildContext, ListContext, CleanContext, StepContext, InstallContext, UninstallContext] VARIANTS=['debug', 'release']

for context in CONTEXTS: for variant_name in VARIANTS: name = context.

unknown: strong => {"type":"strong","children":[{"type":"text","value":"name","position":{"start":{"line":125,"column":26,"offset":3320},"end":{"line":125,"column":30,"offset":3324}}}],"position":{"start":{"line":125,"column":24,"offset":3318},"end":{"line":125,"column":32,"offset":3326}}}
.replace('Context','').lower() class tmp(context): cmd = name + '_' + variant_name variant = variant_name

helpを見ると大量に定義したコマンドが増える。

unknown: blockquote => {"type":"blockquote","children":[{"type":"paragraph","children":[{"type":"text","value":"python waf --help\nwaf [commands] [options]","position":{"start":{"line":131,"column":3,"offset":3492},"end":{"line":132,"column":25,"offset":3534}}}],"position":{"start":{"line":131,"column":3,"offset":3492},"end":{"line":132,"column":25,"offset":3534}}}],"position":{"start":{"line":131,"column":1,"offset":3490},"end":{"line":132,"column":25,"offset":3534}}}

Main commands (example: ./waf build -j4) build : executes the build build_debug : build_release : clean : cleans the project clean_debug : clean_release : configure : configures the project dist : makes a tarball for redistributing the sources distcheck : checks if the project compiles (tarball from 'dist') distclean : removes the build directory install : installs the targets on the system install_debug : install_release : list : lists the targets to execute list_debug : list_release : step : executes tasks in a step-by-step fashion, for debugging step_debug : step_release : uninstall : removes the targets installed uninstall_debug : uninstall_release: update : updates the plugins from the

unknown: emphasis => {"type":"emphasis","children":[{"type":"text","value":"waflib/extras","position":{"start":{"line":157,"column":52,"offset":4429},"end":{"line":157,"column":65,"offset":4442}}}],"position":{"start":{"line":157,"column":51,"offset":4428},"end":{"line":157,"column":66,"offset":4443}}}
directory : : 省略

unknown: blockquote => {"type":"blockquote","children":[{"type":"paragraph","children":[{"type":"text","value":"python waf clean_debug build_debug\n'clean_debug' finished successfully (0.087s)\nWaf: Entering directory ","position":{"start":{"line":162,"column":3,"offset":4464},"end":{"line":164,"column":25,"offset":4568}}},{"type":"inlineCode","value":"C:\\work\\_waf\\debug_release\\build\\debug'\n[1/2] cxx: hello.cpp -> build\\debug\\hello.cpp.1.o\nhello.cpp\n[2/2] cxxprogram: build\\debug\\hello.cpp.1.o -> build\\debug\\hello.exe build\\debug\\hello.exe.manifest\nWaf: Leaving directory ","position":{"start":{"line":164,"column":25,"offset":4568},"end":{"line":168,"column":25,"offset":4793}}},{"type":"text","value":"C:\\work_waf\\debug_release\\build\\debug'\n'build_debug' finished successfully (0.451s)","position":{"start":{"line":168,"column":25,"offset":4793},"end":{"line":169,"column":45,"offset":4877}}}],"position":{"start":{"line":162,"column":3,"offset":4464},"end":{"line":169,"column":45,"offset":4877}}}],"position":{"start":{"line":162,"column":1,"offset":4462},"end":{"line":169,"column":45,"offset":4877}}}

これでdebug, releaseの使い分けはできるようになった。 variantを追加する 64bitビルドや、gccのvariantを追加してみた。

coding: utf-8

APPNAME='hello' VERSION='1.0.0'

VARIANTS=[ 'vc_debug', 'vc_release', 'vc64_debug', 'vc64_release', 'gcc_debug', 'gcc_release', ]

def configure(conf): # config 'debug'を作る conf.setenv('debug') # debugの設定 conf.env['MSVC_VERSIONS'] = ['msvc 10.0'] conf.env['MSVC_TARGETS'] = ['x86'] conf.load('msvc') conf.env.CXXFLAGS = ['/nologo', '/EHsc'] # PDBやNDEBUG等の設定をきっちり書く必要がある

# config 'release'を作る。debugの設定は引き継がない
conf.setenv('release')
# releaseの設定
conf.env['MSVC_VERSIONS'] = ['msvc 10.0']
conf.env['MSVC_TARGETS'] = ['x86']
conf.load('msvc')
conf.env.CXXFLAGS = ['/nologo', '/EHsc']

# config 'debug'を作る
conf.setenv('vc64_debug')
# debugの設定
conf.env['MSVC_VERSIONS'] = ['msvc 10.0']
conf.env['MSVC_TARGETS'] = ['x64']
conf.load('msvc')
conf.env.CXXFLAGS = ['/nologo', '/EHsc']
# PDBやNDEBUG等の設定をきっちり書く必要がある

# config 'release'を作る。debugの設定は引き継がない
conf.setenv('vc64_release')
# releaseの設定
conf.env['MSVC_VERSIONS'] = ['msvc 10.0']
conf.env['MSVC_TARGETS'] = ['x64']
conf.load('msvc')
conf.env.CXXFLAGS = ['/nologo', '/EHsc']

# config 'debug'を作る
conf.setenv('gcc_debug')
# debugの設定
conf.load('gxx')
conf.env.CXXFLAGS = ['-g']
conf.env.LINKFLAGS = ['-g']

# config 'release'を作る。debugの設定は引き継がない
conf.setenv('gcc_release')
# releaseの設定
conf.load('gxx')
conf.env.CXXFLAGS = ['-O2']

BuildContextの設定

def build(bld): if not bld.variant: bld.fatal('call "waf build_debug" or "waf build_release", and try "waf --help"') bld.program( source='hello.cpp', target=APPNAME )

from waflib.Build import BuildContext, ListContext, CleanContext, StepContext, InstallContext, UninstallContext

CONTEXTS=[BuildContext, ListContext, CleanContext, StepContext, InstallContext, UninstallContext]

for context in CONTEXTS: for variant_name in VARIANTS: name = context.

unknown: strong => {"type":"strong","children":[{"type":"text","value":"name","position":{"start":{"line":248,"column":26,"offset":6946},"end":{"line":248,"column":30,"offset":6950}}}],"position":{"start":{"line":248,"column":24,"offset":6944},"end":{"line":248,"column":32,"offset":6952}}}
.replace('Context','').lower() class tmp(context): cmd = name + '_' + variant_name variant = variant_name