Menggunakan msbuild.exe untuk membangun proyek dengan ketergantungan yang memerlukan properti Platform berbeda

Saya memiliki dua proyek C# yang cukup mudah: Proyek yang dapat dieksekusi yang dapat dibuat sebagai x86 atau AnyCPU, yang mereferensikan (melalui <ProjectReference>) proyek DLL yang hanya memiliki konfigurasi AnyCPU. Ini semua berfungsi seperti yang diharapkan dalam Visual Studio.

Saya mencoba membangun versi x86 dari proyek yang dapat dieksekusi (dan dependensinya) dari baris perintah, dengan /p:Platform="x86". Hal ini menyebabkan pembangunan proyek DLL gagal. (Padahal /p:Platform="AnyCPU" berfungsi, mungkin karena valid untuk kedua proyek.)

Baris perintah lengkap yang saya gunakan adalah:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\msbuild MyProject\MyProject.csproj /t:Build /p:Configuration="Release" /p:Platform="x86"

Apa saja pilihan saya agar build ini berfungsi dari baris perintah? Sebaiknya tanpa memodifikasi proyek DLL sama sekali, atau memodifikasi proyek dengan cara yang mengganggu penggunaannya secara normal di Visual Studio.

(Tujuan utamanya di sini adalah file batch yang dapat membuat versi proyek yang bersih untuk didistribusikan.)


Informasi tambahan:

Kedua proyek memiliki konfigurasi "Debug" dan "Rilis". Proyek yang dapat dieksekusi memiliki "x86" dan "AnyCPU" yang tersedia di Platform. Proyek DLL hanya memiliki "AnyCPU" yang tersedia di Platform. Opsi "Target platform" cocok dengan "Platform" dalam semua kasus. (Tidak ada opsi "Pilih 32-bit", karena saya menggunakan VS2010.)

