[.NET] บันทึกการจัดการ NuGet ที่ต้องแยกเฉพาะตาม Platform ครับ

เนื่องจากมีบาง NuGet ที่มันมีความพิเศษ แม้ตัว .NET Core / .NET 5++ มันจะใช้ได้แบบ Cross Platform แล้ว แต่มันมี Third Party บางตัว มันจะยังต้องแยกตาม Platform อยู่ครับ ยกตัวอย่าง เช่น IBM DB2 ครับ

แล้วที่นี่ ถ้าเรามีโจทย์/เงื่อนไขประมาณนี้

  1. ทีม Dev ใช้กันหลากหลาย Platform เช่น Windows / Linux หรือ MacOS จะต้องจูนยังไงให้งานร่วมกันได้
  2. ตอนส่ง Build ลูกค้าหละ ? จะบิ้วยังไง

Solution

แก้ที่ตัว csproj ของเราครับ โดยเราต้องมาดูกันก่อนว่าตัว cs project มันใส่เงื่อนไขได้ไหม ซึ่งมันทำได้ครับ

  • Choose Element (MSBuild) - อันนี้ผมจะใช้แยก Case ในกรณีที่ Build จากตัว Visual Studio กับ จาก Command dotnet build ครับ
  • ในเงื่อนไข Build ผมจะให้ดูจากตัว Runtime Identifier ครับ ในส่วน <When> โดยตัว Runtime Identifier จะเป็น Pattern บอก Platfrom (OS) / Version และ Architecture ที่ต้องการนำไปติดตั้ง+ใช้งาน โดย Pattern เหล่านี้ มันจะช่วยให้การ Restore NuGet นั้นง่ายขึ้น แต่ต้องกำหนด NuGet Package ตาม Pattern มันด้วยนะ (ตัว Driver DB2 ไม่น่าจะใช้แล้ว 55) โดย Pattern เช่น linux-x64, ubuntu.14.04-x64, win7-x64, osx.10.12-x64 หรือ mobile อย่าง android.21-arm กับ ios.15-arm64 ก็มีให้ลองนะ
    Note
    - หากจะดูที่เป็นไปได้ทั้งหมด ดูจากที่นี่เลย runtime/runtime.json at main · dotnet/runtime · GitHub
    - ในคำสั่ง dotnet build ถ้าจะส่งตัว Runtime Identifier ให้ดูที่ --r หรือ --os (แบบย่อ)
  • Case ใช้ command dotnet build เนื่องจาก Runtime Identifier ยังแยกไม่ได้หมด เลยมากำหนด Condition ใน Package Reference ครับ โดยผมจะจับจาก String StartsWith ชื่อ OS ครับ
    <When Condition="$(RuntimeIdentifier) != ''">
      <ItemGroup>
        <PackageReference Condition="$(RuntimeIdentifier.StartsWith('win'))" Include="Net.IBM.Data.Db2" Version="6.0.0.300" />
        <PackageReference Condition="$(RuntimeIdentifier.StartsWith('linux'))" Include="Net.IBM.Data.Db2-lnx" Version="6.0.0.300" />
        <PackageReference Condition="$(RuntimeIdentifier.StartsWith('osx'))" Include="Net.IBM.Data.Db2-osx" Version="6.0.0.300" />
      </ItemGroup>
    </When>
  • อย่าลืม Case ของ Visual Studio ด้วย ในส่วน <Otherwise> ตรง Package Reference ผมเลยให้ Condition ไปเรียกใช้งาน bool IsOsPlatform(string platformString) ของ MS Build แต่เท่าที่ให้น้องที่ทำงานลองในส่วนของ Mac มัน return macOS ถ้าดูใน doc จะเป็น OSX
    <Otherwise>
      <ItemGroup>
        <PackageReference Condition="$([MSBuild]::IsOsPlatform('Windows'))" Include="Net.IBM.Data.Db2" Version="6.0.0.300" />
        <PackageReference Condition="$([MSBuild]::IsOsPlatform('Linux'))" Include="Net.IBM.Data.Db2-lnx" Version="6.0.0.300" />
        <PackageReference Condition="$([MSBuild]::IsOsPlatform('macOS'))" Include="Net.IBM.Data.Db2-osx" Version="6.0.0.300" />
      </ItemGroup>
    </Otherwise>
  • ส่วนสุดท้าย ds.DAO อันนี้ไม่มีเงื่อนไข ในส่วนของ Platform ใช้แบบเดิมได้เลย
  <ItemGroup>
    <PackageReference Include="ds.DAO" Version="2.0.2" />
  </ItemGroup>
  • ตัว csproj ทั้งหมดครับ
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <Choose>
    <When Condition="$(RuntimeIdentifier) != ''">
      <ItemGroup>
        <PackageReference Condition="$(RuntimeIdentifier.StartsWith('win'))" Include="Net.IBM.Data.Db2" Version="6.0.0.300" />
        <PackageReference Condition="$(RuntimeIdentifier.StartsWith('linux'))" Include="Net.IBM.Data.Db2-lnx" Version="6.0.0.300" />
        <PackageReference Condition="$(RuntimeIdentifier.StartsWith('osx'))" Include="Net.IBM.Data.Db2-osx" Version="6.0.0.300" />
      </ItemGroup>
    </When>
    <Otherwise>
      <ItemGroup>
        <PackageReference Condition="$([MSBuild]::IsOsPlatform('Windows'))" Include="Net.IBM.Data.Db2" Version="6.0.0.300" />
        <PackageReference Condition="$([MSBuild]::IsOsPlatform('Linux'))" Include="Net.IBM.Data.Db2-lnx" Version="6.0.0.300" />
        <PackageReference Condition="$([MSBuild]::IsOsPlatform('macOS'))" Include="Net.IBM.Data.Db2-osx" Version="6.0.0.300" />
      </ItemGroup>
    </Otherwise>
  </Choose>

  <ItemGroup>
    <PackageReference Include="ds.DAO" Version="2.0.2" />
  </ItemGroup>

