Skip to content

Commit

Permalink
[scrape.yml] New OCaml Planet blog posts and videos (#2924)
Browse files Browse the repository at this point in the history
Co-authored-by: cuihtlauac <[email protected]>
  • Loading branch information
github-actions[bot] and cuihtlauac authored Jan 16, 2025
1 parent a720577 commit 81ffda1
Showing 1 changed file with 30 additions and 0 deletions.
30 changes: 30 additions & 0 deletions data/planet/tarides/using-clang-cl-with-ocaml-5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: Using `clang-cl` With OCaml 5
description: Antonin shares his findings from building OCaml 5 with Clang-cl during
the MSVC port restoration project, part of the effort to improve OCaml on Windows!
url: https://tarides.com/blog/2025-01-15-using-clang-cl-with-ocaml-5
date: 2025-01-15T00:00:00-00:00
preview_image: https://tarides.com/blog/images/clang-cl-1360w.webp
authors:
- Tarides
source:
---

<p>Bringing new features to OCaml is not a trivial procedure, and any new contribution is subject to rigorous testing and inspection. The introduction of <a href="https://tarides.com/blog/2023-07-07-making-ocaml-5-succeed-for-developers-and-organisations/">Multicore OCaml</a> added a whole new dimension of complexity to the process, and this post takes you behind-the-scenes of a project that sprang from troubleshooting the restoration of MSVC to OCaml 5.</p>
<h2>Motivation</h2>
<p><a href="https://tarides.com/blog/2025-01-09-ocaml-5-3-features-and-fixes/">OCaml 5.3 is released</a> and comes with a restored <a href="https://learn.microsoft.com/en-us/cpp/?view=msvc-170">MSVC</a> (Microsoft Visual C/C++ compiler) port. It had been removed with the introduction of the multicore runtime in OCaml 5.0. The <a href="https://github.com/ocaml/ocaml/pull/12954">Restore the MSVC port of OCaml #12954</a> PR lists all the prerequisite changes, and the final streak of changes, required to restore support.</p>
<p>The OCaml 5 runtime requires <a href="https://en.cppreference.com/w/c/atomic">C11 atomic</a> support from the C compiler, which for MSVC was introduced in <a href="https://devblogs.microsoft.com/cppblog/c11-atomics-in-visual-studio-2022-version-17-5-preview-2/">Visual Studio 2022 version 17.5 Preview 2</a>. This early version had a few bugs during code generation and we were wondering if they would impact the OCaml runtime (fortunately, they did not). While the Microsoft team worked hard to fix the bugs, we learned about <a href="https://clang.llvm.org/docs/UsersManual.html#clang-cl"><code>clang-cl</code></a>, a driver program for Clang that attempts to be compatible with MSVC's <code>cl.exe</code>. It is ABI-compatible with MSVC, implements all MSVC compiler extensions, and is also a drop-in command-line replacement for <code>cl.exe</code>.</p>
<p>I wanted to try building OCaml with <code>clang-cl</code>, mostly because it would get us a second compiler's opinion on our code, as Clang has a different set of warnings and hints than MSVC. Seeing that <code>clang-cl</code> was already <a href="https://blog.llvm.org/2018/03/clang-is-now-used-to-build-chrome-for.html">used to build Chrome</a> and Firefox (<a href="https://blog.mozilla.org/nfroyd/2018/05/29/when-implementation-monoculture-right-thing/">1</a>, <a href="https://blog.mozilla.org/nfroyd/2019/04/25/an-unexpected-benefit-of-standardizing-on-clang-cl/">2</a>), I was hoping the needs of the OCaml runtime would have already been covered and bugs fixed, and that we could adopt it seamlessly.</p>
<p>The OCaml 5 runtime uses the POSIX threads (pthreads) library on Unix-like systems for all its concurrency primitives. For the OCaml 5.3 branch we've chosen to use the <code>winpthreads</code> library, part of the MinGW-w64 project, which implements <code>pthreads</code> on Windows. The OCaml 5 MinGW-w64 port uses it, and we found out we could use it with MSVC too. I then submitted two patch series to <code>winpthreads</code> (<a href="https://sourceforge.net/p/mingw-w64/mailman/mingw-w64-public/thread/[email protected]/#msg58709057">Patches and cleanups towards MSVC support</a>, <a href="https://sourceforge.net/p/mingw-w64/mailman/mingw-w64-public/thread/[email protected]/#msg58729186">MSVC support without GCC extensions</a>), checking my work with MinGW-w64+GCC, MinGW-w64+clang, MSVC, and <code>clang-cl</code>, foreshadowing their use within the OCaml runtime. What an adventure! And thanks to the MinGW-w64 team for reviewing this work.</p>
<h2>Using <code>clang-cl</code></h2>
<p>Clang on Unix-like systems masquerades as GCC, supports all GNU C extensions and defines the <code>__GNUC__</code> macro. On Windows, it masquerades as MSVC and defines the <code>_MSC_VER</code> macro instead, but <em>still</em> supports the GNU C extensions that we can take advantage of!</p>
<p>The build system only required <a href="https://github.com/ocaml/ocaml/pull/13093">a few changes</a>. For instance, MSVC currently defaults to C99 and needs two flags to switch to C11 and enable experimental C11 atomic support, whereas <code>clang-cl</code> defaults to C17. We also <a href="https://lists.gnu.org/archive/html/autoconf/2024-04/msg00000.html">discussed</a> how to improve the support of MSVC in Autoconf, which led to a few patches. We could then use <code>clang-cl</code> to discover new problems reported by the warnings it raised and fix them. In conjunction with this work, I raised the warning level of MSVC on the OCaml runtime C code from none to <code>-W2</code>.</p>
<p>Fortunately, most of the warnings were quite minor (see <a href="https://github.com/ocaml/ocaml/pull/13081">#13081</a> and <a href="https://github.com/ocaml/ocaml/pull/13243">#13243</a>), mainly consisting of warnings for deprecated functions or implicit truncations when converting integers or floating points values of different sizes. Switching to newer compilers also allowed us to remove dead code and workarounds for older versions of the compilers.</p>
<p>I found out that most of the uses of compiler <a href="https://clang.llvm.org/docs/AttributeReference.html">attributes</a> or <a href="https://clang.llvm.org/docs/LanguageExtensions.html#id33">builtins</a> were guarded by the <code>__GNUC__</code> macro, and as such were only enabled by GCC or Clang on Unix, even though <code>clang-cl</code> on Windows supports them too. Compiler attributes may enable more checks and warnings from the compiler. For instance, the <a href="https://clang.llvm.org/docs/AttributeReference.html#format"><code>format</code></a> attribute tags a function to be <code>printf</code>-like and checks the types of the list of values passed to it against the specifiers inside a format string. Compiler builtins may enable more optimisations, such as <a href="https://clang.llvm.org/docs/LanguageExtensions.html#builtin-expect"><code>__builtin_expect</code></a>. So, instead of <em>guarding</em> their use, we could <em>discover</em> whether the compiler provides them using newer macros such as <code>__has_attribute</code> or <code>__has_builtin</code>. This improved <a href="https://github.com/ocaml/ocaml/pull/13280">feature parity</a> between the <code>clang-cl</code> port and an OCaml build using GCC or Clang.</p>
<p>In particular, we could <a href="https://github.com/ocaml/ocaml/pull/13239">detect the labels as values</a> (also known as <em>computed gotos</em>) compiler extension to enable threaded code interpretation, which dramatically improves the speed of <code>ocamlc</code>, the OCaml bytecode interpreter. This optimisation isn't supported by MSVC and would require us to use inline assembly on x86 or write part of the bytecode interpreter in assembly on other architectures. If you're often using the bytecode interpreter, there's now a clear advantage of using <code>clang-cl</code> over MSVC. Another interesting optimisation uses <a href="https://github.com/ocaml/ocaml/pull/13238">software prefetching</a> to speed up the GC when traversing the graph of values. We had worked on <a href="https://github.com/ocaml/ocaml/pull/11827">restoring it in OCaml 5</a> from <a href="https://github.com/ocaml/ocaml/pull/10195">OCaml 4</a> but forgot to port it to Windows!</p>
<p>The overall work on restoring the MSVC port of OCaml and also building it with <code>clang-cl</code> led to a few bug reports to Microsoft and to the <a href="https://github.com/llvm/llvm-project/issues?q=is:issue%20author:MisterDA">LLVM project</a>, which I hope will benefit the community. The OCaml project now has an extra set of compiler eyes that scrutinise each and every change on Windows. Windows users may now take advantage of a (compliant) C11 and C23 FOSS compiler, with a wide range of optimisations and checks available.</p>
<p>I'm grateful to my colleagues at Tarides for helping me with this work, the OCaml core team for reviewing it, and Jane Street for sponsoring this effort.</p>
<h2>Try it Out and Stay in Touch!</h2>
<p>With the release of <a href="https://opam.ocaml.org/blog/opam-2-2-0/"><code>opam</code> 2.2</a> (now 2.3) supporting Windows, the restoration of the Cygwin port in OCaml 5.1, the MSVC port in OCaml 5.3, and the option to build OCaml with <code>clang-cl</code>, and the swarm of bug fixes that accompanied them, using OCaml on Windows has never been easier! Give it a whirl!</p>
<p>Connect with Tarides online on <a href="https://bsky.app/profile/tarides.com">Bluesky</a>, <a href="https://twitter.com/tarides_">X</a>, <a href="https://mastodon.social/@tarides">Mastodon</a>, <a href="https://www.threads.net/@taridesltd">Threads</a>, and <a href="https://www.linkedin.com/company/tarides">LinkedIn</a> or sign up for our mailing list to stay updated on our latest projects.</p>

0 comments on commit 81ffda1

Please sign in to comment.