Runtime: Single exe self contained console app

Created on 3 Nov 2016  ·  98Comments  ·  Source: dotnet/runtime

Publishing a self-contained console application in .net core, as described here results in a directory with a lot of files, even one with "smaller footprint".

Is it possible to bundle all the dependencies so we get a single executable? One large-ish myapp.exe when targeting Windows, for example.

I suppose I'm looking for something similar to ILMerge, but for .net core. Is it possible by some option flag on dotnet publish or some other command? If not, please consider as a feature request. Thanks.

area-Meta question

Most helpful comment

This is just horrible i wonder why this was approved during design process, want to distribute your application to one of your client, then good luck to him to find what to open:
image

This is just ugly and a complete mess

runtime/
MyProgram.exe
MyLib.dll

This would have been a way better idea

Even Java handle that better:
explorer_2018-04-21_16-42-33

All 98 comments

This scenario isn't supported right now. Keep an eye on the https://github.com/dotnet/corert repo for work that will lead down this path.

CoreRT is the right place to search for this solution.

Thanks. It looks like CoreRT is exactly what I was looking for.

For others that may stumble on this, read here

I specifically want this feature without ahead of time compilation. I don't want corert– I want the same jit and debugging and runtime experience as a normal self-contained app– but I also don't want to distribute four files per utility. That's inconvenient for whoever wants to use the utility. I just want it packed and run from a single exe. This is causing me to choose .NET Framework over .NET Core for many utilities.

.NET Framework is "cheating" as you have plenty of files already present in the OS.
You can achieve the same with .NET Core, by installing machine-wide shared .NET Core if that is what you want.

Refactoring CoreCLR to merge all its files into one (incl. native + managed) is non-trivial work and I don't think the scenario is that interesting for too many customers.

The difference is that every Windows machine is guaranteed to have .NET Framework but not .NET Core, so unless there's a special reason that is worth making deployment more complex, I guess I'll end up staying there.
I guess customers don't typically write single exe utilities. Maybe one day. :-)

unless there's a special reason that is worth making deployment more complex

There are MANY reasons to prefer .NET Core over .NET Framework. Performance, modularity, serviceability, isolation, etc. And that is ignoring cross-platform-ness.

Having a single exe utility is mostly a cosmetic concern. There's no real functional difference (for anyone involved) if the executable is a single file or a single folder with a handful of files in it.

@mellinoe Oh I agree for projects in general, that is certainly true. In the small utilities where this cosmetic is desirable, .NET Framework has thus far done a good enough job. I agree it's cosmetic in the same sense as being able to specify an assembly company and copyright message. But being a cosmetic thing doesn't make me like it less. Obviously not a priority here, that's quite understandable.

It's not mostly cosmetic. Imagine that I want to distribute an application that has several components embedded inside, like say Idsrv4 or RavenDb + my own stuff. They take a dependency on the aspnet core bits. This all works fine as long as they depend on the same version of aspnet core. As soon as one of them rolls forward to the next version it probably will no longer work. If OTOH I could ilmerge each component down to a single .dll the problem goes away.

One thing to keep in mind is that there are more technical problems than just ILMerge not working. The runtime itself is fundamentally split into many files, and there are also auxiliary files like the CLR host, the runtime dependencies text file, and more. The only reason a single-file executable has worked in the past is because the .NET Framework, a global system-wide installation, was relied upon. Comparing the two scenarios is a bit unfair, because the .NET Framework doesn't really have a "self-contained" option.

This all works fine as long as they depend on the same version of aspnet core. As soon as one of them rolls forward to the next version it probably will no longer work.

This isn't really true. You can publish several different applications against different runtime versions and then bundle them into the same "uber-app". You just cannot mix their dependencies into a single folder. Even if you use the framework-dependent publish option, you can still mix and match versions. I understand that this is less convenient than having literally a single file, and might prevent things like embedding an exe as a resource in the PE. I'm not sure if that's what you're referring to, though, since you'd probably still need to extract the file to execute it, which you could still do with a directory.

I didn't mean runtime version, I know that isn't going to work. What I mean is, what happens in my scenario when each component takes a dependency on [email protected]. Component a then updates to [email protected]. Normally that's fine, but in this hypothetical the authors of LibXYZ don't know / don't care about semantic versioning. Ilmerge made this problem go away.

As well as @thefringeninja pertinent point, I would suggest that a single deployable binary unit reduces the ops overhead. It reduces the likelihood of something going wrong with a deployment, lowers the burden of cognitively appreciating what you've shipped and reduces config for ops tooling be it scripting, or desired state.

I appreciate the dotnet tooling is nascent and has only just reached 2.0, but compared to alternatives such as golang this feature is sorely missing. Please consider adding it to the roadmap?

As a lib developer, I'd appreciate having ILMerge back in Core. 👍

