Building on Cross targeting scenarios and 64-bit MSBuild

Visual Studio Blog

UPDATE: Most issues around MSBuild support for cross-bitness and 64-bit builds are fixed in .NET 4.5. As always, feedback is welcome! Please leave your comments in this blog post and report any bugs on Microsoft Connect.

 

During the Visual Studio 2010 development cycle a push to make the build experience better on Cross compilation scenarios as well on making sure a build using 32-bit MSBuild was identical (in outputs) to a build using 64-bit MSBuild.

In most cases, 64-bit and 32-bit MSBuild will indeed produce the same output. However there are some cases, generally cross compilation scenarios, where this is not the case.

Note that since Visual Studio is a 32-bit application, if you build from Visual Studio, it is equivalent to running the 32-bit MSBuild.

ResolveAssemblyReference: Reference resolution ignores Processor Architecture except when resolving from the Global Assembly Cache

Description:

If you have two assemblies whose identities differ only by the processor architecture, i.e.

myTypes, Version=1.0.1234.0, Culture=en-US, PublicKeyToken=b77a5c561934e089c, ProcessorArchitecture=msil myTypes, Version=1.0.1234.0, Culture=en-US, PublicKeyToken=b77a5c561934e089c, ProcessorArchitecture=x86

And you try to reference one of them specifically:

<Reference Include=”myTypes, Version=1.0.1234.0, Culture=en-US,  PublicKeyToken=b77a5c561934e089c, ProcessorArchitecture=x86″/>

You will notice that the first reference found will be picked up.

It will also cause the CopyLocal property being set to false.

Affected scenarios:

Building with MSBuild 32-bit or 64-bit.

Workaround:

Add your affected references to the Global Assembly Cache. See KB315682 on how to do that.

64-bit MSBuild is not able to find VCBuild.exe while building a VC++ 3.5 solution

Description:

You keep facing the following error:

Build FAILED.

“mysolution.sln” (Rebuild target) (1) ->(mcpplib1:Rebuild target) -> MSBUILD : error MSB3411: Could not load the Visual C++ component “VCBuild.exe”. If the component is not installed, either 1) install the Microsoft Windows SDK for Windows Server 2008 and .NET Framework 3.5, or 2) install Microsoft Visual Studio 2008.      0 Warning(s) 1 Error(s)

Affected scenarios:

Building with MSBuild 64-bit only.

 

Workaround:

In order to properly build solutions with MSBuild containing 3.5 and earlier VC++ project files (*.vcproj) the PATH environment variable should contain the path to VCBuild.exe, which happens to be a 32-bit only executable. To build with 64-bit MSBuild you should point to the location under “Program Files (x86)” path.

LC.exe causes build failures while building AMD64 configurations inside Visual Studio

Description:

When building the AMD64 configuration of a solution, LC.exe is being picked up from %Program Files (x86)%Microsoft SDKsWindowsv7.0AbinNETFX 4.0 ToolsLC.exe instead of being picked of from %Program Files (x86)%Microsoft SDKsWindowsv7.0AbinNETFX 4.0 Toolsx64LC.exe. Or if you are using Visual Studio 2008, from the directory %Program Files%Microsoft SDKsWindowsv6.0Abin.

This will make you face an error like this:

LC : error LC0000: ‘Could not load file or assembly ‘MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’ or one of its dependencies. An attempt was made to load a program with an incorrect format.’

This issue is caused by the fact that LC.exe is not able to satisfy the Cross-Compilation scenarios because of some specific requirements on how it needs to load the referenced dynamic libraries.

NOTE: your build will succeed if you use 64-bit MSBuild on the command line.

Affected scenarios:

Cross compilation scenarios. Building x64 platforms with 32-bit MSBuild or x86 platform with 32-bit MSBuild.

Workaround:

Your build will succeed if you use 64-bit MSBuild in the command line, however if you still want to build inside Visual Studio IDE you can use the following to your project file (by manually editing it):

<PropertyGroup Condition=” ‘$(Configuration)|$(Platform)’ == ‘Release|x64’ “>

<LCToolPath>C:Program FilesMicrosoft SDKsWindowsv6.0Abinx64</LCToolPath>

RegisterAssembly task fails on Cross targeting scenarios

Description:

If you have a project in your solution targeted to build an x64 platform and you:

  • set it to be registered for COM Interop (on the Project Build properties)
  • or set the RegisterForComInterop property in the project file to true

You will face the following issue while building it:

