sn
ほとんどの人にとって機能する方法で msbuild スクリプトでor (私が求めているもの)のようなツールを適切に参照するsqlmetal
には、動作環境とフレームワークの実装のさまざまな側面を考慮する必要があります。主なケースは 2 つあります。Microsoft Windows と、Microsoft によるフレームワークの実装と、その後に続くその他すべて (Mono/unix を意味します) です。私が考えることができる状況をサポートする正しいアプローチの例は、最後にリストされています.
マイクロソフト
sn
Windows のどこに、または他の同様のツールが存在するかを見つける適切な方法は、既に述べたように、 GetFrameworkSdkPath タスクから開始することです。
ただし、質問が示唆するように、FrameworkSdkPath 内sn
または別のツールが存在する正確な場所を直接特定することはできません。bin
参照された回答は、ツールが存在する FrameworkSdkPath の下にある唯一の可能なフォルダーはとであることを示唆していますbin/NETFX 4.0 Tools
。ただし、他の値も使用できます (Visual Studio 2013 プレビューでは を使用しますbin/NETFX 4.5.1 Tools
)。したがって、検索する唯一の適切な方法sn
は、グロブ式を使用するか、再帰的に検索することです。MSBuild でグロブ展開を行う方法がわかりません。組み込みの MSBuild タスクは、特定のユーティリティの FrameworkSdkPath での検索をサポートしていないようです。ただし、cmdWHERE
にはこの機能があり、検索に使用できます。結果は、次の msbuild コードのようになります。
<Target Name="GetSNPath" BeforeTargets="AfterBuild">
<GetFrameworkSdkPath>
<Output TaskParameter="Path" PropertyName="WindowsSdkPath" />
</GetFrameworkSdkPath>
<Exec Command="WHERE /r "$(WindowsSdkPath.TrimEnd('\\'))" sn > sn-path.txt" />
<ReadLinesFromFile File="sn-path.txt">
<Output TaskParameter="Lines" PropertyName="SNPath"/>
</ReadLinesFromFile>
<Delete Files="sn-path.txt" />
<PropertyGroup>
<SNPath>$([System.Text.RegularExpressions.Regex]::Replace('$(SNPath)', ';.*', ''))</SNPath>
</PropertyGroup>
</Target>
(ここで使用できる理由については、プロパティ関数を参照してください。末尾のスラッシュが好きではありません。編集:プロパティ関数の使用を追加して、プロパティ内の最初に見つかったパス以外のすべてを削除するアクセスを追加しました。友人のマシンの呼び出しの 1 つで、複数の特定のコマンドの結果を取得し、fond ツールへの試行を中断しました. この変更により、結果が 1 つだけ見つかり、実際に成功することが保証されます.)String.TrimEnd
WHERE
Regex.Replace()
SNPath
WHERE
<Exec/>
<Exec/>
で呼び出すことができるようsn
になりまし<Exec Command=""$(SNPath)"" />
た。
ポータブル
当然のことながら、パスの解決は、sn
Windows 以外のオペレーティング システムでははるかに簡単です。Mac OSX および Linux の任意のディストリビューションでsn
は、PATH に含まれています。このような状況では、を使用GetFrameworkSdkPath
しても役に立ちません。実際、sn
少なくとも xbuild を使用してテストした古いバージョンの mono-2.10 では、これは見つからないパスを返すようです。
- Mac OSX
FrameworkSdkPath
では/Library/Frameworks/Mono.framework/Versions/2.10.5/lib/mono/2.0
、 および/usr/bin/sn
は へのシンボリック リンク/Library/Frameworks/Mono.framework/Commands/sn
です。
- 特定の Linux インストールでは、
FrameworkSdkPath
is/usr/lib64/mono/2.0
およびsn
is (で/usr/bin/sn
呼び出すシェル スクリプト)。/usr/lib64/mono/4.0/sn.exe
mono
したがって、必要なことは を実行することだけsn
です。非標準の場所に実装を配置する UNIX ユーザーsn
は、PATH を適切に更新することを既に知っているため、ビルド スクリプトでそれを検索する必要はありません。また、WHERE
unix には存在しません。したがって、UNIX の場合、最初の<Exec/>
呼び出しをsn
、UNIX でのみ出力し、Windows で実行したときに完全な検索を行うものに置き換えたいと考えています。true
UNIX ライクな環境と Windows 環境を区別するために、UNIX シェルのコマンドとコマンドのラベル構文のショートカットを利用するトリックを使用します。簡単な例として、次のスクリプトはI’m unix!
UNIX シェルアウトとI’m Windows :-/
Windows シェルアウトで出力します。
:; echo 'I’m unix!'; exit $?
echo I’m Windows :-/
これを利用して、結果のGetSNPath
Task は次のようになります。
<Target Name="GetSNPath" BeforeTargets="AfterBuild">
<GetFrameworkSdkPath>
<Output TaskParameter="Path" PropertyName="WindowsSdkPath" />
</GetFrameworkSdkPath>
<Exec Command=":; echo sn > sn-path.txt; exit $?
WHERE /r "$(WindowsSdkPath.TrimEnd('\\'))" sn > sn-path.txt" />
<ReadLinesFromFile File="sn-path.txt">
<Output TaskParameter="Lines" PropertyName="SNPath"/>
</ReadLinesFromFile>
<Delete Files="sn-path.txt" />
<PropertyGroup>
<SNPath>$([System.Text.RegularExpressions.Regex]::Replace('$(SNPath)', ';.*', ''))</SNPath>
</PropertyGroup>
</Target>
結果は、呼び出しに必要な文字列を見つけるための移植可能なメソッドですsn
。この最後のソリューションにより、Microsoft とその msbuild の両方、および xbuild を使用する他のすべてのプラットフォームをサポートできます。またbin\NETFX 4.0 Tools
、.csproj ファイルへのハードコーディングを克服して、Microsoft ツールの将来および現在のバージョンを同時にサポートします。