Dotnet.exe is a single file. NuGet.exe is a single file. I think cosmetics are important, and a single file exe shouts simplicity in a way that a folder with 100 files in doesn't! Would be great to find a way to achieve this with dotnetcore

I assumed this was possible, and after several weeks of work, came to publish CLI console tool to a single .exe ... ummm seems at the moment I cant just get a single *.exe ??
I thought that was the point of self contained core apps?

@PRIMETSS

I thought that was the point of self contained core apps?

The point of self-contained apps is that they are self-contained, that is, they don't require .Net Core to be installed on the target machine, because the app itself contains everything it needs to run.

To deploy such an app, you have to copy an entire directory of files. Having just a single file would make the deployment easier, but that's it, it's still a self-contained app even without that.

For large and service-like apps this maybe not that important, but it is essential for command-line tools and small apps to be as simple as possible and COPY-deployment friendly.

I regularly write command line tools in .NET and having them as 1 EXE makes upgrades/deployments/packaging WAY simpler. I always pack all .config and other required files inside EXE.

Think of that single-EXE as a mini-container. Almost all benefits of container-based deployments apply here.

This is just horrible i wonder why this was approved during design process, want to distribute your application to one of your client, then good luck to him to find what to open:
image

This is just ugly and a complete mess

runtime/
MyProgram.exe
MyLib.dll

This would have been a way better idea

Even Java handle that better:
explorer_2018-04-21_16-42-33

Yes I was thinking along the same lines, since the self contained apps need to have the runtime files included with it with it (obviously!) (and we dont have a way to merge those), then I also thought just a folder separation would be neater, and yes I also think the runtime files should be stored off in a runtime folder, so anyone trying to use a Command Line Tool written in core, would at least find it a bit more intuitive as what to run..

@Scellow @PRIMETSS I have to agree

How is this even still an issue? The demand is through the roof for this.

yes to this separate folder with the addition to zip that into a bin and have two files, the exe and the bin. Easy distribution.

Another +1 to re-open and have as a feature.

I was expecting self-contained deployment was self-contained and found my way here. I'd also like to see this happen.

How can anyone say this is just a cosmetic issue? (Only Framework developers ...)
Nobody thought of tools which are not installed? (.NET solved dll-hell, and .net core brings it back)

I just want my Command Line tool to be be self-contained.

This is bad, really bad!

+1

+1 I've just tried to run custom activity in Azure Batch on a cluster without .net core runtime and it cannot handle the high number of files the "self-contained" version creates.

Total size of resourceFiles cannot be more than 32768 characters

This isn't an official solution, but it might be useful. I'm the author of warp, a tool that allows you create self-contained single binary applications: https://github.com/dgiagio/warp

I think warp is basically what everybody is looking for here! It's just about the ability to have a single exe file, whatever be in the background, nothing more. Think about NuGet packages: it's a single .nuget file and that's it; it's not something more complex than a file packaging other files.

warp is a hacky solution, this isn't what we want

What we want is:

dotnet publish --self-contained -c Release -r win10-x64

And it produce:

App.exe
runtime/

Or better like GO/Rust etc

App.exe

Everything else isn't wanted

Warp produces an App.exe... How is it hacky? Obviously it's not part of the framework, but achieves the "one exe file" goal.

This is what i mean, it should be default behavior, not using 3rd party solution (i think)

Warp works a treat. Thanks for your work @dgiagio!

+1

I'd very much like to see some kind of single-file archive that bundles the executable and all the dependencies. Doesn't have to include the native ones - I think it's perfectly fine to require dotnet core do be installed on the system. Something very similar to Java's jar files. A dar file?

Something like:
dotnet publish --self-contained
dotnet run --self-contained MyApp.dar

It looks like there's a proposal up for this now: https://github.com/dotnet/designs/pull/52/files?short_path=28dba55

Here's the tracking issue: https://github.com/dotnet/coreclr/issues/20287

I read the proposal and i saw this:

image

That's not what i had in mind, this sounds like a slow process, basically just zipping everything..
I though all the code would be merged into a single executable/dll? or maybe i missed something in the proposal ?

@RUSshy Are you asking about native-compiling all the managed code and linking everything together to get one executable (as in CoreRT)? This is not a goal for the current single-file work in .Net Core.

However, there are proposed solutions for reducing disk extraction and startup time (ex: load certain file types directly from the bundle, reuse extracted files). The stages of development of single-file solution are described here.

CC: @jeffschwMSFT

Why do the files need to be extracted? We used to get away with this in .NET with ILMerge.

@phillip-haydon, as described here, ILMerge and single-file solutions achieve different objectives.

ILMerge combines the IL from many assemblies into one, but in the process, loses the original identity of the merged assemblies. So, things like using reflection based on original assembly names will fail. Apps can still use ILMerge if they can tolerate this change.

