Skip to content

Commit

Permalink
Update project documentation for Package.juvix
Browse files Browse the repository at this point in the history
  • Loading branch information
paulcadman committed Nov 6, 2023
1 parent 8dc91d6 commit 453b120
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 61 deletions.
117 changes: 56 additions & 61 deletions docs/howto/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,41 @@ search:

# How to setup a Juvix project

A _juvix project_ is a collection of juvix modules plus some extra metadata
gathered in a `juvix.yaml` file. The most convenient way to create a juvix
A _Juvix project_ is a collection of Juvix modules plus some extra metadata
gathered in a `Package.juvix` file. The most convenient way to create a Juvix
project is to run the command:

```shell
--8<------ "docs/howto/project/CLI.yaml:init"
```

## Juvix YAML file
## Package.juvix file

A project is rooted in a directory. The root is set by creating a `juvix.yaml`,
which contains the following fields, no order is required:
A project is rooted in a directory. The root is set by creating a `Package.juvix`. The simplest `Package.juvix` file, which uses the default configuration, is:

- `name`
- `version`
- `dependencies`
- `main`
```juvix
--8<------ "docs/howto/project/Package.juvix:Package"
```

You can override the default options by passing arguments to `defaultPackage`:

```juvix
--8<------ "docs/howto/project/ex1/Package.juvix:Example"
```

You can check the documentation of the `Package` type or the `defaultPackage` function by using the go-to-definition feature in your IDE.

The fields are explained below.
The arguments are explained below.