Error 1 File “MyDll.dll” is not a valid assembly. C:WindowsMicrosoft.NETFrameworkv4.0.20904Microsoft.Common.targets 3257 9 ClassLibrary3

MSBuild cannot register a library for COM Interop if its architecture does not match the architecture of the MSBuild.exe (or DevEnv.exe) hosting the build process.

So on a 64-bit OS, the following scenarios will not work when the RegisterAssembly task is invoked as part of the build:

  • In the IDE the user changes the platform of the project to x64 and builds
  • In the command line, 32-bit MSBuild will fail to build a project targeting a x64 platform
  • In the command line, 64-bit MSBuild will fail to build a project targeting the x86 platform
Affected scenarios:

Cross compilation scenarios. Building x64 platforms with 32-bit MSBuild or x86 platform with 32-bit MSBuild.

Workaround:
  1. You need to match the architecture of MSBuild.exe with the platform you are attempting to build, or
  2. Instead of setting the “RegisterForComInterop” property to true, add a custom step to your build that runs RegAsm.exe to register your COM library. It must run the version of RegAsm.exe that matches the architecture of your library. For details on how to add a custom build step, see here. Or follow this steps:
        1. In the project properties, select “Build Events…” from the compile page.
        2. Add the following post build command line: “%Windir%Microsoft.NETFramework[64]v4.0.xxxxxregasm” “$(TargetPath)”
          • Be careful to select the Framework directory that matches the architecture you are targeting

COM references are not resolved on cross targeting scenarios

Description:

If you have a COM object registered by using regsvr32.exe, consider that there is a 32-bit and 64-bit regsvr32.exe. If you used 32-bit regsvr32.exe to register your COM object and you are attempting to build a project targeting x86 platform but using 64-bit MSBuild. The build will fail, this issue is caused by the fact that the library was registered with a pure 32-bit regsvr32.exe and thus it only registers the component under the WOW registry section, that is invisible to 64-bit processes that do not attempt an explicit look up on the WOW nodes.

The opposite is also true, using the 64-bit regsvr32.exe to register the library and attempting to build a project targeting a x64 platform with 32-bit MSBuild. This process has no way to access the 64-bit part of the registry.

One manifestation of this issue would be if your build is failing with an AxImp error when building a project that consumes a registered PIA of an ActiveX control:

Build FAILED. “ActiveXWithPiaConsumer.csproj” (default target) (1) –> (ResolveComReferences target) -> C:WindowsMicrosoft.NETFramework64v4.0.21112Microsoft.Common.targets(1543,9): warning MSB3283: Cannot find wrapper assembly for type library “AxActiveXControlLib”. [ActiveXWithPiaConsumer.csproj] “ActiveXWithPiaConsumer.csproj” (default target) (1) –> (ResolveComReferences target) -> AXIMP : AxImp error : Did not find a registered ActiveX control in ‘ActiveXWithPiaActiveXControl.dll’. [ActiveXWithPiaConsumer.csproj]

 

Affected scenarios:

Mismatches between the architecture of the regsvr32.exe used to register the library and the architecture of MSBuild used to build:

  1. 32-bit regsvr32.exe and 64-bit MSBuild.exe
  2. 64-bit regsvr32.exe and 32-bit MSBuild.exe

NOTE: if you are using a 32-bit only COM object while trying to build a x64 platform the Interop assembly cannot be generated, and the same applies if you are using a 64-bit only COM object and you are trying to build the x86 platform.

Workaround:

Build using a matching MSBuild architecture with the architecture of regsvr32 and the platform to build:

  1. You want to build the x86 platform, use 32-bit MSBuild + 32-bit regsvr32.exe.
  2. You want to build a x64 platform, use 64-bit MSBuild + 64-bit regsvr32.exe.

Cannot build Silverlight project targeting a x64 platform or using 64-bit MSBuild

Description:

You have a Silverlight project and you change the platform to x64. You might face one of the following errors:

The “ValidateXaml” task failed unexpectedly. System.BadImageFormatException: Could not load file or assembly ‘objx64DebugSilverlightApplication1.dll’ or one of its dependencies. An attempt was made to load a program with an incorrect format.

or if you are building using 64-bit MSBuild:

“SilverlightApplication1.csproj” (GetXapOutputFile target) (2:2) -> C:Program Files (x86)MSBuildMicrosoftSilverlightv3.0Microsoft.Silverlight.Common.targets(101,9): error : The Silverlight 3 SDK is not installed. [SilverlightApplication1.csproj]

