views:

380

answers:

5

Hi all,

I can't understand why If I compile the same source with Visual Studio 2008 (MSBuild) and then with csc (or NANT) at command line I can't obtain exacly the same binary file (the same assembly).

The command line is the same that is invoked by visual studio because I copy the command from the output window and then paste the command to the vs2008 command prompt.

I know that if I compile the same source at different time I obtain different binary because of the timestamps in the assembly metadata. In fact, if I compare two binaries produced by vs2008 at different time I notice small difference between the binary data.

But if I compile with vs and then with csc the binaries are very very different! Do you know why? What's wrong?

A: 

A very bold guess, but maybe the environment variables are not the same in the VS IDE and your terminal. In a worse case scenario maybe your terminal version links against another .NET framework or at least against a couple of other libraries/ code files or compiler switches?

merkuro
it's a timestamp issue
Scott Weinstein
@Scott: The timestamp issue explains why building two binaries at different times produces *slightly* different binaries - but not why the binaries built from the command-line are *very* different from the VS ones.
Jon Skeet
A: 

You haven't said whether you're building debug or binary builds in Visual Studio. I'm not sure that the command-line default is the same as either of them.

Try building with explicit /debug and /o switches (set to however you want them) and match them up in Visual Studio. Also define the DEBUG and/or TRACE symbols if you have them defined in the Visual Studio build configuration.

Jon Skeet
A: 

@Jon:

Ciao Jon, thanks for your reply.

The Csc command line arguments it's exacly the same because I take it from the output window of visual studio and copy it in the visual studio 2008 prompt.

Following the command line:

C:\Windows\Microsoft.NET\Framework\v3.5\Csc.exe /noconfig /nowarn:1701,1702 /errorreport:prompt /warn:4 /define:TRACE;USING_NET_35_SP1 /reference:..\..\lib\Iesi.Collections.dll /reference:..\..\lib\NHibernate.dll /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Data.Services.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /debug- /filealign:512 /keyfile:..\NH.Linq.snk /optimize+ /out:obj\Release\NHibernate.Linq.dll /target:library Expressions\CollectionAccessExpression.cs Expressions\NHibernateExpression.cs Expressions\QuerySourceExpression.cs INHibernateQueryable.cs QueryOptions.cs Transform\TypeSafeConstructorMemberInitResultTransformer.cs Util\SessionFactoryUtil.cs Visitors\BinaryBooleanReducer.cs Visitors\BinaryCriterionType.cs Visitors\BinaryCriterionVisitor.cs Visitors\BinaryCriterionDelegates.cs Visitors\AssociationVisitor.cs CriteriaResultReader.cs Visitors\BinaryExpressionOrderer.cs Visitors\CollectionAliasVisitor.cs Visitors\RootVisitor.cs Visitors\EntityExpressionVisitor.cs Visitors\Evaluator.cs Expressions\EntityExpression.cs Expressions\NHibernateExpressionType.cs Expressions\PropertyAccessExpression.cs Visitors\InheritanceVisitor.cs Visitors\MemberNameVisitor.cs Visitors\ImmediateResultsVisitor.cs Visitors\NHibernateExpressionVisitor.cs NHibernateQueryProvider.cs Query.cs QueryProvider.cs Visitors\PropertyToMethodVisitor.cs Visitors\SelectManyVisitor.cs Transform\LinqJoinResultsTransformer.cs Util\DetachedCriteriaAdapter.cs Util\CriteriaUtil.cs Expressions\SqlFunctionAttribute.cs Expressions\SqlFunctionExpression.cs Expressions\SqlAggregateFunctionProjection.cs Visitors\GroupingArgumentsVisitor.cs Transform\LinqGroupingResultTransformer.cs NHibernateExtensions.cs IDbMethods.cs Visitors\ExpressionVisitor.cs Util\LinqUtil.cs NHibernateContext.cs Visitors\NHibernateQueryTranslator.cs Properties\AssemblyInfo.cs Util\QueryUtil.cs Visitors\SelectArgumentsVisitor.cs SqlClient\SqlClientExtensions.cs Util\TypeSystem.cs Visitors\WhereArgumentsVisitor.cs
Lorenzo Melato
Actually, VS doesn't *really* run csc in this way... that is a white lie; it shows this to be helpful, but I seem to recall that it interacts with the compiler more directly. I'd be surprised if you saw a significant difference, though. I'm not 100% sure what "very very different" includes, though - you'd need ILDASM etc.
Marc Gravell
Hello Marc, I have found this interesting post about the "two compiler thesis":http://blogs.msdn.com/ed_maurer/archive/2008/06/11/a-tale-of-two-compilers.aspx
Lorenzo Melato
A: 

@ Marc Gravell, Divo, Jon: I have try to disassemble the two assemplies with ILDASM. After a deep analysis and compare, I have see that the IL contents is exacly the same, but all the classes and methods, property getter and setter, etc. are in a very different order in the assembly! So if I compare the two assemblies with and hex editor/comparer I see a completely different binary body!

Now I need to understand why VS and Csc interacts with the compiler in this different way!

Do you have a reference to a document that explain the two approches?

Lorenzo Melato
+1  A: 

There's no guarantee of any particular order of metadata made by the compiler. That said, there's nothing intentionally causing a different ordering between the in-proc compiler and csc.exe.