]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/build/native.rs
rustbuild: Fix compiler-rt build on gnueabihf
[rust.git] / src / bootstrap / build / native.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use std::path::Path;
12 use std::process::Command;
13 use std::fs;
14
15 use build_helper::output;
16 use cmake;
17
18 use build::Build;
19 use build::util::{exe, staticlib};
20
21 pub fn llvm(build: &Build, target: &str) {
22     // If we're using a custom LLVM bail out here, but we can only use a
23     // custom LLVM for the build triple.
24     if let Some(config) = build.config.target_config.get(target) {
25         if let Some(ref s) = config.llvm_config {
26             return check_llvm_version(build, s);
27         }
28     }
29
30     // If the cleaning trigger is newer than our built artifacts (or if the
31     // artifacts are missing) then we keep going, otherwise we bail out.
32     let dst = build.llvm_out(target);
33     let stamp = build.src.join("src/rustllvm/llvm-auto-clean-trigger");
34     let llvm_config = dst.join("bin").join(exe("llvm-config", target));
35     build.clear_if_dirty(&dst, &stamp);
36     if fs::metadata(llvm_config).is_ok() {
37         return
38     }
39
40     let _ = fs::remove_dir_all(&dst.join("build"));
41     t!(fs::create_dir_all(&dst.join("build")));
42     let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};
43
44     // http://llvm.org/docs/CMake.html
45     let mut cfg = cmake::Config::new(build.src.join("src/llvm"));
46     cfg.target(target)
47        .host(&build.config.build)
48        .out_dir(&dst)
49        .profile(if build.config.llvm_optimize {"Release"} else {"Debug"})
50        .define("LLVM_ENABLE_ASSERTIONS", assertions)
51        .define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC")
52        .define("LLVM_INCLUDE_EXAMPLES", "OFF")
53        .define("LLVM_INCLUDE_TESTS", "OFF")
54        .define("LLVM_INCLUDE_DOCS", "OFF")
55        .define("LLVM_ENABLE_ZLIB", "OFF")
56        .define("WITH_POLLY", "OFF")
57        .define("LLVM_ENABLE_TERMINFO", "OFF")
58        .define("LLVM_ENABLE_LIBEDIT", "OFF")
59        .define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string());
60
61     if target.starts_with("i686") {
62         cfg.define("LLVM_BUILD_32_BITS", "ON");
63     }
64
65     // http://llvm.org/docs/HowToCrossCompileLLVM.html
66     if target != build.config.build {
67         // FIXME: if the llvm root for the build triple is overridden then we
68         //        should use llvm-tblgen from there, also should verify that it
69         //        actually exists most of the time in normal installs of LLVM.
70         let host = build.llvm_out(&build.config.build).join("bin/llvm-tblgen");
71         cfg.define("CMAKE_CROSSCOMPILING", "True")
72            .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
73            .define("LLVM_TABLEGEN", &host)
74            .define("LLVM_DEFAULT_TARGET_TRIPLE", target);
75     }
76
77     // MSVC handles compiler business itself
78     if !target.contains("msvc") {
79         if build.config.ccache {
80            cfg.define("CMAKE_C_COMPILER", "ccache")
81               .define("CMAKE_C_COMPILER_ARG1", build.cc(target))
82               .define("CMAKE_CXX_COMPILER", "ccache")
83               .define("CMAKE_CXX_COMPILER_ARG1", build.cxx(target));
84         } else {
85            cfg.define("CMAKE_C_COMPILER", build.cc(target))
86               .define("CMAKE_CXX_COMPILER", build.cxx(target));
87         }
88         cfg.build_arg("-j").build_arg(build.jobs().to_string());
89     }
90
91     // FIXME: we don't actually need to build all LLVM tools and all LLVM
92     //        libraries here, e.g. we just want a few components and a few
93     //        tools. Figure out how to filter them down and only build the right
94     //        tools and libs on all platforms.
95     cfg.build();
96 }
97
98 fn check_llvm_version(build: &Build, llvm_config: &Path) {
99     if !build.config.llvm_version_check {
100         return
101     }
102
103     let mut cmd = Command::new(llvm_config);
104     let version = output(cmd.arg("--version"));
105     if version.starts_with("3.5") || version.starts_with("3.6") ||
106        version.starts_with("3.7") {
107         return
108     }
109     panic!("\n\nbad LLVM version: {}, need >=3.5\n\n", version)
110 }
111
112 pub fn compiler_rt(build: &Build, target: &str) {
113     let dst = build.compiler_rt_out(target);
114     let arch = target.split('-').next().unwrap();
115     let mode = if build.config.rust_optimize {"Release"} else {"Debug"};
116     let (dir, build_target, libname) = if target.contains("linux") {
117         let os = if target.contains("android") {"-android"} else {""};
118         let arch = if arch.starts_with("arm") && target.contains("eabihf") {
119             "armhf"
120         } else {
121             arch
122         };
123         let target = format!("clang_rt.builtins-{}{}", arch, os);
124         ("linux".to_string(), target.clone(), target)
125     } else if target.contains("darwin") {
126         let target = format!("clang_rt.builtins_{}_osx", arch);
127         ("builtins".to_string(), target.clone(), target)
128     } else if target.contains("windows-gnu") {
129         let target = format!("clang_rt.builtins-{}", arch);
130         ("windows".to_string(), target.clone(), target)
131     } else if target.contains("windows-msvc") {
132         (format!("windows/{}", mode),
133          "lib/builtins/builtins".to_string(),
134          format!("clang_rt.builtins-{}", arch.replace("i686", "i386")))
135     } else {
136         panic!("can't get os from target: {}", target)
137     };
138     let output = dst.join("build/lib").join(dir)
139                     .join(staticlib(&libname, target));
140     build.compiler_rt_built.borrow_mut().insert(target.to_string(),
141                                                 output.clone());
142     if fs::metadata(&output).is_ok() {
143         return
144     }
145     let _ = fs::remove_dir_all(&dst);
146     t!(fs::create_dir_all(&dst));
147     let build_llvm_config = build.llvm_out(&build.config.build)
148                                  .join("bin")
149                                  .join(exe("llvm-config", &build.config.build));
150     let mut cfg = cmake::Config::new(build.src.join("src/compiler-rt"));
151     cfg.target(target)
152        .host(&build.config.build)
153        .out_dir(&dst)
154        .profile(mode)
155        .define("LLVM_CONFIG_PATH", build_llvm_config)
156        .define("COMPILER_RT_DEFAULT_TARGET_TRIPLE", target)
157        .define("COMPILER_RT_BUILD_SANITIZERS", "OFF")
158        .define("COMPILER_RT_BUILD_EMUTLS", "OFF")
159        // inform about c/c++ compilers, the c++ compiler isn't actually used but
160        // it's needed to get the initial configure to work on all platforms.
161        .define("CMAKE_C_COMPILER", build.cc(target))
162        .define("CMAKE_CXX_COMPILER", build.cc(target))
163        .build_target(&build_target);
164     cfg.build();
165 }