]>
Commit | Line | Data |
---|---|---|
7453a54e SL |
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()); | |
54a0048b SL |
89 | |
90 | cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" ")); | |
91 | cfg.define("CMAKE_CXX_FLAGS", build.cflags(target).join(" ")); | |
7453a54e SL |
92 | } |
93 | ||
94 | // FIXME: we don't actually need to build all LLVM tools and all LLVM | |
95 | // libraries here, e.g. we just want a few components and a few | |
96 | // tools. Figure out how to filter them down and only build the right | |
97 | // tools and libs on all platforms. | |
98 | cfg.build(); | |
99 | } | |
100 | ||
101 | fn check_llvm_version(build: &Build, llvm_config: &Path) { | |
102 | if !build.config.llvm_version_check { | |
103 | return | |
104 | } | |
105 | ||
106 | let mut cmd = Command::new(llvm_config); | |
107 | let version = output(cmd.arg("--version")); | |
108 | if version.starts_with("3.5") || version.starts_with("3.6") || | |
109 | version.starts_with("3.7") { | |
110 | return | |
111 | } | |
112 | panic!("\n\nbad LLVM version: {}, need >=3.5\n\n", version) | |
113 | } | |
114 | ||
115 | pub fn compiler_rt(build: &Build, target: &str) { | |
116 | let dst = build.compiler_rt_out(target); | |
117 | let arch = target.split('-').next().unwrap(); | |
118 | let mode = if build.config.rust_optimize {"Release"} else {"Debug"}; | |
54a0048b SL |
119 | let (dir, build_target, libname) = if target.contains("linux") || |
120 | target.contains("freebsd") || | |
121 | target.contains("netbsd") { | |
7453a54e SL |
122 | let os = if target.contains("android") {"-android"} else {""}; |
123 | let arch = if arch.starts_with("arm") && target.contains("eabihf") { | |
124 | "armhf" | |
125 | } else { | |
126 | arch | |
127 | }; | |
128 | let target = format!("clang_rt.builtins-{}{}", arch, os); | |
129 | ("linux".to_string(), target.clone(), target) | |
130 | } else if target.contains("darwin") { | |
131 | let target = format!("clang_rt.builtins_{}_osx", arch); | |
132 | ("builtins".to_string(), target.clone(), target) | |
133 | } else if target.contains("windows-gnu") { | |
134 | let target = format!("clang_rt.builtins-{}", arch); | |
135 | ("windows".to_string(), target.clone(), target) | |
136 | } else if target.contains("windows-msvc") { | |
137 | (format!("windows/{}", mode), | |
138 | "lib/builtins/builtins".to_string(), | |
139 | format!("clang_rt.builtins-{}", arch.replace("i686", "i386"))) | |
140 | } else { | |
141 | panic!("can't get os from target: {}", target) | |
142 | }; | |
143 | let output = dst.join("build/lib").join(dir) | |
144 | .join(staticlib(&libname, target)); | |
145 | build.compiler_rt_built.borrow_mut().insert(target.to_string(), | |
146 | output.clone()); | |
147 | if fs::metadata(&output).is_ok() { | |
148 | return | |
149 | } | |
150 | let _ = fs::remove_dir_all(&dst); | |
151 | t!(fs::create_dir_all(&dst)); | |
152 | let build_llvm_config = build.llvm_out(&build.config.build) | |
153 | .join("bin") | |
154 | .join(exe("llvm-config", &build.config.build)); | |
155 | let mut cfg = cmake::Config::new(build.src.join("src/compiler-rt")); | |
156 | cfg.target(target) | |
157 | .host(&build.config.build) | |
158 | .out_dir(&dst) | |
159 | .profile(mode) | |
160 | .define("LLVM_CONFIG_PATH", build_llvm_config) | |
161 | .define("COMPILER_RT_DEFAULT_TARGET_TRIPLE", target) | |
162 | .define("COMPILER_RT_BUILD_SANITIZERS", "OFF") | |
163 | .define("COMPILER_RT_BUILD_EMUTLS", "OFF") | |
164 | // inform about c/c++ compilers, the c++ compiler isn't actually used but | |
165 | // it's needed to get the initial configure to work on all platforms. | |
166 | .define("CMAKE_C_COMPILER", build.cc(target)) | |
167 | .define("CMAKE_CXX_COMPILER", build.cc(target)) | |
168 | .build_target(&build_target); | |
169 | cfg.build(); | |
170 | } |