Comment by rwmj
15 days ago
This is quite timely as we need to write a simple UI for Windows (a few buttons, status, maybe a file menu). The main constraint is it must compile to a single binary (.exe) with no dependencies such as runtimes, DLLs, languages etc. It also needs to run on some older unsupported Windows systems, probably Windows >= 7, 32 bit.
My first thought was MFC. Basic, fast, well understood.
But then maybe WxWindows so we can cross-compile it (from Linux) and use the same UI on other platforms? It could probably be compiled statically although I've not tested it.
Or Mono, but that needs a runtime?
Edit: Some comments mention Qt which could also work although how large is the runtime? Can it be compiled statically?
Pure Win32 will do exactly what you want. Single tiny .exe that works from Win95 to 11. Even Linux with WINE.
Get started learning here: https://news.ycombinator.com/item?id=21459616
Qt is compiled to a native .exe. It doesn't have a runtime. To give you a rough idea of size, I have 3 GUI application written using Qt/C++. The installers are 72 MB, 69 MB and 32 MB. The first 2 include a significant amount of documentation. I could probably get them a bit smaller if I really needed to.
Delphi or Lazarus (https://www.lazarus-ide.org) should solve it.
Nice, I didn't know there was a free software version of Delphi nowadays.
If you mean Delphi Community, it has some restrictions, but probably 99% works?
If you mean Lazarus, it is fully open source. No restrictions but the ones of the software itself.
With restrictions of course.
1 reply →
For what you describe, .NET + WinForms or WPF will work just fine. These days it can built self-contained executables, although they won't be small (but then again, when many websites have multiple megabytes of JS...). Or you can target .NET 4.8 - for something this simple I doubt there'd be much difference but then you can ship an .exe that measures in kilobytes, and the runtime is included with every version of Windows going back 10 years.
You can build single-file executables for .NET 4, and I do, but there's no static linking, so you need to restrict yourself to assemblies that ship with the framework and whatever other prerequisites you're willing to install or assume will be installed.
Two notable caveats:
1. Certain newer C# language features require runtime support that doesn't ship with older versions of .NET, which can include quite a few DLLs.
2. In-process COM components can only be instantiated in .NET runtimes runtimes with the same processor architecture, even if the .NET program itself is processor-independent (which by default will use the runtime matching the native architecture), so you may need to ship multiple executables to match multiple COM dependency versions even if your program is otherwise processor-independent or you only intend to ship it for a single processor architecture.
For example, if you build a processor-independent program that relies on the Microsoft Access DAO library, it will by default work correctly on 32-bit Windows if 32-bit Access is installed, and on 64-bit Windows if 64-bit Access is installed, but there's no way to get it to work on 64-bit Windows with 32-bit Access without shipping a second executable (that can be identical with the exception of the 32BITREQUIRED flag in the CLR header[1] that can be set as part of the build process or with the .NET SDK corflags utility).
Rather than ship separate "32-bit (or 64-bit with 32-bit <bar>" and "64-bit" versions of a program <foo> that interops with some in-proc COM component <bar>, I prefer to build a single executable <foo>.exe, then create a copy <foo>32.exe with the flag set as part of the build process, and ship both to be installed side-by-side.
Then, since the native COM DLL isn't loaded until you actually create an interop object referencing it, you can just try to create an Interop.<Bar>.<something> object at program start, catch ComException with HResult == REGDB_E_CLASSNOTREG, then in the exception handler, run <foo>32.exe as a subprocess with identical command-line arguments and exit with <foo>32's exit code, unless you're already running in a 32-bit CLR, in which case you just fail normally.
[1] https://ecma-international.org/wp-content/uploads/ECMA-335_5...
> but there's no static linking
Not out of the box, but there are ways to do it, e.g. ILMerge.
> so you may need to ship multiple executables
OP's baseline is native code tho, so they are already planning to do that.
> Edit: Some comments mention Qt which could also work although how large is the runtime? Can it be compiled statically?
You need a commercial license for that, but yes you could. But since applications are typically distributed with install bundles that put into application-local program files directories, it's not super-important as long as you only cherry-pick the Qt libraries you need.
This is wrong. There's a misconception that you can't statically link your app when using the open-source LGPL version of Qt. From my reading of the LGPL license this doesn't appear to be the case[1]. The LGPL allows you to statically link your app as long as you provide the object files and allow users to relink your app with a different version of Qt.
I've observed many people spreading this misinformation about only being able to dynamically link with the LGPL version of Qt. Please stop this.
[1] https://www.gnu.org/licenses/gpl-faq.html#LGPLStaticVsDynami...
Yes, that is true, but in practice nobody has ever done that. And the material complexity of offering that mode is higher than just dynamically linking the library.
Also, modern compilers make this method much harder to use. It is much harder to stably relink object files like that than to just use the normal dynamic link method.
.net will work. Use a weaver (fody) or the modern features to roll everything into 1 .exe.
Use self-contained to have everything together.
https://learn.microsoft.com/en-us/dotnet/core/deploying/sing...
For such a trivial thing I'd just take imgui.
MFC, wx, Qt .. it's all overcomplex pointless bloat for this task imo.