CoreRT is something else, AOT compilation of your .NET code, it does look interesting, but not yet ready (i wish MS would focus on it, and allocates more resources.. this is exactly what people want, and why they moved to GO)

Anyway, i don't have technical knowledge to talk about the detail, but use case is:

Publish a single self-contained executable, and just that, nothing zipped, nothing extracted, no overhead, just the executable

@swaroop-sridhar do you have an example of this working for dotnet core on linux? according to https://github.com/dotnet/ILMerge/blob/master/ILMerge/ILMerge.csproj#L13 this is a windows / mono only project.

@thefringeninja ILMerge is a windows tool, I don't know of any plans to port ILMerge to other platforms.
The Single-file solution will be implemented cross-platform. This is in the process of development.

@karelz @mellinoe
Deploy Deploy Deploy !
if Single or less like 1-3 files thats will be better for Deploy (Inlcude Publish,Update)!

CoreRT is AOT
but ppl want AOT ?
the project(CoreRT) always not Readly to use(its from 2014). Now is 2019!(about take 5 years)
What a precious 5 years for a pragram language!
the CoreRT even not any plan for next release !!!
let ppl wait for more another 5 years?

@swaroop-sridhar That's unfortunate. ILMerge/ILRepack is great for library developers to avoid the diamond dependency problem.

There are plans to support it in .NET Core 3.0 - @richlander can update you on status.
It's been mentioned in .NET Core 3.0 blog posts - e.g. here: https://devblogs.microsoft.com/dotnet/net-core-3-and-support-for-windows-desktop-applications/ in "Side-by-side and App-local Deployment" section.
Also read: https://www.hanselman.com/blog/BrainstormingCreatingASmallSingleSelfcontainedExecutableOutOfANETCoreApplication.aspx

.net shouldn't need all these hacks to produce small single self-contained executable.. it should be default behavior, you get eaten alive by GO, Rust is coming too, focus on CoreRT or ILMerge, .net core apps are already too long to start because of all the files to load, don't add more overheard to this with zip/unzip like mentioned in the proposal, this is not the way to go

.net shouldn't need all these hacks to produce small single self-contained executable.. it should be default behavior, you get eaten alive by GO, Rust is coming too, focus on CoreRT or ILMerge, .net core apps are already too long to start because of all the files to load, don't add more overheard to this with zip/unzip like mentioned in the proposal, this is not the way to go

As you like .net shouldn't need alive,because ppl has java.
go or rust or dlang shouldn't support build target to Single executable program,because they have the Fuck Zip/Unzip !

@RUSshy

.net shouldn't need all these hacks to produce small single self-contained executable

Agreed. At the same time, .NET provides certain features over other languages that are challenging to reconcile with the requirements of a static linker (for example, on the fly code generation, reflection, data binding etc). We've experimented with excluding these features in scenarios where single file / static linking is important. We've learned from customer feedback that the result of this doesn't feel like .NET anymore, partially because the number of libraries you can consume from ecosystem drastically drops.

So doing a linker properly that doesn't compromise on the fidelity of the features that we've all taken a dependency and love in .NET, is a hard problem. As part of solving this, we're experimenting with various approaches. You call this hacks, I call this open minded and willing to think outside the box. But just blindly turning .NET into Go/Rust/C++ isn't the right answer.

We've experimented with excluding these features in scenarios where single file / static linking is important. We've learned from customer feedback that the result of this doesn't feel like .NET anymore, partially because the number of libraries you can consume from ecosystem drastically drops.

Have the team thought about creating a separate version of .net focused for native development and constrained environments, like jetbrains did with kotlin JVM / kotlin NATIVE ?

As you said trying to make .net fit into every use cases isn't the smartest option so a specific flavor might be the right answer to this problem

And tbh, afaik, this problem didn't really exists before .net core since every windows install had already .net framework, so you only had to distribute your few KBs exe, and what annoys me is nobody seems to have thought about this kind of issue when designing .net core which was basically a rewrite of .net framework.. this is why i'm saying these options mentioned are plain hacks, they are here to fix design mistakes

After reading https://github.com/dotnet/designs/blob/master/accepted/single-file/staging.md there seems to be more steps for the proposal, and it doesn't end at zip/unzip so that's not a lost fight, hopefully the team will be able to come with something lighter, which is mentioned in that document, good!

Things like this are why Windows remains a toy OS.

@kjkrum Things like what?

@cryru it’s what people say when they don’t know what they’re doing.

@Cryru Things like not being able to build a standalone executable, and the oblivious dismissal of the very real need to do so. Pretty much every other build system in existence will not only build a statically linked executable, it will strip unused parts of dependencies. Stripping dependencies has been a standard feature for at least a decade; static linking since the invention of compliers.

