Warunkowo użyj odniesienia 32/64 bitowego podczas budowania w Visual Studio

Mam projekt, który buduje się w 32/64-bitowych i ma odpowiednie zależności 32/64-bitowe. Chcę mieć możliwość przełączania konfiguracji i poprawnego odniesienia, ale nie wiem, jak powiedzieć Visual Studio, aby używało zależności odpowiedniej dla architektury.

Może robię to źle, ale chcę mieć możliwość przełączania się między x86 i x64 w rozwijanym menu konfiguracyjnym i mieć odnośną bibliotekę DLL odpowiednią bitness.

Author: Holf, 2010-09-30

6 answers

Oto, co zrobiłem w poprzednim projekcie, który będzie wymagał ręcznej edycji .plik(y) csproj. Potrzebujesz również oddzielnych katalogów dla różnych binariów, najlepiej rodzeństwa siebie nawzajem i o tej samej nazwie, co platforma, na którą kierujesz.

Po dodaniu referencji jednej platformy do projektu, otwórz .csproj w edytorze tekstu. Przed pierwszym elementem {[2] } w elemencie <Project> Dodaj następujący kod, który pomoże określić, która platforma biegasz (i budujesz) dalej.

<!-- Properties group for Determining 64bit Architecture -->
<PropertyGroup>
  <CurrentPlatform>x86</CurrentPlatform>
  <CurrentPlatform Condition="'$(PROCESSOR_ARCHITECTURE)'=='AMD64' or '$(PROCESSOR_ARCHITEW6432)'=='AMD64'">AMD64</CurrentPlatform>
</PropertyGroup>

Następnie, w odniesieniu do konkretnych odniesień do platformy, wprowadzasz następujące zmiany:

<ItemGroup>
  <Reference Include="Leadtools, Version=16.5.0.0, Culture=neutral, PublicKeyToken=9cf889f53ea9b907, processorArchitecture=x86">
    <SpecificVersion>False</SpecificVersion>
    <HintPath>..\..\Lib\Leadtools\$(CurrentPlatform)\Leadtools.dll</HintPath>
  </Reference>
  <Reference Include="Leadtools.Codecs, Version=16.5.0.0, Culture=neutral, PublicKeyToken=9cf889f53ea9b907, processorArchitecture=x86">
    <SpecificVersion>False</SpecificVersion>
    <HintPath>..\..\Lib\Leadtools\$(CurrentPlatform)\Leadtools.Codecs.dll</HintPath>
  </Reference>
  <Reference Include="Leadtools.ImageProcessing.Core, Version=16.5.0.0, Culture=neutral, PublicKeyToken=9cf889f53ea9b907, processorArchitecture=x86">
    <SpecificVersion>False</SpecificVersion>
    <HintPath>..\..\Lib\Leadtools\$(CurrentPlatform)\Leadtools.ImageProcessing.Core.dll</HintPath>
  </Reference>
  <Reference Include="System" />
  <Reference Include="System.Core" />
  <Reference Include="System.Data.Entity" />
  <!--  Other project references -->
</ItemGroup>

Zwróć uwagę na użycie właściwości $(CurrentPlatform), którą zdefiniowaliśmy powyżej. Możesz zamiast tego użyć warunków, dla których zestawów zawierać dla której platformy. Możesz też:

  • Zastąp $(PROCESSOR_ARCHITEW6432) i $(PROCESSOR_ARCHITECTURE) $(Platform), aby uwzględnić tylko docelową platformę projektów
  • zmienić logikę określania platformy w kolejności aby być odpowiednim do aktualnej maszyny, aby nie budować / odwoływać się do 64-bitowego binarnego do wykonania na platformie 32-bitowej.

Miałem to napisane pierwotnie dla wewnętrznej Wiki w pracy, jednak zmodyfikowałem go i opublikowałem pełny proces na moim blogu , jeśli jesteś zainteresowany szczegółowymi instrukcjami krok po kroku.

 94
Author: Hugo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-28 15:20:41

AFAIK, jeśli twój projekt wymaga referencji, które są specyficzne dla 32-bitowych lub 64-bitowych (np. COM-interop assemblies), a nie jesteś zainteresowany ręczną edycją .plik csproj, następnie będziesz musiał utworzyć oddzielne projekty 32-bitowe i 64-bitowe.

Powinienem zauważyć, że poniższe rozwiązanie nie jest testowane, ale powinno zadziałać. Jeśli chcesz ręcznie edytować .plik csproj, a następnie powinien być w stanie osiągnąć pożądany wynik z jednego projektu. The .plik csproj to tylko MSBuild skrypt, więc dla pełnego odniesienia, spójrz tutaj . Po otwarciu .plik csproj w edytorze odszukaj elementy <Reference>. Powinieneś być w stanie podzielić te elementy na 3 różne grupy elementów : odniesienia, które nie są specyficzne dla platformy, odniesienia specyficzne dla x86 i odniesienia specyficzne dla x64.

Oto przykład, który zakłada, że projekt jest skonfigurowany z platformami docelowymi o nazwie " x86 "i"x64"

