dotnet / orleans

Cloud Native application framework for .NET
https://docs.microsoft.com/dotnet/orleans
MIT License
10.07k stars 2.03k forks source link

Project fails to build after adding OrleansCodeGenerator.Build package if platform is x86 #2896

Closed novabe closed 6 years ago

novabe commented 7 years ago

Build error is: The command ""c:\Projects\orleanstest\packages\Microsoft.Orleans.OrleansCodeGenerator.Build.1.4.0\build..\tools\ClientGenerator.exe" "@obj\Release\orleanstest.codegen.args.txt"" exited with code 3.

Build output is:

1>------ Rebuild All started: Project: orleanstest, Configuration: Release Any CPU ------
1>  [OrleansCodeGeneration] - Project=orleanstest
1>  orleanstest -> c:\Projects\orleanstest\orleanstest\bin\Release\orleanstest.exe
1>  Orleans-CodeGen - command-line = "c:\Projects\orleanstest\packages\Microsoft.Orleans.OrleansCodeGenerator.Build.1.4.0\build\..\tools\ClientGenerator.exe"  "@obj\Release\orleanstest.codegen.args.txt"
1>  Orleans-CodeGen - Reading code-gen params from file=obj\Release\orleanstest.codegen.args.txt
1>  MISSING: Path not exists: c:\Projects\orleanstest\orleanstest\obj\Release\orleanstest.codegen.cs
1>  Orleans-CodeGen - Options 
1>      InputLib=c:\Projects\orleanstest\orleanstest\obj\Release\orleanstest.exe
1>      OutputFileName=c:\Projects\orleanstest\orleanstest\obj\Release\orleanstest.codegen.cs
1>  Orleans-CodeGen - Using referenced libraries:
1>      Microsoft.CodeAnalysis.CSharp.dll => c:\Projects\orleanstest\packages\Microsoft.CodeAnalysis.CSharp.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.dll
1>      Microsoft.CodeAnalysis.dll => c:\Projects\orleanstest\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll
1>      Microsoft.CSharp.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Microsoft.CSharp.dll
1>      Microsoft.Extensions.DependencyInjection.Abstractions.dll => c:\Projects\orleanstest\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.0.0\lib\netstandard1.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
1>      Microsoft.Extensions.DependencyInjection.dll => c:\Projects\orleanstest\packages\Microsoft.Extensions.DependencyInjection.1.0.0\lib\netstandard1.1\Microsoft.Extensions.DependencyInjection.dll
1>      mscorlib.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\mscorlib.dll
1>      Newtonsoft.Json.dll => c:\Projects\orleanstest\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll
1>      Orleans.dll => c:\Projects\orleanstest\packages\Microsoft.Orleans.Core.1.4.0\lib\net451\Orleans.dll
1>      System.Collections.Immutable.dll => c:\Projects\orleanstest\packages\System.Collections.Immutable.1.1.37\lib\dotnet\System.Collections.Immutable.dll
1>      System.Core.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Core.dll
1>      System.Data.DataSetExtensions.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Data.DataSetExtensions.dll
1>      System.Data.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Data.dll
1>      System.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.dll
1>      System.Net.Http.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Net.Http.dll
1>      System.Reflection.Metadata.dll => c:\Projects\orleanstest\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll
1>      System.Xml.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Xml.dll
1>      System.Xml.Linq.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Xml.Linq.dll
1>      System.Collections.Concurrent.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Collections.Concurrent.dll
1>      System.Collections.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Collections.dll
1>      System.ComponentModel.Annotations.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.ComponentModel.Annotations.dll
1>      System.ComponentModel.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.ComponentModel.dll
1>      System.ComponentModel.EventBasedAsync.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.ComponentModel.EventBasedAsync.dll
1>      System.Diagnostics.Contracts.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Diagnostics.Contracts.dll
1>      System.Diagnostics.Debug.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Diagnostics.Debug.dll
1>      System.Diagnostics.Tools.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Diagnostics.Tools.dll
1>      System.Diagnostics.Tracing.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Diagnostics.Tracing.dll
1>      System.Dynamic.Runtime.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Dynamic.Runtime.dll
1>      System.Globalization.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Globalization.dll
1>      System.IO.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.IO.dll
1>      System.Linq.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Linq.dll
1>      System.Linq.Expressions.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Linq.Expressions.dll
1>      System.Linq.Parallel.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Linq.Parallel.dll
1>      System.Linq.Queryable.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Linq.Queryable.dll
1>      System.Net.NetworkInformation.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Net.NetworkInformation.dll
1>      System.Net.Primitives.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Net.Primitives.dll
1>      System.Net.Requests.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Net.Requests.dll
1>      System.ObjectModel.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.ObjectModel.dll
1>      System.Reflection.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Reflection.dll
1>      System.Reflection.Emit.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Reflection.Emit.dll
1>      System.Reflection.Emit.ILGeneration.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Reflection.Emit.ILGeneration.dll
1>      System.Reflection.Emit.Lightweight.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Reflection.Emit.Lightweight.dll
1>      System.Reflection.Extensions.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Reflection.Extensions.dll
1>      System.Reflection.Primitives.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Reflection.Primitives.dll
1>      System.Resources.ResourceManager.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Resources.ResourceManager.dll
1>      System.Runtime.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Runtime.dll
1>      System.Runtime.Extensions.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Runtime.Extensions.dll
1>      System.Runtime.InteropServices.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Runtime.InteropServices.dll
1>      System.Runtime.InteropServices.WindowsRuntime.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Runtime.InteropServices.WindowsRuntime.dll
1>      System.Runtime.Numerics.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Runtime.Numerics.dll
1>      System.Runtime.Serialization.Json.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Runtime.Serialization.Json.dll
1>      System.Runtime.Serialization.Primitives.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Runtime.Serialization.Primitives.dll
1>      System.Runtime.Serialization.Xml.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Runtime.Serialization.Xml.dll
1>      System.Security.Principal.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Security.Principal.dll
1>      System.ServiceModel.Duplex.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.ServiceModel.Duplex.dll
1>      System.ServiceModel.Http.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.ServiceModel.Http.dll
1>      System.ServiceModel.NetTcp.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.ServiceModel.NetTcp.dll
1>      System.ServiceModel.Primitives.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.ServiceModel.Primitives.dll
1>      System.ServiceModel.Security.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.ServiceModel.Security.dll
1>      System.Text.Encoding.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Text.Encoding.dll
1>      System.Text.Encoding.Extensions.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Text.Encoding.Extensions.dll
1>      System.Text.RegularExpressions.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Text.RegularExpressions.dll
1>      System.Threading.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Threading.dll
1>      System.Threading.Tasks.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Threading.Tasks.dll
1>      System.Threading.Tasks.Parallel.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Threading.Tasks.Parallel.dll
1>      System.Threading.Timer.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Threading.Timer.dll
1>      System.Xml.ReaderWriter.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Xml.ReaderWriter.dll
1>      System.Xml.XDocument.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Xml.XDocument.dll
1>      System.Xml.XmlSerializer.dll => C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Facades\System.Xml.XmlSerializer.dll
1>  -- Code-gen FAILED -- 
1>  
1>  Exc level 0: System.BadImageFormatException: Could not load file or assembly 'file:///c:\Projects\orleanstest\orleanstest\obj\Release\orleanstest.exe' or one of its dependencies. An attempt was made to load a program with an incorrect format.
1>     at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
1>     at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
1>     at System.Reflection.RuntimeAssembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boolean forIntrospection, Boolean suppressSecurityChecks, StackCrawlMark& stackMark)
1>     at System.Reflection.Assembly.LoadFrom(String assemblyFile)
1>     at Orleans.CodeGeneration.GrainClientGenerator.CreateGrainClient(CodeGenOptions options)
1>     at Orleans.CodeGeneration.GrainClientGenerator.CreateGrainClient(CodeGenOptions options)
1>     at Orleans.CodeGeneration.GrainClientGenerator.CreateGrainClientAssembly(CodeGenOptions options)
1>     at Orleans.CodeGeneration.GrainClientGenerator.RunMain(String[] args)

