Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Best Known Methods #107

Merged
merged 28 commits into from Sep 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f93ee42
Fix tutorials
tmattio Sep 22, 2021
efbb983
Add workflows
tmattio Sep 22, 2021
2ff3207
Format code
tmattio Sep 22, 2021
79e3c4c
Update data/workflows/en/03_update_deps.md
tmattio Sep 22, 2021
4c93a3a
Update data/workflows/en/03_update_deps.md
tmattio Sep 22, 2021
b6b495b
Update data/workflows/en/05_select_compiler.md
tmattio Sep 22, 2021
52ed728
Update data/workflows/en/01_bootstrap_project.md
tmattio Sep 22, 2021
ab4eab6
Update data/workflows/en/01_bootstrap_project.md
tmattio Sep 22, 2021
28b5469
Update data/workflows/en/05_select_compiler.md
tmattio Sep 22, 2021
6a3a00c
Update data/workflows/en/02_install_deps.md
tmattio Sep 22, 2021
56049d4
Update data/workflows/en/02_install_deps.md
tmattio Sep 22, 2021
829f55e
Update data/workflows/en/02_install_deps.md
tmattio Sep 22, 2021
89b7899
Update data/workflows/en/05_select_compiler.md
tmattio Sep 22, 2021
c5f229f
Update data/workflows/en/07_run_tests.md
tmattio Sep 22, 2021
0c79734
Update data/workflows/en/07_run_tests.md
tmattio Sep 22, 2021
aaa507c
Update data/workflows/en/08_create_libraries.md
tmattio Sep 22, 2021
4121fa2
Update data/workflows/en/09_publish_packages.md
tmattio Sep 22, 2021
d0e26ac
Update data/workflows/en/09_publish_packages.md
tmattio Sep 22, 2021
e6d1890
Update data/workflows/en/09_publish_packages.md
tmattio Sep 22, 2021
383935b
Update data/workflows/en/10_setup_vscode.md
tmattio Sep 22, 2021
bf88e1e
Update data/workflows/en/10_setup_vscode.md
tmattio Sep 22, 2021
a05268b
Update data/workflows/en/01_bootstrap_project.md
tmattio Sep 22, 2021
7161259
Update data/workflows/en/01_bootstrap_project.md
tmattio Sep 22, 2021
fe7c1f0
Update data/workflows/en/01_bootstrap_project.md
tmattio Sep 22, 2021
cf9a523
Update data/workflows/en/01_bootstrap_project.md
tmattio Sep 22, 2021
70ebdf3
Update data/workflows/en/01_bootstrap_project.md
tmattio Sep 22, 2021
af2228f
Update data/workflows/en/01_bootstrap_project.md
tmattio Sep 22, 2021
e6f0c00
Link to opam documentation
tmattio Sep 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions asset/tutorials/undraw_Queue_j6ij.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions data/tutorials/en/001_a_first_hour_with_ocaml.md
Expand Up @@ -33,7 +33,7 @@ Use `;;` to indicate that you've finished entering each expression and prompt
OCaml to evaluate it. We run OCaml and evaluate a simple expression:

```console
OCaml version {{! get LATEST_OCAML_VERSION !}}
OCaml version 4.12.0

# 50 * 50;;
- : int = 2500
Expand All @@ -43,7 +43,7 @@ This is how it looks using `utop`:

```console
───────┬─────────────────────────────────────────────────────────────┬────
│ Welcome to utop version 2.7.0 (using OCaml version {{! get LATEST_OCAML_VERSION !}})! │
│ Welcome to utop version 2.7.0 (using OCaml version 4.12.0)! │
└─────────────────────────────────────────────────────────────┘

Type #utop_help for help about using utop.
Expand All @@ -61,7 +61,7 @@ and load its contents directly with the `#use` directive:

```console
$ ocaml
OCaml version {{! get LATEST_OCAML_VERSION !}}
OCaml version 4.12.0

# #use "program.ml"
```
Expand Down
2 changes: 1 addition & 1 deletion data/tutorials/en/008_modules.md
Expand Up @@ -140,7 +140,7 @@ val hello : unit -> unit

(note the double asterisk at the beginning of the comment - it is a good habit
to document .mli files using the format supported by
[ocamldoc](/releases/{{! get LATEST_OCAML_VERSION_MAIN !}}/htmlman/ocamldoc.html))
[ocamldoc](/releases/4.12.0/htmlman/ocamldoc.html))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing once we have releases we could point this to /releases/latest which redirects to the latest release we have?