@Cryru Things like not being able to build a standalone executable, and the oblivious dismissal of the very real need to do so. Pretty much every other build system in existence will not only build a statically linked executable, it will strip unused parts of dependencies. Stripping dependencies has been a standard feature for at least a decade; static linking since the invention of compliers.

Agree,This is actually related to the position of C # programs in the operating system.
C# programs always cant became the a First-class citizen.
Only to be the Second-class.

This is resolved.
TLDR: dotnet publish -r win10-x64 /p:PublishSingleFile=true

Details:
https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-core-3-0#single-file-executables
https://github.com/dotnet/designs/blob/master/accepted/single-file/design.md

This is resolved.
TLDR: dotnet publish -r win10-x64 /p:PublishSingleFile=true

Details:
https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-core-3-0#single-file-executables
https://github.com/dotnet/designs/blob/master/accepted/single-file/design.md

In which version of dotnet-core was this feature added? I am using 3.0.100-preview5-011568and got this error:
error MSB4030: "/p:PublishSingleFile=true" is an invalid value for the "SelfContained" parameter of the "ResolveFrameworkReferences" task. The "SelfContained" parameter is of type "System.Boolean".

LE: Actually it is working, it seems only there is a syntax error in the https://github.com/dotnet/designs/blob/master/accepted/single-file/design.md which states publishing with dotnet publish -r win10-x64 --self-contained /p:PublishSingleFile=true and actually is without adding --self-contained.

Thanks @mihaimyh I'll fix the typo in the design doc.

im always against using zip/unzip solution for Single exe self contained feature.
because this will cause the next issue.
How to reduce the Single exe file size !

In fact, from the outset should use IL-Merge similar ways.

There shouldn't be a debate, this is time waste, nobody asked for zip/unzip the whole thing, and yet they came with this design and wasted their time and ours

People ask for single executable and AOT, stop waste our time Microsoft

I explicitly want single-file without AOT. I prefer the ability to JIT so that I can use reflection, generics, and runtime-generated code.

i guess MS don't want to hear, ok

im always against using zip/unzip solution for Single exe self contained feature.
because this will cause the next issue.
How to reduce the Single exe file size !

Not sure I understand, as if its Zipped its already compressed. Or are you meaning reduction of redundant dependencies and therefore reduced size before compression?

Not understanding the negativity. Ive not used it yet other than quick test. But seems the single executable works well for the situation deploying an app to client, or as a CLI tool. Which is where I believe this feature is useful. Outside of that, in Dev or other environment I dont see a use case for it, so what they have done works fine as a solution for now..

@RUSshy

i guess MS don't want to hear, ok

On the contrary, they are asking for and collecting a wide range of use cases which you can see in related threads. Your opinion is important, but the opinions of others in the community are just as important and you should not be mocking Microsoft for listening to them.

Based on your statement I think you might have mistaken me for Microsoft. I'm just a community member like yourself who does not speak for Microsoft in any capacity.

im always against using zip/unzip solution for Single exe self contained feature.
because this will cause the next issue.
How to reduce the Single exe file size !

Not sure I understand, as if its Zipped its already compressed. Or are you meaning reduction of redundant dependencies and therefore reduced size before compression?

if u use WebApi or MVC or ConsoleApp write an HelloWorld! ur well know what my mean.
the packed file is too large.its bring too much code but never will be execute.
if IL-Merge ways will Reduce unused code branch.

Yes sure I did a console HelloWorld and yes sure its 68K
Capture
The none self contained was 67K
But its C# not assembly. If I wanted a <1K HelloWorld then why use c#?
Larger apps use more of the framework, so at a point its more custom code than framework..
Are we really worried about a few 100K? If so, dont use a framework and spend the time writing everything from scratch??
What am I missing here?

im always against using zip/unzip solution for Single exe self contained feature.
because this will cause the next issue.
How to reduce the Single exe file size !
if u use WebApi or MVC or ConsoleApp write an HelloWorld! ur well know what my mean.
the packed file is too large.its bring too much code but never will be execute.
if IL-Merge ways will Reduce unused code branch.

@sgf there are two somewhat separate issues here:

  • How to reduce the code for an app?
  • How to package the app into a single file?

For code-reduction, there are further several techniques

  • Merging IL: This is not for all apps, because it loses assembly identity in the process. This is not a goal for the current single-exe work.
  • Trimming unused IL: The ILLinker aims to trim unused IL. This feature is integrated into the dotnet SDK (PublishTrimmed property), and more optimizations in the ILLinker are under development.
  • Zip/Unzip: dotnet publish doesn't currently zip the published single file, but it can be done.

How to package the app into a single file?
dotnet publish supports publishing into a single file -- the published file will be as big as the app would otherwise be.

Regarding the generating native code:

  • Currently the support for generating native code is through ready-to-run compiler (PublishReadyToRun property).
  • Publishing via AOT compilation is great (CoreRT), but it is not available yet. With AOT compilation too, the size of the executable depends on the compilation options: ex: do we include the jit for executing generated code, etc.?

