Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Teach CircleCI to build Rust wrapper #353

Merged
merged 9 commits into from
Jan 28, 2019
Merged

Conversation

ilammy
Copy link
Collaborator

@ilammy ilammy commented Jan 22, 2019

Let's start checking Rust-Themis during our regular builds.

But first we have to fix a build issue with libthemis-src crate. There's a peculiar story there in commit messages. Anyway, this approach should work fine for now. Thanks for supporting symlinks, git! (No thanks to cargo package for not supporting them. I'll talk at you later.)

After that we add Rust toolchain installation into the loop and actually exercise the test suite along with other automated checks. Humans can use them too, just do tests/rust/run_tests.sh before submitting a pull request. If that fails then it's likely to be the same on the build server.

I have no idea how long this build will take on the CI. Hopefully not too long. Let's try and see... Bloated compilation times are a well-know issue with Rust. Honestly, I would not be surprised to see it taking more time than Android build. At least for the first run. Later ones may be faster due to caching, but we still have to build a metric ton of unrelated dependencies because many rustaceans seem to have been bitten by stray npm.js residents.

That's assuming the build actually works, te-he-he...

We change the build system in the next commit. This removal is done
separately because some older versions of git do not handle symlinks
well during rebases and I got tired of having to manually resolve
nonexistent merge conflicts every time I update the branch.
libthemis-src needs to embed the source code of core Themis library.
Previously, we did this by using git submodules when rust-themis was
developed in a separate repository. It was... satisfactory. (Not great
because "cargo package" refused to package "themis" directory as it
contained a Cargo.toml file.)

git submodule has been converted into a symlink to the root directory
when rust-themis was merged into the main repository. This should have
worked well, but it didn't. First of all, the "copy_dir" crate does not
copy symlinks and this breaks the build. Second, the root directory now
contains Cargo's target directory which is huge and copying it as well
significantly increases build times.

In order to reduce build time let's copy only the essential files.
Replace the quick-and-dirty "themis" symlink with a more refined
selection of files necessary to compile core Themis library. We don't
really need all the wrappers, documentation, etc. Just copy the source
code, the build system, and some other files which are unconditionally
included by the top-level makefile. (This should also significantly
reduce the size of the crate.)

Next, drop the "copy_dir" crate and replace it with our ad-hoc utility
for copying files that handles symlinks the way we need it. It's not
a general-purpose utility but it does its job well enough.

And while we're here, redirect output of "make install" to /dev/null.
It's annoying to look at when we run tests. Ideally we would like to
redirect it into stderr, but that's not possible with Command's API.
(We keep the original stderr though, so we'll see compilation errors
just fine.)

Unfortunately, running "cargo package" for libthemis-src is still kinda
broken because Cargo does not handle symlinks. This is a known issue.
Currently we will have to manually copy the source directory to resolve
all the symlinks and just get a distributable files. Annoying, yes.
We install Rust using rustup which is the most common way to do this.
This gets us the current stable version (updated if necessary). I would
like to use the Debian package for this, but Rust is not stable enough
for that yet. The language is evolving, the libraries adopt new compiler
features, and the Rust team supports only the latest stable version.
Therefore we go for downloading stuff from the Internet via rustup.rs.

In addition to core Rust toolchain we install a couple of tools that we
use for quality assurance: code formatter, static analyzer, and dead
link checker. "deadlinks" take a while to compile and install, sadly.

In general, Rust tooling *looooves* to pull lots of stuff from the net
so we cache the downloaded packages and installed binaries if possible.
This cuts down compilation time considerably, but there's still way to
go. We do a clean build of Themis so we take our time to compile all
the dependencies of dependencies...

Aside from rustc we install a couple of native dependencies. pkg-config
is required to locate Themis after installation. Clang is a dependency
of bindgen crate which is used to generate bindings for Themis.
Add "test_rust" target to Makefile which runs rust-themis tests similar
to other language wrappers. We skip the tests if Rust does not seem to
be installed on the system.

The test suite may be a bit large. We'll see how much time it takes
to run on the CI. It replicates the current setup used by the original
rust-themis on TravisCI [1]

- Disallow any warning by any tool (the compiler and alike)
- Ensure consistent code formatting with rustfmt
- Avoid common mistakes by running static analysis with Clippy
- Check both dynamic and static linkage to core Themis library
- Compile and run automated test suite for all packages
- Check that API documentation is likely to build on docs.rs
- Check that documentation does not contain dead URLs

[1]: https://github.com/ilammy/rust-themis/blob/master/.travis.yml
@ilammy ilammy added infrastructure Automated building and packaging W-RustThemis 🦀 Wrapper: Rust-Themis, Rust API, Cargo crates labels Jan 22, 2019
CircleCI runs each build step in a separate shell. Therefore we lose
environment variables set by "source ~/.cargo/env" during rustup
installation.

Append the environment configuration file to $BASH_ENV in order to
set the PATH correctly for next commands. This is a special file
read by CircleCI's bash.
It's actually not alright.

This test is flaky and is not really safe to run. It happens to behave
itself in single-threaded environment, but in reality the memory freed
from the keys is instantly reused by the allocator and does not contain
zeros anymore. It's not even guaranteed to be actually allocated.

I guess it's fine to trust zeroize to do its thing and do not verify
that memory is indeed zeroed out. Let's drop this test because flaky
CI builds are bad.
Writing some random value at arbitrary offset sometimes is not enough
to break Secure Cell. Internally, Secure Cell uses randomized keys
so the ciphertext may actually happen to contain "42" at exactly that
offset. Or so it seems to be when the tests are run by CircleCI.

Try flipping the bits instead of writing a constant. We do so in
documentation tests and this should be a better way to simulate
corrupted data.
@ilammy
Copy link
Collaborator Author

ilammy commented Jan 22, 2019

The last two commits do not really belong to this pull request. But we have to have a green build, so fix the tests here and now. I'm actually relieved that they are useful.

(Nice commit hash btw, 0463666 👹)

@ilammy ilammy mentioned this pull request Jan 23, 2019
11 tasks
I'm not a fan of this kind of installation that downloads random stuff
from the Internet, but we'll have to live with it for a while, until
Rust is stable enough for disto-packaged versions not becoming outdated
after half a year.

Let's at least add a comment about the source of the spell below so
that it can be properly audited.
src/wrappers/themis/rust/libthemis-src/src/lib.rs Outdated Show resolved Hide resolved
tests/rust/keys.rs Show resolved Hide resolved
It turns out that we can avoid copying Themis source code. The build
system supports out-of-source builds with BUILD_PATH environment
variable. Just point it into OUT_DIR and Cargo should be fine.

Remove all the copying utilities and blatant lies about Themis from
the comments.

We still keep the "optimized" symlinks instead of reverting back to
a single one pointing to the root directory of the repo. This way
it's more friendly towards crate packaging: "themis" directory won't
have a Cargo.toml inside it and the whole crate size is smaller.
@vixentael
Copy link
Contributor

@ilammy please ping when this PR is ready to be reviewed again :)

@ilammy
Copy link
Collaborator Author

ilammy commented Jan 27, 2019

@vixentael @Lagovas The PR is ready for another review round.

@vixentael vixentael merged commit 37e168d into cossacklabs:master Jan 28, 2019
@vixentael
Copy link
Contributor

Great job!

@ilammy ilammy mentioned this pull request Jan 28, 2019
@ilammy ilammy deleted the rust-build branch January 28, 2019 18:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
infrastructure Automated building and packaging W-RustThemis 🦀 Wrapper: Rust-Themis, Rust API, Cargo crates
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants