Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
Add rpath-like $ORIGIN support to compiler flags embedded in cma/cmxa #6642
Original bug ID: 6642
Let me begin with a motivating example. A typical native application consists of a bunch of executables and a bunch of shared libraries that can depend on each other. If you invoke an executable, the dynamic linker would normally only look into the default system paths like /lib, /usr/lib, etc. However, what if you want to make an application that doesn't care where it is installed?
Enter -rpath. -rpath instructs ld to embed a special string in the ELF executable or shared object that provides additional paths to the dynamic linker, a lá LD_LIBRARY_PATH (but it's not global or as fragile). What's more, it also replaces $ORIGIN in these paths with the path to the ELF file itself, allowing the application to be fully relocatable.
OCaml currently has something that's very similar to -rpath--it allows to embed compiler flags (and dllpaths) in the cma/cmxa. However, those paths must be absolute. I propose to make the frontend expand $CAMLORIGIN with the name of cma/cmxa file that is being linked together, so that a cma file in .../lib/ocaml could pass the -L.../lib flag to the linker.
This would greatly help the LLVM OCaml bindings, which currently have to rely on odd hacks, and I imagine there would be other uses as well.
Comment author: @damiendoligez
I see 3 problems with this patch:
I'm not convinced Buffer.add_substitute is the right tool for this job: not only it forces to add a layer of quoting for just one variable, but its quoting conventions are not surjective.
It looks like the $CAMLORIGIN notation only ever makes sense at the beginning of the string anyway, so why not search and replace it with simple substring manipulations?
Comment author: @gasche
I think you should use Misc.search_substring to implement replace_origin (that would both make the code simpler and make it work for usages that are not at the beginning), and this suggests adding a Misc.replace_substring function to factorize usage -- note that it ought to replace all occurences of the substring, not only the first.
I find it problematic that the Changes entry mentions "$(CAMLORIGIN)" while only "$CAMLORIGIN" works according to the implementation.
Comment author: @gasche
The replace function of the current patch is rather terrible for any usage other than $CAMLORIGIN (in particular it loops when replacing "a" with "a"). I think I'll push the patch in both 4.02 and trunk, but with a more sensible implementation, such as:
let replace_substring ~pat ~sub str =