Such .mli files must be compiled just before the matching .ml files. They are
compiled using `ocamlc`, even if .ml files are compiled to native code using
Expand Down
62 changes: 62 additions & 0 deletions data/workflows/en/01_bootstrap_project.md
@@ -0,0 +1,62 @@
---
title: "Bootstrap a project"
---

> **TL;DR**
>
> if you need a minimal project to start hacking quickly, use `dune init`. If you need a complete development environment that follows best practices, use `spin`.
As the recommended build system for OCaml, Dune offers a command `dune init` to bootstrap new projects.

Once you have successfully installed opam, you can install Dune with `opam install dune`.

This will install Dune's binary in your current Opam switch, so `dune` should now be in your `PATH`. If it not, you probably need to run `eval $(opam env)` to configure your current terminal with Opam environment.

To bootstrap a new project with `dune init`, run:

```
dune init proj hello my_project/
```

Where proj is the kind of project to initialize. Here we want to generate an entire project, so we use `proj`. `hello` is the name of the project and `my_project/` is the path where the project will be generated.

`dune init proj` does not generate a `dune-project` for you, so you need to go in the generated project and create one:

```
echo "(lang dune 2.0)" > dune-project
```

At this point, you can build the project and run the binary:

```
dune build
dune exec bin/main.exe
```

`dune init` is the quickest way to get a working OCaml project and start hacking, but you may need a bit more, for instance:

- How to setup the IDE
- How to setup the CI/CD

Or you may be looking for the best way to get started with a specific kind of project:

- A library
- A command line interface
- A web application

If that's the case, we recommend using `spin`, the OCaml project generator. Spin comes with official templates for common project types. The official templates will get you up and running with everything you need to get a productive development environment, including the IDE setup, the CI/CD, the code formatter, the unit tests, etc.

You can install `spin` with opam: `opam install spin`.

Once it's installed, you can list the available templates with `spin ls`. For the purpose of this workflow, we'll use `bin` that bootstraps a project with an executable:

```
spin new bin my_project/
```

This will take some time, because Spin will install all of the dependencies in a new opam local switch (a.k.a local sandbox), which needs to compile an OCaml compiler.

Once the project is generated, you can run the executable with `make start`.

You can also open the project in VSCode, which should detect your installation of the LSP server, code formatter and other Platform tools to offer the full range of its capabilities.

Happy hacking :)
44 changes: 44 additions & 0 deletions data/workflows/en/02_install_deps.md
@@ -0,0 +1,44 @@
---
title: "Installing dependencies"
---

> **TL;DR**
>
> ```
> opam switch create . --deps-only --with-test --with-doc
> ```
It is recommended to install the dependencies of a project in a local opam switch to sandbox your development environment.

If you're using opam `2.0.X`, you can do this with:

```
# if you need external dependencies
opam pin add -n .
opam depext -i <packages>
opam install . --deps-only --with-test --with-doc
```

If you use opam `2.1.X`, it will install the system dependencies automatically, so you can run:

```
opam install . --deps-only --with-test --with-doc
```

Now, if for some reason you prefer to install your dependencies in a global switch, you can run:

```
opam switch set <switch_name>
opam install . --deps-only --with-test --with-doc
```

Once the dependencies have been installed successfully, and assuming the project uses `dune` as the build system, you can compile it with:

```
opam exec -- dune build
```

Or if you set your environment with `eval $(opam env)`:

```
dune build
```
61 changes: 61 additions & 0 deletions data/workflows/en/03_update_deps.md
@@ -0,0 +1,61 @@
---
title: "Updating dependencies"
---

> **TL;DR**
>
> If the project generates the `*.opam` file from the `dune-project`, add the dependency in the `package` stanza and run `opam install . --deps-only`.
> If the project does not generate the `*.opam` file, add the dependency in the `*.opam` file and run `opam install . --deps-only`.
To avoid duplicating the project configuration into multiple files, Dune allows to generate the `*.opam` file of the project from the
package definitions in `dune-project` when adding the `(generate_opam_files true)` stanza.

However, opam remains a central piece of the ecosystem and it's very likely that you will have to work with `*.opam` files at some point,
so we don't take a stance on wether you should specify your dependencies in the `*.opam` file or in `dune-project`.

If the project generates the opam file from the `dune-project` (you can tell by the line `# This file is generated by dune, edit dune-project instead` at the top of the `*.opam` file), you can add your dependencies in the `dune-project` in the appropriate `package` stanza. It should look like this:

```
(package
(name demo)
(synopsis "A short, but powerful statement about your project")
(description "An complete and exhaustive description everything your project does.")
(depends
(ocaml
(>= 4.08.0))
dune
(alcotest :with-test)
(odoc :with-doc)))
```