</Project>

อ๋อ แต่การแก้แบบนี้ อาจจะต้องตรวจสอบด้วยนะครับ ว่า NuGet ที่เราเอามาใช้งาน ถ้ามีการขยับ Version อย่าลืมตรวจสอบด้วยนะครับ ว่าทุก Platform หรือ ในส่วนของ Visual Studio กับตัว dotnet build เวอร์ชันสอดคล้องกันไหมครับ

และก็ตอน Build จากระบบ CI/CD อย่างเช่น Jenkins / Gitlab ถ้าจะระบุ Platform ตอน Build ต้องมาปรับ Param ด้วยครับ

  • กรณีที่ใช้ dotnet build ส่วน --os <OS>
dotnet build ds.Invest.WebAPI.csproj  --configuration Release -p:Version=${INVEST_SERVICE_VERSION} -p:AssemblyVersion=${INVEST_SERVICE_VERSION} -p:Authors='${COMNAME}' --os ${TARGET_OS}

//SAMPLE
dotnet build ds.Invest.WebAPI.csproj  --configuration Release -p:Version=${INVEST_SERVICE_VERSION} -p:AssemblyVersion=${INVEST_SERVICE_VERSION} -p:Authors='${COMNAME}' --os linux

dotnet build ds.Invest.WebAPI.csproj  --configuration Release -p:Version=${INVEST_SERVICE_VERSION} -p:AssemblyVersion=${INVEST_SERVICE_VERSION} -p:Authors='${COMNAME}' --os win
dotnet build ds.Invest.WebAPI.csproj  --configuration Release -p:Version=${INVEST_SERVICE_VERSION} -p:AssemblyVersion=${INVEST_SERVICE_VERSION} -p:Authors='${COMNAME}' --r ${TARGET_RUNTIME}

//SAMPLE
dotnet build ds.Invest.WebAPI.csproj  --configuration Release -p:Version=${INVEST_SERVICE_VERSION} -p:AssemblyVersion=${INVEST_SERVICE_VERSION} -p:Authors='${COMNAME}' --r ubuntu.18.04-x64
Reference

Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts sent to your email.