- **name**: This is the name assigned to the project. The name must not be empty
and cannot exceed 100 characters. Lower case letters, digits and hyphen `-`
are acceptable characters. The first letter must not be a hyphen.
Summarizing, it must match the following regexp: `[a-z0-9][a-z0-9-]{0,99}`.
- **version** (_optional_): The version of the project. It must follow the
[SemVer](https://semver.org/) specification. If the version is missed then it
will be assumed to be _0.0.0_.
[SemVer](https://semver.org/) specification. If unspecified, the default version is "0.0.0".
- **main** (_optional_): The main module of the project used as entry point.
- **dependencies** (_optional_): The dependencies of the project is given as a
list. See below for more information.
list. See below for more information. If unspecified, the default is `defaultStdlib`.

!!! info "Note"

Expand All @@ -47,71 +52,61 @@ The fields are explained below.
1. Modules in a hidden (or hanging from a hidden) directory are not part of the
project. E.g., if the root of a project is `dir`, then the module
`dir/.d/Lib.juvix` does not belong to the project rooted in `dir`.
1. A `juvix.yaml` file shadows other `juvix.yaml` files in parent
1. A `Package.juvix` file shadows other `Package.juvix` files in parent
directories. E.g. if the root of a project is `dir` and the files
`dir/juvix.yaml` and `dir/nested/juvix.yaml` exist, then the module
`dir/Package.juvix` and `dir/nested/Package.juvix` exist, then the module
`dir/nested/Lib.juvix` would belong to the project in `dir/nested`.

!!! info "Note"

Any Juvix module outside of a project is considered a _standalone module_ and lives in its own (global) project. In other words, there is no need to create a `juvix.yaml` file for a standalone module.
Any Juvix module outside of a project is considered a _standalone module_ and lives in its own (global) project. In other words, there is no need to create a `Package.juvix` file for a standalone module.

## Package dependencies

In order to specify the list of dependencies for a package, the field
`dependencies` has been added to the `juvix.yaml`. The `dependencies` field is a
list of directories (relative or absolute) or git dependencies. If the
dependency is a directory then its location must contain a `juvix.yaml` file. As
expected, if we add a package to the list of dependencies, we will be able to
access its modules through import statements. External dependencies are
supported through git dependencies.

By default, the compiler include the standard library as a dependency, and
therefore a user can use it including the following line in the `juvix.yaml`

```yaml
# -- juvix.yaml
dependencies:
- .juvix-build/stdlib/
name: juvix-docs
version: 0.0.0
```
In `Package.juvix`, the `Package` type includes a dependencies field, which lists the other Juvix packages required by the project, with each dependency represented as an element of the `Dependency` type.

Your project's code can use modules from dependent packages via standard Juvix `import` statements.

### External dependencies
To use external dependencies, it is required to have `git` installed. You can
add a git block to the dependencies list:

```yaml
name: HelloWorld
main: HelloWorld.juvix
dependencies:
- .juvix-build/stdlib
- git:
url: https://my.git.repo
name: myGitRepo
ref: main
version: 0.1.0
There are three types of dependencies, all illustrated in the following snippet:

```juvix
--8<------ "docs/howto/project/ex2/Package.juvix:Dependencies"
```

Git block required fields:
### Git Dependencies

A `git` dependency is a Juvix package located at the root of an external git
repository. You can specify such a dependency in two ways:

- `url`: The URL of the git repository
1. By using the `git` constructor of the `Dependency` type, you can declare the dependency by providing its name (used to name the directory where the repository is cloned), the git repository URL, and the specific reference (like a version tag or branch). For example:

- `ref`: The git reference that should be checked out
```
git "juvix-containers" "https://github.com/anoma/juvix-containers" "v0.7.1"
```

2. By using the `github` function, which is a convenient method for packages hosted on GitHub. This function requires the GitHub organization name, the repository name, and the reference you're targeting. For example:

```
github "anoma" "juvix-containers" "v0.7.1"
```

!!! info Inline end "Note"

The values of the `name` fields must be unique among the git blocks in the dependencies list.

- `name`: The name for the dependency. This is used to name the
directory of the
clone, it is required. Perhaps we could come up with a way to automatically
name the clone directory. Current ideas are to somehow encode the URL / ref
combination or use a UUID. However, there's some value in having the clone
directory named in a friendly way.
### Path Dependencies

A `path` dependency is a Juvix package located on your local filesystem. You can refer to such dependencies using absolute or relative paths. For example:

```
path ".deps/a/juvix/package"
```

### The built-in Juvix standard library - `defaultStdlib`

The Juvix standard library is included with the Juvix compiler, and you can depend on it by using the `defaultStdlib` constructor.

#### Behaviour
## Behaviour of Git dependencies

When dependencies for a package are registered, at the beginning of the compiler
pipeline, all remote dependencies are processed:
Expand All @@ -128,15 +123,15 @@ pipeline, all remote dependencies are processed:

!!! info "Lock file"

* A lock file is generated in the same directory as for `juvix.yaml`. This file is used to
* A lock file, juvix.lock.yaml is generated in the same directory as `Package.juvix`. This file is used to
determine if any dependency needs to be updated. If the `ref` in the
lock file does not match the `ref` in the package file, it is considered out of date.

<!-- Add more about the new `juvix dependencies` -->

#### Fixing errors

- Missing fields in the Git dependency block are YAML parse errors
- Juvix parse or typechecker errors will be reported by the Juvix compiler.
- Duplicate `name` values in the dependencies list is an error thrown when the package file is processed
- The `ref` does not exist in the clone or the clone directory is otherwise
corrupt. An error with a suggestion to `juvix clean` is given. The package
Expand Down
7 changes: 7 additions & 0 deletions docs/howto/project/Package.juvix
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
--8<-- [start:Package]
module Package;

import PackageDescription.V1 open;

package : Package := defaultPackage;
--8<-- [end:Package]
16 changes: 16 additions & 0 deletions docs/howto/project/ex1/Package.juvix
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module Package;

import Stdlib.Prelude open;
import PackageDescription.V1 open;

--8<-- [start:Example]
package : Package :=
defaultPackage
{name := "my-package";
version := mkVersion 0 1 0;
dependencies := [ defaultStdlib
; github "anoma" "juvix-containers" "v0.7.1"
];
main := just "Main.juvix"
};
--8<-- [end:Example]
17 changes: 17 additions & 0 deletions docs/howto/project/ex2/Package.juvix
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module Package;

import Stdlib.Prelude open;
import PackageDescription.V1 open;

--8<-- [start:Dependencies]
package : Package :=
defaultPackage
{name := "my-package";
version := mkVersion 0 1 0;
dependencies := [ defaultStdlib
; github "anoma" "juvix-containers" "v0.7.1"
; git "my-dependency" "https://my-git-repo-url" "my-git-ref"
; path "a/path/to/a/juvix/package"
]
};
--8<-- [end:Dependencies]

0 comments on commit 453b120

Please sign in to comment.