summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorVersus Void2017-11-12 20:26:18 +0000
committerVersus Void2017-11-12 20:26:18 +0000
commit8e2fc1d0a0f0645ca52e33acf109022b9525fa9c (patch)
treed7ddc10dada79524e0b4e0725616092dcfe12807
downloadaur-8e2fc1d0a0f0645ca52e33acf109022b9525fa9c.tar.gz
Initial
-rw-r--r--.SRCINFO20
-rw-r--r--PKGBUILD43
-rw-r--r--color.patch171
-rw-r--r--cross-package-cache.patch62
-rw-r--r--sccache.install3
5 files changed, 299 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 000000000000..f28005995ec4
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,20 @@
+pkgbase = sccache-git
+ pkgdesc = ccache-like tool. Wraps compiler and avoids compilation when possible. Supports rustc
+ pkgver = r412.cbb72b8
+ pkgrel = 1
+ url = https://github.com/mozilla/sccache
+ install = sccache.install
+ arch = i686
+ arch = x86_64
+ license = Apache
+ makedepends = git
+ makedepends = rust
+ source = git+https://github.com/mozilla/sccache/
+ source = color.patch
+ source = cross-package-cache.patch
+ sha256sums = SKIP
+ sha256sums = 82ed21e16bb38274bdc4f5ae2e3941c487ddf1859de4984a2610a065928806f5
+ sha256sums = 43a7c03ddc6c9a957ad330de2a938aebafebbae350869ad76302ebf8e0719a5d
+
+pkgname = sccache-git
+
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 000000000000..d8e6d387975a
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,43 @@
+# Maintainer: Versus Void <chaoskeeper@mail.ru>
+pkgname=sccache-git
+pkgver=r412.cbb72b8
+pkgrel=1
+pkgdesc="ccache-like tool. Wraps compiler and avoids compilation when possible. Supports rustc"
+arch=(i686 x86_64)
+url="https://github.com/mozilla/sccache"
+license=('Apache')
+makedepends=('git' 'rust')
+install=sccache.install
+source=('git+https://github.com/mozilla/sccache/'
+ 'color.patch'
+ 'cross-package-cache.patch')
+sha256sums=('SKIP'
+ '82ed21e16bb38274bdc4f5ae2e3941c487ddf1859de4984a2610a065928806f5'
+ '43a7c03ddc6c9a957ad330de2a938aebafebbae350869ad76302ebf8e0719a5d')
+
+pkgver() {
+ cd "$srcdir/${pkgname%-git}"
+ printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
+}
+
+prepare() {
+ cd "$srcdir/${pkgname%-git}"
+ git apply "$srcdir/color.patch"
+ git apply "$srcdir/cross-package-cache.patch"
+}
+
+build() {
+ cd "$srcdir/${pkgname%-git}"
+ cargo build --release
+}
+
+check() {
+ cd "$srcdir/${pkgname%-git}"
+ cargo test --release
+}
+
+package() {
+ cd "$srcdir/${pkgname%-git}"
+ cargo install --root "$pkgdir/usr"
+ rm -f "$pkgdir/usr/.crates.toml"
+}
diff --git a/color.patch b/color.patch
new file mode 100644
index 000000000000..55db31047c1b
--- /dev/null
+++ b/color.patch
@@ -0,0 +1,171 @@
+diff --git a/src/commands.rs b/src/commands.rs
+index d5d5e08..3535d6c 100644
+--- a/src/commands.rs
++++ b/src/commands.rs
+@@ -36,6 +36,8 @@ use std::io::{
+ };
+ #[cfg(unix)]
+ use std::os::unix::process::ExitStatusExt;
++#[cfg(unix)]
++use std::os::unix::io::AsRawFd;
+ use std::path::{
+ Path,
+ };
+@@ -435,16 +437,64 @@ fn status_signal(_status : process::ExitStatus) -> Option<i32> {
+ None
+ }
+
++/// Write content of `buf` to `out` assuming it is ANSI colored text
++/// and strip color formatting.
++fn write_all_stripping_colors(out: &mut Write, buf: Vec<u8>) -> Result<()> {
++ let mut start = 0;
++ let mut color_description = false;
++ for (i, &c) in buf.iter().enumerate() {
++ if color_description {
++ if c == b'm' {
++ color_description = false;
++ start = i + 1;
++ }
++ } else {
++ if c == b'\x1b' {
++ color_description = true;
++ if i > start {
++ out.write_all(&buf[start..i])?;
++ }
++ }
++ }
++ }
++ Ok(())
++}
++
++/// Check if stream handle is "connected" to terminal.
++#[cfg(unix)]
++fn isatty<T: AsRawFd>(stream: T) -> bool {
++ use libc;
++ unsafe {
++ let res = libc::isatty(stream.as_raw_fd());
++ return res != 0;
++ }
++}
++
++#[cfg(not(unix))]
++fn isatty<T>(_: T) -> bool {
++ false
++}
++
+ /// Handle `response`, the output from running a compile on the server. Return the compiler exit status.
+ fn handle_compile_finished(response: CompileFinished,
+ stdout: &mut Write,
+- stderr: &mut Write) -> Result<i32> {
++ stderr: &mut Write,
++ colored_output: Option<bool>) -> Result<i32> {
+ trace!("handle_compile_finished");
+ // It might be nice if the server sent stdout/stderr as the process
+ // ran, but then it would have to also save them in the cache as
+ // interleaved streams to really make it work.
+- stdout.write_all(&response.stdout)?;
+- stderr.write_all(&response.stderr)?;
++ if colored_output.unwrap_or(isatty(io::stdout())) {
++ stdout.write_all(&response.stdout)?;
++ } else {
++ write_all_stripping_colors(stdout, response.stdout)?;
++ }
++
++ if colored_output.unwrap_or(isatty(io::stderr())) {
++ stderr.write_all(&response.stderr)?;
++ } else {
++ write_all_stripping_colors(stderr, response.stderr)?;
++ }
+
+ if let Some(ret) = response.retcode {
+ trace!("compiler exited with status {}", ret);
+@@ -458,6 +508,34 @@ fn handle_compile_finished(response: CompileFinished,
+ }
+ }
+
++/// Examines compiler's `cmdline` to decide if we should pass colored output or strip colors from it.
++/// Some(true), None, Some(false) corresponds to "always", "auto", "never"
++fn want_color(cmdline: &Vec<OsString>) -> Option<bool> {
++ for i in 1..cmdline.len() {
++ let arg = cmdline[i].to_str();
++ // TODO: process -fdiagnostics-color and -fno-diagnostics-color
++ if !arg.map(|s| s.starts_with("--color")).unwrap_or(false) {
++ continue;
++ }
++
++ let mut arg = arg.unwrap();
++ if !arg.contains('=') {
++ let s = cmdline[i + 1].to_str();
++ if s.is_none() {
++ return None;
++ }
++ arg = s.unwrap();
++ }
++ if arg.ends_with("always") {
++ return Some(true);
++ } else if arg.ends_with("never") {
++ return Some(false);
++ }
++ break;
++ }
++ None
++}
++
+ /// Handle `response`, the response from sending a `Compile` request to the server. Return the compiler exit status.
+ ///
+ /// If the server returned `CompileStarted`, wait for a `CompileFinished` and
+@@ -482,7 +560,7 @@ fn handle_compile_response<T>(mut creator: T,
+ // Wait for CompileFinished.
+ match conn.read_one_response() {
+ Ok(Response::CompileFinished(result)) => {
+- return handle_compile_finished(result, stdout, stderr)
++ return handle_compile_finished(result, stdout, stderr, want_color(&cmdline))
+ }
+ Ok(_) => bail!("unexpected response from server"),
+ Err(Error(ErrorKind::Io(ref e), _))
+diff --git a/src/compiler/rust.rs b/src/compiler/rust.rs
+index 608e307..d3c8b4a 100644
+--- a/src/compiler/rust.rs
++++ b/src/compiler/rust.rs
+@@ -367,7 +367,6 @@ fn parse_arguments(arguments: &[OsString], cwd: &Path) -> CompilerArguments<Pars
+ let mut static_link_paths: Vec<PathBuf> = vec![];
+
+ for item in ArgsIter::new(arguments.iter().map(|s| s.clone()), &ARGS[..]) {
+- let arg = item.arg.to_os_string();
+ let value = match item.arg.get_value() {
+ Some(v) => {
+ if let Ok(v) = OsString::from(v).into_string() {
+@@ -378,7 +377,6 @@ fn parse_arguments(arguments: &[OsString], cwd: &Path) -> CompilerArguments<Pars
+ }
+ None => None,
+ };
+- args.push((arg, item.arg.get_value().map(|s| s.into())));
+ match item.data {
+ Some(TooHard) => {
+ return CompilerArguments::CannotCache(item.arg.to_str().expect(
+@@ -458,7 +456,14 @@ fn parse_arguments(arguments: &[OsString], cwd: &Path) -> CompilerArguments<Pars
+ }
+ }
+ }
+- Some(PassThrough) => {}
++ Some(PassThrough) => {
++ match item.arg.to_str() {
++ // Skip --color argument, as we unconditionaly add --color=always
++ // and strip color when necessary.
++ Some("--color") => continue,
++ _ => {},
++ }
++ }
+ None => {
+ match item.arg {
+ Argument::Raw(ref val) => {
+@@ -473,7 +478,9 @@ fn parse_arguments(arguments: &[OsString], cwd: &Path) -> CompilerArguments<Pars
+ }
+ }
+ }
++ args.push((item.arg.to_os_string(), item.arg.get_value().map(|s| s.into())));
+ }
++ args.push((OsString::from("--color"), Some(OsString::from("always"))));
+
+ // Unwrap required values.
+ macro_rules! req {
diff --git a/cross-package-cache.patch b/cross-package-cache.patch
new file mode 100644
index 000000000000..29da43844f02
--- /dev/null
+++ b/cross-package-cache.patch
@@ -0,0 +1,62 @@
+diff --git a/src/compiler/rust.rs b/src/compiler/rust.rs
+index 608e307..5606f24 100644
+--- a/src/compiler/rust.rs
++++ b/src/compiler/rust.rs
+@@ -589,6 +596,25 @@ impl<T> CompilerHasher<T> for RustHasher
+ let cwd = cwd.to_owned();
+ let env_vars = env_vars.to_vec();
+ let hashes = source_hashes.join3(extern_hashes, staticlib_hashes);
++
++ // Absolute path to package (crate) being compiled. Usually contains "Cargo.toml" and "target".
++ let mut package_absolute_path = None;
++ // If output directory specified as absolute path
++ if output_dir.has_root() {
++ let mut i = None;
++ // .. find last component with name "target"
++ for (j, p) in output_dir.iter().enumerate() {
++ if p == r"target" {
++ i = Some(j);
++ }
++ }
++ if i.is_some() {
++ // .. and take "target"'s parent as path to package
++ let p : PathBuf = output_dir.iter().take(i.unwrap()).collect();
++ package_absolute_path = p.to_str().map(|s| s.to_owned());
++ }
++ }
++
+ Box::new(hashes.and_then(move |(source_hashes, extern_hashes, staticlib_hashes)|
+ -> SFuture<_> {
+ // If you change any of the inputs to the hash, you should change `CACHE_VERSION`.
+@@ -601,8 +627,7 @@ impl<T> CompilerHasher<T> for RustHasher
+ m.update(d.as_bytes());
+ }
+ // 3. The full commandline (self.arguments)
+- // TODO: there will be full paths here, it would be nice to
+- // normalize them so we can get cross-machine cache hits.
++ // TODO: normalize paths in arguments so we can get cross-machine cache hits.
+ // A few argument types are not passed in a deterministic order
+ // by cargo: --extern, -L, --cfg. We'll filter those out, sort them,
+ // and append them to the rest of the arguments.
+@@ -616,7 +641,20 @@ impl<T> CompilerHasher<T> for RustHasher
+ iter::once(arg).chain(val.as_ref())
+ })
+ .fold(OsString::new(), |mut a, b| {
+- a.push(b);
++ match package_absolute_path {
++ // If we know absolute path of compiled package
++ Some(ref prefix) => {
++ let b = b.to_str().unwrap_or("");
++ // .. remove it from all arguments
++ for p in b.split(prefix) {
++ a.push(p);
++ }
++ },
++ // Otherwise hash args as-is
++ None => {
++ a.push(b);
++ }
++ }
+ a
+ })
+ };
diff --git a/sccache.install b/sccache.install
new file mode 100644
index 000000000000..18619c4d9e85
--- /dev/null
+++ b/sccache.install
@@ -0,0 +1,3 @@
+post_remove() {
+ echo 'sccache is removed. You may want to remove $SCCACHE_DIR (~/.cache/sccache by default)'
+}