Test the Resolver against the varisat Library
Resolution can be reduced to the SAT problem. So this is an alternative implementation of the resolver that uses a SAT library for the hard work. This is intended to be easy to read, as compared to the real resolver, and run as part of the test sweet to make sure the real resolver works as expected. Part of #6120.
Some notes on performance:
The initial version did not support public & private deps:
~64 loc, `O(nln(n))` vars, `O(nln(n) + n*d)` clauses, 0.5x slower on `prop_passes_validation`
The final version:
~163 loc, `O(dn^2`) vars, `O(dn^3)` clauses, 1.5x slower on `prop_passes_validation`
That comparison makes me feel better about spending months trying to get public & private deps to be fast enough for stabilization.
Parse less JSON on null builds
This commit fixes a performance pathology in Cargo today. Whenever Cargo
generates a lock file (which happens on all invocations of `cargo build`
for example) Cargo will parse the crates.io index to learn about
dependencies. Currently, however, when it parses a crate it parses the
JSON blob for every single version of the crate. With a lock file,
however, or with incremental builds only one of these lines of JSON is
relevant. Measured today Cargo building Cargo parses 3700 JSON
dependencies in the registry.
This commit implements an optimization that brings down the number of
parsed JSON lines in the registry to precisely the right number
necessary to build a project. For example Cargo has 150 crates in its
lock file, so now it only parses 150 JSON lines (a 20x reduction from
3700). This in turn can greatly improve Cargo's null build time. Cargo
building Cargo dropped from 120ms to 60ms on a Linux machine and 400ms
to 200ms on a Mac.
The commit internally has a lot more details about how this is done but
the general idea is to have a cache which is optimized for Cargo to read
which is maintained automatically by Cargo.
Closes#6866
This commit fixes a performance pathology in Cargo today. Whenever Cargo
generates a lock file (which happens on all invocations of `cargo build`
for example) Cargo will parse the crates.io index to learn about
dependencies. Currently, however, when it parses a crate it parses the
JSON blob for every single version of the crate. With a lock file,
however, or with incremental builds only one of these lines of JSON is
relevant. Measured today Cargo building Cargo parses 3700 JSON
dependencies in the registry.
This commit implements an optimization that brings down the number of
parsed JSON lines in the registry to precisely the right number
necessary to build a project. For example Cargo has 150 crates in its
lock file, so now it only parses 150 JSON lines (a 20x reduction from
3700). This in turn can greatly improve Cargo's null build time. Cargo
building Cargo dropped from 120ms to 60ms on a Linux machine and 400ms
to 200ms on a Mac.
The commit internally has a lot more details about how this is done but
the general idea is to have a cache which is optimized for Cargo to read
which is maintained automatically by Cargo.
Closes#6866
This is intended to fix#6747 where multiple Cargos invoked with the
same jobserver would all have their own token but not actually run
concurrently due to file locking. Instead the fix is that whenever Cargo
blocks for a file lock with a configured global jobserver, a token is
released just before we block and then reacquired afterwards. This way
we should ensure that we're not hogging a cpu/token unnecessarily
without doing any work!
Closes#6747
It can be difficult to figure out what's wrong when a user reports that
`cargo fix` fails. There's often a large list of warnings, and it can
be hard to figure out which one caused a compile error.
This makes the deny(warnings) in the testsuite conditional on a new
"deny-warnings" feature, that is then enabled in CI.
Ideally I could use the (reasonably well established) CI env var (like
we do for proptests), but I don't know how to get the attribute to be
defined in terms of an env var.
We're already pulling in zlib for other dependencies like curl/libgit2
so there's not really much use in duplicating the compression code with
miniz, so let's instruct `flate2` to use libz as well to compress and
decompress chunks.
This commit switches Cargo to using HTTP/2 by default. This is
controlled via the `http.multiplexing` configuration variable and has
been messaged out for testing [1] (although got very few responses).
There's been surprisingly little fallout from parallel downloads, so
let's see how this goes!
[1]: https://internals.rust-lang.org/t/testing-cargos-parallel-downloads/8466
Fix timeouts firing while tarballs are extracted
This commit fixes#6125 by ensuring that while we're extracting tarballs
or doing other synchronous work like grabbing file locks we're not
letting the timeout timers of each HTTP transfer keep ticking. This is
curl's default behavior (which we don't want in this scenario). Instead
the timeout logic is inlined directly and we manually account for the
synchronous work happening not counting towards timeout limits.
Closes#6125
This commit fixes#6125 by ensuring that while we're extracting tarballs
or doing other synchronous work like grabbing file locks we're not
letting the timeout timers of each HTTP transfer keep ticking. This is
curl's default behavior (which we don't want in this scenario). Instead
the timeout logic is inlined directly and we manually account for the
synchronous work happening not counting towards timeout limits.
Closes#6125
use proptest to fuzz the resolver
This has been a long time goal. This uses proptest to generate random registry indexes and throws them at the resolver.
It would be simple to generate a registry by,
1. make a list of name and version number each picked at random
2. for each pick a list of dependencies by making a list of name and version requirements at random.
Unfortunately, it would be extremely unlikely to generate any interesting cases, as the chance that the random name you depend on was also generated as the name of a crate is vanishingly small. So this implementation works very hard to ensure that it only generates valid dependency requirements.
This is still a WIP as it has many problems:
- [x] The current strategy is very convoluted. It is hard to see that it is correct, and harder to see how it can be expanded. Thanks to @centril for working with me on IRC to get this far. Do you have advice for improving it?
- [X] It is slow as molasses when run without release. I looked with a profilere and we seem to spend 2/3 of the time in `to_url`. Maybe we can special case `example.com` for test, like we do for `crates.io` or something? Edit: Done. `lazy_static` did its magic.
- [x] `proptest` does not yet work with `minimal-versions`, a taste of my own medicine.
- [x] I have not verified that, if I remove the fixes for other test that this regenerates them.
The current strategy does not:
- [x] generate interesting version numbers, it just dose 1.0.0, 2.0.0 ...
- [x] guarantee that the version requirements are possible to meet by the crate named.
- [ ] generate features.
- [ ] generate dev-dependencies.
- [x] build deep dependency trees, it seems to prefer to generate crates with 0 or 1 dependents so that on average the tree is 1 or 2 layers deep.
And last but not least, there are no interesting properties being tested. Like:
- [ ] If resolution was successful, then all the transitive requirements are met.
- [x] If resolution was successful, then unpublishing a version of a crate that was not selected should not change that.
- [x] If resolution was unsuccessful, then it should stay unsuccessful even if any version of a crate is unpublished.
- [ ] @maurer suggested testing for consistency. Same registry, same cargo version, same lockfile, every time.
- [ ] @maurer suggested a pareto optimality property (if all else stays the same, but new package versions are released, we don't get a new lockfile where every version is <= the old one, and at least one is < the old one)
This commit tweaks how configuration is loaded for `cargo install`, ensuring
that we only load configuration from `$HOME` instead of the current working
directory. This should make installations a little more consistent in that they
probably shouldn't cover project-local configuration but should respect global
configuration!
Closes#6025
This is actually a super tricky problem. We don't really have the capacity for
more than one line of update-able information in Cargo right now, so we need to
squeeze a lot of information into one line of output for Cargo. The main
constraints this tries to satisfy are:
* At all times it should be clear what's happening. Cargo shouldn't just hang
with no output when downloading a crate for a long time, a counter ideally
needs to be decreasing while the download progresses.
* If a progress bar is shown, it shouldn't jump around. This ends up just being
a surprising user experience for most. Progress bars should only ever
increase, but they may increase at different speeds.
* Cargo has, currently, at most one line of output (as mentioned above) to pack
information into. We haven't delved into fancier terminal features that
involve multiple lines of update-able output.
* When downloading crates as part of `cargo build` (the norm) we don't actually
know ahead of time how many crates are being downloaded. We rely on the
calculation of unit dependencies to naturally feed into downloading more
crates.
* Furthermore, once we decide to download a crate, we don't actually know how
big it is! We have to wait for the server to tell us how big it is.
There doesn't really seem to be a great solution that satisfies all of these
constraints unfortunately. As a result this commit implements a relatively
conservative solution which should hopefully get us most of the way there. There
isn't actually a progress bar but rather Cargo prints that it's got N crates
left to download, and if it takes awhile it prints out that there are M bytes
remaining.
Unfortunately the progress is pretty choppy and jerky, not providing a smooth
UI. This appears to largely be because Cargo will synchronously extract
tarballs, which for large crates can cause a noticeable pause. Cargo's not
really prepared internally to perform this work on helper threads, but ideally
if it could do so it would improve the output quite a bit! (making it much
smoother and also able to account for the time tarball extraction takes).
This commit implements parallel downloads using `libcurl` powered by
`libnghttp2` over HTTP/2. Using all of the previous refactorings this actually
implements usage of `Multi` to download crates in parallel. This achieves some
large wins locally, taking download times from 30s to 2s in the best case.
The standard output of Cargo is also changed as a result of this commit. It's
no longer useful for Cargo to print "Downloading ..." for each crate really as
they all start instantaneously. Instead Cargo now no longer prints `Downloading`
by default (unless attached to a pipe) and instead only has one progress bar for
all downloads. Currently this progress bar is discrete and based on the total
number of downloads, no longer specifying how much of one particular download
has happened. This provides a less granular view into what Cargo is doing but
it's hoped that it looks reasonable from an outside perspective as there's
still a progress bar indicating what's happening.
BUG fuzzing found a bug in the resolver, we need a complete set of conflicts to do backjumping
As mentioned in https://github.com/rust-lang/cargo/pull/5921#issuecomment-418890269, the new proptest found a live bug! This PR so far tracs my attempt to minimize the problematic input.
The problem turned out to be that we where backjumping on incomplete set of conflicts.
run some tests with minimal-versions on CI
In #5757 we discovered that sum test don't pass with minimal-versions, and so only added CI for `cargo check`. This PR is to see if that is still needed, and if it is then which test rely on upstream bugfix.
Improve verbose console and log for finding git repo in package check
Third attempt to resolve#5823 by improving logging and tests. This exposes the issue to testing, via verbose console output and is dependent on alexcrichton/git2-rs#341 as just released in git2 0.7.5 crate. Thus tests *should* now pass on all platforms, incl. windows, but I also intend to bump the minimal git2 release dependency (in a subsequently added commit).
cc: @Eh2406 thanks for your fix and help!
Fully capture rustc and rustdoc output when -Zcompile-progress is passed
Fixes#5764 and #5695.
On Windows, we will parse the ANSI escape code into console commands via my `fwdansi` package, based on @ishitatsuyuki's idea in https://github.com/rust-lang/cargo/issues/5695#issuecomment-406300234. Outside of Windows the content is forwarded as-is.
This commit updates the `cargo fix` implementation to iteratively apply fixes
from the compiler instead of only once. Currently the compiler can sometimes
emit overlapping suggestions, such as in the case of transitioning
::foo::<::Bar>();
to ...
crate::foo::<crate::Bar>();
and `rustfix` rightfully can't handle overlapping suggestions as there's no
clear way of how to disambiguate the fixes. To fix this problem Cargo will now
run `rustc` and `rustfix` multiple times, attempting to reach a steady state
where no fixes failed to apply.
Naturally this is a pretty tricky thing to do and we want to be sure that Cargo
doesn't loop forever, for example. A number of safeguards are in place to
prevent Cargo from going off into the weeds when fixing files, notably avoiding
to reattempt fixes if no successful fixes ended up being applied.
Closes#5813Closesrust-lang/rust#52754
This commit imports the `cargo fix` subcommand in rust-lang-nursery/rustfix
directly into Cargo as a subcommand. This should allow us to ease our
distribution story of `cargo fix` as we prepare for the upcoming 2018 edition
release.
It's been attempted here to make the code as idiomatic as possible for Cargo's
own codebase. Additionally all tests from cargo-fix were imported into Cargo's
test suite as well. After this lands and is published in nightly the `cargo-fix`
command in rust-lang-nursery/rustfix will likely be removed.
cc rust-lang/rust#52272
Right now the rust-lang/rust integration is compiling Cargo twice on dist
builds, once for Cargo and once for the RLS. This is due to a dependency of
Cargo being recompiled with different features when used from the RLS or not.
For now paper over this problem with a synthetic dependency to prevent Cargo
from being compiled twice.
Clap
Reopening of #5129
So, looks like all tests are 🍏 on my machine!
I definitely want to refactor it some more, and also manually checked that we haven't regressed any help messages, but all the major parts are in place already.
This hasn't been updated in awhile and in general we've been barely using it.
This drops the outdated dependency and vendors a small amount of the
functionality that it provided. I think eventually we'll want to transition away
from this method of assertions but I wanted to get this piece in to avoid too
much churn in one commit.
There are some important fixes in jobserver >=0.1.8. With earlier
versions, it's possible for cargo to panic with a "failed to acquire
jobserver token" error, which can be very hard to track down.
Requiring the latest version of jobserver makes sure that no such error
can make it into downstream distributions.
Cargo.toml: Replace '/' with 'OR' in 'license'
Catch up with our recommendations from 7dee65fe (#4898), which deprecated `/` in favor of vanilla SPDX license expressions.
I've gone with the disjunctive `OR`, because the README has:
> Cargo is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0).
Catch up with our recommendations from 7dee65fe (src/doc/manifest: Pin
'license' to SPDX 2.1 expressions and the 2.4 list, 2018-01-04,
#4898), which deprecated '/' in favor of vanilla SPDX license
expressions.
I've gone with the disjunctive OR, because the README has:
> Cargo is primarily distributed under the terms of both the MIT
> license and the Apache License (Version 2.0).
This commit updates the handling of git checkouts from the database to use
hardlinks if possible, speeding up this operation for large repositories
significantly.
As a refresher, Cargo caches git repositories in a few locations to speed up
local usage of git repositories. Cargo has a "database" folder which is a bare
checkout of any git repository Cargo has cached historically. This database
folder contains effectively a bunch of databases for remote repos that are
updated periodically.
When actually building a crate Cargo will clone this database into a different
location, the checkouts folder. Each rev we build (ever) is cached in the
checkouts folder. This means that once a checkout directory is created it's
frozen for all of time.
This latter step is what this commit is optimizing. When checking out the
database onto the local filesystem at a particular revision. Previously we were
instructing libgit2 to fall back to a "git aware" transport which was
exceedingly slow on some systems for filesystem-to-filesystem transfers. This
optimization (we just forgot to turn it on in libgit2) is a longstanding one and
should speed this up significantly!
Closes#4604
This commit is the initial steps to migrate Cargo's error handling from the
`error-chain` crate to the `failure` crate. This is intended to be a low-cost
(in terms of diff) transition where possible so it's note "purely idiomatic
`failure` crate" just yet.
The `error-chain` dependency is dropped in this commit and Cargo now canonically
uses the `Error` type from the `failure` crate. The main last remnant of
`error-chain` is a custom local extension trait to use `chain_err` instead of
`with_context`. I'll try to follow up with a commit that renames this later but
I wanted to make sure everything worked first! (and `chain_err` is used
practically everywhere).
Some minor tweaks happened in the tests as I touched up a few error messages
here and there but overall the UI of Cargo should be exactly the same before and
after this commit.
Although the checks are desirable, they cause warnings in the rust build
(due to workspaces) which could cause needless concern. The checks
aren't too important, so just disable them.
There's now a lock file upstream in rust-lang/rust so the one here isn't
actually used, and otherwise this crate is used as a dependency so the lock file
isn't respected anyway!
Use `same-file` to avoid unnecessary hard links
This is targeted at removing the need for a workaround in rust-lang/rust#39518,
allowing the main rust build system to move back to hard links which should be
much more efficient.
This is targeted at removing the need for a workaround in rust-lang/rust#39518,
allowing the main rust build system to move back to hard links which should be
much more efficient.
Add gitignore-like pattern matching logic to `list_files()` and throw
warnings for paths getting different inclusion/exclusion results from
the old and the new methods.
Migration Tracking: <https://github.com/rust-lang/cargo/issues/4268>
The API of `termcolor` fits what the system gives us much more nicely and should
be well battle-tested from ripgrep. Additionally we don't really need huge
terminfo parsers, that wasn't every really the intention of the color support
here.
Removing some allocations arounds the stored hashes by having nested hash maps
instead of tuple keys. Also remove an intermediate array when parsing
dependencies through a custom implementation of `Deserialize`. While this
doesn't make this code path blazingly fast it definitely knocks it down in the
profiles below other higher-value targets.
This commit adds a GNU make jobserver implementation to Cargo, both as a client
of existing jobservers and also a creator of new jobservers. The jobserver is
actually just an IPC semaphore which manifests itself as a pipe with N bytes
of tokens on Unix and a literal IPC semaphore on Windows. The rough protocol
is then if you want to run a job you read acquire the semaphore (read a byte on
Unix or wait on the semaphore on Windows) and then you release it when you're
done.
All the hairy details of the jobserver implementation are housed in the
`jobserver` crate on crates.io instead of Cargo. This should hopefully make it
much easier for the compiler to also share a jobserver implementation
eventually.
The main tricky bit here is that on Unix and Windows acquiring a jobserver token
will block the calling thread. We need to either way for a running job to exit
or to acquire a new token when we want to spawn a new job. To handle this the
current implementation spawns a helper thread that does the blocking and sends a
message back to Cargo when it receives a token. It's a little trickier with
shutting down this thread gracefully as well but more details can be found in
the `jobserver` crate.
Unfortunately crates are unlikely to see an immediate benefit of this once
implemented. Most crates are run with a manual `make -jN` and this overrides the
jobserver in the environment, creating a new jobserver in the sub-make. If the
`-jN` argument is removed, however, then `make` will share Cargo's jobserver and
properly limit parallelism.
Closes#1744
Convert CargoResult, CargoError into an implementation provided by error-chain. The previous is_human machinery is mostly removed; now errors are displayed unless of the Internal kind, verbose mode will print all errors.
Add year to project template variables
This adds the current year as a `year` variable for project templates. Some license files / headers include the year, so this should make it easier to include those in a template.
This commit migrates Cargo as much as possible from rustc-serialize to
Serde. This not only provides an excellent testing ground for the toml
0.3 release but it also is a big boost to the speed of parsing the JSON
bits of the registry.
This doesn't completely excise the dependency just yet as docopt still
requires it along with handlebars. I'm sure though that in time those
crates will migrate to serde!
PR #3004 This is a resubmission of the PR #1747 (from scratch) which adds
support for templating in Cargo. The templates are implemented using the
handlebars crate (where the original PR used mustache).
Examples:
cargo new --template https://url/to/template somedir foo
cargo new --template https://url/to/templates --template-subdir somedir foo
cargo new --template ../path/to/template somedir foo
The primary targets here are openssl and openssl-sys crates 0.9,
bringing support for OpenSSL 1.1.0. This requires updating the curl
and git2 related dependencies as well.
A small change is required in cargo itself for the new Hasher API.
Results from the hasher are simply unwrapped for now, matching the
Windows behavior that already panics on error.
This commit alters Cargo's behavior when the `-vv` option is passed (two verbose
flags) to stream output of all build scripts to the console. Cargo makes not
attempt to prevent interleaving or indicate *which* build script is producing
output, rather it simply forwards all output to one to the console.
Cargo still acts as a middle-man, capturing the output, to parse build script
output and interpret the results. The parsing is still deferred to completion
but the stream output happens while the build script is running.
On Unix this is implemented via `select` and on Windows this is implemented via
IOCP.
Closes#1106
Update TOML parser to pick up a bugfix
Cargo has previously accepted invalid TOML as valid, but this bugfix should fix
the problem. In order to prevent breaking all crates immediately toml-rs has a
compatibility mode which emulates the bug that was fixed. Cargo will issue a
warning if this compatibility is required to parse a crate.
Cargo has previously accepted invalid TOML as valid, but this bugfix should fix
the problem. In order to prevent breaking all crates immediately toml-rs has a
compatibility mode which emulates the bug that was fixed. Cargo will issue a
warning if this compatibility is required to parse a crate.
Compiling everything in one binary was getting annoying as it just took forever
to build, instead shard it all up so we can build just particular test suites at
a time.
Dearest Reviewer,
This branch resolves#1602 which relates to retrying network
issues automatically. There is a new utility helper for retrying
any network call.
There is a new config called net.retry value in the .cargo.config
file. The default value is 2. The documentation has also been
updated to reflect the new value.
Thanks
Becker
and each cargo-install instance creates and uses its own build directory. This
allows running several cargo-install instances in parallel.
If we fail to create a temporary directory for whatever reason fallback to
creating and using a target-install directory in the current directory.
closes#2606
Cargo has historically had no protections against running it concurrently. This
is pretty unfortunate, however, as it essentially just means that you can only
run one instance of Cargo at a time **globally on a system**.
An "easy solution" to this would be the use of file locks, except they need to
be applied judiciously. It'd be a pretty bad experience to just lock the entire
system globally for Cargo (although it would work), but otherwise Cargo must be
principled how it accesses the filesystem to ensure that locks are properly
held. This commit intends to solve all of these problems.
A new utility module is added to cargo, `util::flock`, which contains two types:
* `FileLock` - a locked version of a `File`. This RAII guard will unlock the
lock on `Drop` and I/O can be performed through this object. The actual
underlying `Path` can be read from this object as well.
* `Filesystem` - an unlocked representation of a `Path`. There is no "safe"
method to access the underlying path without locking a file on the filesystem
first.
Built on the [fs2] library, these locks use the `flock` system call on Unix and
`LockFileEx` on Windows. Although file locking on Unix is [documented as not so
great][unix-bad], but largely only because of NFS, these are just advisory, and
there's no byte-range locking. These issues don't necessarily plague Cargo,
however, so we should try to leverage them. On both Windows and Unix the file
locks are released when the underlying OS handle is closed, which means that
if the process dies the locks are released.
Cargo has a number of global resources which it now needs to lock, and the
strategy is done in a fairly straightforward way:
* Each registry's index contains one lock (a dotfile in the index). Updating the
index requires a read/write lock while reading the index requires a shared
lock. This should allow each process to ensure a registry update happens while
not blocking out others for an unnecessarily long time. Additionally any
number of processes can read the index.
* When downloading crates, each downloaded crate is individually locked. A lock
for the downloaded crate implies a lock on the output directory as well.
Because downloaded crates are immutable, once the downloaded directory exists
the lock is no longer needed as it won't be modified, so it can be released.
This granularity of locking allows multiple Cargo instances to download
dependencies in parallel.
* Git repositories have separate locks for the database and for the project
checkout. The datbase and checkout are locked for read/write access when an
update is performed, and the lock of the checkout is held for the entire
lifetime of the git source. This is done to ensure that any other Cargo
processes must wait while we use the git repository. Unfortunately there's
just not that much parallelism here.
* Binaries managed by `cargo install` are locked by the local metadata file that
Cargo manages. This is relatively straightforward.
* The actual artifact output directory is just globally locked for the entire
build. It's hypothesized that running Cargo concurrently in *one directory* is
less of a feature needed rather than running multiple instances of Cargo
globally (for now at least). It would be possible to have finer grained
locking here, but that can likely be deferred to a future PR.
So with all of this infrastructure in place, Cargo is now ready to grab some
locks and ensure that you can call it concurrently anywhere at any time and
everything always works out as one might expect.
One interesting question, however, is what does Cargo do on contention? On one
hand Cargo could immediately abort, but this would lead to a pretty poor UI as
any Cargo process on the system could kick out any other. Instead this PR takes
a more nuanced approach.
* First, all locks are attempted to be acquired (a "try lock"). If this
succeeds, we're done.
* Next, Cargo prints a message to the console that it's going to block waiting
for a lock. This is done because it's indeterminate how long Cargo will wait
for the lock to become available, and most long-lasting operations in Cargo
have a message printed for them.
* Finally, a blocking acquisition of the lock is issued and we wait for it to
become available.
So all in all this should help Cargo fix any future concurrency bugs with file
locking in a principled fashion while also allowing concurrent Cargo processes
to proceed reasonably across the system.
[fs2]: https://github.com/danburkert/fs2-rs
[unix-bad]: http://0pointer.de/blog/projects/locking.htmlCloses#354
This crate was recently updated to the next release of libgit2, and I've noticed
historically that a noop `cargo build` was slow in the git2-rs repository.
Curious to see if the new libgit2 version helped speed things up at all, I
tested it out.
Before this commit, a noop `cargo build` produced 599108 syscalls. After this
commit, a noop build produced 86925 syscalls, an 85% reduction in the number of
syscalls! Needless to say it's much faster.
Before v0.4, term used to return `Ok(true)` if something succeeded,
`Ok(false)` if the operation was unsupported, and `Err(io::Error)` if
there was an IO error. Now, it returns `Ok(())` if the operation
succeeds and `Err(term::Error)` if the operation fails. If the operation
is unsupported, it returns `Err(term::Error::NotSupported)`. This means
that, if `op` is unsupported, `try!(term.op())` will now return an error
instead of silently failing (well, return false but that's effectively
silent).
Fixes#2338
This is undoing part of commit dd34296Fix#2338
(Unfortunately I do not have a suggestion for how to make a unit test
for this problem; doing so would require putting in a bit more effort
than I have time for at the moment.)
* Updates git2-rs back to 0.3 now that the distribution issue on OSX has been
fixed.
* Updates libgit2-sys to using the `cmake` crate so building with VS 2015 can
work.
* Update pkg-config to totally disable it on MSVC (basically guaranteed to never
work)
This commit started out identifying a relatively simple bug in Cargo. A recent
change made it such that the resolution graph included all target-specific
dependencies, relying on the structure of the backend to filter out those which
don't need to get built. This was unfortunately not accounted for in the portion
of the backend that schedules work, mistakenly causing spurious rebuilds if
different runs of the graph pulled in new crates. For example if `cargo build`
didn't build any target-specific dependencies but then later `cargo test` did
(e.g. a dev-dep pulled in a target-specific dep unconditionally) then it would
cause a rebuild of the entire graph.
This class of bug is certainly not the first in a long and storied history of
the backend having multiple points where dependencies are calculated and those
often don't quite agree with one another. The purpose of this rewrite is
twofold:
1. The `Stage` enum in the backend for scheduling work and ensuring that maximum
parallelism is achieved is removed entirely. There is already a function on
`Context` which expresses the dependency between targets (`dep_targets`)
which takes a much finer grain of dependencies into account as well as
already having all the logic for what-depends-on-what. This duplication has
caused numerous problems in the past, an unifying these two will truly grant
maximum parallelism while ensuring that everyone agrees on what their
dependencies are.
2. A large number of locations in the backend have grown to take a (Package,
Target, Profile, Kind) tuple, or some subset of this tuple. In general this
represents a "unit of work" and is much easier to pass around as one
variable, so a `Unit` was introduced which references all of these variables.
Almost the entire backend was altered to take a `Unit` instead of these
variables specifically, typically providing all of the contextual information
necessary for an operation.
A crucial part of this change is the inclusion of `Kind` in a `Unit` to ensure
that everyone *also* agrees on what architecture they're compiling everything
for. There have been many bugs in the past where one part of the backend
determined that a package was built for one architecture and then another part
thought it was built for another. With the inclusion of `Kind` in dependency
management this is handled in a much cleaner fashion as it's only calculated in
one location.
Some other miscellaneous changes made were:
* The `Platform` enumeration has finally been removed. This has been entirely
subsumed by `Kind`.
* The hokey logic for "build this crate once" even though it may be depended on
by both the host/target kinds has been removed. This is now handled in a much
nicer fashion where if there's no target then Kind::Target is just never used,
and multiple requests for a package are just naturally deduplicated.
* There's no longer any need to build up the "requirements" for a package in
terms of what platforms it's compiled for, this now just naturally falls out
of the dependency graph.
* If a build script is overridden then its entire tree of dependencies are not
compiled, not just the build script itself.
* The `threadpool` dependency has been replaced with one on `crossbeam`. The
method of calculating dependencies has quite a few non-static lifetimes and
the scoped threads of `crossbeam` are now used instead of a thread pool.
* Once any thread fails to execute a command work is no longer scheduled unlike
before where some extra pending work may continue to start.
* Many functions used early on, such as `compile` and `build_map` have been
massively simplified by farming out dependency management to
`Context::dep_targets`.
* There is now a new profile to represent running a build script. This is used
to inject dependencies as well as represent that a library depends on running
a build script, not just building it.
This change has currently been tested against cross-compiling Servo to Android
and passes the test suite (which has quite a few corner cases for build scripts
and such), so I'm pretty confident that this refactoring won't have at least too
many regressions!
Unfortunately this flew past on the bots because we didn't built on one of the
10.7 bots, but it looks like libgit2 doesn't currently build on OSX 10.7 so
we'll have to wait until that's fixed to update.
This commit tweaks some metadata here and there to publish Cargo on crates.io.
* License fields are added to Cargo.tomls
* `registry` was renamed to `crates-io`
* API docs for the `cargo` crate are now generated via `make doc`
Cargo will soon support testing the cross compilation capabilities between 32/64
bit Windows, meaning that there's not "one true value" for any of these
environment variables that Cargo is setting (e.g. where to find `cl`, `link`,
etc). Instead, all dependencies have been updated to probe the system (in the
same manner as the compiler) for the tools that they're using.
All of the logic is housed in the `gcc` crate which now exposes a function to
probe the system for a particular tool. The updated crates here then use the
result of this probe to run the various build scripts. This all boils down to
being able to build MSVC targets inside an MSYS shell instead of requiring use
of a MSVC shell (which doesn't allow for simultaneous host builds and cross
builds).
* Download all snapshots and such from static.rust-lang.org (drive-by fix)
* Update dependencies to work and build on MSVC
* ssh2-sys uses `nmake` to build libssh2
* libgit2-sys uses `cmake` to build libgit2
* curl-sys uses `nmake` to build libcurl
* libz-sys uses `nmake` to build zlib
* miniz-sys uses `gcc-rs` to drive `cl.exe` manually
* term updated to pick up windows-specific deps on MSVC
* Updated .travis.install.deps.sh to install MSVC target libraries on Windows,
so the compiler can be used to target MSVC. A 64-bit target is now used by
default as well.
* Updated the configure script and Makefile to set appropriate environment
variables to build Cargo from a MSYS shell with a MSVC target. This is similar
to how Rust bootstraps on MSVC as well.
With this commit Cargo can successfully bootstrap itself on MSVC (use the MSVC
product to build itself again). The tests currently do not pass because
unwinding is not implemented, but soon!
This commit moves Cargo onto 100% stable Rust now that the necessary fs features
have been stabilized. The tests were updated to understand when they're running
with a non-nightly compiler and disable all plugin-related tests. The only major
feature here is that the calls to `fs::set_file_times` were reimplemented
manually in the tests that Cargo has.
Cargo still requires a *nightly compiler* due to the stable features not having
made their way into the stable channel yet, but it will soon work on all of the
stable, beta, and nightly compilers once 1.1 is released!
This commit adds support to allow specifying a custom output directory to Cargo.
First, the `build.target-dir` configuration key is checked, and failing that the
`CARGO_TARGET_DIR` environment variable is checked, and failing that the root
package's directory joined with the directory name "target" is used.
There are a few caveats to switching target directories, however:
* If the target directory is in the current source tree, and the folder name is
not called "target", then Cargo may walk the output directory when determining
whether a tree is fresh.
* If the target directory is not called "target", then Cargo may look inside it
currently for `Cargo.toml` files to learn about local packages.
* Concurrent usage of Cargo will still result in badness (#354), and this is now
exascerbated because many Cargo projects can share the same output directory.
* The top-level crate is not cached for future compilations, so if a crate is
built into directory `foo` and then that crate is later used as a dependency,
it will be recompiled.
The naming limitations can be overcome in time, but for now it greatly
simplifies the crawling routines and shouldn't have much of a negative impact
other than some Cargo runtimes (which can in turn be negated by following the
"target" name convention).
Closes#482