Yes sure I did a console HelloWorld and yes sure its 68K
Capture
The none self contained was 67K
But its C# not assembly. If I wanted a <1K HelloWorld then why use c#?
Larger apps use more of the framework, so at a point its more custom code than framework..
Are we really worried about a few 100K? If so, dont use a framework and spend the time writing everything from scratch??
What am I missing here?

sorry as ur img shown,with self contianed.Thats 68626KB,its about 68mb=68KK,not only 68K!!!
we wont need <1kb (With self contianed That's impossible),<3000KB is ok,accept.
But 68mb is more 30X+
U wont always just write a HelloWorld Program !!!

Apologies, late at night mistake with the K's
Thanks for the added explanation/info swaroop-sridhar, some new switches there I was not aware of.
Just tried with 3.preview 6 with the following switches

dotnet publish -r RID /p:PublishTrimmed=true /p:PublishSingleFile=true
and now down to 29,000K

Sure not all apps will be Hello World, but for a C# Core SelfContained App, that also contains the runtime... Personally Im not to worried. Sure I understand if your writing a tiny console tool it would be nice to have it 3K. But why use C# for that in the first place?
Interesting discussion though guys!

image
Capture

30mb LOL, call me when it'll be something like 1-3mb, runtime is full of bloat, check GO, people migrate in wave

https://www.jetbrains.com/lp/devecosystem-2019/

Even kotlin starts to gain shares, and with kotlin native it put c# to shame

And Swift is comming to windows https://forums.swift.org/t/swift-win32-programming/20686

So here some suggestions:

  • Add option to remove Reflection
  • Add option to remove JIT stuff
  • Better optimize C# code so you don't rely on JIT

30mb LOL, call me when it'll be something like 1-3mb, runtime is full of bloat, check GO, people migrate in wave

https://www.jetbrains.com/lp/devecosystem-2019/

Even kotlin starts to gain shares, and with kotlin native it put c# to shame

And Swift is comming to windows https://forums.swift.org/t/swift-win32-programming/20686

So here some suggestions:

  • Add option to remove Reflection
  • Add option to remove JIT stuff
  • Better optimize C# code so you don't rely on JIT

I think this is not fair. .NET was not designed for building the smallest single file console applications. We use it for Asp.Net websites and apis. Therefore, the framework itself brings a ton of features with it in addition to tons of nuget packages that you can include. I can't imagine that there is a concern if an web application is 50 or several hundreds of megabytes in size. The primary concern is speed, memory usage and in the long term maintainability. Who cares about the size on the server.

If your only intention is to built small single mb size console application, why not use the right tool for the job. Instead of complaining that an application with a full featured framework packed into a single file is several tens of megabyte in size even for a "hallo world", why not go with Rust for example?

Microsoft is doing a great job with .NET since its beginning and even more in the last couple of years, so thank you for that.

What to reply to such non sense, lies and lack of sense of efficiency ?

You fail to realize how wrong .net core direction was, and only just recently they started to realize it by working on Distribution/IL Merge/AOT

And now to move on the web-assembly wagon they can't because .net runtime is such a HUGE bloat that they are unable to deploy decent sized files

And you still stuck with "Who cares about the size on the server.", this way of thinking is what made the "supposed to be modern" .net core into an already outdated and irrelevant tech stack

Microsoft is not doing great job with .net, they failed because they wanted to please old people for .net framework compatibility, it was one of their mistake

Sorry if i sound rude but sometimes you need to be to make changes

Sorry if i sound rude but

You sound rude, period. That, and your dismissals and jumping to conclusions, do not have the effect of being persuasive.

Apologies, late at night mistake with the K's
Thanks for the added explanation/info swaroop-sridhar, some new switches there I was not aware of.
Just tried with 3.preview 6 with the following switches

dotnet publish -r RID /p:PublishTrimmed=true /p:PublishSingleFile=true
and now down to 29,000K

Sure not all apps will be Hello World, but for a C# Core SelfContained App, that also contains the runtime... Personally Im not to worried. Sure I understand if your writing a tiny console tool it would be nice to have it 3K. But why use C# for that in the first place?
Interesting discussion though guys!

image
Capture

don't as a modern language should have a little ambition to unify the world?
Do you want all developers writing c# back home for C++? or push them to Go,Kotlin,Swift ?
Market share and further erode c#?

.Net because does not implement cross-platform missed the first 15+ years of the great development opportunity.
But Now .net is back to right Way.

Yeah as I commented before Im not sure why the negativity.
.Net Core has been nothing but fantastic if you are coming from Full Framework. And the .Net Standard +Core amalgamation vision I think is sensible and progressive.

Comparing .NET to GO or any other language/framework is pointless.
Anyway, Im OUT on this topic, as I think the solution they are working on and improving for Single .exe has resolved my 'ask' from several years back quite well... Good enough for me, and suits my immediate needs.

So thanks Guys & Gals!

OUT

I would like to remind everyone on this thread about Code of Conduct.

It is ok to disagree or have different opinion, but please, let's be civil and let's express that as technical discussion. No need to use strong words.
Also, targeting ideas, implementations with your opinions is fair game. HOWEVER, it is NOT ACCEPTABLE to attack PEOPLE behind them. Please let's all be respectful to each other, let's hear different opinions and let's refrain from strong statements and offensive comments.

Also, I wold like to ask everyone to be open to other view points and opinions. Before making judgements, it is typically good to hear out the other side -- there is often a story behind why things are the way they are. Poking at ideas and solutions when one knows why they are the way they are is typically more productive.

Thank you!

im always against using zip/unzip solution for Single exe self contained feature.
because this will cause the next issue.
How to reduce the Single exe file size !
if u use WebApi or MVC or ConsoleApp write an HelloWorld! ur well know what my mean.
the packed file is too large.its bring too much code but never will be execute.
if IL-Merge ways will Reduce unused code branch.

@sgf there are two somewhat separate issues here:

  • How to reduce the code for an app?
  • How to package the app into a single file?

For code-reduction, there are further several techniques

  • Merging IL: This is not for all apps, because it loses assembly identity in the process. This is not a goal for the current single-exe work.
  • Trimming unused IL: The ILLinker aims to trim unused IL. This feature is integrated into the dotnet SDK (PublishTrimmed property), and more optimizations in the ILLinker are under development.
  • Zip/Unzip: dotnet publish doesn't currently zip the published single file, but it can be done.

How to package the app into a single file?
dotnet publish supports publishing into a single file -- the published file will be as big as the app would otherwise be.

Regarding the generating native code:

  • Currently the support for generating native code is through ready-to-run compiler (PublishReadyToRun property).
  • Publishing via AOT compilation is great (CoreRT), but it is not available yet. With AOT compilation too, the size of the executable depends on the compilation options: ex: do we include the jit for executing generated code, etc.?

As required dynamic merge native-DLLs to One name likes: XXX.exe (UnManaged).
Using static analysis to analysis when compile the nativeDLLs(UnManaged) Function-Level Linking.

api-ms-win-core-console-l1-1-0.dll
api-ms-win-core-datetime-l1-1-0.dll
api-ms-win-core-debug-l1-1-0.dll
api-ms-win-core-errorhandling-l1-1-0.dll
api-ms-win-core-file-l1-1-0.dll
api-ms-win-core-file-l1-2-0.dll
api-ms-win-core-file-l2-1-0.dll
api-ms-win-core-handle-l1-1-0.dll
api-ms-win-core-heap-l1-1-0.dll
api-ms-win-core-interlocked-l1-1-0.dll
api-ms-win-core-libraryloader-l1-1-0.dll
api-ms-win-core-localization-l1-2-0.dll
api-ms-win-core-memory-l1-1-0.dll
api-ms-win-core-namedpipe-l1-1-0.dll
api-ms-win-core-processenvironment-l1-1-0.dll
api-ms-win-core-processthreads-l1-1-0.dll
api-ms-win-core-processthreads-l1-1-1.dll
api-ms-win-core-profile-l1-1-0.dll
api-ms-win-core-rtlsupport-l1-1-0.dll
api-ms-win-core-string-l1-1-0.dll
api-ms-win-core-synch-l1-1-0.dll
api-ms-win-core-synch-l1-2-0.dll
api-ms-win-core-sysinfo-l1-1-0.dll
api-ms-win-core-timezone-l1-1-0.dll
api-ms-win-core-util-l1-1-0.dll
api-ms-win-crt-conio-l1-1-0.dll
api-ms-win-crt-convert-l1-1-0.dll
api-ms-win-crt-environment-l1-1-0.dll
api-ms-win-crt-filesystem-l1-1-0.dll
api-ms-win-crt-heap-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
api-ms-win-crt-math-l1-1-0.dll
api-ms-win-crt-multibyte-l1-1-0.dll
api-ms-win-crt-private-l1-1-0.dll
api-ms-win-crt-process-l1-1-0.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-string-l1-1-0.dll
api-ms-win-crt-time-l1-1-0.dll
api-ms-win-crt-utility-l1-1-0.dll
aspnetcorev2_inprocess.dll
clrcompression.dll
clretwrc.dll
clrjit.dll
coreclr.dll
dbgshim.dll
dotnet-aspnet-codegenerator-design.dll
hostfxr.dll
hostpolicy.dll
mscordaccore_amd64_amd64_4.6.27317.07.dll
mscordbi.dll
mscorrc.dll
mscorrc.debug.dll
sni.dll
sos.dll
sos_amd64_amd64_4.6.27317.07.dll
ucrtbase.dll
...etc...

if do good job the result maybe be willl 2-3mb. when im direct packed all of them with 7zip,its take about 4.85mb.Now we get XXX.exe

develop the similar Function-Level Link with IL-merge.
For a managed DLL same old trick again.
At Last embed managed DLL as the PE.exe Sections(mark as .net section).

For reflect,analysis DLL of the reflection type. Retain metadata and type of reflection ( including function ) and all of its tree - dependent.

I apologize, I don't want to take the more time to participate in the discussion about this any more.Opinions cannot be unified.
At first I had expected the result. But now,I should probably consider other programming languages to fulfill my needs(maybe Dlang maybe Go maybe Kotlin maybe Nim or maybe Rust is the best).

thanks for all talk this with me. sorry for my nagging. out

@sgf I think you made some good points and I know you've signed off on the topic. Just wanted to say that I believe the features you are asking for, will be coming over the next couple of years to .NET Core. In fact if you wanted to get small file size today, it may be possible if you target mono.

  1. Mono already supports AOT compilation with Linking to reduce file size. This is one reason why mono was chosen for the browser .net runtime implementation. https://www.mono-project.com/docs/advanced/aot/ and I assume it's why Blazor projects can have a Linker.

  2. Microsoft have declared that they want to cosolidate their .NET runtimes into one "all powerful" one. Rather than have mono for some things, and .NET Core for others, they want a single runtime that can deliver on all scenarios. This defacto means it will need to support AOT and Linking / Code stripping etc. Therefore I expect over the next few years, either the .NET Core runtime to get these features, or for Mono and .NET Core features to be consolidated into a new Runtime.

If anyone knows better, please inform me.

+2¢

I think the problem is it seems decisions are being made without much information. These days everywhere I look people are talking about this; the vast majority of people deploying programs have this on top of their wish list, and many are moving away from C# to other languages with better AOT/deployability. I think that's a pretty established fact which becomes very evident if you're active in the community. Yet it doesn't seem to be affecting the decisions in the slightest.

The thing is, it seems nobody knows exactly to what extent this is important. To me personally it's extremely important, so of course I'm very biased but the impression I have is that overall this is of prime importance and it seem MS just isn't giving it the attention it deserves, leaving a lot of us the impression they're taking uniformed decisions what in turn doesn't make us confident about the future of the technology as a whole.

I agree with @RUSshy. CoreRT is an incredible project and definitely going in the right direction, but overall it seems all efforts are focused on server/web technologies. Things like runtimes, jits and large binaries speak for themselves in that regard. Nobody deploying software want those things.

That being said I'm personally still using the tech although I'm not really holding me breath about its future in some areas.

I would like to see more participation from the community in the direction being taken, even if it turns out it's the opposite of what I'm personally expecting. But so far it seems decisions are being made without taking that into account. It seems server/web is what makes money and people deploying programs are a negligible minority (at least in terms of profits), but if that's the case I'd at least want to know that's what they're basing their decisions on (which is very likely), because from the outside it looks like they're flipping a coin.

@Alan-FGR

But so far it seems decisions are being made without taking that into account.

Do you have specific examples of such decisions to share, as I'd be curious to learn more.

I think MS are very aware of the shortcomings of the current dotnet core runtime and that's why they will seek feature parity with mono runtime in the future.

Just look at the release notes for .net core 3.0.0 preview 6:

Today, we are announcing .NET Core 3.0 Preview 6. It includes updates for compiling assemblies for improved startup, optimizing applications for size with linker and EventPipe improvements. We’ve also released new Docker images for Alpine on ARM64.

It looks like to me they are very aware that application size is important for certain scenarios - especially now with Blazor in the mix.

@Alan-FGR Agreed, the web focus is rather strange considering that IIS has about 8% market share and falling. ASP.NET is irrelevant, and no improvement to C# or its standard libraries is ever going to change that. C# is being sustained by console apps, Windows services, mobile apps, and PC games. It owes its continued existence to Unity and Xamarin. Which is a shame, because C# is a really enjoyable language to develop in. That's high praise coming from a long time Java developer who still thinks Microsoft left its high water mark with Windows XP.

As required dynamic merge native-DLLs to One name likes: XXX.exe (UnManaged).
Using static analysis to analysis when compile the nativeDLLs(UnManaged) Function-Level Linking.

I'm not sure what you mean by dynamic merge, but there is a plan to statically link the native components together with the host. Please see this section.

develop the similar Function-Level Link with IL-merge.
For reflect,analysis DLL of the reflection type. Retain metadata and type of reflection ( including function ) and all of its tree - dependent.

We've discussed the option of merging assemblies into one, and having side meta-data tables to support dynamic features. It does provide considerable size-savings. But the cost of implementing it is quite high -- because of the new meta-data support, and the changes required in debuggers/profilers etc to handle it.

There are a few other options to reduce the binary size -- for example, when we're able to execute a single-file directly (without having to extract to files), we can drop the signature/certificates on each DLL in favor of signing the app as a whole. This can save a few MBs sometimes.

But so far it seems decisions are being made without taking that into account.

Do you have specific examples of such decisions to share, as I'd be curious to learn more.

I think MS are very aware of the shortcomings of the current dotnet core runtime and that's why they will seek feature parity with mono runtime in the future.

@dazinator I think the very fact that MS somehow thinks Mono is a decent solution for anything goes to show that they really don't know their products. I've used Mono, and while it's an important piece of tech and helped popularize .NET immensely, it's definitely lacking some quality... Xamarin did some great marketing work promoting their tech, but it was based on over-promising and under-delivering, and it seems that whoever is taking those decisions at MS just saw some of their promo material and never really used the tech. CoreRT on the other hand is a technology that so far has greatly over-delivered for me. It's on another level of quality in my opinion, and yet it's being neglected by MS in favor of some tech that I suspect is held together with duck tape.

Agreed, the web focus is rather strange considering that IIS has about 8% market share and falling. ASP.NET is irrelevant, and no improvement to C# or its standard libraries is ever going to change that. C# is being sustained by console apps, Windows services, mobile apps, and PC games.

@kjkrum that's the point. However, maybe for them 8% market share on the web is still much more important than the Windows and mobile apps. Good web techs at very least help Windows server sales, so their interest on that is quite obvious, but focusing so much on it is also a very shallow strategy and I refuse to believe that's what drives their decisions. MS seemed to be going the right direction with the dotnet foundation and so many promising projects going on, but it seems they're letting the opportunity to have a dominant tech pass by.

I know this is anecdotal so probably meaningless, but all the people I know who were using C# for their projects (mostly game dev) moved into something else because of limitations that were totally solvable. They moved to Rust, D, Go, and C++. I myself use C++ on a regular basis and I'm learning Rust, but I'm still using C# for some personal projects because it's so much better, even though deploying a quality product is a pain in the rear.

It owes its continued existence to Unity and Xamarin.

Yes, what's a blessing and a curse because of the many technical problems. Unity for example has a very bad reputation but luckily that didn't seem to affect .NET/C#.
XNA however, although far from perfect still has an incredibly great reputation among users and developers.

Happy to see this land with .NET Core 3.0 today. Thanks folks! 👍

I'm not sure that is what people want, if we end up with simple calculator that is 141mb exe, then the feature is a failure (and i believe the real cost is 141mb * 2, since it's gonna extract stuff somewhere right)

