snほとんどの人にとって機能する方法で msbuild スクリプトでor (私が求めているもの)のようなツールを適切に参照するsqlmetalには、動作環境とフレームワークの実装のさまざまな側面を考慮する必要があります。主なケースは 2 つあります。Microsoft Windows と、Microsoft によるフレームワークの実装と、その後に続くその他すべて (Mono/unix を意味します) です。私が考えることができる状況をサポートする正しいアプローチの例は、最後にリストされています.
マイクロソフト
snWindows のどこに、または他の同様のツールが存在するかを見つける適切な方法は、既に述べたように、 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.TrimEndWHERERegex.Replace()SNPathWHERE<Exec/><Exec/>
で呼び出すことができるようsnになりまし<Exec Command=""$(SNPath)"" />た。
ポータブル
当然のことながら、パスの解決は、snWindows 以外のオペレーティング システムでははるかに簡単です。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 インストールでは、
FrameworkSdkPathis/usr/lib64/mono/2.0およびsnis (で/usr/bin/sn呼び出すシェル スクリプト)。/usr/lib64/mono/4.0/sn.exemono
したがって、必要なことは を実行することだけsnです。非標準の場所に実装を配置する UNIX ユーザーsnは、PATH を適切に更新することを既に知っているため、ビルド スクリプトでそれを検索する必要はありません。また、WHEREunix には存在しません。したがって、UNIX の場合、最初の<Exec/>呼び出しをsn、UNIX でのみ出力し、Windows で実行したときに完全な検索を行うものに置き換えたいと考えています。trueUNIX ライクな環境と Windows 環境を区別するために、UNIX シェルのコマンドとコマンドのラベル構文のショートカットを利用するトリックを使用します。簡単な例として、次のスクリプトはI’m unix!UNIX シェルアウトとI’m Windows :-/Windows シェルアウトで出力します。
:; echo 'I’m unix!'; exit $?
echo I’m Windows :-/
これを利用して、結果のGetSNPathTask は次のようになります。
<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 ツールの将来および現在のバージョンを同時にサポートします。