Thicket data repository for the EEG
at main 4.4 kB view raw
1{ 2 "id": "https://www.tunbury.org/2025/06/17/static-linking", 3 "title": "Static linking in OCaml", 4 "link": "https://www.tunbury.org/2025/06/17/static-linking/", 5 "updated": "2025-06-17T00:00:00", 6 "published": "2025-06-17T00:00:00", 7 "summary": "Most of the time, you don’t think about how your file is linked. We’ve come to love dynamically linked files with their small file sizes and reduced memory requirements, but there are times when the convenience of a single binary download from a GitHub release page is really what you need.", 8 "content": "<p>Most of the time, you don’t think about how your file is linked. We’ve come to love dynamically linked files with their small file sizes and reduced memory requirements, but there are times when the convenience of a single binary download from a GitHub release page is really what you need.</p>\n\n<p>To do this in OCaml, we need to add <code>-ccopt -static</code> to the <code>ocamlopt</code>. I’m building with <code>dune</code>, so I can configure that in my <code>dune</code> file using a <code>flags</code> directive.</p>\n\n<div><div><pre><code>(flags (:standard -ccopt -static))\n</code></pre></div></div>\n\n<p>This can be extended for maximum compatibility by additionally adding <code>-ccopt -march=x86-64</code>, which ensures the generated code will run on any x86_64 processor and will not use newer instruction set extensions like SSE3, AVX, etc.</p>\n\n<p>So what about Windows? The Mingw tool chain accepts <code>-static</code>. Including <code>(flags (:standard -ccopt \"-link -Wl,-static -v\"))</code> got my options applied to my <code>dune</code> build:</p>\n\n<div><div><pre><code>x86_64-w64-mingw32-gcc -mconsole -L. -I\"C:/Users/Administrator/my-app/_opam/lib/ocaml\" -I\"C:\\Users\\Administrator\\my-app\\_opam\\lib\\mccs\" -I\"C:\\Users\\Administrator\\my-app\\_opam\\lib\\mccs\\glpk/internal\" -I\"C:\\Users\\Administrator\\my-app\\_opam\\lib\\opam-core\" -I\"C:\\Users\\Administrator\\my-app\\_opam\\lib\\sha\" -I\"C:/Users/Administrator/my-app/_opam/lib/ocaml\\flexdll\" -L\"C:/Users/Administrator/my-app/_opam/lib/ocaml\" -L\"C:\\Users\\Administrator\\my-app\\_opam\\lib\\mccs\" -L\"C:\\Users\\Administrator\\my-app\\_opam\\lib\\mccs\\glpk/internal\" -L\"C:\\Users\\Administrator\\my-app\\_opam\\lib\\opam-core\" -L\"C:\\Users\\Administrator\\my-app\\_opam\\lib\\sha\" -L\"C:/Users/Administrator/my-app/_opam/lib/ocaml\\flexdll\" -o \"bin/main.exe\" \"C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\2\\build_d62d04_dune\\dyndllb7e0e8.o\" \"@C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\2\\build_d62d04_dune\\camlrespec7816\" \"-municode\" \"-Wl,-static\"\n</code></pre></div></div>\n\n<p>However, <code>ldd</code> showed that this wasn’t working:</p>\n\n<div><div><pre><code>$ ldd main.exe | grep mingw\n libstdc++-6.dll =&gt; /mingw64/bin/libstdc++-6.dll (0x7ffabf3e0000)\n libgcc_s_seh-1.dll =&gt; /mingw64/bin/libgcc_s_seh-1.dll (0x7ffac3130000)\n libwinpthread-1.dll =&gt; /mingw64/bin/libwinpthread-1.dll (0x7ffac4b40000)\n</code></pre></div></div>\n\n<p>I tried <em>a lot</em> of different variations. I asked Claude… then I asked <a href=\"https://www.dra27.uk/blog/\">@dra27</a> who recalled @kit-ty-kate working on this for opam. <a href=\"https://github.com/ocaml/opam/pull/5680\">PR#5680</a></p>\n\n<p>The issue is the auto-response file, which precedes my static option. We can remove that by adding <code>-noautolink</code>, but now we must do all the work by hand and build a massive command line.</p>\n\n<div><div><pre><code>(executable\n (public_name main)\n (name main)\n (flags (:standard -noautolink -cclib -lunixnat -cclib -lmccs_stubs -cclib -lmccs_glpk_stubs -cclib -lsha_stubs -cclib -lopam_core_stubs -cclib -l:libstdc++.a -cclib -l:libpthread.a -cclib -Wl,-static -cclib -ladvapi32 -cclib -lgdi32 -cclib -luser32 -cclib -lshell32 -cclib -lole32 -cclib -luuid -cclib -luserenv -cclib -lwindowsapp))\n (libraries opam-client))\n</code></pre></div></div>\n\n<p>It works, but it’s not for the faint-hearted.</p>\n\n<p>I additionally added <code>(enabled_if (= %{os_type} Win32))</code> to my rule so it only runs on Windows.</p>", 9 "content_type": "html", 10 "author": { 11 "name": "Mark Elvers", 12 "email": "mark.elvers@tunbury.org", 13 "uri": null 14 }, 15 "categories": [ 16 "OCaml", 17 "tunbury.org" 18 ], 19 "source": "https://www.tunbury.org/atom.xml" 20}