<!-- this group contains references that are not platform specific -->
<ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <!-- any other references that aren't platform specific -->
</ItemGroup>

<!-- x86 specific references -->
<ItemGroup Condition=" '$(Platform)' == 'x86' ">
    <Reference Include="MyComAssembly.Interop">
        <HintPath>..\..\lib\x86\MyComAssembly.Interop.dll</HintPath>
    </Reference>

    <!-- any additional x86 specific references -->
</ItemGroup>

<!-- x64 specific referneces -->
<ItemGroup Condition=" '$(Platform)' == 'x64' ">
    <Reference Include="MyComAssembly.Interop">
        <HintPath>..\..\lib\x64\MyComAssembly.Interop.dll</HintPath>
    </Reference>

    <!-- any additional x64 specific references -->
</ItemGroup>

Teraz, gdy ustawisz swój projekt / rozwiązanie build Konfiguracja aby kierować się na platformę x86 lub x64, powinna zawierać odpowiednie odniesienia w każdym przypadku. Oczywiście trzeba będzie się bawić elementami <Reference>. Możesz nawet skonfigurować atrapy projektów, w których dodajesz odwołania do x86 i x64, a następnie po prostu skopiuj niezbędne elementy <Reference> z tych atrap plików projektu do" prawdziwego " pliku projektu.


Edit 1
Oto link do wspólnych elementów projektu MSBuild, które przypadkowo pominąłem z oryginalnego postu: http://msdn.microsoft.com/en-us/library/bb629388.aspx

 52
Author: Justin Holzer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-27 22:32:37

Możesz użyć warunku ItemGroup dla odniesień dll w pliku projektu.
Spowoduje to, że program visual studio ponownie sprawdzi stan i odniesienia za każdym razem, gdy zmienisz aktywną konfigurację.
Wystarczy dodać warunek dla każdej konfiguracji.

Przykład:

 <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <Reference Include="DLLName">
      <HintPath>..\DLLName.dll</HintPath>
    </Reference>
    <ProjectReference Include="..\MyOtherProject.vcxproj">
      <Project>{AAAAAA-000000-BBBB-CCCC-TTTTTTTTTT}</Project>
      <Name>MyOtherProject</Name>
    </ProjectReference>
  </ItemGroup>
 19
Author: Yochai Timmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-11 14:22:07

Odwołuję się do bibliotek DLL x86, znajdujących się np. w \component \ v3_NET4, w moim projekcie. Specyficzne biblioteki DLL dla x86 / x64 znajdują się w podfolderach o nazwach " x86 "i" x64 " lub "x64".

Następnie używam wstępnie zbudowanego skryptu, który kopiuje odpowiednie biblioteki DLL (x86/x64) do wskazanego folderu, bazując na $(PlatformName).

xcopy /s /e /y "$(SolutionDir)..\component\v3_NET4\$(PlatformName)\*" "$(SolutionDir)..\component\v3_NET4"
Mi pasuje.
 7
Author: Micke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-14 10:09:50

Spotkałem się z tym samym problemem i spędziłem sporo czasu szukając przyzwoitego rozwiązania. Większość osób oferuje ręczną edycję plików rozwiązań Visual Studio, co jest dość żmudne,podatne na błędy i mylące podczas eksploracji tych edytowanych plików w interfejsie graficznym Visual Studio. Kiedy już się poddałem, rozwiązanie pojawiło się samo. Jest to bardzo podobne do tego, co Micke zaleca w swojej odpowiedzi powyżej.

W account managerze jak zwykle stworzyłem dwa oddzielne cele kompilacji dla platform x86 i x64. Następnie dodałem do mojego projektu odniesienie do montażu x86. W tej kwestii wierzyłem, że projekt jest skonfigurowany tylko dla x86 build i nigdy nie będzie budowany dla konfiguracji x64, chyba że dokonam ręcznej edycji go zgodnie z sugestią Hugo powyżej.

Po chwili w końcu zapomniałem o ograniczeniu i przypadkowo zacząłem budować x64. Oczywiście budowa nie powiodła się. Ale ważny był komunikat o błędzie, który otrzymałem. Komunikat o błędzie informował, że zespół o nazwie dokładnie tak, jak mój wymieniony zespół x86 jest brak w folderze przeznaczonym jako cel kompilacji x64 dla mojego rozwiązania.

Zauwaĺźywszy to, rÄ ™ cznie skopiowaĺ ' em odpowiedni montaĹź x64 do tego katalogu. Chwała! Mój x64 build cudownie powiódł się z prawidłowym montażem znalezionym i połączonym pośrednio. To było kwestia minut, aby zmodyfikować moje rozwiązanie, aby ustawić docelowy katalog kompilacji x64 w tym folderze. Po tych krokach rozwiązanie buduje się automatycznie zarówno dla x86, jak i x64 bez ręcznej edycji plików MSBuild.

To suma:

    Tworzenie celów x86 i x64 w jednym projekcie]}
  1. Dodaj wszystkie odpowiednie odniesienia do projektu do zestawów x86
  2. Ustaw jeden wspólny katalog docelowy dla wszystkich zestawów x64
  3. jeśli masz gotowe zestawy x64, po prostu skopiuj je raz do katalogu docelowego x64

