4

By binary I mean both bytecode and native code.

I've built a program that only depends on the Standard Library, using ocamlbuild with a minimal set of flags:

ocamlbuild -I … -use-ocamlfind -libs str program.byte

It runs OK. Just for info, I use OCaml 4.02.1, Mac OS X Mountain Lion.

With ocamlobjinfo program.byte I get an overview of its contents:

…
Imported units:
        9c1885d2c36e2eb94f56f21da9040d87 UnixLabels
        30a4cc8e5f4f902ea609c91caec48af7 Unix
        0ce699458ce4430954d7e6a78874647c Sys
…
        8988208489274193e4e3f69dc6ec2f75 MyModule1
        4164567363e873f17809de38a8c5f09e MyModule2
…
Used DLLs:
        dllcamlstr
        dllunix
Primitives used:
        re_string_match
        re_partial_match
…

1) My understanding is, program.byte embeds my entire bytecode. I guess it embeds the entire bytecode of the Standard Library's modules that I use, but does it?

I assume ocamlrun loads the 2 dynamically loaded libraries at run-time and by so-doing it's able to find the primitives; they are required by the Standard library.

I think a bytecode executable can't run without ocamlrun so I don't understand why OCaml would embed parts of the Standard Library in my program, as opposed to packaging them with ocamlrun instead.

Especially since the bytecode appears to be incompatible between OCaml versions. I mean, I can't build with v4.01 then run with v4.02 or vice versa, anyway.

From the technical standpoint, I'm curious but I can live with that so long as the bytecode is portable across Unices. From the legal standpoint, though, that leaves me with concerns about the distribution of a bytecode executable that embeds parts licensed under the LGPL. That's probably why additional exceptions are applied to the OCaml Library.

2) The second part of my question is, what are the binary dependencies for ocamlrun at run-time? Whereas bytecode portability would be great for distribution, that incompatibity thing between versions defeats the purpose. After an OCaml upgrade, how would you manage to still run bytecode programs of various OCaml versions?

I tried in a simplistic fashion to keep a copy of ocamlrun, whose version is the same as the ocamlc that built a bytecode executable. Then run this executable with this ocamlrun on a machine for which an older implementation of OCaml had been installed. As expected, that failed miserably.

Bonus question) I don't have a Windows build machine. My program performs system calls that don't exist in Windows; it was built on Mac, yet works fine on Linux as-is. Assuming there are no 32bit/64bit problems, would it likely run on Cygwin in practice?

I was unable to find information by googling all that, so I appreciate even a pointer to an up-to-date description.

Cheers!

EDIT: I'm trying to find out if source recompilation can be avoided. Use case:

  • I provide a bytecode executable B
  • I can tell users: "So you won't be using OCaml version x.y.z anymore in six months/a couple of years? Well, don't worry, by keeping a copy of those binaries from the x.y.z distribution, and by following these steps, you can still run B without breaking everything else.

I have B but I don't know anything about those binaries and these steps. As much as possible I'd rather not go framework, and keep it simple for the users.

I'm already aware of the OCaml Binary Compatibility issues with Windows, but since Cygwin does a great job at providing a POSIX abstraction layer, I wonder if someone has had success in running a bytecode executable that utilizes POSIX-specific system features of the Unix, Sys etc. modules (e.g. signals; otherwise for Windows only sigkill is emulated). I'm not speaking of cross compilation for MinGW etc, but of dynamically linking with the Cygwin DLL - as in, using the Cygwin console.

eruve
  • 661
  • 5
  • 12

1 Answers1

2

1) Yes, cmos of the used modules are linked with your bytecode program.

Yes, C libraries for primitives are linked dynamically.

Bytecode should be portable for any ocamlrun of the same version: thanks to this, OCaml's initial boot compiler boot/ocamlc is distributed as a bytecode.

You can link ocamlrun with your bytecode explicitly with -custom option, but ocamlrun is about a half mb and attaching it to each bytecode executable is waste.

I think your guess about OCaml's linking exception of LGPL is correct.

2) As I stated, bytecode portability is assured only for the same version of the runtime. If we upgrade OCaml version, we simply recompile everything. In some minor upgrades, old bytecodes may work in the new ocamlrun since the bytecode was not changed in the upgrade... But it is just by luck and you should never rely on it. BTW, OPAM permit you to have more than one OCaml systems and you may want to use it if you want to keep older bytecode programs.

Bonus question) It depends. For example, boot/ocamlc, the initial boot compiler for OCaml, works on all the systems. But if your bytecode relys on OS specific external primitives, it wont work on the other systems. For example, Unix has different sets of C primitives in Unix and Windows therefore bytecode programs linked with Unix does not work both on Unix and Windows normally.

camlspotter
  • 8,990
  • 23
  • 27
  • Thanks for confirming my concerns :p I've edited my question. I don't know if the bytecode executable is still portable after adding `-lflag -custom`, but on my end there's still something missing: the program doesn't run elsewhere. – eruve May 06 '15 at 12:08