しばしば、ビルドされている SKU といった多くの要因に従って ビルド時にセットアップの異なる部品を追加する必要があります。 これは、それが WiX コンパイラー (candle) に送られる前に xml をフィルターする条件文を使う事によって なされます。 もし文が true になるならば、xml のブロックは candle に送られます。 もし文が false になるならば、candle は決してそのセクションの xml を見ません。
条件文は、環境変数、xml 中で定義された変数、リテラル値、その他いろいろに基づいたブール演算子表現です。
例で始めましょう。 “Enterprise SKU” をビルドしていて ファイルをインクルードしたいと考えて下さい。 あなたのビルドは、この sku を指定するのに環境変数 %MySku%=Enterprise を使用します。
Enterprise sku をビルドする時、このファイルは candle に渡される xml 中にインクルードされます。 違う sku をビルドする時、EnterpriseFeature.wxs からの xml は無視されます。
<?if $(env.MySku) = Enterprise ?> <?include EnterpriseFeature.wxs ?> <?endif ?>
上の例に示されるように、ファイルは include タグを使う事によってインクルードされ得ます。 タグ中で参照されるファイル名は、まるでそれがこのファイルの一部であるかのように処理されます。
include file のルートエレメントは、<Include> でなくてはなりません。 期待される wix スキーマの他には必要条件はありません。例えば、
<Include> <Feature Id='MyFeature' Title='My 1st Feature' Level='1'> <ComponentRef Id='MyComponent' /> </Feature> </Include>
あらゆる変数が、その値や単にその存在についてテストされ得ます。 カスタム変数も xml 中で定義できます。
次の3つのタイプの変数がサポートされています:<?if?> 式と属性値の中を含めて、プリプロセッサーは文書全体にわたって変数を評価します。
あらゆる環境変数が、$(env.VarName) シンタックスで参照され得ます。 例えば、もし環境変数 %_BuildArch% を取得したいならば $(env._BuildArch) を使います。 環境変数は 大文字小文字を区別しません。
WiX は、いくつかのビルトイン変数を持っています。 それらは $(sys.VARNAME) シンタックスで参照され、常に大文字です。
もしカスタム変数を定義したいなら、<?define?> 文を使う事ができます。 コマンドラインで candle.exe を使って -d スイッチを使っても 変数を定義できます。 後で変数は <?if?> 文中で $(var.VarName) シンタックスで参照されます。 変数名は大文字小文字を 区別します。
変数の存在の定義の仕方:
<?define MyVariable ?>
変数の値の定義の仕方(注:もし値や値の中の他の変数の展開がスペースを含んでいるなら 引用符が必要です):
<?define MyVariable = “Hello World” ?>
<?define MyVariable = “$(var.otherVariableContainingSpaces)” ?>
定義の右辺が 他の変数を参照する事もできます:
<?define MyVariable = $(var.BuildPath)\x86\bin\ ?>
変数の無効化( undefine )の仕方:
<?undef MyVariable ?>
コマンドラインで変数を定義するには、以下の様なコマンドを打てます:
candle.exe -dMyVariable="Hello World" ...
コマンドラインだけで定義された変数をソース中で参照できますが、 もしその変数をコマンドラインで定義しないと candle.exe はソースコードをプリプロセスしている時に エラーになります。
条件文の目的は、ビルド時に部分的な xml をインクルードや除外する事を 可能にする事です。 もし式が True になるなら、インクルードされます。 もしそれが False になるなら、無視されます。
条件文は常に、<?if ?>, <?ifdef ?>, <?ifndef ?> タグのどれかで始まります。 つぎに xml ブロック、オプションで <?else?> か <?elseif ?> タグが続き、<?endif?> タグで終わらなければなりません。
例えば: <?if [式]?>
<?if ?> と <?elseif ?> タグの内側に見られる式は、ブール演算子式です。 それはこれらのルールに従う簡単な文法に従います:
例えば: <?ifdef [変数] ?>
<ifdef ?> について、もし変数が定義されてしまっていれば この式は True になります。 <ifndef ?> はちょうど逆の方に働きます。
<?define myValue = "3"?> <?define system32=$(env.windir)\system32 ?> <?define B = "good var" ?> <?define C =3 ?> <?define IExist ?> <?if $(var.Iexist) ?><?endif?> <!-- true --> <?if $(var.myValue) = 6 ?><?endif?> <!-- false --> <?if $(var.myValue)!=3 ?><?endif?> <!-- false --> <?if not "x"= "y"?> <?endif?> <!-- true --> <?if $(env.systemdrive)=a?><?endif?> <!-- false --> <?if 3 < $(var.myValue)?> <?endif?> <!-- false --> <?if $(var.B) = "good VAR"?> <?endif?> <!-- false --> <?if $(var.A) and not $(env.MyEnvVariable) ?> <?endif?> <!-- false --> <?if $(var.A) Or ($(var.B) And $(var.myValue) >=3)?><?endif?> <!-- true --> <?ifdef IExist ?> <!-- true --> <?else?> <!-- false --> <?endif?>
例:
<?ifndef RequiredVariable ?> <?error RequiredVariable が定義されなければなりません ?> <?endif?>
例を少し:
<?foreach LCID in "1033;1041;1055"?> <Fragment Id='Fragment.$(var.LCID)'> <DirectoryRef Id='TARGETDIR'> <Component Id='MyComponent.$(var.LCID)' /> </DirectoryRef> </Fragment> <?endforeach?>または
<?define LcidList=1033;1041;1055?> <?foreach LCID in $(var.LcidList)?> <Fragment Id='Fragment.$(var.LCID)'> <DirectoryRef Id='TARGETDIR'> <Component Id='MyComponent.$(var.LCID)' /> </DirectoryRef> </Fragment> <?endforeach?>または
filename: ExtentOfLocalization.wxi <Include> <?define LcidList=1033;1041;1055?> </Include> and <?include ExtentOfLocalization.wxi ?> <?foreach LCID in $(var.LcidList)?> <Fragment Id='Fragment.$(var.LCID)'> <DirectoryRef Id='TARGETDIR'> <Component Id='MyComponent.$(var.LCID)' /> </DirectoryRef> </Fragment> <?endforeach?>
foreach 処理の代案は、テンプレート WiX フラグメントを別個のファイルに書き、WiX に渡されるオーサリングを生成する別の処理を行う事です。 この代案の最大の長所は、デバッグするのがより容易である事です。
プリプロセッサは、もし $ か ( が続くと $ 文字を特別に扱います。 もしリテラル $$ を使いたいなら 代わりに $$$$ を使って下さい。 二つの $ 文字ごとに一つに置き換えられます。 例えば $$$$$ は $$$ に置き換えられます。
WiX は PreprocessorExtension クラスを経由して プリプロセッサーエクステンションのサポートを持っています。 PreprocessorExtension は、foreach 初期化でのコンテクストを持つコールバック、変数評価、関数定義、(フルカスタム プリプロセスの為に)コンパイラが実行される前の最後のコールを 提供できます。