Affected scenarios:
  1. Attempts to build a Silverlight project targeting a x64 platform with either 32-bit or 64-bit MSBuild.
  2. Attempts to build a Silverlight project with 64-bit MSBuild.
Workaround:

No workaround. Silverlight DOES NOT support x64 platforms. And Silverlight projects cannot be built by 64-bit MSBuild. You must use the 32-bit MSBuild and target x86 or AnyCPU platforms to build your Silverlight projects.

If you are using Team Build select x86 for the MSBuild platform setting.

Interop assemblies are not generated correctly if the project targets the default platform

Description:

If you have a class library project (for example) and you haven’t changed the platform of the project, it will be targeting the AnyCPU platform. However if you add a reference to a COM object you will find out that the generated Interop assembly is specifically targeting the x86 platform.

This is because Interop assemblies always have an explicit target platform, and in the absence of an explicit platform from the project consuming the Interop assembly this target platform is defaulted to the value of an Environment Variable named “PROCESSOR_ARCHITECTURE”, which inside Visual Studio IDE it evaluates to the x86 platform.

The effect of this is that if your application (targeting AnyCPU platform) is run in a 64-bit Operating System, it will run as a 64-bit process and the will fail to load the Interop assembly.

Note that applications built as AnyCPU will always run as 64-bit under a 64-bit Operating System, no matter if you launch them from a 64-bit or 32-bit command window.

Affected scenarios:

Projects targeting the default platform and consuming Interop assemblies. This will happen either with 32-bit and 64-bit MSBuild.

Workaround:

Explicitly set the platform on your project or manually add it to the project by defining the PlatformTarget property to your configuration block in the project file:

  <PlatformTarget>AnyCPU</PlatformTarget>

 

An error occurs when compiling a .resx file with MSBuild

Description:

On a 64-bit OS you have a project targeting the x86 platform and it targets 3.5 .NET Framework or below. Your project has a reference to a 32-bit only assembly, and when you build you get the following error:

ResourceFrm.resx(1436,5): error RG0000: Could not load file or assembly ’32bitOnlyAssembly.dll’ or one of its dependencies. An attempt was made to load a program with an incorrect format. Line 1436, position 5.

This issue is caused by the fact that in the 3.5 .NET tools resgen.exe in both the x86 and x64 bin directories is marked as IL (architecture agnostic), causing it to run on a 64-bit Operating System as a64-bit executable no matter what. As a 64-bit process, resgen.exe is unable to load the 32-bit only library.

Also if you are targeting 4.0 .NET, MSBuild will fail in the same way if you are referencing a 32-bit only assembly while using 64-bit MSBuild and vice versa.

Affected scenarios:

Cross targeting scenarios while building projects which contain resource files with MSBuild:

  1. In a 64-bit Operating System If you are targeting 3.5 .NET and the project references a 32-bit assembly with either 32-bit or 64-bit MSBuild.
  2. The project references a 32-bit assembly and you are using 64-bit MSBuild.
  3. The project references a 64-bit assembly and you are using 32-bit MSBuild.
Workaround:
  1. Make the library referred on the error target the AnyCPU platform, or (if this is not a option as the assembly involved is produced from a third party)
  2. You need to workaround the fact that resgen.exe is shipped as an MSIL tool on the Windows SDK, to do so follow these steps:
    1. Use corflagsto set the 32bit flag on resgen.exe, to do so open a Visual Studio command prompt and type:
      1. # corflags /32bit+ “%ProgramFiles(x86)%Microsoft SDKsWndowsv7.0Abinresgen.exe” /force
    2. Add in the project file the following property:
      1. <ResGenToolArchitecture>Managed32Bit</ResGenToolArchitecture>
    3. NOTE: this workaround will cause problems if you have also resx files that have types declared on 64-bit assemblies.

Cannot build SQL Server project using 64-bit MSBuild

Description:

You have a SQL server project and you attempt to build it using 64-bit MSBuild, the following error is displayed:

  SqlServerProject1.vbproj(149,3): error MSB4019: The imported project “C:WindowsMicrosoft.NETFramework64v4.0.xxxxxSqlServer.targets” was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.

Workaround:

Copy C:WindowsMicrosoft.NETFramework64v4.0.xxxxxSqlServer.targets to C:WindowsMicrosoft.NETFrameworkv4.0.xxxxxSqlServer.targets

 


Daniel Estrada – Software Development Engineer in Test, MSBuild Team

0 comments

Discussion is closed.

Feedback usabilla icon