To recreate this bug, simply create a new project, add the latest Microsoft.Orleans.OrleansCodeGenerator.Build nuget package, change the project's platform target to x86, and build.

sergeybykov commented 7 years ago

We generally compile for AnyCPU (with an exception for Microsoft.Orleans.ServiceFabric.dll, which is x64). and the code should be runnable on either x86 or x64. Can't you instead set your grain interfaces/classes project as AnyCPU?

novabe commented 7 years ago

We generally compile for AnyCPU

I only checked ClientGenerator.exe and found it was AnyCPU, and didn't investigate further so I'm not sure why it had a problem with x86.

Can't you instead set your grain interfaces/classes project as AnyCPU?

Unfortunately in this case no, because that project has a VC++ dependency and as far as I know it's not really possible to make an AnyCPU VC++ DLL. Alternatively, x64 does work. But I still think it doesn't feel right that it would work with AnyCPU and x64, but not x86. I might be wrong.

I assume the reproduction steps successfully demonstrated the issue.

sergeybykov commented 7 years ago

Thank for the additional details. I was able to reproduce the issue, and looks like what's happening is pretty simple. ClientGenerator.exe being AnyCPU, on an x64 OS it starts as an x64 process, and because of that it fails to load the x86 binary later.

After I rebuilt ClientGenerator.exe privately as x86, and manually replaced with it the one in packages\Microsoft.Orleans.OrleansCodeGenerator.Build.1.4.1\tools of my test project, it worked. So everything seems to work if ClientGenerator.exe starts as an x86 process. Hence, I expect it work out of the box on an x86 OS.

