Is there a recommended way (or example) to build a simple binary distribution of an OCaml project using the GitHub CI? I am mostly interested in building the executables and packaging them in some archive format and make that available for download for different architectures.
I have such a workflow for one of my project, see this workflow file. It automatically triggers on new releases, builds the project with the appropriate compiler (e.g.
flambda), and uploads the built artefact to the release page where it can be downloaded. It currently works for both linux and mac (last time I tried it with windows I got some errors and I haven’t yet had the time to look into that, so i don’t know if the errors were caused by the workflow, or my project).
That was a weird coincidence that I released a GitHub workflow [ANN] setup-dkml.yml GitHub Actions workflow for distributing binaries for this today. @zozozo’s solution is simpler if it works for your intended target audience.
I did the same for my little project bob but it provides a Cosmopolitan binary which should run anywhere, see the workflow and the last uploaded artifact .
Do you know what the Cosmopolitan story is for signing binaries for Windows and macOS? That is, when you sign the binary does it destroy the magic byte arrangement that Cosmopolitan relies on? The only thing I can see is help with 'macOS cannot verify that this app is free from malware' · Issue #147 · jart/cosmopolitan · GitHub which wasn’t terribly encouraging. (Of course not every use case is going to require signing the binary directly; sometimes you can embed an unsigned binary in a signed installer and that will be sufficient)
I don’t want to speak on behalf of Justine, but as far as I can know, there is no plan to provide, in the same time, a polyglot and signed executable for Windows/MacOS.
From my opinion and my goal about
bob, I don’t really want to go on this path (specially when I don’t want to provide an installer) when I mostly focused on portability on the easiest way possible. Reproducible build of
bob will be the next goal from the robur.io / @hannes’s work - so even if we can not sign the application, it gives a new argument to trust the final binary.
I should make clear that I do not want (nor think it possible) to get a multiple party signed, crossplatform universal binary.
I’m interested in Cosmopolitan not for its crossplatform universal binary but for its crossplatform universal build process.
My thinking is:
- Generate a crossplatform executable once with Cosmopolitan. Call that “A”
- Sign A for Apple. Call that “B”
- Sign A for Microsoft. Call that “C”
Distribute A, B, and C to your end users. For security auditing only A needs to be reproducible.
Explicit assumption: End users have enough self awareness to know if they are using a Mac (B), Windows (C) or some other operating system (A).
The above works only if B is still a valid Mach-O binary that behaves identically after signing. And C is still a valid PE executable that behaves identically after signing. I can open an issue.
Hmmhmm, I think it’s wrong to believe that cosmopolitan provides an “universal build process”. I mean, currently, it deeply trusts on the GNU linker to be able to craft a polyglot binary.Then, at the beginning of a Cosmopolitan program, a piece of code (see ape) is able to recognize the platform where the program is running and it injects several values (“constants” and so functions) to provide then a POSIX API which dispatches well to the real syscall.
Two solutions exists then:
- the APE code will writing the program itself (the real term is “assimilate”) to correspond exactly to what the platform (Windows, MacOS, Linux or BSD) provides - that mostly means that after the first run, the program become not polyglot anymore
- the second solution is to still keep the program as a polyglot one but the program provides an
--assimilateoption which does what I explained above
For the signing part, I think, as you said, it can be possible to do something after you produced your A but I’m not an expert at this stage and I’m deeply focus to provide a Cosmopolitan/OCaml cross-compiler first - but if you are interested, you should take a look on Esperanto and propose something on top of that, I will be happy to participate and integrate it
My feeling is that the Linux part of a reusable release workflow should use the musl variant by default and force static linking, but provide an option to disable it for those who want to make dynamically linked executables.
If a project doesn’t rely on non-OCaml libraries other than libc, there’s no reason to prevent people from running it on, say, older CentOS, by linking it against the glibc of ubuntu-latest. If it does, then there’s no way to distribute it as a single binary anyway.