Hello, Rust! #1 – Cargo: the package manager

Continuation of this post.

Post #0 was verbose, but from now on I’ll try to go straight to the point. Comments either too verbose or out of scope will usually be placed on footnotes, like this one [1], so it’s up to you to choose if you will read them or not.

Cargo is the de-facto — and standard — rust package manager. it is not only a package manager, but a “build manager” too. So let’s analyze what this means:

(i): build manager

Think of it as C/C++ cmake, or make, or Scala’s SBT (Simple Build Tool). You can put your project metadata and its build dependencies on a file which cargo can read and do cool stuff about it. This file is Cargo.toml.

I remember seeing this TOML thing before: https://github.com/toml-lang/toml

It is like a JSON or a YAML file; or, even better for our analogy purposes, like a ‘.ini’ file. The contents of this file are just key/pair values, divided in sections (or subsections, if you want to call them this way).

The default Cargo.toml file that is created for me after I create a new Rust project with

cargo new --vcs git --bin sudoku

is simply

name = "sudoku"
version = "0.1.0"
authors = ["Thiago Perrotta "]

Note that the ‘authors’ value was extracted from my ~/.gitconfig file. So,

cargo build

will do pretty much what you expect. By default, it builds an executable in DEBUG mode. If you want a production version of your program, just add ‘–release’ to the previous command. Let’s look at our current directory structure now:

$ tree
├── Cargo.lock
├── Cargo.toml
├── src
│   └── main.rs
└── target
 └── debug
 ├── build
 ├── deps
 ├── examples
 ├── native
 └── sudoku

The build created the ‘target/debug’ directory. If you opted for the production version, a ‘target/release’ one would be created instead. Both can coexist at the same time. Now, if you run ‘cargo build’ again, it will finish faster than before, because there is nothing new to compile. I suppose cargo uses a mechanism similar to GNU Make, where compilations are done only if the source code is newer (in time) than its dependencies.

Okay, cargo looks like a good friend. We can do cargo {new, build, clean} and it looks enough. A tab complete on zsh or bash, however, will reveal several more subcommands that might be useful later on.  A few examples include:

  • cargo run ==> if you’re in a hurry (think of this as ‘scala main.scala’, instead of ‘scalac main.scala’)
  • cargo doc ==> we don’t have documentation yet, just a hello world
  • cargo test ==> yaaay, (unit?) test
  • cargo bench ==> this is like Golang…benchmarks
  • cargo publish ==> hmmmm…it looks like a way for us to create our own packages and maybe, later on, put them on a public repository (such as crates.io <== analogous to npm)

OK, let’s stop for now. Oh, just one more: ‘cargo search’ (!). A quick example…’cargo search regex’. It returns a few results. If you want to explore more, run ‘cargo –list’ to see all available commands.

(ii) package manager

I already said a few bits about it in the previous section: by being able to interact with the crates.io server, cargo also acts as Rust package manager. You can search for packages, download them, add them as build dependencies of your project, possibly specifying the version you want, and so on.

You can also use the same cargo command-line tool to publish packages to the official repository. It is really simple, just a matter of ‘cargo login’ first, then figuring out how to update your package 😉

For me, it looks better than python’s pip and comparable to ruby gems and node’s npm, but it is still too early to make any judgements.

Wrapping up

Okay, so cargo looks really simple yet efficient. It reminds me of ‘lein’ for clojure and ‘sbt’ for scala: it seems to have sane defaults so the rust programmer probably won’t struggle configuring the build system — now, this doesn’t mean that he won’t struggle with the compiler…well, I guess we are set up now and can live by ourselves without an IDE, at least for managing our future project.

Next post.


  • [1]: see? Also, I’m a learner, so I’ll describe the things the way I expect them to be. However, my description won’t always be 100% correct. So pay attention if you intend to use any of this information in production.
Hello, Rust! #1 – Cargo: the package manager

Here be packages! FreeBSD Overview (Part II)

TL;DR: in this post: about getting software and managing packages and ports on FreeBSD 10. The first post on this series is available here.

Binary package management

pkgng seems to be the defacto standard way to manage and install binary FreeBSD packages. Its interface is pretty tradicional; users of Ruby Gems, node’s npm and stuff should not have trouble using it. For example, pkg install bash was one of the first things I tried. The second one was pkg install emacs, but this has failed. Then a simple pkg search emacs would reveal that the correct name should be emacs24, emacs23 or emacs-nox11. I opted for the last one. Other simple commands involve pkg remove, pkg info, pkg stats and pkg help. For starters, this is enough. A feature that I love in any package manager is the reverse query, where you enter a file in your system and then get the package that installed it. pkg which does that. Another one which helps learning how files are organized within a package is listing all the files inside a package. pkg info -l does that. I like to introspect quickly what are the commands of a package manager by inspecting the source code of pacapt. A remarkable feature is pkg audit, which shows the user any known vulnerabilities. I’ve never seen this before – Linux distributions simply update their packages, that’s the way of being safe, so I’m not sure of the usefulness of audit. Finally, to locally install a .txz package you use pkg add /path/to/pkg. All the commands I listed here should be enough to get your feet wet. What’s next? Let’s try to remove a dependent package. For example, pkg info -d emacs-nox11 shows me that emacs depends on libxml2. So, let’s try to remove this dependency? pkg remove libxml2 gives me an error, telling me that it depends on emacs. Nice. If I want to forcefully and cleanly remove it, I should enter pkg remove -R. This would remove emacs as well. As the quantity of binary packages available, I’ve found out that there are 24k packages. For comparison, the debian base has about 40k and the Arch Linux one 7k (if you add the Arch User Repository, this list gets bigger than 50k). So I could say that the quantity is reasonable. While I don’t expect to find everything, this base should cover standard use cases. What about out-of-dateness of those packages? You know, Debian, CentOS and these “stable server family” are slow about updating their packages; I’ve made quick tests by searching for nodejs, nginx, apache, mongodb. I’m impressed, they were all up-to-date. Even calibre (which is changing faster nowadays) was up-to-date (in the 1.43 version). I used this to learn about pkg, plus pkg itself (it looks well documented). It is worth noting that this pkg utility has been introduced in this tenth release of FreeBSD. Before it, it looks like there were a collection of programs responsible for package management, such as pkg_add, portmaster, something along these lines.

