summary refs log tree commit diff
path: root/doc/rustpkg.md
blob: 399a76426654ac76dd2e82aca1cf590b6e1b2069 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
% Rustpkg Reference Manual

# Introduction

This document is the reference manual for the Rustpkg packaging and build tool for the Rust programming language.

## Disclaimer

Rustpkg is a work in progress, as is this reference manual.
If the actual behavior of rustpkg differs from the behavior described in this reference,
that reflects either an incompleteness or a bug in rustpkg.

# Package searching

rustpkg searches for packages using the `RUST_PATH` environment variable,
which is a colon-separated list (semicolon-separated on Windows) of directories.

Each directory in this list is a *workspace* for rustpkg.

`RUST_PATH` implicitly contains an entry for `./.rust` (as well as
`../.rust`, `../../.rust`,
and so on for every parent of `.` up to the filesystem root).
That means that if `RUST_PATH` is not set,
then rustpkg will still search for workspaces in `./.rust` and so on.
`RUST_PATH` also implicitly contains an entry for the system path:
`/usr/local` or the equivalent on Windows.
This entry comes after the implicit entries for `./.rust` and so on.
Finally, the last implicit entry in `RUST_PATH` is `~/.rust`
or the equivalent on Windows.

Each workspace may contain one or more packages.

When building code that contains one or more directives of the form `extern mod P`,
rustpkg automatically searches for packages named `P` in the `RUST_PATH` (as described above).
It builds those dependencies if necessary.
Thus, when using rustpkg,
there is no need for `-L` flags to tell the linker where to find libraries for external crates.

# Package structure

A valid workspace must contain each of the following subdirectories:

* 'src/': contains one subdirectory per package. Each subdirectory contains source files for a given package.

     For example, if `foo` is a workspace containing the package `bar`,
     then `foo/src/bar/main.rs` could be the `main` entry point for
     building a `bar` executable.
* 'lib/': `rustpkg install` installs libraries into a target-specific subdirectory of this directory.

     For example, on a 64-bit machine running Mac OS X,
     if `foo` is a workspace containing the package `bar`,
     rustpkg will install libraries for bar to `foo/lib/x86_64-apple-darwin/`.
     The libraries will have names of the form `foo/lib/x86_64-apple-darwin/libbar-[hash].dylib`,
     where [hash] is a hash of the package ID.
* 'bin/': `rustpkg install` installs executable binaries into this directory.

     For example, rustpkg will install executables for `bar` to
     `foo/bin`.
     The executables will have names of the form `foo/bin/bar`.
* 'build/': `rustpkg build` stores temporary build artifacts in a target-specific subdirectory of this directory.

     For example, on a 64-bit machine running Mac OS X,
     if `foo` is a workspace containing the package `bar` and `foo/src/bar/main.rs` exists,
     then `rustpkg build` will create `foo/build/x86_64-apple-darwin/bar/main.o`.

# Package identifiers

A package identifier identifies a package uniquely.
A package can be stored in a workspace on the local file system,
or on a remote Web server, in which case the package ID resembles a URL.
For example, `github.com/mozilla/rust` is a package ID
that would refer to the git repository browsable at `http://github.com/mozilla/rust`.
A package ID can also specify a version, like:
`github.com/mozilla/rust#0.3`.
In this case, `rustpkg` will check that the repository `github.com/mozilla/rust` has a tag named `0.3`,
and report an error otherwise.
A package ID can also specify a particular revision of a repository, like:
`github.com/mozilla/rust#release-0.7`.
When the refspec (portion of the package ID after the `#`) can't be parsed as a decimal number,
rustpkg passes the refspec along to the version control system without interpreting it.
rustpkg also interprets any dependencies on such a package ID literally
(as opposed to versions, where a newer version satisfies a dependency on an older version).
Thus, `github.com/mozilla/rust#5c4cd30f80` is also a valid package ID,
since git can deduce that 5c4cd30f80 refers to a revision of the desired repository.

A package identifier can name a subdirectory of another package.
For example, if `foo` is a workspace, and `foo/src/bar/lib.rs` exists,
as well as `foo/src/bar/extras/baz/lib.rs`,
then both `bar` and `bar/extras/baz` are valid package identifiers
in the workspace `foo`.

## Source files

rustpkg searches for four different fixed filenames in order to determine the crates to build:

* `main.rs`: Assumed to be a main entry point for building an executable.
* `lib.rs`: Assumed to be a library crate.
* `test.rs`: Assumed to contain tests declared with the `#[test]` attribute.
* `bench.rs`: Assumed to contain benchmarks declared with the `#[bench]` attribute.

## Versions

`rustpkg` packages do not need to declare their versions with an attribute inside one of the source files,
because `rustpkg` infers it from the version control system.
When building a package that is in a `git` repository,
`rustpkg` assumes that the most recent tag specifies the current version.
When building a package that is not under version control,
or that has no tags, `rustpkg` assumes the intended version is 0.1.

> **Note:** A future version of rustpkg will support semantic versions.
> Also, a future version will add the option to specify a version with a metadata
> attribute like `#[link(vers = "3.1415")]` inside the crate module,
> though this attribute will never be mandatory.

# Dependencies

rustpkg infers dependencies from `extern mod` directives.
Thus, there should be no need to pass a `-L` flag to rustpkg to tell it where to find a library.
(In the future, it will also be possible to write an `extern mod` directive referring to a remote package.)

# Custom build scripts

A file called `pkg.rs` at the root level in a workspace is called a *package script*.
If a package script exists, rustpkg executes it to build the package
rather than inferring crates as described previously.

Inside `pkg.rs`, it's possible to call back into rustpkg to finish up the build.
`rustpkg::api` contains functions to build, install, or clean libraries and executables
in the way rustpkg normally would without custom build logic.

# Command reference

## build

`rustpkg build foo` searches for a package with ID `foo`
and builds it in any workspace(s) where it finds one.
Supposing such packages are found in workspaces X, Y, and Z,
the command leaves behind files in `X`'s, `Y`'s, and `Z`'s `build` directories,
but not in their `lib` or `bin` directories.

## clean

`rustpkg clean foo` deletes the contents of `foo`'s `build` directory.

## install

`rustpkg install foo` builds the libraries and/or executables that are targets for `foo`.
If `RUST_PATH` is declared as an environment variable, then rustpkg installs the
libraries and executables into the `lib` and `bin` subdirectories
of the first entry in `RUST_PATH`.
Otherwise, it installs them into `foo`'s `lib` and `bin` directories.

## test

`rustpkg test foo` builds `foo`'s `test.rs` file if necessary,
then runs the resulting test executable.