This change allows for importing modules using a qualified name and deals with any conflicts on the way. Given a module C defined at `A/B/C.enso` with ``` type C type C a ``` it is now possible to import it as ``` import project.A ... val x = A.B.C 10 ``` Given a module located at `A/B/C/D.enso`, we will generate intermediate, synthetic, modules that only import and export the successor module along the path. For example, the contents of a synthetic module B will look like ``` import <namespace>.<pkg-name>.A.B.C export <namespace>.<pkg-name>.A.B.C ``` If module B is defined already by the developer, the compiler will _inject_ the above statements to the IR. Also removed the last elements of some lowercase name resolution that managed to survive recent changes (`Meta.Enso_Project` would now be ambiguous with `enso_project` method). Finally, added a pass that detects shadowing of the synthetic module by the type defined along the path. We print a warning in such a situation. Related to https://www.pivotaltracker.com/n/projects/2539304 # Important Notes There was an additional request to fix the annoying problem with `from` imports that would always bring the module into the scope. The changes in stdlib demonstrate how it is now possible to avoid the workaround of ``` from X.Y.Z as Z_Module import A, B ``` (i.e. `as Z_Module` part is almost always unnecessary).
7.6 KiB
layout | title | category | tags | order | |||
---|---|---|---|---|---|---|---|
developer-doc | Enso Libraries Packaging | distribution |
|
2 |
Enso Libraries Packaging
Given the nature of Enso as an open-source programming language and platform, it is crucial that we provide users with an extensible package management system. This document describes the current state of our packaging efforts, as well as future directions and enhancements to it.
Enso Package Structure
The general directory structure of an Enso package is as follows:
My_Package
├── package.yaml
├── polyglot
│ ├── java
│ │ └── jar.jar
│ └── js
│ └── library.js
├── src
│ ├── Main.enso
│ └── Sub_Module
│ ├── Helper.enso
│ └── Util.enso
├── visualization (optional)
│ └── ...
└── data (optional)
The src
Directory
The src
directory contains all Enso sources, organized in a hierarchical
structure. The structure of this directory dictates how particular modules are
imported in all of Enso code.
Note that all files and directories in this subtree must be named according to
the Enso style for referent names (i.e. Upper_Snake_Case
, see
the syntax specification).
A file located at the path My_Package/src/Sub_Module/Helper.enso
will be
imported like so:
import My_Package.Sub_Module.Helper
Please note the following:
- The name of the package appears as the first segment of the name.
- The package name is not specified by the containing directory's name, but
rather it is described in the
package.yaml
file.
The exact transformation is as follows:
- The name of the package becomes the first segment of the qualified module name.
- Any subdirectories on the path from the
src
directory to the source file are appended as consecutive segments. - The name of the source file, with the
.enso
extension stripped, becomes the last segment.
The polyglot
Directory
The polyglot
directory contains per-language subdirectories containing files
used by the supported polyglot languages. The contents of each subdirectory is
specified on a per-language basis, in the
polyglot documentation.
The data
Directory
The data
directory contains any data files and resources that the user needs
quick access to. Allows referring to resource files in a location-independent
way, by using the enso_project.data
method.
The package.yaml
File
package.yaml
describes certain package metadata, such as its name, authors and
version. It also includes the list of extra dependencies of the package
(dependencies that are not present in the resolver or need a version override).
The following is an example of this manifest file.
license: MIT
name: My_Package
version: 1.0.1
edition:
extends: 2021.3
enso-version: 0.2.12
libraries:
- name: Foo.Bar
version: 1.2.3
repository: main
prefer-local-libraries: false
authors:
- name: John Doe
email: john.doe@example.com
maintainers:
- name: Jane Doe
email: jane.doe@example.com
The following is the specification of the manifest fields. Fields marked as Optional (required for publishing) are completely optional during development - if not specified, their default values will be used. However, they must be specified before publishing the package. A package missing any of these fields cannot be published.
license
Optional (required for publishing) String: The short license name of this
package. Defaults to None
, meaning the package is not safe for use by third
parties.
edition
Optional (required for publishing) Edition: Defines the Edition settings of the package that determine the engine version and library resolution settings. It is a sub-setting that can consist of multiple fields, see the Edition documentation for the format description.
The field was added in version 0.2.12 as a replacement for enso-version
as it
supersedes its functionality.
If the edition
field is not specified, a default edition is used.
enso-version
Deprecated String: Specifies the Enso version that should be used for this
project. If not set or set to default
, the default locally installed Enso
version will be used.
The field was deprecated in version 0.2.12. Currently it is still supported, but
the newer tools will migrate it to the edition
format when the config is
modified.
If old tools see a config file that includes an edition
setting but does not
include the engine-version
(for example after the migration), they will fall
back to using the default engine version - that is because old tools were not
aware of the edition
field, so they will simply ignore it.
If a config defines the edition
field it should not define the
engine-version
field anymore, as that could lead to inconsistent engine
version settings.
version
Optional (required for publishing) String: The
semantic versioning string, in the major.minor.patch
format. If not set, it defaults to dev
(which can be used for development, but
is not a valid version for publishing).
authors
Optional List of contacts: The name(s) and contact info(s) of the author(s) of this library.
A contact is of the form:
name: Contact Name
email: email@example.com
Both name
and email
fields are optional, but at least one of them has to be
present.
maintainers
Optional List of contacts: The name(s) and contact info(s) of the current
maintainer(s) of this library, in the same format as authors
above.
prefer-local-libraries
Optional Boolean: A flag that tells the library resolver to prefer local
library versions over the ones specified by the edition configuration. This is
useful to make all local libraries easily accessible, but in more sophisticated
scenarios individual local
repository overrides should be used instead of
that. See Library Resolution for
more details.
If the flag is not specified, it defaults to false
, delegating all library
resolution to the edition configuration. However, newly created projects will
have it set to true
.
The visualization
Directory
As Enso is a visual language, a package may contain a specification of how data
can be displayed in various tools, for example
Enso IDE. The Enso package structure may
optionally contain a visualization
directory which may contain visualization
definitions.
For more information on how visualization definitions should work with the Enso IDE, see this example.
Build Reproducibility
It is crucial for any good development environment to provide reproducible builds, such that it is impossible for it to go wrong by mismatching library versions.
The actionables for this section are:
- Decide on the strategies of ensuring consistent library resolution. This may include hashing the downloaded versions of libraries and publishing stack-style resolvers for sets of libraries that are proven to work well together.