Ports (source) system

Using pkg is not the only way of getting software installed on FreeBSD. The user may also opt for using its ports system. It works like the Arch Build System (ABS) and Gentoo’s portage. cd into /usr/ports, then you’ll see several directories with categories. I’ve made a quick test with editors/uemacs. There were a couple of files inside this directory. Most notably, a Makefile ; and additionally, several files with metadata. I expected to see something like a PKGBUILD or a ebuild, but I didn’t. I believe the equivalent of these on the FreeBSD world are fetched on-the-fly. make built the package; make package installed it. Hmmm, I expected that this last command would create a .txz package, then I should install it with pkg add, but this wasn’t the case. make install and make clean both also work. I’m suspecting that this BSD makefile is just the GNU Makefile of uemacs, but with a few patches applied to it (in fact, there are indeed some patches lying there). But how we update our ports to the newest versions? portsnap is the answer. You can see the in the manual. portsnap fetch looks like the most common command, followed by portsnap update. However, the manual recommends doing portsnap fetch; portsnap extract (this takes a while) the first time you issue this command. Then forget extract and just use update. portsnap fetch update is a one-shot way of doing this. It is also possible to use subversion to update the ports tree, but I’m okay with the recommended method. (I later discovered that program source code is installed into /usr/ports/distfiles.) This is a manual about creating new ports. I expect to create some if I decide {I like,to stick to} FreeBSD, for the same reason that I maintain a collection of PKGBUILDs for Arch Linux. What about upgrading ports? Install portmaster (using pkg or the ports system, the way you prefer), then issue portmaster -a. It is recommended to use portmaster -L prior to that. It looks like there is another utility to do this function, called portupgrade (suggestive, huh?). Last thing about ports: portsclean frees up some disk space (see its manual).

What’s next?

I decided to create an org file to track what I’ll try next. Here is a snapshot of it as of this post:
* DONE Binary packages
* DONE Ports
* TODO X Window System (X11)
* TODO nginx hello world
* TODO C/C++ Hello World
* TODO golang Hello World
* TODO create a new port (poudriere?)
* TODO jails, chroot, etc
* TODO services (rc.conf, /etc/rc)
* TODO Linux compatibility?
* TODO what about user contributions? Is there something like AUR? Maybe freshports?

And what are my problems for now?

  • poor resolution (I believe it is 640×480).
  • american keyboard
  • no autocompletion and no colors! I’m still using csh (the default shell, as echo $SHELL shows), despite of installing bash. I’ll probably change my default shell to bash or zsh later on, and install a few plug-ins to them (no, not oh-my-zsh stuff, it is much bloated for servers).

Next post.

Edit: (2014-07-29): thanks Alex for correcting me in the comments.

Here be packages! FreeBSD Overview (Part II)

Setups no Windows, nunca mais

Uma vez que você se acostuma com package managers no Linux, é bastante inconveniente voltar à vibe de ficar instalando programa por programa no Windows, clicando em ‘next’ o tempo todo.

Para resolver isso foi criado o chocolatey, um repositório com vários pacotes para o Windows, descrevendo-o a grosso modo.

Eu o uso há bastante tempo, para falar a verdade. Só que agora me apareceu um novo problema: como reproduzir a mesma instalação em vários computadores diferentes, de uma vez só?

Motivado por isso, criei um repositório com o sugestivo nome de windows-setups-nevermore. As instruções estão no arquivo README. Resumidamente, basta você especificar todos os pacotes que você quer em um arquivo chamado packages.config, depois executar o arquivo setup.cmd. E voilà, em poucos minutos todos os seus programas serão automagicamente instalados, adicionados ao PATH e ao menu iniciar.

Naturalmente isso se limita, a priori, somente aos pacotes na galeria/catálogo do chocolatey. Se o pacote que você quiser não estiver lá, você terá que adicioná-lo sozinho, ou instalá-lo manualmente, o que for preferível. Além do mais, só estão lá os programas cujas licenças admitem que eles sejam redistribuídos (você não vai encontrar o Microsoft Office lá, por exemplo).

Update (2014-07-07): esse método provavelmente não instala bloatware — por exemplo, as diversas barras de ferramentas ou outros plug-ins para seus web browsers. No entanto, a melhor forma de comprovar isso é ou analisando o código-fonte do pacote ou instalando-o.

Setups no Windows, nunca mais