CINXE.COM
Bootstrapping a Project 路 OCaml Documentation
<!DOCTYPE html> <html lang="en"> <head id="htmx-head"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content="How to set up a project with Dune "> <meta name="twitter:title" content="Bootstrapping a Project 路 OCaml Documentation"> <meta name="twitter:description" content="How to set up a project with Dune "> <meta name="twitter:image" content="https://ocaml.org/_/MWIyY2ZmMWM5YzdkYWNmYWI4NGQ0MDBjOGFiZTYxOTg/ocaml_org_social_media.png"> <meta property="og:site_name" content="OCaml"> <meta property="og:type" content="object"> <meta property="og:title" content="Bootstrapping a Project 路 OCaml Documentation"> <meta property="og:description" content="How to set up a project with Dune "> <meta name="og:image" content="https://ocaml.org/_/MWIyY2ZmMWM5YzdkYWNmYWI4NGQ0MDBjOGFiZTYxOTg/ocaml_org_social_media.png"> <meta name="theme-color" content="#fff" > <meta name="color-scheme" content="white"> <meta name="ahrefs-site-verification" content="6ff715b377cdcd566334b44ae8888791189ce24640c8a403eacdc3bcbaa9449b"> <link rel="canonical" href="https://ocaml.org/docs/bootstrapping-a-dune-project"> <link rel="icon" type="image/x-icon" href="/_/ZDJmMjgzN2NkZmJlMzgxNGQxMTMxNGVlMzk1NzZkN2I/favicon.ico"> <link rel="manifest" href="/manifest.json"> <link rel="stylesheet" href="/_/M2QzNTJkMGFlMzUxZDFkZDE4MDdjYzljNThkN2U1YjQ/css/main.css"> <link rel="stylesheet" href="/_/NmFjYjY5ZmIxYWRhMWQxMTQxODM4ZDEwYTgwMDcwNmI/vendors/font-files/inter.css"> <link rel="stylesheet" href="/_/YjM3OGY4YzIwN2E2ZmUxZTczOWVkNDQwZWRhMDU0MGM/vendors/font-files/roboto-mono.css"> <script defer src="/_/OWYyZDQyZjg4MTFlNWEzZjE4ZGY0YWM0OTU1NGEzYTI/vendors/alpine-clipboard.js"></script> <script defer src="/_/NGI1NjQzZjdkODY0MTY2MmViNThhM2VlZTYwMDk3NTI/vendors/alpine.min.js"></script> <script defer src="/_/YTNhODI2Yzg0Yzk4M2ZiNDcxYmRiYzdhY2FiN2Y0OWQ/vendors/htmx.min.js"></script> <script defer data-domain="ocaml.org" src="https://plausible.ci.dev/js/script.js"></script> <link rel="search" href="/opensearch.xml" type="application/opensearchdescription+xml" title="OCaml"> <title>Bootstrapping a Project 路 OCaml Documentation</title> </head> <body> <script> if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)) { document.body.classList.add("dark"); } else { document.body.classList.remove("dark"); } </script> <header class="h-20 flex items-center bg-sand dark:bg-dark-background_navigation" x-data="{ open: false }"> <nav class="container-fluid wide header flex justify-between items-center gap-5 xl:gap-8"> <ul class="order-0 space space-x-5 xl:space-x-8 items-center flex text-content font-medium dark:text-title dark:text-opacity-60 dark:font-semibold"> <li style="width:132px"> <a href="/" class="block pb-2"> <img src="/_/MDBjN2M4YjIxY2Y1YWExZWE3Njk4M2FiZTg1NWZjNTM/logo-with-name.svg" width="132" alt="OCaml logo" class="dark:hidden"> <img src="/_/MTE3YWE5YzJlZmExNmYyMmI3ZmEwYjliMDEwNDBkMDY/logo-with-name-white.svg" width="132" alt="OCaml logo" class="hidden dark:inline"> </a> </li> </ul> <ul class="order-2 hidden lg:flex items-center"> <li> <form x-data="{ row: null, col: 0, max: 0, total: 0 }" @submit="if (row !== null) { window.location = document.getElementById('package-autocomplete-'+row+'-'+col).getAttribute('href'); $event.stopPropagation(); $event.preventDefault(); return false }" action="/packages/search" method="GET"> <div class="dropdown-container flex items-center justify-center h-10 rounded-md focus-within:outline-primary_25 dark:focus-within:outline-dark-primary_40 focus-within:outline focus-within:outline-2 lg:w-56 xl:w-80" tabindex="0"> <label for="q" class="sr-only">Search OCaml packages</label> <input type="search" name="q" placeholder="Search OCaml packages" @keydown.escape="$event.target.blur()" class="bg-white dark:bg-dark-card text-title dark:text-dark-title h-full w-full font-normal focus:border-primary dark:focus:border-dark-primary focus:ring-0 border-primary dark:border-dark-primary rounded-md rounded-r-none px-3 py-1 placeholder-text-content dark:placeholder:text-dark-content appearance-none focus:outline-none" @keydown.stop @keyup.down="if (row === null) { row = 0; col = 0; } else { row +=1; if (row > max) { row = max } }" @keyup.up="if (row !== null) { row -=1; if (row < 0) { row = null } }" @keyup.right="if (col < 1) col++" @keyup.left="if (col >= 1) col--" :aria-activedescendant="row !== null ? 'package-autocomplete-'+row+'-'+col : null" hx-get="/packages/autocomplete" hx-params="q" hx-trigger="keyup changed, search" hx-target="#header-search-results" hx-indicator="#header-search-indicator" autocomplete="off" > <button aria-label="search" class="h-full flex items-center justify-center rounded-r-md bg-primary dark:bg-dark-primary text-white dark:text-dark-white px-4" type="submit" ><svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /> </svg> </button> <div class="dropdown w-full lg:w-[32rem] xl:w-[32rem] z-10 absolute rounded-md mt-12 shadow-2xl top-1 p-2 bg-background dark:bg-dark-background shadow-3xl dark:outline dark:outline-1 dark:outline-primary"> <div id="header-search-results" aria-live="polite"></div> <a class="flex py-2 px-2 mx-2 gap-4 hover:bg-primary_nav_block_hover_10 dark:hover:bg-dark-primary_nav_block_hover_10 font-normal rounded-md text-primary dark:text-dark-primary" href="/api"> Standard Library API <svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path> </svg> </a> </div> </div> </form> </li> </ul> <ul class="order-1 mr-auto items-center hidden lg:flex font-medium dark:text-white dark:text-opacity-60 dark:font-semibold"> <li><a href="/docs" class="block font-normal py-3 mg:py-4 px-1 lg:px-3 hover:text-primary dark:hover:text-dark-primary text-primary dark:text-dark-primary underline">Learn</a> </li> <li><a href="/tools" class="block font-normal py-3 mg:py-4 px-1 lg:px-3 hover:text-primary dark:hover:text-dark-primary text-title dark:text-dark-title">Tools</a> </li> <li><a href="/packages" class="block font-normal py-3 mg:py-4 px-1 lg:px-3 hover:text-primary dark:hover:text-dark-primary text-title dark:text-dark-title">Packages</a> </li> <li><a href="/community" class="block font-normal py-3 mg:py-4 px-1 lg:px-3 hover:text-primary dark:hover:text-dark-primary text-title dark:text-dark-title">Community</a> </li> <li><a href="/changelog" class="block font-normal py-3 mg:py-4 px-1 lg:px-3 hover:text-primary dark:hover:text-dark-primary text-title dark:text-dark-title">News</a> </li> <li><a href="/play" class="block font-normal py-3 mg:py-4 px-1 lg:px-3 hover:text-primary dark:hover:text-dark-primary text-title dark:text-dark-title">Play</a> </li> </ul> <ul class="order-3 hidden lg:flex items-center"> <li><a href="/docs/get-started" class="border border-primary dark:border-dark-primary text-primary dark:text-dark-primary font-bold py-2.5 px-7 whitespace-nowrap rounded">Get Started</a></li> </ul> <ul class="order-1 lg:hidden flex items-center"> <li class="h-12 w-12 hover:bg-primary_25 dark:hover:bg-primary_20 flex items-center justify-center rounded-full text-content dark:text-dark-title"> <button aria-label="open menu" @click="open = ! open"> <svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h16M4 18h16" /> </svg> </button> </li> </ul> </nav> <div class="bg-black fixed w-full h-full left-0 top-0 opacity-60 z-40" x-show='open' x-cloak></div> <nav class="z-50 h-full fixed right-0 top-0 max-w-full w-96 bg-background dark:bg-dark-background shadow-lg" x-show="open" x-cloak @click.away="open = false" x-transition:enter="transition duration-200 ease-out" x-transition:enter-start="translate-x-full" x-transition:leave="transition duration-100 ease-in" x-transition:leave-end="translate-x-full"> <ul class="text-content p-6 font-semibold"> <li class="flex justify-between items-center"> <a href="/"> <img src="/_/MDBjN2M4YjIxY2Y1YWExZWE3Njk4M2FiZTg1NWZjNTM/logo-with-name.svg" width="132" alt="OCaml logo" class="dark:hidden"> <img src="/_/MTE3YWE5YzJlZmExNmYyMmI3ZmEwYjliMDEwNDBkMDY/logo-with-name-white.svg" width="132" alt="OCaml logo" class="hidden dark:inline"> </a> <div class="" x-on:click="open = false"> <button aria-label="close" class="text-content dark:text-dark-title"> <svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> </svg> </button> </div> </li> <li class="mt-6 mb-3"> <form action="/packages/search" method="GET"> <div class="dropdown-container flex items-center justify-center h-10 rounded-md focus-within:outline-primary_25 dark:focus-within:outline-dark-primary_40 focus-within:outline focus-within:outline-2 " tabindex="0"> <label for="q" class="sr-only">Search OCaml packages</label> <input type="search" name="q" placeholder="Search OCaml packages" @keydown.escape="$event.target.blur()" class="bg-white dark:bg-dark-card text-title dark:text-dark-title h-full w-full font-normal focus:border-primary dark:focus:border-dark-primary focus:ring-0 border-primary dark:border-dark-primary rounded-md rounded-r-none px-3 py-1 placeholder-text-content dark:placeholder:text-dark-content appearance-none focus:outline-none" > <button aria-label="search" class="h-full flex items-center justify-center rounded-r-md bg-primary dark:bg-dark-primary text-white dark:text-dark-white px-4" type="submit" ><svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /> </svg> </button> </div> </form> </li> <li><a href="/docs" class="block font-normal py-3 mg:py-4 px-1 lg:px-3 hover:text-primary dark:hover:text-dark-primaryblock text-primary dark:text-dark-primary underline">Learn</a> </li> <li><a href="/tools" class="block font-normal py-3 mg:py-4 px-1 lg:px-3 hover:text-primary dark:hover:text-dark-primaryblock text-title dark:text-dark-title">Tools</a> </li> <li><a href="/packages" class="block font-normal py-3 mg:py-4 px-1 lg:px-3 hover:text-primary dark:hover:text-dark-primaryblock text-title dark:text-dark-title">Packages</a> </li> <li><a href="/community" class="block font-normal py-3 mg:py-4 px-1 lg:px-3 hover:text-primary dark:hover:text-dark-primaryblock text-title dark:text-dark-title">Community</a> </li> <li><a href="/changelog" class="block font-normal py-3 mg:py-4 px-1 lg:px-3 hover:text-primary dark:hover:text-dark-primaryblock text-title dark:text-dark-title">News</a> </li> <li><a href="/play" class="block font-normal py-3 mg:py-4 px-1 lg:px-3 hover:text-primary dark:hover:text-dark-primaryblock text-title dark:text-dark-title">Play</a> </li> <li> <a href="/api" class="flex py-3 px-1 gap-4 font-semibold text-primary dark:text-dark-primary">Standard Library API<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path> </svg> </a> </li> <li class="mt-3 mb-6"> <a href="/docs/get-started" class="w-full rounded font-normal py-3 px-7 flex items-center justify-center bg-primary dark:bg-dark-primary text-white dark:text-dark-title">Get started</a> </li> <li> <div class="space-x-6 text-2xl flex items-center"> <a aria-label="OCaml's Discord" href="https://discord.gg/cCYQbqN" class="opacity-60 hover:opacity-100 text-content dark:text-dark-title hover:text-primary dark:hover:text-dark-primary"> <svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"> <path fill-rule="evenodd" d="M18.9419 5.29661C17.6473 4.69088 16.263 4.25066 14.8157 4C14.638 4.32134 14.4304 4.75355 14.2872 5.09738C12.7487 4.86601 11.2245 4.86601 9.7143 5.09738C9.57116 4.75355 9.3588 4.32134 9.17947 4C7.73067 4.25066 6.3448 4.6925 5.05016 5.29982C2.43887 9.24582 1.73099 13.0938 2.08493 16.8872C3.81688 18.1805 5.49534 18.9662 7.14548 19.4804C7.55291 18.9196 7.91628 18.3235 8.22931 17.6953C7.63313 17.4688 7.06211 17.1892 6.52256 16.8647C6.6657 16.7586 6.80571 16.6478 6.94098 16.5337C10.2318 18.0729 13.8074 18.0729 17.0589 16.5337C17.1958 16.6478 17.3358 16.7586 17.4774 16.8647C16.9362 17.1908 16.3637 17.4704 15.7675 17.697C16.0805 18.3235 16.4423 18.9212 16.8513 19.4819C18.503 18.9678 20.183 18.1822 21.915 16.8872C22.3303 12.4897 21.2056 8.67705 18.9419 5.29661ZM8.67765 14.5543C7.68977 14.5543 6.87963 13.632 6.87963 12.509C6.87963 11.3859 7.67247 10.4621 8.67765 10.4621C9.68285 10.4621 10.493 11.3843 10.4757 12.509C10.4772 13.632 9.68285 14.5543 8.67765 14.5543ZM15.3223 14.5543C14.3344 14.5543 13.5243 13.632 13.5243 12.509C13.5243 11.3859 14.3171 10.4621 15.3223 10.4621C16.3275 10.4621 17.1376 11.3843 17.1203 12.509C17.1203 13.632 16.3275 14.5543 15.3223 14.5543Z" clip-rule="evenodd" /> </svg> </a> <a aria-label="The OCaml Compiler on GitHub" href="https://github.com/ocaml/ocaml" class="opacity-60 hover:opacity-100 text-content dark:text-dark-title hover:text-primary dark:hover:text-dark-primary"> <svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"> <path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd" /> </svg> </a> <a aria-label="The OCaml Language Twitter Account" href="https://twitter.com/ocaml_org" class="opacity-60 hover:opacity-100 text-content dark:text-dark-title hover:text-primary dark:hover:text-dark-primary"> <svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"> <path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84" /> </svg> </a> </div> </li> </ul> </nav> </header> <script> window.addEventListener('keydown', function(event) { if (event.key === "/") { event.preventDefault(); document.querySelector("input[type='search']").focus() } }) </script> <main class="bg-background dark:bg-dark-background"><nav aria-label="breadcrumbs" class="px-4 flex bg-title dark:bg-[#111827] text-white dark:text-dark-title md:hidden"> <ul> <li class="inline-block"> <a href="/docs" class="flex items-center px-2 py-2 border-transparent border-2 border-b-4"> Learn <span> <svg xmlns="http://www.w3.org/2000/svg" class="w-3 h-3 ml-2" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" /> </svg> </span> </a> </li> <li class="inline-block"> <select onchange="location = this.value;" class="appearance-none border-2 border-b-4 bg-transparent bg-none font-bold border-none w-auto p-0 m-0 cursor-pointer focus:outline-none focus:ring-0"> <option value="/docs" > Overview </option> <option value="/docs/get-started" > Get Started </option> <option value="/docs/language" > Language </option> <option value="/docs/tools" selected> Platform </option> <option value="/docs/guides" > Guides </option> <option value="/cookbook" > Cookbook </option> <option value="/exercises" > Exercises </option> <option value="/books" > Books </option> </select> <span class="text-primary dark:text-dark-primary cursor-pointer">▾</span> </li> </ul> </nav> <div class="bg-title dark:bg-[#111827] hidden md:flex"> <nav class="container-fluid wide flex flex-wrap"> <a href="/docs" class="justify-start px-4 py-2 text-white dark:text-dark-title items-center font-normal border-2 border-b-4 border-transparent rounded opacity-80 hover:text-primary dark:hover:text-dark-primary"> Overview </a> <a href="/docs/get-started" class="justify-start px-4 py-2 text-white dark:text-dark-title items-center font-normal border-2 border-b-4 border-transparent rounded opacity-80 hover:text-primary dark:hover:text-dark-primary"> Get Started </a> <a href="/docs/language" class="justify-start px-4 py-2 text-white dark:text-dark-title items-center font-normal border-2 border-b-4 border-transparent rounded opacity-80 hover:text-primary dark:hover:text-dark-primary"> Language </a> <a href="/docs/tools" class="justify-start px-4 py-2 text-white dark:text-dark-title items-center font-normal border-2 border-b-4 border-transparent rounded border-b-primary dark:border-b-dark-primary"> Platform </a> <a href="/docs/guides" class="justify-start px-4 py-2 text-white dark:text-dark-title items-center font-normal border-2 border-b-4 border-transparent rounded opacity-80 hover:text-primary dark:hover:text-dark-primary"> Guides </a> <a href="/cookbook" class="justify-start px-4 py-2 text-white dark:text-dark-title items-center font-normal border-2 border-b-4 border-transparent rounded opacity-80 hover:text-primary dark:hover:text-dark-primary"> Cookbook </a> <a href="/exercises" class="justify-start px-4 py-2 text-white dark:text-dark-title items-center font-normal border-2 border-b-4 border-transparent rounded opacity-80 hover:text-primary dark:hover:text-dark-primary"> Exercises </a> <a href="/books" class="justify-start px-4 py-2 text-white dark:text-dark-title items-center font-normal border-2 border-b-4 border-transparent rounded opacity-80 hover:text-primary dark:hover:text-dark-primary"> Books </a> </nav> </div> <div class="bg-background dark:bg-dark-background" x-data="{ sidebar: window.matchMedia('(min-width: 64em)').matches, showOnMobile: false}" @resize.window="sidebar = window.matchMedia('(min-width: 64em)').matches" x-on:close-sidebar="sidebar=window.matchMedia('(min-width: 64em)').matches"> <button :title='(sidebar? "close" : "open")+" sidebar"' class="flex items-center bg-[#D54000] p-4 z-30 rounded-full text-white shadow-custom bottom-24 md:bottom-36 fixed lg:hidden right-10" x-on:click="sidebar = ! sidebar"> <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24" > <path d="M14.25 14.375H19.875C20.4962 14.375 21 13.8712 21 13.25V9.875C21 9.25377 20.4962 8.75 19.875 8.75H14.25C13.6288 8.75 13.125 9.25377 13.125 9.875V11H7.5V7.625H9.75C10.3712 7.625 10.875 7.12122 10.875 6.5V3.125C10.875 2.50378 10.3712 2 9.75 2H4.125C3.50378 2 3 2.50378 3 3.125V6.5C3 7.12122 3.50378 7.625 4.125 7.625H6.375V19.4375C6.375 19.7482 6.62677 20 6.9375 20H13.125V21.125C13.125 21.7462 13.6288 22.25 14.25 22.25H19.875C20.4962 22.25 21 21.7462 21 21.125V17.75C21 17.1288 20.4962 16.625 19.875 16.625H14.25C13.6288 16.625 13.125 17.1288 13.125 17.75V18.875H7.5V12.125H13.125V13.25C13.125 13.8712 13.6288 14.375 14.25 14.375ZM14.25 9.875H19.875V13.25H14.25V9.875ZM4.125 6.5V3.125H9.75V6.5H4.125ZM14.25 17.75H19.875V21.125H14.25V17.75Z"/> </svg> </button> <div class="fixed z-10 inset-0 bg-tertiary_25 backdrop-blur-sm lg:hidden" :class='sidebar ? "" : "hidden"' aria-hidden="true" x-on:click="sidebar = ! sidebar"></div> <div class="container-fluid wide pt-10"> <div class="flex flex-col lg:flex-row lg:gap-6 xl:gap-12"> <div class="z-20 bg-background dark:bg-dark-background flex-col fixed h-screen overflow-auto lg:flex left-0 top-0 lg:sticky p-6 lg:px-0 w-80 lg:w-72 lg:px-0 lg:pt-6 lg:pb-72" x-show="sidebar" x-transition:enter="transition duration-200 ease-out" x-transition:enter-start="-translate-x-full" x-transition:leave="transition duration-100 ease-in" x-transition:leave-end="-translate-x-full"> <div class="flex flex-col gap-5"> <div class="pl-2 pr-8 flex flex-col"> <div class="text-lg font-normal text-title dark:text-dark-title leading-10 flex py-1 uppercase">Projects</div> <a class="border-l-2 py-2 px-3 rounded-sm leading-6 font-normal text-title dark:text-dark-title bg-primary_nav_block_hover_10 dark:bg-primary_nav_block_hover_10 border-primary dark:border-dark-primary" href="/docs/bootstrapping-a-dune-project"> Bootstrapping a Project </a> <a class="border-l-2 py-2 px-3 rounded-sm leading-6 font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary border-transparent" href="/docs/managing-dependencies"> Managing Dependencies With opam </a> <a class="border-l-2 py-2 px-3 rounded-sm leading-6 font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary border-transparent" href="/docs/install-a-specific-ocaml-compiler-version"> Installing a Specific Compiler Version </a> <a class="border-l-2 py-2 px-3 rounded-sm leading-6 font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary border-transparent" href="/docs/running-executables-and-tests-with-dune"> Running Executables and Tests </a> <a class="border-l-2 py-2 px-3 rounded-sm leading-6 font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary border-transparent" href="/docs/opam-path"> Running Commands in an opam Switch </a> </div> <div class="pl-2 pr-8 flex flex-col"> <div class="text-lg font-normal text-title dark:text-dark-title leading-10 flex py-1 uppercase">Editor Support</div> <a class="border-l-2 py-2 px-3 rounded-sm leading-6 font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary border-transparent" href="/docs/formatting-your-code"> Formatting Your Code </a> </div> <div class="pl-2 pr-8 flex flex-col"> <div class="text-lg font-normal text-title dark:text-dark-title leading-10 flex py-1 uppercase">Documentation</div> <a class="border-l-2 py-2 px-3 rounded-sm leading-6 font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary border-transparent" href="/docs/generating-documentation"> Generating Documentation </a> </div> <div class="pl-2 pr-8 flex flex-col"> <div class="text-lg font-normal text-title dark:text-dark-title leading-10 flex py-1 uppercase">Libraries & Packages</div> <a class="border-l-2 py-2 px-3 rounded-sm leading-6 font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary border-transparent" href="/docs/creating-libraries"> Creating Libraries </a> <a class="border-l-2 py-2 px-3 rounded-sm leading-6 font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary border-transparent" href="/docs/publishing-packages-w-dune"> Publishing a Package </a> </div> </div> </div> <div class="flex-1 z-0 z- min-w-0 lg:pt-6 lg:max-w-3xl"> <div class="prose prose-orange dark:prose-invert max-w-full"> <h1 id="bootstrapping-a-dune-project" ><a class="anchor" aria-hidden="true" href="#bootstrapping-a-dune-project"></a>Bootstrapping a Project with Dune</h1> <p><a href="https://dune.readthedocs.io/en/stable/overview.html">Dune</a> is recommended for bootstrapping projects. To install <code>dune</code>, please see <a href="/install">the OCaml install page</a>.</p> <p>To start a new project, you can run:</p> <pre><code><span class='sh-source'>$ opam </span><span class='sh-support-function-builtin'>exec</span><span class='sh-source'> -- dune init project hello_world </span><span class='sh-source'>Success: initialized project component named hello_world </span></code></pre> <p>You can now build and run your new project:</p> <pre><code><span class='sh-source'>$ </span><span class='sh-support-function-builtin'>cd</span><span class='sh-source'> hello_world </span><span class='sh-source'>$ opam </span><span class='sh-support-function-builtin'>exec</span><span class='sh-source'> -- dune </span><span class='sh-support-function-builtin'>exec</span><span class='sh-source'> bin/main.exe </span><span class='sh-source'>Hello, world</span><span class='sh-keyword-operator-pipe'>!</span><span class='sh-source'> </span></code></pre> <p>To create a new library in the current project, use:</p> <pre><code><span class='sh-source'>$ opam </span><span class='sh-support-function-builtin'>exec</span><span class='sh-source'> -- dune init lib my_lib ./path/to/my_lib </span><span class='sh-source'>Success: initialized library component named my_lib </span></code></pre> <p>To create a new executable in the current project, use:</p> <pre><code><span class='sh-source'>$ opam </span><span class='sh-support-function-builtin'>exec</span><span class='sh-source'> -- dune init </span><span class='sh-support-function-builtin'>exec</span><span class='sh-source'> my_bin ./path/to/my_bin </span><span class='sh-source'>Success: initialized executable component named my_bin </span></code></pre> <p>To create a new test in the current project, use:</p> <pre><code><span class='sh-source'>$ opam </span><span class='sh-support-function-builtin'>exec</span><span class='sh-source'> -- dune init </span><span class='sh-support-function-builtin'>test</span><span class='sh-source'> my_test ./path/to/my_test </span><span class='sh-source'>Success: initialized </span><span class='sh-support-function-builtin'>test</span><span class='sh-source'> component named my_test </span></code></pre> <h2 id="more-comprehensive-scaffolding"><a class="anchor" aria-hidden="true" href="#more-comprehensive-scaffolding"></a>More Comprehensive Scaffolding</h2> <p>If you're looking for project templates that include more than the basics, there are other community projects that offer more comprehensive project scaffolding:</p> <ul> <li><a href="https://github.com/tmattio/spin">spin</a></li> <li><a href="https://ocamlpro.github.io/drom/sphinx/about.html">drom</a></li> <li><a href="https://github.com/dbuenzli/carcass">carcass</a></li> </ul> <div class="my-5 pt-5"> <div class="grid-cols-2 gap-4 border-t border-gray-200 md:grid"> <div class="border-b border-gray-200 px-6 pb-3 md:border-b-0 md:border-r"> <h2 class="mb-2 text-lg font-bold leading-6">Still need help?</h2> <div class="mb-2 text-sm"> <a href="https://discuss.ocaml.org/" class="flex items-center gap-2 font-normal sm:text-lg no-underline bg-transparent cursor-pointer hover:underline"> <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M18 18.72a9.094 9.094 0 003.741-.479 3 3 0 00-4.682-2.72m.94 3.198l.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0112 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 016 18.719m12 0a5.971 5.971 0 00-.941-3.197m0 0A5.995 5.995 0 0012 12.75a5.995 5.995 0 00-5.058 2.772m0 0a3 3 0 00-4.681 2.72 8.986 8.986 0 003.74.477m.94-3.197a5.971 5.971 0 00-.94 3.197M15 6.75a3 3 0 11-6 0 3 3 0 016 0zm6 3a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0zm-13.5 0a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0z" /> </svg> Ask the OCaml Community</a > </div> <div class="mb-2 text-sm"> <a href="https://github.com/ocaml/ocaml.org/issues/new" class="flex items-center gap-3 font-normal sm:text-lg no-underline bg-transparent cursor-pointer hover:underline"> <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"> <path d="M8 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"></path> <path fill-rule="evenodd" d="M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z"></path> </svg> Open an Issue</a > </div> </div> <div class="px-6 pb-3"> <h2 class="mb-2 text-lg font-bold leading-6">Help Improve Our Documentation</h2> <p class="text-sm text-lighter leading-relaxed mb-0">All OCaml docs are open source. See something that's wrong or unclear? Submit a pull request.</p> <div class="mb-5 text-sm"> <a href="https://github.com/ocaml/ocaml.org/blob/97400fe896b64a4a52e5d580d9dee19a773d7c13/data/tutorials/platform/0_00_bootstrap_project.md" class="flex items-center gap-2 bg-transparent font-normal sm:text-lg no-underline hover:underline"> <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M10.05 4.575a1.575 1.575 0 10-3.15 0v3m3.15-3v-1.5a1.575 1.575 0 013.15 0v1.5m-3.15 0l.075 5.925m3.075.75V4.575m0 0a1.575 1.575 0 013.15 0V15M6.9 7.575a1.575 1.575 0 10-3.15 0v8.175a6.75 6.75 0 006.75 6.75h2.018a5.25 5.25 0 003.712-1.538l1.732-1.732a5.25 5.25 0 001.538-3.712l.003-2.024a.668.668 0 01.198-.471 1.575 1.575 0 10-2.228-2.228 3.818 3.818 0 00-1.12 2.687M6.9 7.575V12m6.27 4.318A4.49 4.49 0 0116.35 15m.002 0h-.002" /> </svg> Contribute</a > </div> </div> </div> </div> </div> <footer x-data class="flex flex-col gap-3 md:gap-5 pt-5 mt-6 border-separator_20 dark:border-dark-separator_30 border-t"> <div class="flex w-full items-center justify-between"> <a href="/"> <img class="h-8 dark:hidden" src="/_/MDBjN2M4YjIxY2Y1YWExZWE3Njk4M2FiZTg1NWZjNTM/logo-with-name.svg" alt="OCaml"> <img src="/_/MTE3YWE5YzJlZmExNmYyMmI3ZmEwYjliMDEwNDBkMDY/logo-with-name-white.svg" width="132" alt="OCaml logo" class="h-8 hidden dark:inline"> </a> <div class="hidden md:flex"> <button class="flex grow basis-0 justify-center items-center py-2 px-4 text-sm border rounded-l rounded-l-full border-r-0" :class='$store.themeSettings.preference === "light" ? "bg-gradient-to-r from-[#FFA932] to-[#C24F1E] text-white dark:text-dark-title outline-none" : "bg-white text-content outline-2 outline-card_border dark:outline-dark-separator_30"' @click='$store.themeSettings.setPreference("light")' > <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none" class="mr-2"> <path d="M7 0.5V2.125M11.5962 2.40378L10.4472 3.55283M13.5 7H11.875M11.5962 11.5962L10.4472 10.4472M7 11.875V13.5M3.55283 10.4472L2.40378 11.5962M2.125 7H0.5M3.55283 3.55283L2.40378 2.40378M9.70833 7C9.70833 7.71829 9.42299 8.40717 8.91508 8.91508C8.40717 9.42299 7.71829 9.70833 7 9.70833C6.28171 9.70833 5.59283 9.42299 5.08492 8.91508C4.57701 8.40717 4.29167 7.71829 4.29167 7C4.29167 6.28171 4.57701 5.59283 5.08492 5.08492C5.59283 4.57701 6.28171 4.29167 7 4.29167C7.71829 4.29167 8.40717 4.57701 8.91508 5.08492C9.42299 5.59283 9.70833 6.28171 9.70833 7Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> </svg> Light </button> <button class="flex grow basis-0 justify-center items-center py-2 px-4 text-sm border border-r-0" :class='$store.themeSettings.preference === "dark" ? "bg-gradient-to-r from-[#0F254F] to-[#0B1228] text-white dark:text-dark-title outline-none" : "bg-white text-content outline-2 outline-card_border dark:outline-dark-separator_30"' @click='$store.themeSettings.setPreference("dark")' > <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none" class="mr-2"> <path d="M11.1573 7.90842C10.5134 8.17678 9.8226 8.3145 9.125 8.31358C6.20812 8.31358 3.84375 5.94921 3.84375 3.03233C3.84375 2.31192 3.98783 1.62562 4.24892 1C3.28663 1.40144 2.46465 2.07865 1.88651 2.94635C1.30836 3.81404 0.999911 4.83342 1 5.87608C1 8.79296 3.36437 11.1573 6.28125 11.1573C7.32391 11.1574 8.34329 10.849 9.21099 10.2708C10.0787 9.69268 10.7559 8.8707 11.1573 7.90842Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> </svg> Dark </button> <button class="flex grow basis-0 justify-center items-center py-2 px-4 text-sm border rounded-r rounded-r-full" :class='$store.themeSettings.preference === "system" ? "bg-gradient-to-r from-[#2B7866] to-[#004039] text-white dark:text-dark-title outline-none" : "bg-white text-content outline-2 outline-card_border dark:outline-dark-separator_30"' @click='$store.themeSettings.setPreference("system")' > <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none" class="mr-2"> <path d="M7.19553 2.955C7.26303 2.5485 7.61553 2.25 8.02803 2.25H9.97278C10.3853 2.25 10.7378 2.5485 10.8053 2.955L10.965 3.91575C11.0123 4.19625 11.1998 4.43025 11.4488 4.56825C11.5043 4.59825 11.559 4.6305 11.6138 4.6635C11.8575 4.8105 12.1538 4.85625 12.42 4.7565L13.3328 4.4145C13.5198 4.34416 13.7258 4.34248 13.9139 4.40978C14.1021 4.47708 14.2603 4.60899 14.3603 4.782L15.3323 6.46725C15.4321 6.64028 15.4672 6.8431 15.4315 7.03962C15.3958 7.23615 15.2916 7.41363 15.1373 7.5405L14.385 8.16075C14.1653 8.3415 14.0565 8.6205 14.0625 8.90475C14.0636 8.9685 14.0636 9.03225 14.0625 9.096C14.0565 9.3795 14.1653 9.6585 14.385 9.83925L15.138 10.4595C15.456 10.722 15.5385 11.1758 15.333 11.532L14.3595 13.2172C14.2597 13.3902 14.1017 13.5222 13.9137 13.5896C13.7257 13.657 13.5198 13.6556 13.3328 13.5855L12.42 13.2435C12.1538 13.1438 11.8575 13.1895 11.613 13.3365C11.5587 13.3696 11.5037 13.4016 11.448 13.4325C11.1998 13.5697 11.0123 13.8037 10.965 14.0842L10.8053 15.045C10.7378 15.4523 10.3853 15.75 9.97278 15.75H8.02728C7.61478 15.75 7.26303 15.4515 7.19478 15.045L7.03503 14.0842C6.98853 13.8037 6.80103 13.5698 6.55203 13.4318C6.49642 13.4011 6.44141 13.3693 6.38703 13.3365C6.14328 13.1895 5.84703 13.1438 5.58003 13.2435L4.66728 13.5855C4.48033 13.6556 4.27456 13.6572 4.08656 13.5899C3.89856 13.5226 3.74051 13.3908 3.64053 13.218L2.66778 11.5328C2.56799 11.3597 2.53282 11.1569 2.56852 10.9604C2.60423 10.7639 2.7085 10.5864 2.86278 10.4595L3.61578 9.83925C3.83478 9.65925 3.94353 9.3795 3.93828 9.096C3.93711 9.03226 3.93711 8.96849 3.93828 8.90475C3.94353 8.61975 3.83478 8.3415 3.61578 8.16075L2.86278 7.5405C2.70869 7.41367 2.60454 7.23633 2.56884 7.03997C2.53314 6.84361 2.56819 6.64095 2.66778 6.468L3.64053 4.78275C3.74042 4.6096 3.89854 4.47754 4.08672 4.4101C4.27489 4.34266 4.4809 4.34422 4.66803 4.4145L5.58003 4.7565C5.84703 4.85625 6.14328 4.8105 6.38703 4.6635C6.44103 4.6305 6.49653 4.599 6.55203 4.5675C6.80103 4.43025 6.98853 4.19625 7.03503 3.91575L7.19553 2.955Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> <path d="M11.25 9C11.25 9.59674 11.0129 10.169 10.591 10.591C10.169 11.0129 9.59674 11.25 9 11.25C8.40326 11.25 7.83097 11.0129 7.40901 10.591C6.98705 10.169 6.75 9.59674 6.75 9C6.75 8.40326 6.98705 7.83097 7.40901 7.40901C7.83097 6.98705 8.40326 6.75 9 6.75C9.59674 6.75 10.169 6.98705 10.591 7.40901C11.0129 7.83097 11.25 8.40326 11.25 9Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> </svg> System </button> </div> </div> <section class="flex flex-col gap-6 md:gap-0 md:flex-row md:justify-between md:items-end"> <div> <p class="text-base font-normal leading-6 text-content dark:text-dark-content mt-2">Innovation. Community. Security.</p> </div> <div class="flex items-center gap-4 pr-4"> <a href="https://github.com/ocaml" class="text-title dark:text-dark-title hover:text-primary dark:hover:text-dark-primary"> <span class="sr-only">GitHub</span> <svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"> <path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd" /> </svg> </a> <a href="https://discord.gg/cCYQbqN" class="text-title dark:text-dark-title hover:text-primary dark:hover:text-dark-primary"> <span class="sr-only">Discord</span> <svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"> <path fill-rule="evenodd" d="M18.9419 5.29661C17.6473 4.69088 16.263 4.25066 14.8157 4C14.638 4.32134 14.4304 4.75355 14.2872 5.09738C12.7487 4.86601 11.2245 4.86601 9.7143 5.09738C9.57116 4.75355 9.3588 4.32134 9.17947 4C7.73067 4.25066 6.3448 4.6925 5.05016 5.29982C2.43887 9.24582 1.73099 13.0938 2.08493 16.8872C3.81688 18.1805 5.49534 18.9662 7.14548 19.4804C7.55291 18.9196 7.91628 18.3235 8.22931 17.6953C7.63313 17.4688 7.06211 17.1892 6.52256 16.8647C6.6657 16.7586 6.80571 16.6478 6.94098 16.5337C10.2318 18.0729 13.8074 18.0729 17.0589 16.5337C17.1958 16.6478 17.3358 16.7586 17.4774 16.8647C16.9362 17.1908 16.3637 17.4704 15.7675 17.697C16.0805 18.3235 16.4423 18.9212 16.8513 19.4819C18.503 18.9678 20.183 18.1822 21.915 16.8872C22.3303 12.4897 21.2056 8.67705 18.9419 5.29661ZM8.67765 14.5543C7.68977 14.5543 6.87963 13.632 6.87963 12.509C6.87963 11.3859 7.67247 10.4621 8.67765 10.4621C9.68285 10.4621 10.493 11.3843 10.4757 12.509C10.4772 13.632 9.68285 14.5543 8.67765 14.5543ZM15.3223 14.5543C14.3344 14.5543 13.5243 13.632 13.5243 12.509C13.5243 11.3859 14.3171 10.4621 15.3223 10.4621C16.3275 10.4621 17.1376 11.3843 17.1203 12.509C17.1203 13.632 16.3275 14.5543 15.3223 14.5543Z" clip-rule="evenodd" /> </svg> </a> <a href="https://twitter.com/ocaml_org" class="text-title dark:text-dark-title hover:text-primary dark:hover:text-dark-primary"> <span class="sr-only">Twitter</span> <svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"> <path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84" /> </svg> </a> <a href="https://watch.ocaml.org/" class="text-title dark:text-dark-title hover:text-primary dark:hover:text-dark-primary"> <span class="sr-only">Peertube</span> <svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"> <path fill-rule="evenodd" d="M5 2V12L12.4998 7.00047" clip-rule="evenodd" /> <path fill-rule="evenodd" d="M5 12V22L12.4998 17.0005" clip-rule="evenodd" /> <path fill-rule="evenodd" d="M12.4998 6.99951V16.9995L19.9995 12" clip-rule="evenodd" /> </svg> </a> <a href="/planet.xml" class="text-title dark:text-dark-title hover:text-primary dark:hover:text-dark-primary"> <span class="sr-only">RSS</span> <svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"> <path fill-rule="evenodd" d="M15.2692 22H11.3846C11.3846 16.8462 7.11538 12.6154 2 12.6154V8.73077C9.26923 8.73077 15.2692 14.7308 15.2692 22ZM18 22C18 13.2308 10.7692 6 2 6V2C12.9615 2 22 11.0385 22 22H18Z" clip-rule="evenodd" /> <path fill-rule="evenodd" d="M4.73077 22C6.23893 22 7.46154 20.7774 7.46154 19.2692C7.46154 17.7611 6.23893 16.5385 4.73077 16.5385C3.22261 16.5385 2 17.7611 2 19.2692C2 20.7774 3.22261 22 4.73077 22Z" clip-rule="evenodd" /> </svg> </a> </div> <div class="flex w-full md:hidden"> <button class="flex grow basis-0 justify-center items-center py-2 px-4 text-sm border rounded-l rounded-l-full border-r-0" :class='$store.themeSettings.preference === "light" ? "bg-gradient-to-r from-[#FFA932] to-[#C24F1E] text-white dark:text-dark-title outline-none" : "bg-white text-content outline-2 outline-card_border dark:outline-dark-separator_30"' @click='$store.themeSettings.setPreference("light")' > <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none" class="mr-2"> <path d="M7 0.5V2.125M11.5962 2.40378L10.4472 3.55283M13.5 7H11.875M11.5962 11.5962L10.4472 10.4472M7 11.875V13.5M3.55283 10.4472L2.40378 11.5962M2.125 7H0.5M3.55283 3.55283L2.40378 2.40378M9.70833 7C9.70833 7.71829 9.42299 8.40717 8.91508 8.91508C8.40717 9.42299 7.71829 9.70833 7 9.70833C6.28171 9.70833 5.59283 9.42299 5.08492 8.91508C4.57701 8.40717 4.29167 7.71829 4.29167 7C4.29167 6.28171 4.57701 5.59283 5.08492 5.08492C5.59283 4.57701 6.28171 4.29167 7 4.29167C7.71829 4.29167 8.40717 4.57701 8.91508 5.08492C9.42299 5.59283 9.70833 6.28171 9.70833 7Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> </svg> Light </button> <button class="flex grow basis-0 justify-center items-center py-2 px-4 text-sm border border-r-0" :class='$store.themeSettings.preference === "dark" ? "bg-gradient-to-r from-[#0F254F] to-[#0B1228] text-white dark:text-dark-title outline-none" : "bg-white text-content outline-2 outline-card_border dark:outline-dark-separator_30"' @click='$store.themeSettings.setPreference("dark")' > <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none" class="mr-2"> <path d="M11.1573 7.90842C10.5134 8.17678 9.8226 8.3145 9.125 8.31358C6.20812 8.31358 3.84375 5.94921 3.84375 3.03233C3.84375 2.31192 3.98783 1.62562 4.24892 1C3.28663 1.40144 2.46465 2.07865 1.88651 2.94635C1.30836 3.81404 0.999911 4.83342 1 5.87608C1 8.79296 3.36437 11.1573 6.28125 11.1573C7.32391 11.1574 8.34329 10.849 9.21099 10.2708C10.0787 9.69268 10.7559 8.8707 11.1573 7.90842Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> </svg> Dark </button> <button class="flex grow basis-0 justify-center items-center py-2 px-4 text-sm border rounded-r rounded-r-full" :class='$store.themeSettings.preference === "system" ? "bg-gradient-to-r from-[#2B7866] to-[#004039] text-white dark:text-dark-title outline-none" : "bg-white text-content outline-2 outline-card_border dark:outline-dark-separator_30"' @click='$store.themeSettings.setPreference("system")' > <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none" class="mr-2"> <path d="M7.19553 2.955C7.26303 2.5485 7.61553 2.25 8.02803 2.25H9.97278C10.3853 2.25 10.7378 2.5485 10.8053 2.955L10.965 3.91575C11.0123 4.19625 11.1998 4.43025 11.4488 4.56825C11.5043 4.59825 11.559 4.6305 11.6138 4.6635C11.8575 4.8105 12.1538 4.85625 12.42 4.7565L13.3328 4.4145C13.5198 4.34416 13.7258 4.34248 13.9139 4.40978C14.1021 4.47708 14.2603 4.60899 14.3603 4.782L15.3323 6.46725C15.4321 6.64028 15.4672 6.8431 15.4315 7.03962C15.3958 7.23615 15.2916 7.41363 15.1373 7.5405L14.385 8.16075C14.1653 8.3415 14.0565 8.6205 14.0625 8.90475C14.0636 8.9685 14.0636 9.03225 14.0625 9.096C14.0565 9.3795 14.1653 9.6585 14.385 9.83925L15.138 10.4595C15.456 10.722 15.5385 11.1758 15.333 11.532L14.3595 13.2172C14.2597 13.3902 14.1017 13.5222 13.9137 13.5896C13.7257 13.657 13.5198 13.6556 13.3328 13.5855L12.42 13.2435C12.1538 13.1438 11.8575 13.1895 11.613 13.3365C11.5587 13.3696 11.5037 13.4016 11.448 13.4325C11.1998 13.5697 11.0123 13.8037 10.965 14.0842L10.8053 15.045C10.7378 15.4523 10.3853 15.75 9.97278 15.75H8.02728C7.61478 15.75 7.26303 15.4515 7.19478 15.045L7.03503 14.0842C6.98853 13.8037 6.80103 13.5698 6.55203 13.4318C6.49642 13.4011 6.44141 13.3693 6.38703 13.3365C6.14328 13.1895 5.84703 13.1438 5.58003 13.2435L4.66728 13.5855C4.48033 13.6556 4.27456 13.6572 4.08656 13.5899C3.89856 13.5226 3.74051 13.3908 3.64053 13.218L2.66778 11.5328C2.56799 11.3597 2.53282 11.1569 2.56852 10.9604C2.60423 10.7639 2.7085 10.5864 2.86278 10.4595L3.61578 9.83925C3.83478 9.65925 3.94353 9.3795 3.93828 9.096C3.93711 9.03226 3.93711 8.96849 3.93828 8.90475C3.94353 8.61975 3.83478 8.3415 3.61578 8.16075L2.86278 7.5405C2.70869 7.41367 2.60454 7.23633 2.56884 7.03997C2.53314 6.84361 2.56819 6.64095 2.66778 6.468L3.64053 4.78275C3.74042 4.6096 3.89854 4.47754 4.08672 4.4101C4.27489 4.34266 4.4809 4.34422 4.66803 4.4145L5.58003 4.7565C5.84703 4.85625 6.14328 4.8105 6.38703 4.6635C6.44103 4.6305 6.49653 4.599 6.55203 4.5675C6.80103 4.43025 6.98853 4.19625 7.03503 3.91575L7.19553 2.955Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> <path d="M11.25 9C11.25 9.59674 11.0129 10.169 10.591 10.591C10.169 11.0129 9.59674 11.25 9 11.25C8.40326 11.25 7.83097 11.0129 7.40901 10.591C6.98705 10.169 6.75 9.59674 6.75 9C6.75 8.40326 6.98705 7.83097 7.40901 7.40901C7.83097 6.98705 8.40326 6.75 9 6.75C9.59674 6.75 10.169 6.98705 10.591 7.40901C11.0129 7.83097 11.25 8.40326 11.25 9Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> </svg> System </button> </div> </section> <section class="mt-4 grid grid-cols-2"> <div class="flex flex-col gap-1"> <div class="flex flex-col"> <h5 class="font-bold text-base leading-7 py-2.5 text-title dark:text-dark-title">About</h5> <a href="/changelog" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Changelog</a> <a href="/releases" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Releases</a> <a href="/industrial-users" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Industrial Users</a> <a href="/academic-users" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Academic Users</a> <a href="/about" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Why OCaml</a> </div> <div class="flex flex-col"> <h5 class="font-bold text-base leading-7 py-2.5 text-title dark:text-dark-title"> Ecosystem </h5> <a href="/packages" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Packages</a> <a href="/community" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Community</a> <a href="/events" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Events</a> <a href="/ocaml-planet" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">OCaml Planet</a> <a href="/jobs" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Jobs</a> </div> </div> <div class="flex flex-col"> <h5 class="font-bold text-base leading-7 py-2.5 text-title dark:text-dark-title">Resources</h5> <a href="/install" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Install OCaml</a> <a href="/docs/get-started" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Get Started</a> <a href="/docs/tools" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Platform Tools</a> <a href="/manual" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Language Manual</a> <a href="/api" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Standard Library API</a> <a href="/books" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Books</a> <a href="/exercises" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Exercises</a> <a href="/papers" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Papers</a> <a href="/play" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">OCaml Playground</a> <a href="/logo" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Logo</a> </div> </section> <div class="flex flex-wrap gap-x-7 md:justify-between items-center py-2 border-solid border-t-[1px] border-separator_20 dark:border-dark-separator_30 bottom-0 bg-background dark:bg-dark-background"> <h5 class="font-bold text-base leading-7 py-2.5 text-title dark:text-dark-title">Policies</h5> <a href="/policies/carbon-footprint" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Carbon Footprint</a> <a href="/governance" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Governance</a> <a href="/policies/privacy-policy" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Privacy</a> <a href="/policies/code-of-conduct" class="font-normal text-content dark:text-dark-content hover:text-primary dark:hover:text-dark-primary leading-7 py-2.5">Code of Conduct</a> </div> <script> document.addEventListener('alpine:init', () => { Alpine.store('themeSettings', { init() { this.storageAccess = localStorage.getItem('storageAccess') this.preference = localStorage.getItem('theme') || "system" this.isSystemDefaultDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches }, selected: '', alertOpen: false, storageAccess: false, preference: undefined, isSystemDefaultDark: false, setPreference(preference) { if (!this.storageAccess) { if (!window.confirm("We will remember your choice in your browser's LocalStorage. Allow this?")) { return; } localStorage.setItem('storageAccess', true) storageAccess = true; } this.selected = preference; this.preference = preference localStorage.setItem('theme', preference) if (preference === 'dark') { document.body.classList.add("dark"); } if (preference === 'light') { document.body.classList.remove("dark"); } if (preference === 'system') { if (this.isSystemDefaultDark) { document.body.classList.add("dark"); } else { document.body.classList.remove("dark"); } localStorage.removeItem('theme') return } }, }) }) </script> </footer> </div> <div class="hidden xl:block top-0 sticky h-screen overflow-auto lg:pt-6"> <div class="w-60 lg:pb-72"> <div x-data='toc' @scroll.window="scrollY = window.scrollY" @resize.window="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)" x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)" > <div class="font-bold text-title dark:text-dark-title text-sm mb-4">On This Page</div> <ol class="leading-6 text-sm border-l"> <li> <a href="#more-comprehensive-scaffolding" class="text-content dark:text-dark-content py-1 pl-2 pr-1 block transition-colors border-l-4 border-t-2 border-b-2 border-r-2 border-transparent rounded" :class='isWithin(scrollY, "#more-comprehensive-scaffolding", sectionYPositions) ? "font-semibold border-l-primary dark:border-l-dark-primary text-title dark:text-dark-title bg-primary_nav_block_hover_10 dark:bg-primary_nav_block_hover_10": "hover:text-title dark:hover:text-dark-title"' :style='isWithin(scrollY, "#more-comprehensive-scaffolding", sectionYPositions) ? "letter-spacing: -0.012em;" : ""' > More Comprehensive Scaffolding </a> </li> </ol> </div> </div> </div> </div> </div> <script> document.addEventListener('alpine:init', () => { function computeSectionYPositions(toc_el) { function get_y(href) { let heading = document.getElementById(href.substring(1)); return heading.getBoundingClientRect().top + window.scrollY - 60; } let sections = {}; let els = toc_el.querySelectorAll("a"); let l = els.length; for (let i=0; i<l; i++) { let target_href = els[i].getAttribute("href"); let next_el_href = i < l-1 ? els[i+1].getAttribute("href") : null; sections[target_href] = { start: get_y(target_href), end: next_el_href ? get_y(next_el_href) : null, } } return sections; } function isWithin(scrollY, href, sectionYPositions) { if (sectionYPositions == null) return false; return scrollY > sectionYPositions[href].start && (scrollY <= sectionYPositions[href].end || sectionYPositions[href].end == null) } Alpine.data('toc', () => ( { scrollY: window.scrollY, sectionYPositions: null, isWithin, computeSectionYPositions, } )) }) </script> </main> <button class="fixed bottom-8 right-10 md:bottom-[5rem] lg:bottom-[8.37rem] lg:right-[6.5rem] border-0 hidden focus:outline-none z-50 rounded-full shadow-custom p-4 bg-primary dark:bg-dark-primary" onclick="scrollToTop()" id="scrollToTop" title="Scroll to top"><svg class="h-6 w-6" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path d="M4.5 10.5L12 3M12 3L19.5 10.5M12 3V21" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg> </button> <script> function scrollToTop() { window.scrollTo(0, 0); } window.onscroll = function() { showScrollButton(); }; function showScrollButton() { if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) { document.getElementById("scrollToTop").style.display = "block"; } else { document.getElementById("scrollToTop").style.display = "none"; } } </script> </body> </html>