diff options
36 files changed, 1398 insertions, 25 deletions
diff --git a/.gitattributes b/.gitattributes index 1d4c6252f2c..e2d04142766 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,7 +4,6 @@ *.cpp rust *.h rust *.rs rust -src/etc/pkg/rust-logo.ico binary -src/etc/pkg/rust-logo.png binary +src/etc/installer/gfx/* binary *.woff binary src/vendor/* binary diff --git a/.travis.yml b/.travis.yml index 0546f6827a6..bbe0cdfb6f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,7 @@ matrix: - env: > SCRIPT="./x.py test && ./x.py dist" - RUST_CONFIGURE_ARGS=--build=i686-apple-darwin + RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-extended" SRC=. DEPLOY=1 os: osx @@ -76,7 +76,7 @@ matrix: after_failure: *osx_after_failure - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS=--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios + RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-extended" SRC=. DEPLOY=1 os: osx diff --git a/appveyor.yml b/appveyor.yml index cd61f95875f..f158d788d16 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,11 +7,11 @@ environment: matrix: # 32/64 bit MSVC - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended SCRIPT: python x.py test && python x.py dist DEPLOY: 1 - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc --enable-extended SCRIPT: python x.py test --host i686-pc-windows-msvc --target i686-pc-windows-msvc && python x.py dist DEPLOY: 1 @@ -51,7 +51,7 @@ environment: # *not* use debug assertions and llvm assertions. This is because they take # too long on appveyor and this is tested by rustbuild below. - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended SCRIPT: python x.py test && python x.py dist MINGW_URL: https://s3.amazonaws.com/rust-lang-ci MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z @@ -67,7 +67,7 @@ environment: - MSYS_BITS: 64 SCRIPT: python x.py test && python x.py dist - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended MINGW_URL: https://s3.amazonaws.com/rust-lang-ci MINGW_ARCHIVE: x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z MINGW_DIR: mingw64 @@ -103,6 +103,10 @@ install: - 7z x -y sccache.tar > nul - set PATH=%PATH%;%CD%\sccache2 + # Install InnoSetup to get `iscc` used to produce installers + - choco install -y InnoSetup + - set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH% + # Help debug some handle issues on AppVeyor - ps: Invoke-WebRequest -Uri https://download.sysinternals.com/files/Handle.zip -OutFile handle.zip - mkdir handle diff --git a/configure b/configure index 208fb7e6836..505767cede5 100755 --- a/configure +++ b/configure @@ -707,6 +707,7 @@ opt_nosave clang 0 "prefer clang to gcc for building the runtime" opt_nosave jemalloc 1 "build liballoc with jemalloc" opt elf-tls 1 "elf thread local storage on platforms where supported" opt full-bootstrap 0 "build three compilers instead of two" +opt extended 0 "build an extended rust tool set" valopt_nosave prefix "/usr/local" "set installation prefix" valopt_nosave local-rust-root "/usr/local" "set prefix for local rust binary" diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index c38bb33aa02..585d9f51b92 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -40,6 +40,9 @@ pub fn collect(build: &mut Build) { } } + build.release_num = release_num.to_string(); + build.prerelease_version = release_num.to_string(); + // Depending on the channel, passed in `./configure --release-channel`, // determine various properties of the build. match &build.config.channel[..] { diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 152164342cd..7d1abcfa6f6 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -47,6 +47,7 @@ pub struct Config { pub vendor: bool, pub target_config: HashMap<String, Target>, pub full_bootstrap: bool, + pub extended: bool, // llvm codegen options pub llvm_assertions: bool, @@ -140,6 +141,7 @@ struct Build { nodejs: Option<String>, python: Option<String>, full_bootstrap: Option<bool>, + extended: Option<bool>, } /// TOML representation of various global install decisions. @@ -276,6 +278,7 @@ impl Config { set(&mut config.submodules, build.submodules); set(&mut config.vendor, build.vendor); set(&mut config.full_bootstrap, build.full_bootstrap); + set(&mut config.extended, build.extended); if let Some(ref install) = toml.install { config.prefix = install.prefix.clone().map(PathBuf::from); @@ -412,6 +415,7 @@ impl Config { ("CODEGEN_TESTS", self.codegen_tests), ("VENDOR", self.vendor), ("FULL_BOOTSTRAP", self.full_bootstrap), + ("EXTENDED", self.extended), } match key { diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index 47e50cb79b4..4b859482562 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -118,6 +118,12 @@ # option to true. #full-bootstrap = false +# Enable a build of the and extended rust tool set which is not only the +# compiler but also tools such as Cargo. This will also produce "combined +# installers" which are used to install Rust and Cargo together. This is +# disabled by default. +#extended = false + # ============================================================================= # General install configuration options # ============================================================================= diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index dc45d3817fe..e5f05059523 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -18,11 +18,14 @@ //! out to `rust-installer` still. This may one day be replaced with bits and //! pieces of `rustup.rs`! +use std::env; use std::fs::{self, File}; -use std::io::Write; +use std::io::{Read, Write}; use std::path::{PathBuf, Path}; use std::process::Command; +use build_helper::output; + use {Build, Compiler, Mode}; use util::{cp_r, libdir, is_dylib, cp_filtered, copy}; @@ -35,6 +38,10 @@ pub fn package_vers(build: &Build) -> &str { } } +fn pkgname(build: &Build, component: &str) -> String { + format!("{}-{}", component, package_vers(build)) +} + fn distdir(build: &Build) -> PathBuf { build.out.join("dist") } @@ -53,8 +60,8 @@ pub fn docs(build: &Build, stage: u32, host: &str) { return } - let name = format!("rust-docs-{}", package_vers(build)); - let image = tmpdir(build).join(format!("{}-{}-image", name, name)); + let name = pkgname(build, "rust-docs"); + let image = tmpdir(build).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); let dst = image.join("share/doc/rust/html"); @@ -94,7 +101,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) { /// in Rust. pub fn mingw(build: &Build, host: &str) { println!("Dist mingw ({})", host); - let name = format!("rust-mingw-{}", package_vers(build)); + let name = pkgname(build, "rust-mingw"); let image = tmpdir(build).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); t!(fs::create_dir_all(&image)); @@ -130,7 +137,7 @@ pub fn mingw(build: &Build, host: &str) { /// Creates the `rustc` installer component. pub fn rustc(build: &Build, stage: u32, host: &str) { println!("Dist rustc stage{} ({})", stage, host); - let name = format!("rustc-{}", package_vers(build)); + let name = pkgname(build, "rustc"); let image = tmpdir(build).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); let overlay = tmpdir(build).join(format!("{}-{}-overlay", name, host)); @@ -274,7 +281,7 @@ pub fn std(build: &Build, compiler: &Compiler, target: &str) { return } - let name = format!("rust-std-{}", package_vers(build)); + let name = pkgname(build, "rust-std"); let image = tmpdir(build).join(format!("{}-{}-image", name, target)); let _ = fs::remove_dir_all(&image); @@ -328,7 +335,7 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) { compiler.clone() }; - let name = format!("rust-analysis-{}", package_vers(build)); + let name = pkgname(build, "rust-analysis"); let image = tmpdir(build).join(format!("{}-{}-image", name, target)); let src = build.stage_out(&compiler, Mode::Libstd).join(target).join("release").join("deps"); @@ -357,7 +364,7 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) { pub fn rust_src(build: &Build) { println!("Dist src"); - let name = format!("rust-src-{}", package_vers(build)); + let name = pkgname(build, "rust-src"); let image = tmpdir(build).join(format!("{}-image", name)); let _ = fs::remove_dir_all(&image); @@ -500,3 +507,372 @@ fn write_file(path: &Path, data: &[u8]) { let mut vf = t!(fs::File::create(path)); t!(vf.write_all(data)); } + +// FIXME(#38531) eventually this should package up a Cargo that we just compiled +// and tested locally, but for now we're downloading cargo +// artifacts from their compiled location. +pub fn cargo(build: &Build, stage: u32, target: &str) { + println!("Dist cargo stage{} ({})", stage, target); + + let branch = match &build.config.channel[..] { + "stable" | + "beta" => { + build.release.split(".").take(2).collect::<Vec<_>>().join(".") + } + _ => "master".to_string(), + }; + + let dst = tmpdir(build).join("cargo"); + let _ = fs::remove_dir_all(&dst); + build.run(Command::new("git") + .arg("clone") + .arg("--depth").arg("1") + .arg("--branch").arg(&branch) + .arg("https://github.com/rust-lang/cargo") + .current_dir(dst.parent().unwrap())); + let sha = output(Command::new("git") + .arg("rev-parse") + .arg("HEAD") + .current_dir(&dst)); + let sha = sha.trim(); + println!("\tgot cargo sha: {}", sha); + + let input = format!("https://s3.amazonaws.com/rust-lang-ci/cargo-builds\ + /{}/cargo-nightly-{}.tar.gz", sha, target); + let output = distdir(build).join(format!("cargo-nightly-{}.tar.gz", target)); + println!("\tdownloading {}", input); + let mut curl = Command::new("curl"); + curl.arg("-f") + .arg("-o").arg(&output) + .arg(&input) + .arg("--retry").arg("3"); + build.run(&mut curl); +} + +/// Creates a combined installer for the specified target in the provided stage. +pub fn extended(build: &Build, stage: u32, target: &str) { + println!("Dist extended stage{} ({})", stage, target); + + let dist = distdir(build); + let rustc_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "rustc"), + target)); + let cargo_installer = dist.join(format!("cargo-nightly-{}.tar.gz", target)); + let docs_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "rust-docs"), + target)); + let mingw_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "rust-mingw"), + target)); + let std_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "rust-std"), + target)); + + let tmp = tmpdir(build); + let overlay = tmp.join("extended-overlay"); + let etc = build.src.join("src/etc/installer"); + let work = tmp.join("work"); + + let _ = fs::remove_dir_all(&overlay); + install(&build.src.join("COPYRIGHT"), &overlay, 0o644); + install(&build.src.join("LICENSE-APACHE"), &overlay, 0o644); + install(&build.src.join("LICENSE-MIT"), &overlay, 0o644); + let version = &build.version; + t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); + install(&etc.join("README.md"), &overlay, 0o644); + + // When rust-std package split from rustc, we needed to ensure that during + // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering + // the std files during uninstall. To do this ensure that rustc comes + // before rust-std in the list below. + let mut input_tarballs = format!("{},{},{},{}", + sanitize_sh(&rustc_installer), + sanitize_sh(&cargo_installer), + sanitize_sh(&docs_installer), + sanitize_sh(&std_installer)); + if target.contains("pc-windows-gnu") { + input_tarballs.push_str(","); + input_tarballs.push_str(&sanitize_sh(&mingw_installer)); + } + + let mut cmd = Command::new("sh"); + cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/combine-installers.sh"))) + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=Rust-is-ready-to-roll.") + .arg(format!("--work-dir={}", sanitize_sh(&work))) + .arg(format!("--output-dir={}", sanitize_sh(&distdir(build)))) + .arg(format!("--package-name={}-{}", pkgname(build, "rust"), target)) + .arg("--legacy-manifest-dirs=rustlib,cargo") + .arg(format!("--input-tarballs={}", input_tarballs)) + .arg(format!("--non-installed-overlay={}", sanitize_sh(&overlay))); + build.run(&mut cmd); + + let mut license = String::new(); + t!(t!(File::open(build.src.join("COPYRIGHT"))).read_to_string(&mut license)); + license.push_str("\n"); + t!(t!(File::open(build.src.join("LICENSE-APACHE"))).read_to_string(&mut license)); + license.push_str("\n"); + t!(t!(File::open(build.src.join("LICENSE-MIT"))).read_to_string(&mut license)); + + let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18"; + let mut rtf = rtf.to_string(); + rtf.push_str("\n"); + for line in license.lines() { + rtf.push_str(line); + rtf.push_str("\\line "); + } + rtf.push_str("}"); + + if target.contains("apple-darwin") { + let pkg = tmp.join("pkg"); + let _ = fs::remove_dir_all(&pkg); + t!(fs::create_dir_all(pkg.join("rustc"))); + t!(fs::create_dir_all(pkg.join("cargo"))); + t!(fs::create_dir_all(pkg.join("rust-docs"))); + t!(fs::create_dir_all(pkg.join("rust-std"))); + + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target)), + &pkg.join("rustc")); + cp_r(&work.join(&format!("cargo-nightly-{}", target)), + &pkg.join("cargo")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target)), + &pkg.join("rust-docs")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target)), + &pkg.join("rust-std")); + + install(&etc.join("pkg/postinstall"), &pkg.join("rustc"), 0o755); + install(&etc.join("pkg/postinstall"), &pkg.join("cargo"), 0o755); + install(&etc.join("pkg/postinstall"), &pkg.join("rust-docs"), 0o755); + install(&etc.join("pkg/postinstall"), &pkg.join("rust-std"), 0o755); + + let pkgbuild = |component: &str| { + let mut cmd = Command::new("pkgbuild"); + cmd.arg("--identifier").arg(format!("org.rust-lang.{}", component)) + .arg("--scripts").arg(pkg.join(component)) + .arg("--nopayload") + .arg(pkg.join(component).with_extension("pkg")); + build.run(&mut cmd); + }; + pkgbuild("rustc"); + pkgbuild("cargo"); + pkgbuild("rust-docs"); + pkgbuild("rust-std"); + + // create an 'uninstall' package + install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755); + pkgbuild("uninstall"); + + t!(fs::create_dir_all(pkg.join("res"))); + t!(t!(File::create(pkg.join("res/LICENSE.txt"))).write_all(license.as_bytes())); + install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644); + let mut cmd = Command::new("productbuild"); + cmd.arg("--distribution").arg(etc.join("pkg/Distribution.xml")) + .arg("--resources").arg(pkg.join("res")) + .arg(distdir(build).join(format!("{}-{}.pkg", + pkgname(build, "rust"), + target))) + .arg("--package-path").arg(&pkg); + build.run(&mut cmd); + } + + if target.contains("windows") { + let exe = tmp.join("exe"); + let _ = fs::remove_dir_all(&exe); + t!(fs::create_dir_all(exe.join("rustc"))); + t!(fs::create_dir_all(exe.join("cargo"))); + t!(fs::create_dir_all(exe.join("rust-docs"))); + t!(fs::create_dir_all(exe.join("rust-std"))); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target)) + .join("rustc"), + &exe.join("rustc")); + cp_r(&work.join(&format!("cargo-nightly-{}", target)) + .join("cargo"), + &exe.join("cargo")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target)) + .join("rust-docs"), + &exe.join("rust-docs")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target)) + .join(format!("rust-std-{}", target)), + &exe.join("rust-std")); + + t!(fs::remove_file(exe.join("rustc/manifest.in"))); + t!(fs::remove_file(exe.join("cargo/manifest.in"))); + t!(fs::remove_file(exe.join("rust-docs/manifest.in"))); + t!(fs::remove_file(exe.join("rust-std/manifest.in"))); + + if target.contains("windows-gnu") { + t!(fs::create_dir_all(exe.join("rust-mingw"))); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-mingw"), target)) + .join("rust-mingw"), + &exe.join("rust-mingw")); + t!(fs::remove_file(exe.join("rust-mingw/manifest.in"))); + } + + install(&etc.join("exe/rust.iss"), &exe, 0o644); + install(&etc.join("exe/modpath.iss"), &exe, 0o644); + install(&etc.join("exe/upgrade.iss"), &exe, 0o644); + install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644); + t!(t!(File::create(exe.join("LICENSE.txt"))).write_all(license.as_bytes())); + + // Generate exe installer + let mut cmd = Command::new("iscc"); + cmd.arg("rust.iss") + .current_dir(&exe); + if target.contains("windows-gnu") { + cmd.arg("/dMINGW"); + } + add_env(build, &mut cmd, target); + build.run(&mut cmd); + install(&exe.join(format!("{}-{}.exe", pkgname(build, "rust"), target)), + &distdir(build), + 0o755); + + // Generate msi installer + let wix = PathBuf::from(env::var_os("WIX").unwrap()); + let heat = wix.join("bin/heat.exe"); + let candle = wix.join("bin/candle.exe"); + let light = wix.join("bin/light.exe"); + + let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"]; + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rustc") + .args(&heat_flags) + .arg("-cg").arg("RustcGroup") + .arg("-dr").arg("Rustc") + .arg("-var").arg("var.RustcDir") + .arg("-out").arg(exe.join("RustcGroup.wxs"))); + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-docs") + .args(&heat_flags) + .arg("-cg").arg("DocsGroup") + .arg("-dr").arg("Docs") + .arg("-var").arg("var.DocsDir") + .arg("-out").arg(exe.join("DocsGroup.wxs")) + .arg("-t").arg(etc.join("msi/squash-components.xsl"))); + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("cargo") + .args(&heat_flags) + .arg("-cg").arg("CargoGroup") + .arg("-dr").arg("Cargo") + .arg("-var").arg("var.CargoDir") + .arg("-out").arg(exe.join("CargoGroup.wxs")) + .arg("-t").arg(etc.join("msi/remove-duplicates.xsl"))); + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-std") + .args(&heat_flags) + .arg("-cg").arg("StdGroup") + .arg("-dr").arg("Std") + .arg("-var").arg("var.StdDir") + .arg("-out").arg(exe.join("StdGroup.wxs"))); + if target.contains("windows-gnu") { + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-mingw") + .args(&heat_flags) + .arg("-cg").arg("GccGroup") + .arg("-dr").arg("Gcc") + .arg("-var").arg("var.GccDir") + .arg("-out").arg(exe.join("GccGroup.wxs"))); + } + + let candle = |input: &Path| { + let output = exe.join(input.file_stem().unwrap()) + .with_extension("wixobj"); + let arch = if target.contains("x86_64") {"x64"} else {"x86"}; + let mut cmd = Command::new(&candle); + cmd.current_dir(&exe) + .arg("-nologo") + .arg("-dRustcDir=rustc") + .arg("-dDocsDir=rust-docs") + .arg("-dCargoDir=cargo") + .arg("-dStdDir=rust-std") + .arg("-arch").arg(&arch) + .arg("-out").arg(&output) + .arg(&input); + add_env(build, &mut cmd, target); + + if target.contains("windows-gnu") { + cmd.arg("-dGccDir=rust-mingw"); + } + build.run(&mut cmd); + }; + candle(&etc.join("msi/rust.wxs")); + candle(&etc.join("msi/ui.wxs")); + candle(&etc.join("msi/rustwelcomedlg.wxs")); + candle("RustcGroup.wxs".as_ref()); + candle("DocsGroup.wxs".as_ref()); + candle("CargoGroup.wxs".as_ref()); + candle("StdGroup.wxs".as_ref()); + + if target.contains("windows-gnu") { + candle("GccGroup.wxs".as_ref()); + } + + t!(t!(File::create(exe.join("LICENSE.rtf"))).write_all(rtf.as_bytes())); + install(&etc.join("gfx/banner.bmp"), &exe, 0o644); + install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644); + + let filename = format!("{}-{}.msi", pkgname(build, "rust"), target); + let mut cmd = Command::new(&light); + cmd.arg("-nologo") + .arg("-ext").arg("WixUIExtension") + .arg("-ext").arg("WixUtilExtension") + .arg("-out").arg(distdir(build).join(filename)) + .arg("rust.wixobj") + .arg("ui.wixobj") + .arg("rustwelcomedlg.wixobj") + .arg("RustcGroup.wixobj") + .arg("DocsGroup.wixobj") + .arg("CargoGroup.wixobj") + .arg("StdGroup.wixobj") + .current_dir(&exe); + + if target.contains("windows-gnu") { + cmd.arg("GccGroup.wixobj"); + } + // ICE57 wrongly complains about the shortcuts + cmd.arg("-sice:ICE57"); + + build.run(&mut cmd); + } +} + +fn add_env(build: &Build, cmd: &mut Command, target: &str) { + let mut parts = build.release_num.split('.'); + cmd.env("CFG_RELEASE_INFO", &build.version) + .env("CFG_RELEASE_NUM", &build.release_num) + .env("CFG_RELEASE", &build.release) + .env("CFG_PRERELEASE_VERSION", &build.prerelease_version) + .env("CFG_VER_MAJOR", parts.next().unwrap()) + .env("CFG_VER_MINOR", parts.next().unwrap()) + .env("CFG_VER_PATCH", parts.next().unwrap()) + .env("CFG_VER_BUILD", "0") // just needed to build + .env("CFG_PACKAGE_VERS", package_vers(build)) + .env("CFG_PACKAGE_NAME", pkgname(build, "rust")) + .env("CFG_BUILD", target) + .env("CFG_CHANNEL", &build.config.channel); + + if target.contains("windows-gnu") { + cmd.env("CFG_MINGW", "1") + .env("CFG_ABI", "GNU"); + } else { + cmd.env("CFG_MINGW", "0") + .env("CFG_ABI", "MSVC"); + } + + if target.contains("x86_64") { + cmd.env("CFG_PLATFORM", "x64"); + } else { + cmd.env("CFG_PLATFORM", "x86"); + } +} diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 6b2b6ad5c02..db2fe2db813 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -170,6 +170,8 @@ pub struct Build { version: String, package_vers: String, local_rebuild: bool, + release_num: String, + prerelease_version: String, // Probed tools at runtime lldb_version: Option<String>, @@ -271,6 +273,8 @@ impl Build { lldb_version: None, lldb_python_dir: None, is_sudo: is_sudo, + release_num: String::new(), + prerelease_version: String::new(), } } diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 289621184f0..697b14c6050 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -618,6 +618,20 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.dist("install", "path/to/nowhere") .dep(|s| s.name("default:dist")) .run(move |s| install::install(build, s.stage, s.target)); + rules.dist("dist-cargo", "cargo") + .host(true) + .only_host_build(true) + .run(move |s| dist::cargo(build, s.stage, s.target)); + rules.dist("dist-extended", "extended") + .default(build.config.extended) + .host(true) + .only_host_build(true) + .dep(|d| d.name("dist-std")) + .dep(|d| d.name("dist-rustc")) + .dep(|d| d.name("dist-mingw")) + .dep(|d| d.name("dist-docs")) + .dep(|d| d.name("dist-cargo")) + .run(move |s| dist::extended(build, s.stage, s.target)); rules.verify(); return rules; diff --git a/src/ci/docker/dist-arm-linux/Dockerfile b/src/ci/docker/dist-arm-linux/Dockerfile index 03ca4c28078..217a724fb9a 100644 --- a/src/ci/docker/dist-arm-linux/Dockerfile +++ b/src/ci/docker/dist-arm-linux/Dockerfile @@ -76,5 +76,5 @@ ENV CC_arm_unknown_linux_gnueabi=arm-unknown-linux-gnueabi-gcc \ ENV HOSTS=arm-unknown-linux-gnueabi ENV HOSTS=$HOSTS,arm-unknown-linux-gnueabihf -ENV RUST_CONFIGURE_ARGS --host=$HOSTS +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-armv7-aarch64-linux/Dockerfile b/src/ci/docker/dist-armv7-aarch64-linux/Dockerfile index 93d9e004c8c..f26885bbb53 100644 --- a/src/ci/docker/dist-armv7-aarch64-linux/Dockerfile +++ b/src/ci/docker/dist-armv7-aarch64-linux/Dockerfile @@ -77,5 +77,5 @@ ENV CC_aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnueabi-gcc \ ENV HOSTS=armv7-unknown-linux-gnueabihf ENV HOSTS=$HOSTS,aarch64-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --host=$HOSTS +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-freebsd/Dockerfile b/src/ci/docker/dist-freebsd/Dockerfile index 4b6db62d389..d824c4041ce 100644 --- a/src/ci/docker/dist-freebsd/Dockerfile +++ b/src/ci/docker/dist-freebsd/Dockerfile @@ -38,5 +38,5 @@ ENV \ ENV HOSTS=x86_64-unknown-freebsd ENV HOSTS=$HOSTS,i686-unknown-freebsd -ENV RUST_CONFIGURE_ARGS --host=$HOSTS +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-mips-linux/Dockerfile b/src/ci/docker/dist-mips-linux/Dockerfile index df189c25809..38ee95038f6 100644 --- a/src/ci/docker/dist-mips-linux/Dockerfile +++ b/src/ci/docker/dist-mips-linux/Dockerfile @@ -27,5 +27,5 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV HOSTS=mips-unknown-linux-gnu ENV HOSTS=$HOSTS,mipsel-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --host=$HOSTS +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-mips64-linux/Dockerfile b/src/ci/docker/dist-mips64-linux/Dockerfile index 9152965caee..c9d89d62874 100644 --- a/src/ci/docker/dist-mips64-linux/Dockerfile +++ b/src/ci/docker/dist-mips64-linux/Dockerfile @@ -27,5 +27,5 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV HOSTS=mips64-unknown-linux-gnuabi64 ENV HOSTS=$HOSTS,mips64el-unknown-linux-gnuabi64 -ENV RUST_CONFIGURE_ARGS --host=$HOSTS +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-powerpc-linux/Dockerfile b/src/ci/docker/dist-powerpc-linux/Dockerfile index d5f9e5269f1..ed4e9a35960 100644 --- a/src/ci/docker/dist-powerpc-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc-linux/Dockerfile @@ -25,7 +25,7 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV HOSTS=powerpc-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --host=$HOSTS +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS # FIXME(#36150) this will fail the bootstrap. Probably means something bad is diff --git a/src/ci/docker/dist-powerpc64-linux/Dockerfile b/src/ci/docker/dist-powerpc64-linux/Dockerfile index 3b222581bd4..6c04048f4dd 100644 --- a/src/ci/docker/dist-powerpc64-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc64-linux/Dockerfile @@ -32,5 +32,5 @@ ENV \ ENV HOSTS=powerpc64-unknown-linux-gnu ENV HOSTS=$HOSTS,powerpc64le-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --host=$HOSTS +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-s390x-linux-netbsd/Dockerfile b/src/ci/docker/dist-s390x-linux-netbsd/Dockerfile index 7350b11a69f..ec38855fe3a 100644 --- a/src/ci/docker/dist-s390x-linux-netbsd/Dockerfile +++ b/src/ci/docker/dist-s390x-linux-netbsd/Dockerfile @@ -36,5 +36,5 @@ ENV \ ENV HOSTS=x86_64-unknown-netbsd ENV HOSTS=$HOSTS,s390x-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --host=$HOSTS +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-x86-linux/Dockerfile b/src/ci/docker/dist-x86-linux/Dockerfile index 283a4aaab56..4e4f5dd6f1e 100644 --- a/src/ci/docker/dist-x86-linux/Dockerfile +++ b/src/ci/docker/dist-x86-linux/Dockerfile @@ -76,5 +76,5 @@ RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | ENV HOSTS=i686-unknown-linux-gnu ENV HOSTS=$HOSTS,x86_64-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --host=$HOSTS +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/etc/installer/README.md b/src/etc/installer/README.md new file mode 100644 index 00000000000..dbefe753bee --- /dev/null +++ b/src/etc/installer/README.md @@ -0,0 +1,28 @@ +# The Rust Programming Language + +This is a compiler for Rust, including standard libraries, tools and +documentation. Rust is a systems programming language that is fast, +memory safe and multithreaded, but does not employ a garbage collector +or otherwise impose significant runtime overhead. + +To install to /usr/local (the default), run the included `install.sh` script: + + $ sudo ./install.sh + +To uninstall: + + $ sudo /usr/local/lib/rustlib/uninstall.sh + +`install.sh` has a few options, including the possibility to set an installation +prefix. You can display these options by running: + + $ sudo ./install.sh --help + +Read [The Book](http://doc.rust-lang.org/book/index.html) to learn how +to use Rust. + +Rust is primarily distributed under the terms of both the MIT license +and the Apache License (Version 2.0), with portions covered by various +BSD-like licenses. + +See LICENSE-APACHE, LICENSE-MIT, and COPYRIGHT for details. diff --git a/src/etc/installer/exe/modpath.iss b/src/etc/installer/exe/modpath.iss new file mode 100644 index 00000000000..35cc0097035 --- /dev/null +++ b/src/etc/installer/exe/modpath.iss @@ -0,0 +1,219 @@ +// ---------------------------------------------------------------------------- +// +// Inno Setup Ver: 5.4.2 +// Script Version: 1.4.1 +// Author: Jared Breland <jbreland@legroom.net> +// Homepage: http://www.legroom.net/software +// License: GNU Lesser General Public License (LGPL), version 3 +// http://www.gnu.org/licenses/lgpl.html +// +// Script Function: +// Allow modification of environmental path directly from Inno Setup installers +// +// Instructions: +// Copy modpath.iss to the same directory as your setup script +// +// Add this statement to your [Setup] section +// ChangesEnvironment=true +// +// Add this statement to your [Tasks] section +// You can change the Description or Flags +// You can change the Name, but it must match the ModPathName setting below +// Name: modifypath; Description: &Add application directory to your environmental path; Flags: unchecked +// +// Add the following to the end of your [Code] section +// ModPathName defines the name of the task defined above +// ModPathType defines whether the 'user' or 'system' path will be modified; +// this will default to user if anything other than system is set +// setArrayLength must specify the total number of dirs to be added +// Result[0] contains first directory, Result[1] contains second, etc. +// const +// ModPathName = 'modifypath'; +// ModPathType = 'user'; +// +// function ModPathDir(): TArrayOfString; +// begin +// setArrayLength(Result, 1); +// Result[0] := ExpandConstant('{app}'); +// end; +// #include "modpath.iss" +// ---------------------------------------------------------------------------- + +procedure ModPath(); +var + oldpath: String; + newpath: String; + updatepath: Boolean; + pathArr: TArrayOfString; + aExecFile: String; + aExecArr: TArrayOfString; + i, d: Integer; + pathdir: TArrayOfString; + regroot: Integer; + regpath: String; + +begin + // Get constants from main script and adjust behavior accordingly + // ModPathType MUST be 'system' or 'user'; force 'user' if invalid + if ModPathType = 'system' then begin + regroot := HKEY_LOCAL_MACHINE; + regpath := 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; + end else begin + regroot := HKEY_CURRENT_USER; + regpath := 'Environment'; + end; + + // Get array of new directories and act on each individually + pathdir := ModPathDir(); + for d := 0 to GetArrayLength(pathdir)-1 do begin + updatepath := true; + + // Modify WinNT path + if UsingWinNT() = true then begin + + // Get current path, split into an array + RegQueryStringValue(regroot, regpath, 'Path', oldpath); + oldpath := oldpath + ';'; + i := 0; + + while (Pos(';', oldpath) > 0) do begin + SetArrayLength(pathArr, i+1); + pathArr[i] := Copy(oldpath, 0, Pos(';', oldpath)-1); + oldpath := Copy(oldpath, Pos(';', oldpath)+1, Length(oldpath)); + i := i + 1; + + // Check if current directory matches app dir + if pathdir[d] = pathArr[i-1] then begin + // if uninstalling, remove dir from path + if IsUninstaller() = true then begin + continue; + // if installing, flag that dir already exists in path + end else begin + updatepath := false; + end; + end; + + // Add current directory to new path + if i = 1 then begin + newpath := pathArr[i-1]; + end else begin + newpath := newpath + ';' + pathArr[i-1]; + end; + end; + + // Append app dir to path if not already included + if (IsUninstaller() = false) AND (updatepath = true) then + newpath := newpath + ';' + pathdir[d]; + + // Write new path + RegWriteStringValue(regroot, regpath, 'Path', newpath); + + // Modify Win9x path + end else begin + + // Convert to shortened dirname + pathdir[d] := GetShortName(pathdir[d]); + + // If autoexec.bat exists, check if app dir already exists in path + aExecFile := 'C:\AUTOEXEC.BAT'; + if FileExists(aExecFile) then begin + LoadStringsFromFile(aExecFile, aExecArr); + for i := 0 to GetArrayLength(aExecArr)-1 do begin + if IsUninstaller() = false then begin + // If app dir already exists while installing, skip add + if (Pos(pathdir[d], aExecArr[i]) > 0) then + updatepath := false; + break; + end else begin + // If app dir exists and = what we originally set, then delete at uninstall + if aExecArr[i] = 'SET PATH=%PATH%;' + pathdir[d] then + aExecArr[i] := ''; + end; + end; + end; + + // If app dir not found, or autoexec.bat didn't exist, then (create and) append to current path + if (IsUninstaller() = false) AND (updatepath = true) then begin + SaveStringToFile(aExecFile, #13#10 + 'SET PATH=%PATH%;' + pathdir[d], True); + + // If uninstalling, write the full autoexec out + end else begin + SaveStringsToFile(aExecFile, aExecArr, False); + end; + end; + end; +end; + +// Split a string into an array using passed delimeter +procedure Explode(var Dest: TArrayOfString; Text: String; Separator: String); +var + i: Integer; +begin + i := 0; + repeat + SetArrayLength(Dest, i+1); + if Pos(Separator,Text) > 0 then begin + Dest[i] := Copy(Text, 1, Pos(Separator, Text)-1); + Text := Copy(Text, Pos(Separator,Text) + Length(Separator), Length(Text)); + i := i + 1; + end else begin + Dest[i] := Text; + Text := ''; + end; + until Length(Text)=0; +end; + + +procedure ModPathCurStepChanged(CurStep: TSetupStep); +var + taskname: String; +begin + taskname := ModPathName; + if CurStep = ssPostInstall then + if IsTaskSelected(taskname) then + ModPath(); +end; + +procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); +var + aSelectedTasks: TArrayOfString; + i: Integer; + taskname: String; + regpath: String; + regstring: String; + appid: String; +begin + // only run during actual uninstall + if CurUninstallStep = usUninstall then begin + // get list of selected tasks saved in registry at install time + appid := '{#emit SetupSetting("AppId")}'; + if appid = '' then appid := '{#emit SetupSetting("AppName")}'; + regpath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\'+appid+'_is1'); + RegQueryStringValue(HKLM, regpath, 'Inno Setup: Selected Tasks', regstring); + if regstring = '' then RegQueryStringValue(HKCU, regpath, 'Inno Setup: Selected Tasks', regstring); + + // check each task; if matches modpath taskname, trigger patch removal + if regstring <> '' then begin + taskname := ModPathName; + Explode(aSelectedTasks, regstring, ','); + if GetArrayLength(aSelectedTasks) > 0 then begin + for i := 0 to GetArrayLength(aSelectedTasks)-1 do begin + if comparetext(aSelectedTasks[i], taskname) = 0 then + ModPath(); + end; + end; + end; + end; +end; + +function NeedRestart(): Boolean; +var + taskname: String; +begin + taskname := ModPathName; + if IsTaskSelected(taskname) and not UsingWinNT() then begin + Result := True; + end else begin + Result := False; + end; +end; diff --git a/src/etc/installer/exe/rust.iss b/src/etc/installer/exe/rust.iss new file mode 100644 index 00000000000..a61a19f909a --- /dev/null +++ b/src/etc/installer/exe/rust.iss @@ -0,0 +1,80 @@ +#define CFG_RELEASE_NUM GetEnv("CFG_RELEASE_NUM") +#define CFG_RELEASE GetEnv("CFG_RELEASE") +#define CFG_PACKAGE_NAME GetEnv("CFG_PACKAGE_NAME") +#define CFG_BUILD GetEnv("CFG_BUILD") + +[Setup] + +SetupIconFile=rust-logo.ico +AppName=Rust +AppVersion={#CFG_RELEASE} +AppCopyright=Copyright (C) 2006-2014 Mozilla Foundation, MIT license +AppPublisher=Mozilla Foundation +AppPublisherURL=http://www.rust-lang.org +VersionInfoVersion={#CFG_RELEASE_NUM} +LicenseFile=LICENSE.txt + +PrivilegesRequired=lowest +DisableWelcomePage=true +DisableProgramGroupPage=true +DisableReadyPage=true +DisableStartupPrompt=true + +OutputDir=.\ +SourceDir=.\ +OutputBaseFilename={#CFG_PACKAGE_NAME}-{#CFG_BUILD} +DefaultDirName={sd}\Rust + +Compression=lzma2/ultra +InternalCompressLevel=ultra +SolidCompression=true + +ChangesEnvironment=true +ChangesAssociations=no +AllowUNCPath=false +AllowNoIcons=true +Uninstallable=yes + +[Tasks] +Name: modifypath; Description: &Add {app}\bin to your PATH (recommended) + +[Components] +Name: rust; Description: "Rust compiler and standard crates"; Types: full compact custom; Flags: fixed +#ifdef MINGW +Name: gcc; Description: "Linker and platform libraries"; Types: full +#endif +Name: docs; Description: "HTML documentation"; Types: full +Name: cargo; Description: "Cargo, the Rust package manager"; Types: full +Name: std; Description: "The Rust Standard Library"; Types: full + +[Files] +Source: "rustc/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rust +#ifdef MINGW +Source: "rust-mingw/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: gcc +#endif +Source: "rust-docs/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: docs +Source: "cargo/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: cargo +Source: "rust-std/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: std + +[Code] +const + ModPathName = 'modifypath'; + ModPathType = 'user'; + +function ModPathDir(): TArrayOfString; +begin + setArrayLength(Result, 1) + Result[0] := ExpandConstant('{app}\bin'); +end; + +#include "modpath.iss" +#include "upgrade.iss" + +// Both modpath.iss and upgrade.iss want to overload CurStepChanged. +// This version does the overload then delegates to each. + +procedure CurStepChanged(CurStep: TSetupStep); +begin + UpgradeCurStepChanged(CurStep); + ModPathCurStepChanged(CurStep); +end; diff --git a/src/etc/installer/exe/upgrade.iss b/src/etc/installer/exe/upgrade.iss new file mode 100644 index 00000000000..29da7c333bb --- /dev/null +++ b/src/etc/installer/exe/upgrade.iss @@ -0,0 +1,61 @@ +// The following code taken from https://stackoverflow.com/questions/2000296/innosetup-how-to-automatically-uninstall-previous-installed-version +// It performs upgrades by running the uninstaller before the install + +///////////////////////////////////////////////////////////////////// +function GetUninstallString(): String; +var + sUnInstPath: String; + sUnInstallString: String; +begin + sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\Rust_is1'); + sUnInstallString := ''; + if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then + RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString); + Result := sUnInstallString; +end; + + +///////////////////////////////////////////////////////////////////// +function IsUpgrade(): Boolean; +begin + Result := (GetUninstallString() <> ''); +end; + + +///////////////////////////////////////////////////////////////////// +function UnInstallOldVersion(): Integer; +var + sUnInstallString: String; + iResultCode: Integer; +begin +// Return Values: +// 1 - uninstall string is empty +// 2 - error executing the UnInstallString +// 3 - successfully executed the UnInstallString + + // default return value + Result := 0; + + // get the uninstall string of the old app + sUnInstallString := GetUninstallString(); + if sUnInstallString <> '' then begin + sUnInstallString := RemoveQuotes(sUnInstallString); + if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then + Result := 3 + else + Result := 2; + end else + Result := 1; +end; + +///////////////////////////////////////////////////////////////////// +procedure UpgradeCurStepChanged(CurStep: TSetupStep); +begin + if (CurStep=ssInstall) then + begin + if (IsUpgrade()) then + begin + UnInstallOldVersion(); + end; + end; +end; diff --git a/src/etc/installer/gfx/banner.bmp b/src/etc/installer/gfx/banner.bmp new file mode 100644 index 00000000000..b5459a797d2 --- /dev/null +++ b/src/etc/installer/gfx/banner.bmp Binary files differdiff --git a/src/etc/installer/gfx/banner.xcf b/src/etc/installer/gfx/banner.xcf new file mode 100644 index 00000000000..53296518ee2 --- /dev/null +++ b/src/etc/installer/gfx/banner.xcf Binary files differdiff --git a/src/etc/installer/gfx/dialogbg.bmp b/src/etc/installer/gfx/dialogbg.bmp new file mode 100644 index 00000000000..7e4674a4fea --- /dev/null +++ b/src/etc/installer/gfx/dialogbg.bmp Binary files differdiff --git a/src/etc/installer/gfx/dialogbg.xcf b/src/etc/installer/gfx/dialogbg.xcf new file mode 100644 index 00000000000..49ca4e0c33e --- /dev/null +++ b/src/etc/installer/gfx/dialogbg.xcf Binary files differdiff --git a/src/etc/installer/gfx/rust-logo.ico b/src/etc/installer/gfx/rust-logo.ico new file mode 100644 index 00000000000..a58225d5acb --- /dev/null +++ b/src/etc/installer/gfx/rust-logo.ico Binary files differdiff --git a/src/etc/installer/gfx/rust-logo.png b/src/etc/installer/gfx/rust-logo.png new file mode 100644 index 00000000000..2c3de300087 --- /dev/null +++ b/src/etc/installer/gfx/rust-logo.png Binary files differdiff --git a/src/etc/installer/msi/remove-duplicates.xsl b/src/etc/installer/msi/remove-duplicates.xsl new file mode 100644 index 00000000000..05b4c9bcc93 --- /dev/null +++ b/src/etc/installer/msi/remove-duplicates.xsl @@ -0,0 +1,24 @@ +<?xml version="1.0" ?> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"> + <!-- Copy all attributes and elements to the output. --> + <xsl:template match="@*|*"> + <xsl:copy> + <xsl:apply-templates select="@*|*"/> + </xsl:copy> + </xsl:template> + <xsl:output method="xml" indent="yes" /> + + <!-- LICENSE* files are installed from rustc dir. --> + <xsl:key name="duplicates-cmp-ids" match="wix:Component[./wix:File[contains(@Source, 'LICENSE')]|./wix:File[contains(@Source, 'rust-installer-version')]]" use="@Id" /> + <xsl:template match="wix:Component[key('duplicates-cmp-ids', @Id)]" /> + <xsl:template match="wix:ComponentRef[key('duplicates-cmp-ids', @Id)]" /> + + <xsl:template match="wix:File[contains(@Source, 'README.md')]"> + <xsl:copy> + <xsl:apply-templates select="@*|*"/> + <xsl:attribute name="Name">README-CARGO.md</xsl:attribute> + </xsl:copy> + </xsl:template> +</xsl:stylesheet> diff --git a/src/etc/installer/msi/rust.wxs b/src/etc/installer/msi/rust.wxs new file mode 100644 index 00000000000..fb076ccb091 --- /dev/null +++ b/src/etc/installer/msi/rust.wxs @@ -0,0 +1,279 @@ +<?xml version="1.0"?> +<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> + + <?if $(sys.BUILDARCH)="x64" ?> + <?define ArchSuffix=" 64-bit" ?> + <?else?> + <?define ArchSuffix="" ?> + <?endif?> + + <?if $(env.CFG_CHANNEL)="stable" ?> + <?define ProductName="Rust $(env.CFG_VER_MAJOR).$(env.CFG_VER_MINOR) ($(env.CFG_ABI)$(var.ArchSuffix))" ?> + <?else?> + <?define ProductName="Rust $(env.CFG_CHANNEL) $(env.CFG_VER_MAJOR).$(env.CFG_VER_MINOR) ($(env.CFG_ABI)$(var.ArchSuffix))" ?> + <?endif?> + + <?define BaseRegKey="Software\[Manufacturer]\Rust $(env.CFG_CHANNEL) ($(env.CFG_ABI)$(var.ArchSuffix))\$(env.CFG_VER_MAJOR).$(env.CFG_VER_MINOR)" ?> + + <!-- Upgrade code should be different for each platform --> + <?if $(sys.BUILDARCH)="x64" ?> + <?if $(env.CFG_ABI)="GNU" ?> + <!-- UpgradeCode shoud stay the same for all MSI versions in channel --> + <?if $(env.CFG_CHANNEL)="stable" ?> + <?define UpgradeCode="B440B077-F8D1-4730-8E1D-D6D37702B4CE" ?> + <?elseif $(env.CFG_CHANNEL)="beta" ?> + <?define UpgradeCode="7205CEDC-CDA6-4B62-8E4E-4D19EC5D88FC" ?> + <?elseif $(env.CFG_CHANNEL)="nightly" ?> + <?define UpgradeCode="622497D9-E0B1-448E-838A-4A33D0C5F82C" ?> + <?elseif $(env.CFG_CHANNEL)="dev" ?> + <?define UpgradeCode="7D32FD99-BB26-45CF-935D-1B0593BBDDBE" ?> + <?endif ?> + <?elseif $(env.CFG_ABI)="MSVC" ?> + <?if $(env.CFG_CHANNEL)="stable" ?> + <?define UpgradeCode="123039F9-68E3-44F1-AC9F-C78ADD4D0723" ?> + <?elseif $(env.CFG_CHANNEL)="beta" ?> + <?define UpgradeCode="ABC640B9-2AB5-4270-9A0D-E54E502A1CCA" ?> + <?elseif $(env.CFG_CHANNEL)="nightly" ?> + <?define UpgradeCode="56263F12-4AA1-4FE1-AFAE-572915C4FA3E" ?> + <?elseif $(env.CFG_CHANNEL)="dev" ?> + <?define UpgradeCode="231A9544-7E39-4A60-A069-0EB3CA4BAB2E" ?> + <?endif ?> + <?endif ?> + <?define PlatformProgramFilesFolder="ProgramFiles64Folder" ?> + <?elseif $(sys.BUILDARCH)="x86" ?> + <?if $(env.CFG_ABI)="GNU" ?> + <?if $(env.CFG_CHANNEL)="stable" ?> + <?define UpgradeCode="1C7CADA5-D117-43F8-A356-DF15F9FBEFF6" ?> + <?elseif $(env.CFG_CHANNEL)="beta" ?> + <?define UpgradeCode="5229EAC1-AB7C-4A62-9881-6FAD2DE7D0F9" ?> + <?elseif $(env.CFG_CHANNEL)="nightly" ?> + <?define UpgradeCode="B94FF1C2-2C7B-4859-A08B-546815516FDA" ?> + <?elseif $(env.CFG_CHANNEL)="dev" ?> + <?define UpgradeCode="7E6D1349-2773-4792-B8CD-EA2685D86A99" ?> + <?endif ?> + <?elseif $(env.CFG_ABI)="MSVC" ?> + <?if $(env.CFG_CHANNEL)="stable" ?> + <?define UpgradeCode="5805719C-45E9-4CF6-9CE7-1E8B57F3C243" ?> + <?elseif $(env.CFG_CHANNEL)="beta" ?> + <?define UpgradeCode="BC0731C1-BED1-424C-BE99-3589C35C84DE" ?> + <?elseif $(env.CFG_CHANNEL)="nightly" ?> + <?define UpgradeCode="FF193BBC-E73B-4FBD-ADE0-12F3CFC84145" ?> + <?elseif $(env.CFG_CHANNEL)="dev" ?> + <?define UpgradeCode="87DFC303-6492-4E9B-911E-56EAD56C5E58" ?> + <?endif ?> + <?endif ?> + <?define PlatformProgramFilesFolder="ProgramFilesFolder" ?> + <?else ?> + <?error Unsupported value of sys.BUILDARCH=$(sys.BUILDARCH)?> + <?endif ?> + + <Product Id="*" + Name="$(var.ProductName)" + Language="1033" + Version="$(env.CFG_VER_MAJOR).$(env.CFG_VER_MINOR).$(env.CFG_VER_PATCH).$(env.CFG_VER_BUILD)" + UpgradeCode="$(var.UpgradeCode)" + Manufacturer="The Rust Project Developers"> + <Package + Comments="Rust is a systems programming language that runs blazingly fast, prevents almost all crashes, and eliminates data races." + InstallerVersion="200" + InstallPrivileges="elevated" + Compressed="yes" /> + + <Icon Id="rust.ico" SourceFile="rust-logo.ico" /> + <Property Id="ApplicationFolderName" Value="Rust $(env.CFG_CHANNEL) $(env.CFG_ABI) $(env.CFG_VER_MAJOR).$(env.CFG_VER_MINOR)" /> + <Property Id="WixAppFolder" Value="WixPerMachineFolder" /> + <Property Id="ARPPRODUCTICON" Value="rust.ico" /> + <Property Id="ARPURLINFOABOUT" Value="https://www.rust-lang.org/" /> + <Property Id="ARPCOMMENTS" Value="$(env.CFG_RELEASE_INFO)" /> + <!-- This is a dual-mode package. http://msdn.microsoft.com/en-us/library/windows/desktop/dd408068.aspx --> + <Property Id="ALLUSERS" Value="2" Secure="yes" /> + <Property Id="MSIINSTALLPERUSER" Secure="yes" /> + <!-- The actual install location (initialized below) --> + <Property Id="INSTALLDIR" Secure="yes" /> + + <!-- Detect path(s) of a previous installation. --> + <Property Id="INSTALLDIR_USER"> + <RegistrySearch Id="InstallDir_User" Type="raw" Root="HKCU" Key="$(var.BaseRegKey)" Name="InstallDir" /> + </Property> + <Property Id="INSTALLDIR_MACHINE"> + <RegistrySearch Id="InstallDir_Mach" Type="raw" Root="HKLM" Key="$(var.BaseRegKey)" Name="InstallDir" /> + </Property> + + <!-- Set ALLUSERS to match the previous installation mode, otherwise FindRelatedProducts will ignore + the previous installation. If both INSTALLDIR_USER and INSTALLDIR_MACHINE are set, prefer the former. --> + <SetProperty Sequence="first" Before="FindRelatedProducts" + Id="ALLUSERS" Value="{}">INSTALLDIR_USER</SetProperty> + + <!-- Set default values if RegSearch found nothing, or if we not upgrading --> + <SetProperty Sequence="both" Before="SetINSTALLDIR1" + Id="INSTALLDIR_USER" Value="[LocalAppDataFolder]Programs\[ApplicationFolderName]">NOT INSTALLDIR_USER</SetProperty> + <SetProperty Sequence="both" Before="SetINSTALLDIR1" + Id="INSTALLDIR_MACHINE" Value="[$(var.PlatformProgramFilesFolder)][ApplicationFolderName]">NOT INSTALLDIR_MACHINE</SetProperty> + + <!-- Choose the default install location according to ALLUSERS (unless set from the command line) --> + <SetProperty Sequence="both" Action="SetINSTALLDIR1" Before="SetINSTALLDIR2" + Id="INSTALLDIR" Value="[INSTALLDIR_USER]">NOT INSTALLDIR AND NOT ALLUSERS</SetProperty> + <SetProperty Sequence="both" Action="SetINSTALLDIR2" Before="CostFinalize" + Id="INSTALLDIR" Value="[INSTALLDIR_MACHINE]">NOT INSTALLDIR AND ALLUSERS</SetProperty> + + <SetProperty Sequence="ui" Before="CostFinalize" + Id="WixAppFolder" Value="WixPerUserFolder">NOT ALLUSERS</SetProperty> + + <!-- UI sets ALLUSERS per user selection; progagate this choice to MSIINSTALLPERUSER before executing installation actions --> + <SetProperty Sequence="ui" Before="ExecuteAction" + Id="MSIINSTALLPERUSER" Value="1">NOT ALLUSERS</SetProperty> + + <!-- Update ARPINSTALLLOCATION to match INSTALLDIR --> + <SetProperty Sequence="execute" Before="CostFinalize" + Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" /> + + <!-- Path of cmd.exe for the shortcut --> + <Property Id="SHORTCUTTARGET" Value="%windir%\System32\cmd.exe" /> + <!-- Microsoft Installer will resolve any Enviroment Variables in the working directory at install time --> + <Property Id="SHORTCUTWKDIR" Value="%SystemDrive%\" /> + + <InstallUISequence> + <FindRelatedProducts After="AppSearch" /> + </InstallUISequence> + <InstallExecuteSequence> + <FindRelatedProducts After="AppSearch" /> + <RemoveExistingProducts Before="InstallInitialize" /> + </InstallExecuteSequence> + + <Upgrade Id="$(var.UpgradeCode)"> + <UpgradeVersion + Minimum="$(env.CFG_VER_MAJOR).$(env.CFG_VER_MINOR).0" + Maximum="$(env.CFG_VER_MAJOR).$(env.CFG_VER_MINOR).65535" + IncludeMinimum="yes" + IncludeMaximum="yes" + MigrateFeatures="yes" + Property="UPGRADE_DETECTED" + /> + </Upgrade> + + <!-- Specifies a single cab file to be embedded in the installer's .msi. --> + <MediaTemplate EmbedCab="yes" CompressionLevel="high" /> + + <!-- Send a WM_SETTINGCHANGE message to tell processes like explorer to update their + environments so any new command prompts get the updated %PATH% --> + <CustomActionRef Id="WixBroadcastEnvironmentChange" /> + + <!-- Installation directory and files are defined in Files.wxs --> + <Directory Id="TARGETDIR" Name="SourceDir"> + <Directory Id="$(var.PlatformProgramFilesFolder)"> + <Directory Id="INSTALLDIR" Name="Rust"> + <!-- Root directories for every feature should have different IDs for correct work of heat.exe --> + <Directory Id="Rustc" Name="." /> + <?if $(env.CFG_MINGW)="1" ?> + <Directory Id="Gcc" Name="." /> + <?endif?> + <Directory Id="Docs" Name="." /> + <Directory Id="Cargo" Name="." /> + <Directory Id="Std" Name="." /> + </Directory> + </Directory> + + <!-- Record our install location --> + <Component Id="InstallDir" Guid="*"> + <RegistryValue Root="HKMU" Key="$(var.BaseRegKey)" + Type="string" + Name="InstallDir" + Value="[INSTALLDIR]" /> + </Component> + + <!-- Add $/bin to PATH --> + <Component Id="PathEnvPerMachine" Guid="*"> + <Condition>ALLUSERS=1 OR (ALLUSERS=2 AND Privileged)</Condition> + <RegistryValue Root="HKMU" Key="$(var.BaseRegKey)" Name="PathEnvPerMachine" Type="string" Value="1" KeyPath="yes" /> + <!-- [INSTALLDIR] contains trailing backslash --> + <Environment Id="PathPerMachine" Name="PATH" Value="[INSTALLDIR]bin" Permanent="no" Part="last" Action="set" System="yes" /> + </Component> + <Component Id="PathEnvPerUser" Guid="*"> + <Condition>ALLUSERS="" OR (ALLUSERS=2 AND (NOT Privileged))</Condition> + <RegistryValue Root="HKMU" Key="$(var.BaseRegKey)" Name="PathEnvPerUser" Type="string" Value="1" KeyPath="yes" /> + <Environment Id="PathPerUser" Name="PATH" Value="[INSTALLDIR]bin" Permanent="no" Part="last" Action="set" System="no" /> + </Component> + + <!-- Start Menu shortcuts --> + <Directory Id="ProgramMenuFolder"> + <Directory Id="ApplicationProgramsFolder" Name="Rust"> + <Component Id="RustShellShortcut" Guid="*"> + <Shortcut Id="RustShell" + Name="$(var.ProductName) Shell" + Description="Opens Command Prompt with Rust tools directory added to the PATH" + Target="[SHORTCUTTARGET]" + Arguments="/K path [INSTALLDIR]bin;%PATH%" + WorkingDirectory="SHORTCUTWKDIR"> + <Icon Id="rust2.ico" SourceFile="rust-logo.ico" /> + </Shortcut> + <RegistryValue Root="HKMU" Key="$(var.BaseRegKey)" Name="RustShell" Type="integer" Value="1" KeyPath="yes" /> + <RemoveFolder Id="ApplicationProgramsFolder1" On="uninstall" /> + </Component> + <Component Id="DocIndexShortcut" Guid="*"> + <Shortcut Id="RustDocs" + Name="$(var.ProductName) Documentation" + Description="Opens Rust HTML documentation in the default browser" + Target="[INSTALLDIR]share\doc\rust\html\index.html" /> + <RegistryValue Root="HKMU" Key="$(var.BaseRegKey)" Name="RustDocs" Type="integer" Value="1" KeyPath="yes" /> + <RemoveFolder Id="ApplicationProgramsFolder2" On="uninstall" /> + </Component> + </Directory> + </Directory> + + </Directory> + + <Feature Id="Rustc" + Title="Rust compiler and standard crates" + Display="1" + Level="1" + Absent="disallow" + AllowAdvertise="no"> + <ComponentGroupRef Id="RustcGroup" /> + <ComponentRef Id="RustShellShortcut" /> + <ComponentRef Id="InstallDir" /> + </Feature> + <Feature Id="Std" + Title="The Rust standard library" + Display="2" + Level="1" + AllowAdvertise="no"> + <ComponentGroupRef Id="StdGroup" /> + </Feature> + <Feature Id="Cargo" + Title="Cargo, the Rust package manager" + Display="3" + Level="1" + AllowAdvertise="no"> + <ComponentGroupRef Id="CargoGroup" /> + </Feature> + <?if $(env.CFG_MINGW)="1" ?> + <Feature Id="Gcc" + Title="Linker and platform libraries" + Description="If you choose to not install this component, you will require an external MinGW installation in order to create executables and libraries." + Display="4" + Level="1" + AllowAdvertise="no"> + <ComponentGroupRef Id="GccGroup" /> + </Feature> + <?endif?> + <Feature Id="Docs" + Title="HTML documentation" + Display="5" + Level="1" + AllowAdvertise="no"> + <ComponentGroupRef Id="DocsGroup" /> + <ComponentRef Id="DocIndexShortcut" /> + </Feature> + <Feature Id="Path" + Title="Add to PATH" + Description="Add Rust to PATH environment variable" + Display="6" + Level="1" + AllowAdvertise="no"> + <ComponentRef Id="PathEnvPerMachine" /> + <ComponentRef Id="PathEnvPerUser" /> + </Feature> + + <UIRef Id="RustUI" /> + </Product> +</Wix> diff --git a/src/etc/installer/msi/rustwelcomedlg.wxs b/src/etc/installer/msi/rustwelcomedlg.wxs new file mode 100644 index 00000000000..0ee5415ffba --- /dev/null +++ b/src/etc/installer/msi/rustwelcomedlg.wxs @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> + <Fragment> + <UI> + <Dialog Id="RustWelcomeDlg" Width="370" Height="270" Title="!(loc.AdvancedWelcomeEulaDlg_Title)"> + <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="!(loc.AdvancedWelcomeEulaDlgBannerBitmap)" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" /> + <Control Id="Title" Type="Text" X="20" Y="10" Width="300" Height="24" Transparent="yes" NoPrefix="yes" Text="!(loc.AdvancedWelcomeEulaDlgTitle)" /> + <Control Id="DescriptionPerMachine" Type="Text" X="20" Y="182" Width="330" Height="31" Transparent="yes" NoPrefix="yes" Hidden="yes" Text="!(loc.AdvancedWelcomeEulaDlgDescriptionPerMachine)"> + <Condition Action="show">NOT UPGRADE_DETECTED AND ALLUSERS</Condition> + </Control> + <Control Id="DescriptionPerUser" Type="Text" X="20" Y="182" Width="330" Height="31" Transparent="yes" NoPrefix="yes" Hidden="yes" Text="!(loc.AdvancedWelcomeEulaDlgDescriptionPerUser)"> + <Condition Action="show">NOT UPGRADE_DETECTED AND NOT ALLUSERS</Condition> + </Control> + <Control Id="DescriptionUpgrade" Type="Text" X="20" Y="182" Width="330" Height="31" Transparent="yes" NoPrefix="yes" Hidden="yes" + Text="Click Install to upgrade the existing version of [ProductName]. Click Advanced to change installation options."> + <Condition Action="show">UPGRADE_DETECTED</Condition> + </Control> + <Control Id="TargetPath" Type="Text" X="20" Y="212" Width="330" Height="31" Transparent="yes" NoPrefix="yes" Hidden="no" + Text="Install Directory: [INSTALLDIR]"> + </Control> + <Control Id="Print" Type="PushButton" X="88" Y="243" Width="56" Height="17" Text="!(loc.WixUIPrint)"> + <Publish Event="DoAction" Value="WixUIPrintEula">1</Publish> + </Control> + <Control Id="Advanced" Type="PushButton" X="156" Y="243" Width="56" Height="17" Text="!(loc.AdvancedWelcomeEulaDlgAdvanced)" /> + <Control Id="Install" Type="PushButton" ElevationShield="yes" X="212" Y="243" Width="80" Height="17" Default="yes" Text="!(loc.AdvancedWelcomeEulaDlgInstall)" Hidden="yes"> + <Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">!(wix.WixUICostingPopupOptOut) OR CostingComplete = 1</Publish> + <Publish Event="EndDialog" Value="Return"><![CDATA[OutOfDiskSpace <> 1]]></Publish> + <Publish Event="SpawnDialog" Value="OutOfRbDiskDlg">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)</Publish> + <Publish Event="EndDialog" Value="Return">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish> + <Publish Event="EnableRollback" Value="False">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish> + <Publish Event="SpawnDialog" Value="OutOfDiskDlg">(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST="F")</Publish> + <Condition Action="show">ALLUSERS</Condition> + </Control> + <Control Id="InstallNoShield" Type="PushButton" ElevationShield="no" X="212" Y="243" Width="80" Height="17" Default="yes" Text="!(loc.AdvancedWelcomeEulaDlgInstall)" Hidden="yes"> + <Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">!(wix.WixUICostingPopupOptOut) OR CostingComplete = 1</Publish> + <Publish Event="EndDialog" Value="Return"><![CDATA[OutOfDiskSpace <> 1]]></Publish> + <Publish Event="SpawnDialog" Value="OutOfRbDiskDlg">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)</Publish> + <Publish Event="EndDialog" Value="Return">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish> + <Publish Event="EnableRollback" Value="False">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish> + <Publish Event="SpawnDialog" Value="OutOfDiskDlg">(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST="F")</Publish> + <Condition Action="show">NOT ALLUSERS</Condition> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.WixUICancel)"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + <Control Id="LicenseText" Type="ScrollableText" X="20" Y="55" Width="330" Height="121" Sunken="yes" TabSkip="no"> + <Text SourceFile="!(wix.WixUILicenseRtf)" /> + </Control> + </Dialog> + </UI> + + <InstallUISequence> + <Show Dialog="RustWelcomeDlg" Before="ProgressDlg">NOT Installed</Show> + </InstallUISequence> + </Fragment> +</Wix> diff --git a/src/etc/installer/msi/squash-components.xsl b/src/etc/installer/msi/squash-components.xsl new file mode 100644 index 00000000000..17b4e0388f9 --- /dev/null +++ b/src/etc/installer/msi/squash-components.xsl @@ -0,0 +1,34 @@ +<?xml version="1.0" ?> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"> + <!-- Copy all attributes and elements to the output. --> + <xsl:template match="@*|*"> + <xsl:copy> + <xsl:apply-templates select="@*|*"/> + </xsl:copy> + </xsl:template> + <xsl:output method="xml" indent="yes" /> + + <!-- Move all files in directory into first component in that directory. --> + <xsl:template match="wix:Component[1]"> + <xsl:copy> + <xsl:apply-templates select="@*|*"/> + <xsl:for-each select="../wix:Component[preceding-sibling::*]/wix:File"> + <xsl:copy> + <!-- Component can only have one KeyPath --> + <xsl:apply-templates select="@*[not(name()='KeyPath')]|*"/> + </xsl:copy> + </xsl:for-each> + </xsl:copy> + </xsl:template> + + <!-- Now the rest of components are empty, find them. --> + <xsl:key name="empty-cmp-ids" match="wix:Component[preceding-sibling::*]" use="@Id" /> + + <!-- And remove. --> + <xsl:template match="wix:Component[preceding-sibling::*]" /> + + <!-- Also remove componentsrefs referencing empty components. --> + <xsl:template match="wix:ComponentRef[key('empty-cmp-ids', @Id)]" /> +</xsl:stylesheet> diff --git a/src/etc/installer/msi/ui.wxs b/src/etc/installer/msi/ui.wxs new file mode 100644 index 00000000000..3e2db6051bc --- /dev/null +++ b/src/etc/installer/msi/ui.wxs @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Based on WixUI_Advanced +--> + +<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> + <Fragment> + <WixVariable Id="WixUISupportPerUser" Value="1" Overridable="yes" /> + <WixVariable Id="WixUISupportPerMachine" Value="1" Overridable="yes" /> + <WixVariable Id="WixUILicenseRtf" Value="LICENSE.rtf" /> + <WixVariable Id="WixUIDialogBmp" Value="dialogbg.bmp" /> + <WixVariable Id="WixUIBannerBmp" Value="banner.bmp" /> + + <UI Id="RustUI"> + <TextStyle Id="WixUI_Font_Normal" FaceName="!(loc.Advanced_Font_FaceName)" Size="!(loc.Advanced_Font_Normal_Size)" /> + <TextStyle Id="WixUI_Font_Bigger" FaceName="!(loc.Advanced_Font_FaceName)" Size="!(loc.Advanced_Font_Bigger_Size)" /> + <TextStyle Id="WixUI_Font_Title" FaceName="!(loc.Advanced_Font_FaceName)" Size="!(loc.Advanced_Font_Title_Size)" Bold="yes" /> + <TextStyle Id="WixUI_Font_Emphasized" FaceName="!(loc.Advanced_Font_FaceName)" Size="!(loc.Advanced_Font_Emphasized_Size)" Bold="yes" /> + + <Property Id="DefaultUIFont" Value="WixUI_Font_Normal" /> + <Property Id="WixUI_Mode" Value="Advanced" /> + + <DialogRef Id="BrowseDlg" /> + <DialogRef Id="DiskCostDlg" /> + <DialogRef Id="ErrorDlg" /> + <DialogRef Id="FatalError" /> + <DialogRef Id="FilesInUse" /> + <DialogRef Id="MsiRMFilesInUse" /> + <DialogRef Id="PrepareDlg" /> + <DialogRef Id="ProgressDlg" /> + <DialogRef Id="ResumeDlg" /> + <DialogRef Id="UserExit" /> + <DialogRef Id="WelcomeDlg"/> + + <Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish> + + <Publish Dialog="BrowseDlg" Control="OK" Event="DoAction" Value="WixUIValidatePath" Order="1">1</Publish> + <Publish Dialog="BrowseDlg" Control="OK" Event="SpawnDialog" Value="InvalidDirDlg" Order="2"><![CDATA[WIXUI_INSTALLDIR_VALID<>"1"]]></Publish> + + <Publish Dialog="RustWelcomeDlg" Control="Advanced" Event="NewDialog" Value="InstallScopeDlg" Order="1" /> + + <Publish Dialog="InstallScopeDlg" Control="Back" Event="NewDialog" Value="RustWelcomeDlg">1</Publish> + <!-- override default WixAppFolder of WixPerMachineFolder as standard user won't be shown the radio group to set WixAppFolder --> + <Publish Dialog="InstallScopeDlg" Control="Next" Property="WixAppFolder" Value="WixPerUserFolder" Order="1">!(wix.WixUISupportPerUser) AND NOT Privileged</Publish> + <Publish Dialog="InstallScopeDlg" Control="Next" Property="ALLUSERS" Value="{}" Order="2">WixAppFolder = "WixPerUserFolder"</Publish> + <Publish Dialog="InstallScopeDlg" Control="Next" Property="ALLUSERS" Value="1" Order="3">WixAppFolder = "WixPerMachineFolder"</Publish> + <Publish Dialog="InstallScopeDlg" Control="Next" Property="INSTALLDIR" Value="[INSTALLDIR_USER]" Order="4">WixAppFolder = "WixPerUserFolder"</Publish> + <Publish Dialog="InstallScopeDlg" Control="Next" Property="INSTALLDIR" Value="[INSTALLDIR_MACHINE]" Order="5">WixAppFolder = "WixPerMachineFolder"</Publish> + <Publish Dialog="InstallScopeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg" Order="6">1</Publish> + + <Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="InstallScopeDlg" /> + <Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish> + <Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish> + <Publish Dialog="InstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish> + <Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="FeaturesDlg" Order="4">WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"</Publish> + <Publish Dialog="InstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish> + <Publish Dialog="InstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish> + + <Publish Dialog="FeaturesDlg" Control="Back" Event="NewDialog" Value="InstallDirDlg">NOT Installed AND WixAppFolder = "WixPerUserFolder"</Publish> + <Publish Dialog="FeaturesDlg" Control="Back" Event="NewDialog" Value="InstallDirDlg">NOT Installed AND WixAppFolder = "WixPerMachineFolder"</Publish> + <Publish Dialog="FeaturesDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg">Installed</Publish> + + <Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish> + + <Publish Dialog="MaintenanceTypeDlg" Control="ChangeButton" Event="NewDialog" Value="FeaturesDlg">1</Publish> + <Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish> + <Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish> + <Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish> + + <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2">Installed AND NOT PATCH</Publish> + <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="3">Installed AND PATCH</Publish> + + <Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish> + </UI> + + <InstallUISequence> + <Show Dialog="WelcomeDlg" Before="RustWelcomeDlg" >Installed AND PATCH</Show> + </InstallUISequence> + + <Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" /> + <UIRef Id="WixUI_Common" /> + </Fragment> +</Wix> diff --git a/src/etc/installer/pkg/Distribution.xml b/src/etc/installer/pkg/Distribution.xml new file mode 100644 index 00000000000..79f99818ba3 --- /dev/null +++ b/src/etc/installer/pkg/Distribution.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<installer-gui-script minSpecVersion="2"> + <title>The Rust Compiler</title> + <license file="LICENSE.txt" mime-type="text/plain"/> + <pkg-ref id="org.rust-lang.rust"/> + <options customize="always" require-scripts="false" hostArchitectures="i386,x86_64"/> + <domains enable_anywhere="false" enable_currentUserHome="false" enable_localSystem="true" /> + <volume-check> + <allowed-os-versions> + <os-version min="10.7"/> + </allowed-os-versions> + </volume-check> + <choices-outline> + <line choice="install"> + <line choice="rustc"/> + <line choice="rust-std"/> + <line choice="cargo"/> + <line choice="rust-docs"/> + </line> + <line choice="uninstall" /> + </choices-outline> + <!-- + These 'selected' scripts ensure that install and uninstall can never be selected at + the same time. Exectly how they work is pretty mysterious, tied to the unspecified algorithm + the installer uses to traverse the options after one is toggled. + --> + <choice id="install" visible="true" + title="Install Rust" description="Install the Rust compiler, package manager and documentation." + customLocation="/usr/local" + selected="!choices.uninstall.selected" + /> + <choice id="uninstall" visible="true" + title="Uninstall Rust" description="Select this option to uninstall an existing Rust installation." + customLocation="/usr/local" + selected="!(choices.install.selected || choices.rustc.selected || choices.cargo.selected || choices['rust-docs'].selected)" + start_selected="false" + > + <pkg-ref id="org.rust-lang.uninstall" /> + </choice> + <choice id="rustc" visible="true" + title="Compiler" description="rustc, the Rust compiler, and rustdoc, the API documentation tool." + selected="(!choices.uninstall.selected && choices.rustc.selected) || (choices.uninstall.selected && choices.install.selected)" + > + <pkg-ref id="org.rust-lang.rustc"/> + </choice> + <choice id="cargo" visible="true" + title="Cargo" description="cargo, the Rust package manager." + selected="(!choices.uninstall.selected && choices.cargo.selected) || (choices.uninstall.selected && choices.install.selected)" + > + <pkg-ref id="org.rust-lang.cargo"/> + </choice> + <choice id="rust-std" visible="true" + title="Standard Library" description="The Rust standard library." + selected="(!choices.uninstall.selected && choices['rust-std'].selected) || (choices.uninstall.selected && choices.install.selected)" + > + <pkg-ref id="org.rust-lang.rust-std"/> + </choice> + <choice id="rust-docs" visible="true" + title="Documentation" description="HTML documentation." + selected="(!choices.uninstall.selected && choices['rust-docs'].selected) || (choices.uninstall.selected && choices.install.selected)" + > + <pkg-ref id="org.rust-lang.rust-docs"/> + </choice> + <pkg-ref id="org.rust-lang.rustc" version="0" onConclusion="none">rustc.pkg</pkg-ref> + <pkg-ref id="org.rust-lang.cargo" version="0" onConclusion="none">cargo.pkg</pkg-ref> + <pkg-ref id="org.rust-lang.rust-docs" version="0" onConclusion="none">rust-docs.pkg</pkg-ref> + <pkg-ref id="org.rust-lang.rust-std" version="0" onConclusion="none">rust-std.pkg</pkg-ref> + <pkg-ref id="org.rust-lang.uninstall" version="0" onConclusion="none">uninstall.pkg</pkg-ref> + <background file="rust-logo.png" mime-type="image/png" + alignment="bottomleft"/> +</installer-gui-script> diff --git a/src/etc/installer/pkg/postinstall b/src/etc/installer/pkg/postinstall new file mode 100755 index 00000000000..fb035a48690 --- /dev/null +++ b/src/etc/installer/pkg/postinstall @@ -0,0 +1,26 @@ +#!/bin/sh + +source_dir="$(dirname "$0")" +dest_dir="$2" +package_id="$INSTALL_PKG_SESSION_ID" + +if [ -z "$source_dir" ]; then + exit 1 +fi +if [ -z "$dest_dir" ]; then + exit 1 +fi +if [ -z "$package_id" ]; then + exit 1 +fi + +if [ "$package_id" = "org.rust-lang.uninstall" ]; then + if [ ! -e "$dest_dir/lib/rustlib/uninstall.sh" ]; then + exit 1 + fi + sh "$dest_dir/lib/rustlib/uninstall.sh" +else + sh "$source_dir/install.sh" --prefix="$dest_dir" +fi + +exit 0 |
