Support debug and release builds in a package

Dec 23, 2011 at 2:56 PM

With the new symbolsource integration, I can see it will be easy (and great) for everyone to publish debug builds with source we can step through:

http://blog.davidebbo.com/2011/04/easy-way-to-publish-nuget-packages-with.html

 

Now the concern is:

1)  People will end up publishing debug packages and release packages, which means you must decide between them.  If you choose debug, when you do a release you would either end up with debug nuget items or have to swap over to release packages (neither one are good).  If you choose release, now if you have an issue you cannot debug!

2)  People will just publish debug packages or release packages because of the above.  This is not good either.

Proposal:

   Have a nuget package to support both debug and release builds of a product in one package.  In general, adding a nuget package to a solution would contain both debug and release assemblies.  If you use the new nuget restore package, potentially it would only download the debug or release version based on what you built.

Dec 23, 2011 at 7:29 PM

One important thing to note is that in .NET, there is no need for debug builds to enable source stepping. As long as release builds are done with /debug:pdbonly or <DebugType>pdbonly</DebugType>, everything will work as expected. Of course with a release mode assembly, the JIT compiler will be allowed to make optimizations that will degrade the debugging experience, but it will still work.

 There is no difference in IL generated by debug and release modes, except for explicit #if DEBUG or ConditionalAttribute stuff.

This is confused very, very often, and has its roots in C/C++, where this does matter, and greatly at that

Still, it would be cool if NuGet supported build modes in packages, and even cooler if it inserted conditional <Reference> tags, like this:

<Reference Include="log4net" Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
  <HintPath>..\..\packages\log4net.1.2.10\lib\2.0\Debug\log4net.dll</HintPath>
</Reference>
<Reference Include="log4net" Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
  <HintPath>..\..\packages\log4net.1.2.10\lib\2.0\Release\log4net.dll</HintPath>
</Reference>
This is supported by MSBuild. With references build this way, appropriate DLLs would be automatically be picked up depending on the current build mode of the consumer project. As I recall, there were unfortunately some issues with this in VS - like warning icons next to references. Someone would have to check. And maybe a VS extension could fix that.

Dec 23, 2011 at 7:44 PM

Yes, thinking that IL through makes sense.  I come from way back, so when I see that checkbox for optimize, you know where I go!

I like what you have suggested, I think this would be a good addition.

Dec 24, 2011 at 3:02 PM

If the reason for releasing debug builds, is being able to step through source code, there is another option which works very well:

Add an ini file to the application bin directory, which uses the dll"s and add the following;
[.NET Framework Debugging Control]
GenerateTrackingInfo=1
AllowOptimize=0

The ini files has to have the same name as your application exe or dll (in case of web applications)
Eg. in case of a web application, if your dll is : MyCompany.MyApp.dll, the file needs to be : MyCompany.MyApp.ini

The JIT compiler optimize non of the dll's referenced in the application, making it easy to debug.
The only difference between a real debug dll is the following:
- it will not contain any of the statements that are inside a conditional compile statement with the tag Debug (#IF Debug) 
- it will not contain any of the Debug.XXX statements as these are not compiled to MSIL in release mode.

However, in most cases, this is acceptable for debugging purposes.

More information can be found at this link : http://msdn.microsoft.com/en-us/library/9dd8z24x.aspx 

 

 

Dec 24, 2011 at 6:45 PM
You get the equivalent behavior by launching the executable under the debugger, because the debugger also stop optimization. Attaching a debugger after the fact to an already running application, on the other hand, likely ends up with optimized code and off-by-one stack traces causes by inlining.
Dec 24, 2011 at 9:15 PM

@BradWilson: I'm not sure that's always true. The trick I've learned to trust is to set the env var COMPLUS_ZapDisable=1 before launching VS. There are cases where without this flag, some assemblies get JIT optimized even when starting in the debugger. COMPLUS_ZapDisable is a big undocumented hack, but it does work.

I didn't know about the .ini technique @rekna mentions. That one seems to act on a per assembly basis rather than globally. Though I'm not clear where you'd put the .ini file when the assembly is GACed? Next to the DLL deep in the GAC?

Dec 28, 2011 at 10:54 PM

Sure seems like a lot of tricks and tips.  What about just supporting release and debug builds inside a nuget package?  :-)

Dec 29, 2011 at 7:05 AM

I'm with Wayne, optional support for debug and release in the same package would make life a lot easier.

Jan 3, 2012 at 2:51 PM

Perhaps if assembly platforms are implemented, release/debug could be done at the same time.

http://nuget.codeplex.com/workitem/679

Feb 9, 2012 at 12:22 PM

I'm building a corporate nuget package library at present; and all the packages I've been releasing are all Release builds with Full PDB information so as to facilitate easier debugging.

However, when running in the dev environment (debug flavour), especially in web projects running on IIS (some of our more advanced web apps simply don't work properly in the development web server), I have found frequently that Debug introspection on variables/parameters etc within those libraries is not possible as it has all been optimised away.  If those referenced assemblies were Debug configurations I believe that wouldn't be the case.

Perhaps this is specifically because IIS apps don't actually launch with the debugger attached; it attaches just after it starts up.  Either way, being able to embed a specific set of debug DLLs would get around the issue.

So you could have support for lib\{framework}[-configuration]\ and then add conditional references as mentioned by TripleEmcoder on 12/23/2011 above.

The process upon adding the package:

Each project configuration gets it's own conditional reference group, always, managed by Nuget.

For each project configuration, try to find a lib\{framework}-configuration folder in the package.  If found, add the contents as references.
  If not found, search for lib\{framework} and then lib\

The only thing I can't figure out is how to handle brand new configurations added after the nugets were added (granted, not common, but you never know) - the only thing I can think of at the moment is another reference group with a condition that says 'when the configuration is none of those known at the time the nuget was added'.  Either that or we simply say that only Debug/Release are supported.