Po wykonaniu tych kroków Twoje rozwiązanie zostanie poprawnie zbudowane zarówno dla konfiguracji x86, jak i x64.

To mi pomogło na Projekt Visual Studio 2010. NET 4.0 C#. Ewidentnie jest to rodzaj nieudokumentowanego wewnętrznego zachowania Visual Studio, które może ulec zmianie w wersjach z 2012, 2013 i 2015 roku. Jeśli ktoś będzie próbował na innych wersjach, Proszę podzielić się swoimi doświadczeniami.

 2
Author: Boris Zinchenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-04 08:33:46

Jeden. Net build z zależnościami x86/x64

Podczas gdy wszystkie inne odpowiedzi dają ci rozwiązanie do tworzenia różnych kompilacji w zależności od platformy, daję ci opcję posiadania tylko konfiguracji "AnyCPU" i tworzenia kompilacji, która działa z bibliotekami DLL x86 i x64.

Musisz napisać do tego jakiś kod hydrauliczny. Nie mogłem pracować z aplikacją.config. Jeśli ktoś inny zna sposób, aby rozwiązać go za pomocą aplikacji.config naprawdę chciałbym wiedzieć.

Rozdzielczość poprawne x86/x64-DLL w czasie wykonywania

Kroki:

  1. użyj AnyCPU w csproj
  2. zdecyduj, czy odwołujesz się tylko do bibliotek DLL x86 lub x64 w swoich csprojs. Dostosuj ustawienia UnitTests do wybranych ustawień architektury. Jest to ważne przy debugowaniu / uruchamianiu testów wewnątrz VisualStudio.
  3. On Reference-Properties set Copy Local & Wersja specjalna do false
  4. pozbądź się ostrzeżeń o architekturze dodając To linia do pierwszej PropertyGroup we wszystkich plikach csproj, do których odwołujesz się do x86/x64: <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
  5. Dodaj ten skrypt postbuild do swojego projektu startowego, użyj i zmodyfikuj ścieżki tego skryptu sp, który kopiuje wszystkie biblioteki DLL x86/x64 w odpowiednich podfolderach twojego build bin\x86 \ bin \ x64 \

    xcopy /E /H /R /Y /I /D $(SolutionDir)\YourPathToX86Dlls $(TargetDir)\x86 xcopy /E /H /R /Y /I /D $(SolutionDir)\YourPathToX64Dlls $(TargetDir)\x64

    -- > kiedy uruchomisz aplikację teraz, otrzymasz wyjątek że Zgromadzenie nie może zostać znalezione.

  6. Zarejestruj AssemblyResolve zdarzenie bezpośrednio na początku punktu wejścia aplikacji

    AppDomain.CurrentDomain.AssemblyResolve += TryResolveArchitectureDependency;
    

    Z tą metodą:

    /// <summary>
    /// Event Handler for AppDomain.CurrentDomain.AssemblyResolve
    /// </summary>
    /// <param name="sender">The app domain</param>
    /// <param name="resolveEventArgs">The resolve event args</param>
    /// <returns>The architecture dependent assembly</returns>
    public static Assembly TryResolveArchitectureDependency(object sender, ResolveEventArgs resolveEventArgs)
    {
        var dllName = resolveEventArgs.Name.Substring(0, resolveEventArgs.Name.IndexOf(","));
    
        var anyCpuAssemblyPath = $".\\{dllName}.dll";
    
        var architectureName = System.Environment.Is64BitProcess ? "x64" : "x86";
    
        var assemblyPath = $".\\{architectureName}\\{dllName}.dll";
    
        if (File.Exists(assemblyPath))
        {
            return Assembly.LoadFrom(assemblyPath);
        }
    
        return null;
    }
    
  7. jeśli masz testy jednostkowe, Utwórz klasę testową z metodą, która ma AssemblyInitializeAttribute, a także zarejestruj powyższą funkcję TryResolveArchitectureDependency-Handler. (Czasami nie będzie to wykonywane, jeśli uruchomisz pojedyncze testy w visual studio, odwołania będą rozwiązywane nie z UnitTest bin. Dlatego decyzja w Kroku 2 jest ważne.)

Korzyści:

  • jedna instalacja / Budowa dla obu platform

Wady: - Brak błędów podczas kompilacji, gdy biblioteki DLL x86/x64 nie pasują. - Nadal należy uruchomić test w obu trybach!

Opcjonalnie Utwórz drugi plik wykonywalny, który jest wyłączny dla architektury x64 z Corflags.exe w skrypcie postbuild

Inne warianty do wypróbowania: - Nie będziesz potrzebował obsługi zdarzenia AssemblyResolve, jeśli zapewnisz, że biblioteki DLL otrzymają skopiowane w folderze binarnym na początku (Evaluate Process architecture - > przenieś odpowiednie biblioteki DLL z x64/x86 do folderu bin i z powrotem.) - W Instalatorze Oceń architekturę i usuń pliki binarne dla niewłaściwej architektury i przenieś właściwe do folderu bin.

 0
Author: Felix Keil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-03 09:54:13