image

Yes, it's definitely what I want. It's still smaller than a regular self-contained deployment.

More aggressive assembly trimming and tree-shaking would be welcome, but this is a very useful start. Incremental improvement is the smartest way to deliver value.

Oh this is what you want? my bad, i didn't know bloated application was popular

A calculator doesn't need JIT, not even Reflection, but since that's what you want, i guess i am in the wrong since the beginning, i should stop programming

@RUSshy It's no more bloated than any other self-contained deployment, right?

Removing JIT and reflection is independent from whether everything is packed into a single exe. I.e. you can remove JIT and reflection without single-exe, and you can have single-exe without removing JIT and reflection. They are separate pieces of work.

I'm not sure that is what people want, if we end up with simple calculator that is 141mb exe, then the feature is a failure (and i believe the real cost is 141mb * 2, since it's gonna extract stuff somewhere right)

its extract the files in to C:Users[YourUserName]AppDataLocalTemp.net

Is there any way to override where single exe will be unpacked?
I ran into problem when it try to extract into /var/.... where user have no permissions to write.

@eiva which OS was this? Was it AWS lambda?
https://github.com/dotnet/core-setup/issues/7940 tracks fixing this issue.

In the meantime, you can set the DOTNET_BUNDLE_EXTRACT_BASE_DIR environment variable to control where the bundled files are extracted.

@swaroop-sridhar Thanks for the reply!
It is centos.7 launching app from the "restricted" service account.

@jnm2 I appreciate that you love C#, I do too. But lets be honest, it's insanity that a calculator is 128 megabytes.

@TechnikEmpire I feel it necessary to point out that that "I love C#" is a pretty intensive reduction of what I said above :D

I'm personally not going to feel entirely satisfied until I have the ability to do tree-shaking of my own code and libs, referenced third party libs, and .NET itself. But that doesn't make the single-exe feature any less valuable to me today. It's a step along one dimension. Tree-shaking is an independent dimension and one that I hope gets a lot of attention.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jzabroski picture jzabroski  ·  3Comments

chunseoklee picture chunseoklee  ·  3Comments

EgorBo picture EgorBo  ·  3Comments

btecu picture btecu  ·  3Comments

jamesqo picture jamesqo  ·  3Comments