ساخت MSBuild SDK سفارشی در داتنت: خداحافظی با کدهای تکراری!
نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۱۰/۰۶ ۰۹:۳۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
Sdk="Microsoft.NET.Sdk" را در ابتدای فایلهای .csproj دیدهایم و بدون اینکه دقیقاً بدانیم پشت پرده چه میگذرد، آن را به عنوان یک "پیشفرض" پذیرفتهایم. اما اگر بدانید که ساختن یک SDK اختصاصی چقدر سادهاست و چه قدرت عظیمی به شما میدهد، احتمالاً همین امروز دستبهکار خواهید شد..props و .targets است. وقتی شما Sdk="MySdk" را در پروژه مینویسید، MSBuild کار زیر را انجام میدهد:Sdk.props را در ابتدای فایل پروژه ایمپورت میکند.Sdk.targets را در انتهای فایل پروژه ایمپورت میکند.MyAwesome.Sdk/ ├── Sdk/ │ ├── Sdk.props ← اول اجرا میشود (تنظیمات پیشفرض) │ └── Sdk.targets ← آخر اجرا میشود (منطق بیلد) └── MyAwesome.Sdk.csproj
نکته مهم: نام پوشه Sdk باید دقیقاً به همین شکل (حروف، بزرگ و کوچک) باشد، وگرنه MSBuild آن را پیدا نمیکند.<Project>
<PropertyGroup>
<TargetFramework Condition="'$(TargetFramework)' == ''">net8.0</TargetFramework>
<ImplicitUsings Condition="'$(ImplicitUsings)' == ''">enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
</Project><Project>
<ItemGroup Condition="'$(EnableDefaultItems)' != 'false'">
<None Include="**/*.config" />
</ItemGroup>
<Target Name="ValidateStuff" BeforeTargets="BeforeBuild">
<Warning Condition="'$(MyRequiredProp)' == ''"
Text="لطفا مقدار MyRequiredProp را مشخص کنید." />
</Target>
</Project>Microsoft.NET.Sdk بایستیم و فقط آن را شخصیسازی کنیم. الگوی صحیح به این صورت است:<Project>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<MyCustomRule>true</MyCustomRule>
</PropertyGroup>
</Project><Project>
<ItemGroup>
<PackageReference Include="Meziantou.Analyzer" Version="2.0.0" />
</ItemGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project><Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageType>MSBuildSdk</PackageType>
<PackageId>MyCompany.Net.Sdk</PackageId>
<Version>1.0.0</Version>
<IncludeBuildOutput>false</IncludeBuildOutput>
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
</PropertyGroup>
<ItemGroup>
<None Include="Sdk\**" Pack="true" PackagePath="Sdk" />
</ItemGroup>
</Project><ItemGroup Condition="'$(IsTestProject)' == 'true'"> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="..." /> <PackageReference Include="xunit" Version="..." /> <PackageReference Include="coverlet.collector" Version="..." /> <PackageReference Include="GitHubActionsTestLogger" Version="..." Condition="'$(GITHUB_ACTIONS)' == 'true'" /> </ItemGroup>
dotnet new classlib را میزند و با ارجاع به SDK شما، تمام زیرساخت تست، گزارشدهی و کاورج (Coverage) به صورت خودکار فراهم میشود.dotnet pack بسازید، یک فولدر لوکال به عنوان NuGet Source تعریف کنید و پکیج را آنجا کپی کنید. (نکته: کش NuGet دیوانهکننده است! هر بار ورژن را تغییر دهید، یا کش را با dotnet nuget locals all --clear پاک کنید).Directory.Build.props پروژه تست:<Project> <Import Project="..\..\MySdk\Sdk\Sdk.props" /> </Project>
global.json است. این کار مدیریت ورژن را متمرکز میکند.{
"msbuild-sdks": {
"MyCompany.Net.Sdk": "1.0.0"
}
}<Project Sdk="MyCompany.Net.Sdk"> </Project>
global.json) را تغییر دهید تا تمام پروژهها آپدیت شوند.Condition از تککوتیشن استفاده کنید: Condition="'$(Prop)' == ''". فراموش کردن این مورد خطای رایجی است.