How viable is delivering binaries linked to Cygwin to Windows customers?

I’m in the early stages of planning a deliverable binary product that will run on Linux, Mac and Windows.

My brief sniff of the air around the OCaml ecosystem says I should expect to target Cygwin to get Windows going (although there’s impressive work to get native Windows stuff done that can become the preferred approach in a few years).

My experience using Cygwin as an operating environment is that it’s pretty darn sluggish compared to Linux on the same computer.

Why is this? There’s an anecdote that says Cygwin can only fork at about 30-50x a second on Windows, due to how it has to adapt it to work within Windows’ task spawning model. (For contrast, Linux can achieve thousands of forks per second if you play around with it).

I understand from another product developer that when they build binaries to deliver to Windows/Cygwin, they actually cross-compile on Linux because of how slowly the toolchain runs on Cygwin.

That sounds like bad news if you want to do UNIXy things, but for a single standalone application this might not be so bad? I assume if I ship a deliverable to Windows/Cygwin, the end user may enjoy good performance, so long as I’m not spawning tons of processes or relying on fork for multi-programming. Is this a safe assumptions?

Any other gotchas when it comes to OCaml on Cygwin w.r.t. performance?

The app pretty much has real-time gaming requirements (though it’s not a game so can side-step worrying about access to GPUs and what-not). Stated another way, although my application will depend on the POSIX layer offered by Cygwin, I expect it not to crunch POSIX related stuff in the main loop.

How has your experience gone?

Maybe some Lexifi folks will tell. I think they have the most experience in OCaml on MS Windows.

I heard that nowadays, it is possible to install a full Linux distro on Windows.
So, depending on the end users, maybe it is OK to not directly target windows nowadays.
But maybe I am just dreaming. :slight_smile:

If I understand correctly, your app needs access to POSIX layer stuff, which is the reason it can’t be a native Windows binary?

To look at this another way, how would you solve this in another language? Say, you decided to use C. What would be the solution to accessing POSIX layer functionality?

WSL2 is not reliable enough for relying on it for shipping the end product.

Since you care about performance, I would advise to use Rust for that, which also has a WAY better Windows end user support.

Windows support is a recurrent question/complaint (including myself), and there is a lot of improvements on that, but not 100% polished yet:

We are building an OCaml application on Linux and Windows, and on Mac until recently (we have given up on Mac for non-Ocaml reasons). We use cygwin only for building our application, but the resulting binary is completely native and customers don’t need cygwin to run it. So I think your assumption that cygwin is needed isn’t true, though it’s more work to get everything working, especially if you have many dependencies.

1 Like

@mbacarella remember that on the Windows native port, the Unix module distributed with OCaml is your POSIX compatibility layer. There are a few entry points to avoid though, the list is at the bottom of this page.

3 Likes

At LexiFi our main application is developed and shipped on Windows. We use the msvc port of OCaml. This means that you need Cygwin to develop, but the resulting application is fully native and does not depend on the Cygwin DLL. As @dbuenzli mentioned, the Unix module is the POSIX compatibility layer.