Kesalahan tersebut tampaknya merupakan kesalahan terkait kompilasi ("tidak ada kode tidak aman yang diizinkan") di DLL, yang -- meskipun saya tidak 100% yakin -- tampaknya terjadi karena tidak ada elemen <PropertyGroup> dalam proyek DLL yang cocok (karena Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " dll) yang akan menentukan parameter yang diperlukan untuk kompilasi (misalnya AllowUnsafeBlocks dan DefineConstants).


person Andrew Russell    schedule 05.10.2017    source sumber
comment
Properti Platform menyetel platform solusi. Detail konfigurasi yang hanya penting untuk proyek C++. Namun pengaturan sebenarnya yang ingin Anda ubah adalah yang muncul pada tab Project › Properties › Build. Selama Anda menambahkan beberapa platform, penting agar platform tersebut cocok atau kebingungan akan berakibat fatal. Biasanya tidak, default proyek adalah AnyCPU untuk platform tetapi kotak centang Prefer 32-bit dicentang. Pastikan untuk mengubah pengaturan konfigurasi Debug dan Rilis.   -  person Hans Passant    schedule 05.10.2017
comment
@HansPassant Saya tidak mengerti apa yang Anda katakan. Target Platform dalam pengaturan proyek (yaitu: <PlatformTarget> dalam file proyek) cocok dengan Platform yang ditentukan oleh $(Platform) (yaitu: platform apa pun yang dipilih untuk pembangunan) dengan cara biasa yang Anda harapkan untuk file proyek, misalnya: <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">. Visual Studio akan membuat kombinasi x86 EXE + AnyCPU DLL dengan baik. Bagaimana saya bisa melakukan ini dari baris perintah? Dimaksudkan untuk dapat membangun EXE di kedua konfigurasi.   -  person Andrew Russell    schedule 06.10.2017
comment
Hmya, itu yang aku maksud dengan fatal. Klik kanan proyek EXE Anda › Properties › tab Build. Ada dua kotak kombo di bagian atas dan dua pengaturan yang Anda pedulikan, Target platform dan Prefer 32-bit. Ada 4 kemungkinan nilai untuk kotak kombo, kombinasi Debug/Release dan x86/AnyCPU. Tuliskan semua nilai pengaturan untuk 4 kombinasi ini dan posting di pertanyaan Anda.   -  person Hans Passant    schedule 06.10.2017
comment
@HansPassant Menambahkan informasi itu di akhir pertanyaan saya. Bagi saya, pertanyaan saya mungkin sejalan dengan apakah ada cara untuk mencegat apa pun yang dilakukan <ProjectReference> (akan cukup sederhana untuk membuat DLL secara terpisah). Saya tidak yakin seberapa praktis hal itu sebenarnya. Namun VS jelas membuat ini berhasil (platform solusi x86 menggunakan platform proyek AnyCPU DLL).   -  person Andrew Russell    schedule 06.10.2017
comment
VS2010, aduh, susah ditegur. Jadi ini sebenarnya tentang kotak centang Izinkan kode tidak aman di proyek DLL. Resep yang sama, Anda memiliki 4 kemungkinan nilai dan pengaturan target platform untuk proyek DLL tidak berperan karena Anda menginginkan AnyCPU untuk keempatnya. Pastikan kotak centang dicentang untuk keempat kemungkinan kombinasi.   -  person Hans Passant    schedule 06.10.2017
comment
@HansPassant Apa yang Anda sarankan sepertinya cukup masuk dan tambahkan $(Configuration)|$(Platform) kombinasi yang Anda berikan, dan berikan pengaturan yang tepat. Yang sepertinya lebih seperti solusi (juga agak menyakitkan, karena saya mencoba menghindari modifikasi file proyek DLL). Saya kira ini lebih merupakan pertanyaan bagaimana cara kerja <ProjectReference> daripada pertanyaan menghilangkan kesalahan.   -  person Andrew Russell    schedule 06.10.2017
comment
Pertanyaan saya mungkin mirip dengan pertanyaan ini, yang dengan sendirinya tidak mendapatkan jawaban yang memuaskan: stackoverflow.com/questions/12348645/   -  person Andrew Russell    schedule 06.10.2017


Jawaban (1)


Menjawab pertanyaan saya sendiri... Pertama-tama, MSBuild dapat membuat file solusi. Ini persis seperti yang Anda harapkan:

msbuild MySolution.sln /p:Configuration="Release" /p:Platform="x86"

Hasilnya adalah x86 yang dapat dieksekusi dengan AnyCPU DLL (sesuai solusi yang ditentukan).

Ada beberapa orang di internet yang menyatakan bahwa perilakunya tidak sempurna cocok untuk Visual Studio dalam beberapa kasus yang tidak jelas. Tapi sepertinya itu berfungsi dengan baik untuk tujuan saya. (Saya pikir mereka mengalami masalah dengan urutan pembuatannya.)

Saya tahu bahwa MSBuild dapat membuat file solusi, tetapi -- ups -- Saya lalai mengujinya pada kasus reproduksi sederhana saya, setelah gagal pada hal lebih kompleks yang sedang saya kerjakan.


Hal di atas saja tidak cukup untuk mendapatkan jawaban yang sepenuhnya memuaskan, terutama jika ada kebutuhan untuk menyesuaikan berbagai hal. Cara MSBuild membuat file solusi adalah dengan membuat file proyek dummy, berdasarkan file solusi. Hal ini dapat diperiksa dengan terlebih dahulu menetapkan variabel lingkungan seperti:

set MSBuildEmitSolution=true

Ini akan mengeluarkan file proyek dummy di sebelah file solusi, yang kemudian dapat diperiksa.

Saya belum sepenuhnya menganalisis apa yang dilakukannya, tetapi sepertinya ia menggunakan <MSBuild> tugas dengan parameter Projects yang meneruskan Configuration dan Platform yang ditentukan solusi yang sesuai untuk setiap proyek. Menurut dokumentasi sepertinya menggunakan yang ditentukan di AdditionalProperties. (Ini sepertinya juga berguna untuk diketahui.)


Sebagai referensi, berikut beberapa kode relevan yang diekstraksi dari file proyek yang dihasilkan:

<Target Name="Build" Outputs="@(CollectedBuildOutput)">
  <MSBuild Projects="@(ProjectReference)" BuildInParallel="True" Properties="BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)" SkipNonexistentProjects="%(ProjectReference.SkipNonexistentProjects)">
    <Output TaskParameter="TargetOutputs" ItemName="CollectedBuildOutput" />
  </MSBuild>
</Target>

Dari mana @(ProjectReference) mengambil data:

<ItemGroup>
  <ProjectReference Include="X:\Solution\MyProject\MyProject.csproj">
    <ToolsVersion>
    </ToolsVersion>
    <SkipNonexistentProjects>False</SkipNonexistentProjects>
    <AdditionalProperties>Configuration=Release; Platform=x86; VisualStudioVersion=10.0</AdditionalProperties>
    <Configuration>Release</Configuration>
    <Platform>x86</Platform>
  </ProjectReference>
  <ProjectReference Include="X:\Solution\DLLProject\DLLProject.csproj">
    <ToolsVersion>
    </ToolsVersion>
    <SkipNonexistentProjects>False</SkipNonexistentProjects>
    <AdditionalProperties>Configuration=Release; Platform=AnyCPU; VisualStudioVersion=10.0</AdditionalProperties>
    <Configuration>Release</Configuration>
    <Platform>AnyCPU</Platform>
  </ProjectReference>
</ItemGroup>

(Perhatikan perbedaannya AdditionalProperties.)

person Andrew Russell    schedule 06.10.2017