|
| 1 | +% Rust Packaging Tutorial |
| 2 | + |
| 3 | +# Introduction |
| 4 | + |
| 5 | +Sharing is caring. Rust comes with a tool, `rustpkg`, which allows you to |
| 6 | +package up your Rust code and share it with other people. This tutorial will |
| 7 | +get you started on all of the concepts and commands you need to give the gift |
| 8 | +of Rust code to someone else. |
| 9 | + |
| 10 | +## Installing External Packages |
| 11 | + |
| 12 | +First, let's try to use an external package somehow. I've made a sample package |
| 13 | +called `hello` to demonstrate how to do so. Here's how `hello` is used: |
| 14 | + |
| 15 | +~~~~ |
| 16 | +extern mod hello; |
| 17 | +
|
| 18 | +fn main() { |
| 19 | + hello::world(); |
| 20 | +} |
| 21 | +~~~~ |
| 22 | + |
| 23 | +Easy! But if you try to compile this, you'll get an error: |
| 24 | + |
| 25 | +~~~~ {.notrust} |
| 26 | +$ rustc main.rs |
| 27 | +main.rs:1:0: 1:17 error: can't find crate for `hello` |
| 28 | +main.rs:1 extern mod hello; |
| 29 | + ^~~~~~~~~~~~~~~~~ |
| 30 | +
|
| 31 | +~~~~ |
| 32 | + |
| 33 | +This makes sense, as we haven't gotten it from anywhere yet! Luckily for us, |
| 34 | +`rustpkg` has an easy way to fetch others' code: the `install` command. It's |
| 35 | +used like this: |
| 36 | + |
| 37 | +~~~ {.notrust} |
| 38 | +$ rustpkg install pkg_id |
| 39 | +~~~ |
| 40 | + |
| 41 | +This will install a package named 'pkg_id' into your current Rust environment. |
| 42 | +I called it 'pkg_id' in this example because `rustpkg` calls this a 'package |
| 43 | +identifier.' When using it with an external package like this, it's often a |
| 44 | +URI fragment. You see, Rust has no central authority for packages. You can |
| 45 | +build your own `hello` library if you want, and that's fine. We'd both host |
| 46 | +them in different places and different projects would rely on whichever version |
| 47 | +they preferred. |
| 48 | + |
| 49 | +To install the `hello` library, simply run this in your terminal: |
| 50 | + |
| 51 | +~~~ {.notrust} |
| 52 | +$ rustpkg install github.com/steveklabnik/hello |
| 53 | +~~~ |
| 54 | + |
| 55 | +You should see a message that looks like this: |
| 56 | + |
| 57 | +~~~ {.notrust} |
| 58 | +note: Installed package github.com/steveklabnik/hello-0.1 to /some/path/.rust |
| 59 | +~~~ |
| 60 | + |
| 61 | +Now, compiling our example should work: |
| 62 | + |
| 63 | +~~~ {.notrust} |
| 64 | +$ rustc main.rs |
| 65 | +$ ./main |
| 66 | +Hello, world. |
| 67 | +~~~ |
| 68 | + |
| 69 | +Simple! That's all it takes. |
| 70 | + |
| 71 | +## Workspaces |
| 72 | + |
| 73 | +Before we can talk about how to make packages of your own, you have to |
| 74 | +understand the big concept with `rustpkg`: workspaces. A 'workspace' is simply |
| 75 | +a directory that has certain sub-directories that `rustpkg` expects. Different |
| 76 | +Rust projects will go into different workspaces. |
| 77 | + |
| 78 | +A workspace consists of any directory that has the following |
| 79 | +directories: |
| 80 | + |
| 81 | +* `src`: The directory where all the source code goes. |
| 82 | +* `build`: This directory contains all of the build output. |
| 83 | +* `lib`: The directory where any libraries distributed with the package go. |
| 84 | +* `bin`: This directory holds any binaries distributed with the package. |
| 85 | + |
| 86 | +There are also default file names you'll want to follow as well: |
| 87 | + |
| 88 | +* `main.rs`: A file that's going to become an executable. |
| 89 | +* `lib.rs`: A file that's going to become a library. |
| 90 | + |
| 91 | +## Building your own Package |
| 92 | + |
| 93 | +Now that you've got workspaces down, let's build your own copy of `hello`. Go |
| 94 | +to wherever you keep your personal projects, and let's make all of the |
| 95 | +directories we'll need. I'll refer to this personal project directory as |
| 96 | +`~/src` for the rest of this tutorial. |
| 97 | + |
| 98 | +### Creating our workspace |
| 99 | + |
| 100 | +~~~ {.notrust} |
| 101 | +$ cd ~/src |
| 102 | +$ mkdir -p hello/src/hello |
| 103 | +$ cd hello |
| 104 | +~~~ |
| 105 | + |
| 106 | +Easy enough! Let's do one or two more things that are nice to do: |
| 107 | + |
| 108 | +~~~ {.notrust} |
| 109 | +$ git init . |
| 110 | +$ cat > README.md |
| 111 | +# hello |
| 112 | +
|
| 113 | +A simple package for Rust. |
| 114 | +
|
| 115 | +## Installation |
| 116 | +
|
| 117 | +``` |
| 118 | +$ rustpkg install github.com/YOUR_USERNAME/hello |
| 119 | +``` |
| 120 | +^D |
| 121 | +$ cat > .gitignore |
| 122 | +.rust |
| 123 | +build |
| 124 | +^D |
| 125 | +$ git commit -am "Initial commit." |
| 126 | +~~~ |
| 127 | + |
| 128 | +If you're not familliar with the `cat >` idiom, it will make files with the |
| 129 | +text you type inside. Control-D (`^D`) ends the text for the file. |
| 130 | + |
| 131 | +Anyway, we've got a README and a `.gitignore`. Let's talk about that |
| 132 | +`.gitignore` for a minute: we are ignoring two directories, `build` and |
| 133 | +`.rust`. `build`, as we discussed earlier, is for build artifacts, and we don't |
| 134 | +want to check those into a repository. `.rust` is a directory that `rustpkg` |
| 135 | +uses to keep track of its own settings, as well as the source code of any other |
| 136 | +external packages that this workspace uses. This is where that `rustpkg |
| 137 | +install` puts all of its files. Those are also not to go into our repository, |
| 138 | +so we ignore it all as well. |
| 139 | + |
| 140 | +Next, let's add a source file: |
| 141 | + |
| 142 | +~~~ |
| 143 | +#[desc = "A hello world Rust package."]; |
| 144 | +#[license = "MIT"]; |
| 145 | +
|
| 146 | +pub fn world() { |
| 147 | + println("Hello, world."); |
| 148 | +} |
| 149 | +~~~ |
| 150 | + |
| 151 | +Put this into `src/hello/lib.rs`. Let's talk about each of these attributes: |
| 152 | + |
| 153 | +### Crate attributes for packages |
| 154 | + |
| 155 | +`license` is equally simple: the license we want this code to have. I chose MIT |
| 156 | +here, but you should pick whatever license makes the most sense for you. |
| 157 | + |
| 158 | +`desc` is a description of the package and what it does. This should just be a |
| 159 | +sentence or two. |
| 160 | + |
| 161 | +### Building your package |
| 162 | + |
| 163 | +Building your package is simple: |
| 164 | + |
| 165 | +~~~ {.notrust} |
| 166 | +$ rustpkg build hello |
| 167 | +~~~ |
| 168 | + |
| 169 | +This will compile `src/hello/lib.rs` into a library. After this process |
| 170 | +completes, you'll want to check out `build`: |
| 171 | + |
| 172 | +~~~ {.notrust} |
| 173 | +$ ls build/x86_64-unknown-linux-gnu/hello/ |
| 174 | +libhello-ed8619dad9ce7d58-0.1.0.so |
| 175 | +~~~ |
| 176 | + |
| 177 | +This directory naming structure is called a 'build triple,' and is because I'm |
| 178 | +on 64 bit Linux. Yours may differ based on platform. |
| 179 | + |
| 180 | +You'll also notice that `src/hello/lib.rs` turned into |
| 181 | +`libhello-ed8619dad9ce7d58-0.1.0.so`. This is a simple combination of the |
| 182 | +library name, a hash of its content, and the version. |
| 183 | + |
| 184 | +Now that your library builds, you'll want to commit: |
| 185 | + |
| 186 | +~~~ {.notrust} |
| 187 | +$ git add src |
| 188 | +$ git commit -m "Adding source code." |
| 189 | +~~~ |
| 190 | + |
| 191 | +If you're using GitHub, after creating the project, do this: |
| 192 | + |
| 193 | +~~~ {.notrust} |
| 194 | +$ git remote add origin [email protected]:YOUR_USERNAME/hello.git |
| 195 | +$ git push origin -u master |
| 196 | +~~~ |
| 197 | + |
| 198 | +Now you can install and use it! Go anywhere else in your filesystem: |
| 199 | + |
| 200 | +~~~ {.notrust} |
| 201 | +$ cd ~/src/foo |
| 202 | +$ rustpkg install github/YOUR_USERNAME/hello |
| 203 | +WARNING: The Rust package manager is experimental and may be unstable |
| 204 | +note: Installed package github.com/YOUR_USERNAME/hello-0.1 to /home/yourusername/src/hello/.rust |
| 205 | +~~~ |
| 206 | + |
| 207 | +That's it! |
| 208 | + |
| 209 | +## More resources |
| 210 | + |
| 211 | +There's a lot more going on with `rustpkg`, this is just to get you started. |
| 212 | +Check out [the rustpkg manual](rustpkg.html) for the full details on how to |
| 213 | +customize `rustpkg`. |
| 214 | + |
| 215 | +A tag was created on GitHub specifically for `rustpkg`-related issues. You can |
| 216 | +[see all the Issues for rustpkg |
| 217 | +here](https://github.com/mozilla/rust/issues?direction=desc&labels=A-pkg&sort=created&state=open), |
| 218 | +with bugs as well as new feature plans. `rustpkg` is still under development, |
| 219 | +and so may be a bit flaky at the moment. |
| 220 | + |
| 221 | +You may also want to check out [this blog |
| 222 | +post](http://tim.dreamwidth.org/1820526.html), which contains some of the early |
| 223 | +design decisions and justifications. |
0 commit comments