modules.md (7901B)
1 # Hare Modules 2 3 *This document is informative. It describes the behavior of the upstream Hare 4 distribution's build driver, but other Hare implementations may differ, and we 5 may revise this behavior in the future.* 6 7 TODO: 8 9 - Describe caching mechanism 10 - hare.ini considerations and linking to static libraries 11 12 The **host** is the machine which is running the build driver and Hare 13 toolchain. The **target** is the machine which the completed program is expected 14 to run on. This may not be the same as the host configuration, for example when 15 **cross-compiling**. The **build driver**, located at `cmd/hare`, orchestrates 16 this process by collecting the necessary source files to build a Hare program, 17 resolving its dependencies, and executing the necessary parts of the toolchain 18 in the appropriate order. 19 20 ## The build driver and the Hare specification 21 22 The Hare language specification is defined at a layer of abstraction that does 23 not include filesystems, leaving it to the implementation to define how Hare 24 sources are organized. The upstream Hare distribution maps the concept of a 25 "module" onto what the spec defines as a *unit*, and each Hare source file in 26 the filesystem provides what the specification refers to as a *subunit*. 27 28 The upstream Hare distribution provides the "hosted" translation environment. 29 Hare programs prepared for the "freestanding" environment may also be compiled 30 with the upstream distribution, but the standard library is not used in this 31 situation. 32 33 ## Build tags 34 35 The upstream distribution defines the concept of a **build tag**, or "tag", 36 which is an alphanumeric string and an "inclusive" or "exclusive" bit, which is 37 used to control the list of source files considered for inclusion in a Hare 38 module. 39 40 The environment defines a number of default build tags depending on the target 41 system it was configured for. For example, a Linux system running on an x86\_64 42 processor defines +linux and +x86\_64 by default, which causes files tagged 43 +linux or +x86\_64 to be included, and files tagged -linux or -x86\_64 to be 44 excluded. 45 46 The host configuration defines a set of default build tags, which may be 47 overridden by specifying an alternate target. The `hare version -v` command 48 prints out the defaults. 49 50 It is important to note that Hare namespaces and build tags are mutually 51 exclusive grammars, thanks to the fact that the + and - symbols may not appear 52 in a Hare identifier. 53 54 ## Locating modules on the filesystem 55 56 Each module, identified by its namespace, is organized into a "**module root**" 57 directory, where all of its source files may be found, either as members or 58 descendants. This directory corresponds to a file path which is formed by 59 replacing the namespace delimiters (`::`) with the path separator for the target 60 host system (e.g. `/`). This forms a relative path, which is then applied to 61 each of several possible **source roots**. 62 63 A source root is a directory which forms the top of a hierarchy of Hare modules 64 and their sources. This directory may also itself be a module, namely the **root 65 module**: it provides the unit for the empty namespace, where, for example, the 66 "main" function can be found. Generally speaking, there will be at least two 67 source roots to choose from: the user's program, and the standard library. 68 69 The current working directory (`.`) is always assigned the highest priority. If 70 the `HAREPATH` environment variable is set, it specifies a colon-delimited (`:`) 71 list of additional candidates in descending order of preference. If unset, a 72 default value is used, which depends on the host configuration, generally 73 providing at least the path to the standard library's installation location, as 74 well the installation location of third-party Hare modules. The `hare version 75 -v` command prints out the defaults configured for this host. 76 77 Each of these source roots is considered in order of precedence by concatenating 78 the source root path and the relative path of the desired module, and checking 79 if a **valid** Hare module is present. A module is considered valid if it 80 contains any regular files, or symlinks to regular files, whose names end in 81 `.ha` or `.s`; or if it contains any directories, or symlinks to directories; 82 whose names begin with `+` or `-` and which would also be considered valid under 83 these criteria, applied recursively. 84 85 The user's program, or any dependency, may *shadow* a module from the standard 86 library (or another dependency) by providing a suitably named directory in a 87 source root with a higher level of precedence. 88 89 ## Assembling the list of source files 90 91 A source file is named with the following convention: 92 93 `<name>[<tags...>].<ext>` 94 95 The \< and \> symbols denote a required parameter, and \[ and \] denote optional 96 parameters. Some example names which follow this convention are: 97 98 - `main.ha` 99 - `pipe+linux.ha` 100 - `example-freebsd.ha` 101 - `longjmp.s` 102 - `foo+linux-x86_64.ha` 103 104 The build driver examines the list of files in a given module's root directory, 105 eliminating those with incompatible build tags, and produces a list of 106 applicable files. Once files with incompatible build tag have been eliminated, 107 only one file for a given "name" may be provided, such that a module with the 108 files `hello.ha` and `hello.s` is invalid. Only the "ha" and "s" extensions are 109 used, respectively denoting Hare sources and assembly sources. 110 111 If any sub-directories of the module's root directory begin with `-` or `+`, 112 they are treated as a set of build tags and considered for their compatibility 113 with the build driver's active set of build tags. If compatible, the process is 114 repeated within that directory, treating its contents as members of the desired 115 module. 116 117 ## Semantics of specific tools 118 119 A summary of how the mechanisms documented above are applied by each tool is 120 provided. 121 122 ### hare build, hare run 123 124 The input to this command is the location of the root module for the Hare 125 program to be built or run. If the path provided identifies a file, that file is 126 used as the sole input file for the root module. If the path identifies a 127 directory, the directory is used as the root directory for the root module, 128 whose source files are assembled according to the algorithm described above. 129 130 ### hare test 131 132 `hare test` walks the current source root (i.e. the current working directory) 133 by recursively checking if that directory, and every directory which is a 134 descendant of it, is a valid Hare module. Each of these modules is compiled with 135 the special +test build tag defined. Dependencies of these modules are also 136 built, but with the +test tag unspecified, with the exception of the rt module, 137 which provides a special test runner in this mode. The resulting executable is 138 executed, which causes all of the `@test` functions in the current source root 139 to be executed. 140 141 The command line arguments for hare test, if given at all, are interpreted by 142 rt+test as a list of namespace wildcards (see [fnmatch]) defining which subsets 143 of the test suite to run. 144 145 [fnmatch]: https://docs.harelang.org/fnmatch 146 147 ### haredoc 148 149 The `haredoc` command accepts a list of identifiers to fetch documentation for, 150 using the same identifiers which the user might use in a Hare source file to 151 utilize the corresponding module or declaration. 152 153 The desired identifier is converted to a path. If this path refers to a 154 directory which is a valid Hare module, documentation for that module is shown. 155 If that path refers to a directory which is not a valid Hare module, it is 156 walked to determine if any of its sub-directories are valid Hare modules; if so, 157 a list of those sub-directories is shown. If the path does not exist, the most 158 specific component of the identifier is removed, and looked up as a module, 159 within which the least-significant component is looked up as a declaration 160 exported from that module. If the module or this declaration still is not found, 161 the identifier is deemed unresolvable and an error is shown.