So the immediate workaround for you I think is to use a private x86 build of ClientGenerator.exe, just like I did. I don't know if there's an app.config setting to force an AnyCPU exe to start as x86 instead of crating a private x86 build.

A potential question here is if we need to build ClientGenerator.exe as x86 instead of AnyCPU.I'm personally skeptical of that because this could cause issues with loading x64 dependencies, and x64 is the mainstream.

novabe commented 7 years ago

If we want it to always work with both x86 and x64 (not sure how important that is to this project), I'm going to propose this solution:

Store both x86 and x64 builds of ClientGenerator, and call the correct one based on the current project's platform. I think this can be done with changes only to the Microsoft.Orleans.OrleansCodeGenerator.Build.targets file (and format of ClientGenerator.exe).

sergeybykov commented 7 years ago

Store both x86 and x64 builds of ClientGenerator, and call the correct one based on the current project's platform. I think this can be done with changes only to the Microsoft.Orleans.OrleansCodeGenerator.Build.targets file (and format of ClientGenerator.exe).

This sounds like a sensible solution. The only additional twist I'd add to it is that it's better to have the x86 version of ClientGenerator.exe under a different name, e.g. ClientGeneratorx86.exe, to minimize the potential confusion and build time implications. If you are willing to prepare a PR, we'll gladly review and take it.

versex commented 6 years ago

I recently needed to compile for x86 and ran into the exact problem. In case anyone else comes across this thread with this problem, a simple resolution for getting the x86 ClientGenerator.exe is to add this to the Pre-Build script of your project

if $(PlatformName) == x86 ( "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7 Tools\CorFlags.exe" "$(SolutionDir)\packages\Microsoft.Orleans.OrleansCodeGenerator.Build.1.5.3\tools\ClientGenerator.exe" /32BITREQ+

Since ClientGenerator.exe is compiled for AnyCPU this will force it to run as 32 bit and the this will allow you to compile using x86. You can put the flags back to normal by running

if $(PlatformName) == x86 ( "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7 Tools\CorFlags.exe" "$(SolutionDir)\packages\Microsoft.Orleans.OrleansCodeGenerator.Build.1.5.3\tools\ClientGenerator.exe" /32BITREQ-

If you want more information on CorFlags, visit https://docs.microsoft.com/en-us/dotnet/framework/tools/corflags-exe-corflags-conversion-tool

After compiling for x86 I ran into the issue at #2795 . The suggested solution there took care of the issue.

sergeybykov commented 6 years ago

@versex Thanks for the workaround tip!