Once you have added your dependency, you can build your project with `dune build` which will re-generate the `*.opam` files.

If the `*.opam` files are not generated, you can add the dependencies in them directly, in the `depends` field. If should look like this:


```
opam-version: "2.0"
synopsis: "A short, but powerful statement about your project"
description: "An complete and exhaustive description everything your project does."
depends: [
"ocaml" {>= "4.08.0"}
"dune"
"alcotest" {with-test}
"odoc" {with-doc}
]
build: [
["dune" "subst"] {pinned}
[
"dune"
"build"
"-p"
name
"-j"
jobs
"@install"
"@runtest" {with-test}
"@doc" {with-doc}
]
]
```

Either way, once you have added your dependency in the appropriate file, you can run `opam install . --deps-only` to update your current switche's dependencies.
36 changes: 36 additions & 0 deletions data/workflows/en/04_update_dev_deps.md
@@ -0,0 +1,36 @@
---
title: "Updating development dependencies"
---

> **TL;DR**
>
> Follow the workflow "Update dependencies" and add a flag `:with-test` or `with-doc` to your dependency.
Opam does not have a notion of development dependencies. Instead, each dependency can be either:

- A normal dependency (used at runtime)
- A build dependency (used to build the project)
- A test dependency (used to test the project)
- A documentation dependency (used to generate the documentation)

When adding a new dependency, as seen in the "Update dependencies" workflow, you can add a flag to your dependency.

For `dune-project`, it looks like this:

```
(alcotest :with-test)
```

And for the `*.opam` file, it looks like:

```
"alcotest" {with-test}
```

The available flags for each dependencies are:

- Normal: no flag
- Build: `build`
tmattio marked this conversation as resolved.
Show resolved Hide resolved
- Test: `with-test`
- Documentation: `with-doc`

See [opam documentation](https://opam.ocaml.org/doc/Manual.html#Package-variables) for more details on the opam syntax.
54 changes: 54 additions & 0 deletions data/workflows/en/05_select_compiler.md
@@ -0,0 +1,54 @@
---
title: "Selecting a compiler"
---

> **TL;DR**
>
> Use `opam switch set` to manually select the switch to use and use `dune-workspace` to automatically run commands in different environment.

Compilation environments are managed with opam switches. The typical workflow is to have a local opam switch for the project, but you may need to select a different compilation environment (i.e. a different compiler version) sometimes. For instance, to run unit tests on an older/newer version of OCaml.

To do this, you'll need to create global opam switches. To create an opam switch with a given version of the compiler, you can use:

```
opam switch create 4.12.0 ocaml-base-compiler.4.12.0
```

This will create a new switch called `4.12.0` with the compiler version `4.12.0`.

The list of available compiler version can be retrieved with:

```
opam switch list-available
```

This will list the available compiler version for all of the configured Opam repositories.

Once you've created a switch (or you already have a switch you'd like to use), you can run:

```
opam switch set <switch_name>
eval $(opam env)
```

to configure the current environment with this switch.

If it is a new switch, you will need to reinstall your dependencies (see "Installing dependencies") with `opam install . --deps-only`.

Alternatively, you may want to automatically run commands in a given set of compilation environments. To do this, you can create a file `dune-workspace` at the root of your project and list the opam switches you'd like to use there:


```
(lang dune 2.0)
(context (opam (switch 4.10.0)))
(context (opam (switch 4.11.0)))
(context (opam (switch 4.12.0)))
```

All the Dune commands you will run will be run on all of the switches listed, so for instance with the definition above:

```
dune runtest --workspace dune-workspace
```

Dune will run the tests for OCaml `4.10.0`, `4.11.0` and `4.12.0`.
33 changes: 33 additions & 0 deletions data/workflows/en/06_run_executables.md
@@ -0,0 +1,33 @@
---
title: "Running executables"
---

> **TL;DR**
>
> Add an `executable` stanza in your dune file and run the executable with `dune exec <executable_path>.exe` or `dune exec <public_name>`.

To tell dune to produce an executable, you can use the executable stanza:

```
(executable
(name <executable_name>)
(public_name <public_name>)
(libraries <libraries...>))
```

The `<executable_name>` is the name of the executable used internally in the project.
The `<public_name>` is the name of the installed binary when installing the package.
Finally, `<libraries...>` is the list of libraries to link to the executable.

Once dune has produced the executable with `dune build`, you can execute it with `dune exec <executable_path>.exe` or `dune exec <public_name>`.

For instance, if you've put your dune file in `bin/dune` with the following content:

```
(executable
(name main)
(public_name my-app)
(libraries))
```

You can run it with `dune exec bin/main.exe` or `dune exec my-app`.