Compilation speed is slower on Windows because process creation is slower on Windows as a general rule, but it is manageable (our application has around 2000 modules + Js_of_ocaml + C bindings + C# component).

We don’t have any issues with runtime performance. The Unix library mentioned above implements Windows support directly without going through any compatibility layer and is quite efficient.

Cheers!

2 Likes

Also, we try to avoid having too many dependencies on third-party OCaml libraries but we do have some and we simply vendor them directly in our source tree (we don’t use ocamlfind nor OPAM).

There is an editor being built in ocaml/reasonml which currently targets windows, linux and macos - https://github.com/onivim/oni2. However, the binary is native windows rather than cygwin derivative. So if you don’t have to use cygwin dependencies then native windows binary could be the way to go.

Also esy - https://github.com/esy/esy makes developing ocaml/reasonml on windows viable.

Perhaps, esy - https://github.com/esy/esy could be viable as it allows you to use opam in windows already.

I have been shipping commercial binaries for Linux (32 and 64 bit), Windows (32 and 64bit) and OS X for years. For example:

And even static or shared libraries in binary form:

On OS X, you need to use MACOSX_DEPLOYMENT_TARGET or similar to make sure your builds will run on older systems. And, in fact, you need to use MACOSX_DEPLOYMENT_TARGET when asking OPAM to compile the OCaml compiler itself. And, you will need to deal with codesigning and notarization. But it’s all doable.

For linux, you may need to build under older linux versions, to make sure that the glibc in use is old enough. This is not an ocaml-specific problem. I have a 64 bit and 32 bit VM with old-ish glibc versions for this purpose.

Under Windows, there are no such backward-compatibility problems. I use the new OCaml for windows system, which comes with OPAM, and is mingw-based. No cygwin remains in the final binary.

For more obscure systems (AIX, HPUX, Sparc etc) customers compile from source (with help from me). Not once in more than ten years has anyone cared that it was written in OCaml.

5 Likes

TLDR: Install the Mingw port of OCaml, freely use most opam libraries, and compile to native Windows binaries, without licensing issues.


I recommend you read the “Release notes for Windows”:

To summarise, there are three Windows ports:

  • Native Microsoft port,
  • Native Mingw port,
  • Cygwin port.

All three require Cygwin for development purposes. I recommend using the Native Mingw, as:

To contrast, Native Microsoft requires Visual Studio, and doesn’t have opam. You can still vendor pure OCaml packages, but as soon as you want to use some C bindings you’re in trouble, because of the “minor” differences between Visual C and GCC. And everything assumes GCC nowadays.

Cygwin port is the one I don’t have experience with, but re-reading the “Release notes for Windows” above it strikes me that it mentions that Cygwin was re-licensed from GPL to LGPL with static linking exception. So it looks like the Cygwin port could be viable for commercial use, but I never tried to statically linked cygwin.dll, and I’m not sure what are the benefits of Cygwin port over the Mingw port.

2 Likes

With soupault, I decided to ship prebuilt binaries for all platforms including Windows. Mostly to see if I can, all its users I know of are on UNIX-like systems and know how to build from source, but that’s beside the point. :wink:

I can confirm everything @keleshev says: fdopen’s package just works, opam works exactly like it does on UNIX, pure OCaml libraries are trivial to install, and the binaries don’t depend on cygwin.
Note that “opam switch create” also just works, you can install either MinGW or MSVC compiler versions as opam switches.
I only ever start the Windows VM to make release builds, and the workflow is exactly the same as on Linux where I’m actually writing code.

My only obstacle on that path was that FileUtils lost its Windows compatibility, but I wanted to use it, so I worked with @gildor478 to make it cross-platform again. Uncovered a bug in the implementation of Unix.utimes in the process, but it’s hardly a commonly used function.

You can also setup AppVeyor builds. It’s not as simple as I wish it would be, but there are projects doing it that you can steal the setup from.

There’s also opam-cross-windows, but it’s very incomplete and needs work to be practical. There are no big obstacles, it just needs work. While files in opam-repository-mingw are normally identical to the default opam repository, the cross one needs small adjustments in every package to specify the toolchain to use, so the required work is mostly a lot of trivial but manual actions. I hope eventually it reaches parity with fdopen’s one and we’ll be able to easily build for Windows without ever touching Windows.

As of static Linux builds, @JohnWhitington’s approach can work, but there’s a better option if you don’t need anything from glibc specifically and don’t link against any C libs: build statically with musl. There’s a +musl+static+flambda compiler flavour. You need musl and gcc-musl to install it, but after that, just build with -ccopt -static flag and you get a binary that doesn’t depend on anything.

1 Like

AFAIK, not a whole Visual Studio required, but just a library plus the build tools - see their Visual Studio C++ Build Tools. After decades of negligence Microsoft finally realized most of the people care about the compiler and not the gigabytes of dreaded VS itself. With a rise of clang-cl (MSVC-compatible frontend of Clang), even the compiler is not necessary anymore. Nowadays clang-cl quality is so good that it builds Google Chrome and Mozila Firefox for Windows. Other projects, like LibreOffice also consider the switch. And it comes with a whole variety of sanitizers - ASAN, UBSAN, TSAN, etc. The day when we can put MSVC in the grave where it rightfully belongs is close.

2 Likes

What makes cygwin a dependency for developing on windows? (And has anyone had success using WSL instead?)