]>
git.proxmox.com Git - rustc.git/blob - src/bootstrap/bootstrap.py
1 # Copyright 2015-2016 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.
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.
19 def get(url
, path
, verbose
=False):
20 print("downloading " + url
)
21 # see http://serverfault.com/questions/301128/how-to-download
22 if sys
.platform
== 'win32':
23 run(["PowerShell.exe", "/nologo", "-Command",
24 "(New-Object System.Net.WebClient).DownloadFile('" + url
+
25 "', '" + path
+ "')"], verbose
=verbose
)
27 run(["curl", "-o", path
, url
], verbose
=verbose
)
29 def unpack(tarball
, dst
, verbose
=False, match
=None):
30 print("extracting " + tarball
)
31 fname
= os
.path
.basename(tarball
).replace(".tar.gz", "")
32 with contextlib
.closing(tarfile
.open(tarball
)) as tar
:
33 for p
in tar
.getnames():
36 name
= p
.replace(fname
+ "/", "", 1)
37 if match
is not None and not name
.startswith(match
):
39 name
= name
[len(match
) + 1:]
41 fp
= os
.path
.join(dst
, name
)
43 print(" extracting " + p
)
45 tp
= os
.path
.join(dst
, p
)
46 if os
.path
.isdir(tp
) and os
.path
.exists(fp
):
49 shutil
.rmtree(os
.path
.join(dst
, fname
))
51 def run(args
, verbose
=False):
53 print("running: " + ' '.join(args
))
55 # Use Popen here instead of call() as it apparently allows powershell on
56 # Windows to not lock up waiting for input presumably.
57 ret
= subprocess
.Popen(args
)
61 print("failed to run: " + ' '.join(args
))
62 raise RuntimeError("failed to run command")
65 def download_rust_nightly(self
):
66 cache_dst
= os
.path
.join(self
.build_dir
, "cache")
67 rustc_cache
= os
.path
.join(cache_dst
, self
.snap_rustc_date())
68 cargo_cache
= os
.path
.join(cache_dst
, self
.snap_cargo_date())
69 if not os
.path
.exists(rustc_cache
):
70 os
.makedirs(rustc_cache
)
71 if not os
.path
.exists(cargo_cache
):
72 os
.makedirs(cargo_cache
)
74 if self
.rustc().startswith(self
.bin_root()) and \
75 (not os
.path
.exists(self
.rustc()) or self
.rustc_out_of_date()):
76 if os
.path
.exists(self
.bin_root()):
77 shutil
.rmtree(self
.bin_root())
78 filename
= "rust-std-nightly-" + self
.build
+ ".tar.gz"
79 url
= "https://static.rust-lang.org/dist/" + self
.snap_rustc_date()
80 tarball
= os
.path
.join(rustc_cache
, filename
)
81 if not os
.path
.exists(tarball
):
82 get(url
+ "/" + filename
, tarball
, verbose
=self
.verbose
)
83 unpack(tarball
, self
.bin_root(),
84 match
="rust-std-" + self
.build
,
87 filename
= "rustc-nightly-" + self
.build
+ ".tar.gz"
88 url
= "https://static.rust-lang.org/dist/" + self
.snap_rustc_date()
89 tarball
= os
.path
.join(rustc_cache
, filename
)
90 if not os
.path
.exists(tarball
):
91 get(url
+ "/" + filename
, tarball
, verbose
=self
.verbose
)
92 unpack(tarball
, self
.bin_root(), match
="rustc", verbose
=self
.verbose
)
93 with
open(self
.rustc_stamp(), 'w') as f
:
94 f
.write(self
.snap_rustc_date())
96 if self
.cargo().startswith(self
.bin_root()) and \
97 (not os
.path
.exists(self
.cargo()) or self
.cargo_out_of_date()):
98 filename
= "cargo-nightly-" + self
.build
+ ".tar.gz"
99 url
= "https://static.rust-lang.org/cargo-dist/" + self
.snap_cargo_date()
100 tarball
= os
.path
.join(cargo_cache
, filename
)
101 if not os
.path
.exists(tarball
):
102 get(url
+ "/" + filename
, tarball
, verbose
=self
.verbose
)
103 unpack(tarball
, self
.bin_root(), match
="cargo", verbose
=self
.verbose
)
104 with
open(self
.cargo_stamp(), 'w') as f
:
105 f
.write(self
.snap_cargo_date())
107 def snap_cargo_date(self
):
108 return self
._cargo
_date
110 def snap_rustc_date(self
):
111 return self
._rustc
_date
113 def rustc_stamp(self
):
114 return os
.path
.join(self
.bin_root(), '.rustc-stamp')
116 def cargo_stamp(self
):
117 return os
.path
.join(self
.bin_root(), '.cargo-stamp')
119 def rustc_out_of_date(self
):
120 if not os
.path
.exists(self
.rustc_stamp()):
122 with
open(self
.rustc_stamp(), 'r') as f
:
123 return self
.snap_rustc_date() != f
.read()
125 def cargo_out_of_date(self
):
126 if not os
.path
.exists(self
.cargo_stamp()):
128 with
open(self
.cargo_stamp(), 'r') as f
:
129 return self
.snap_cargo_date() != f
.read()
132 return os
.path
.join(self
.build_dir
, self
.build
, "stage0")
134 def get_toml(self
, key
):
135 for line
in self
.config_toml
.splitlines():
136 if line
.startswith(key
+ ' ='):
137 return self
.get_string(line
)
140 def get_mk(self
, key
):
141 for line
in iter(self
.config_mk
.splitlines()):
142 if line
.startswith(key
):
143 return line
[line
.find(':=') + 2:].strip()
147 config
= self
.get_toml('cargo')
150 return os
.path
.join(self
.bin_root(), "bin/cargo" + self
.exe_suffix())
153 config
= self
.get_toml('rustc')
156 config
= self
.get_mk('CFG_LOCAL_RUST')
158 return config
+ '/bin/rustc' + self
.exe_suffix()
159 return os
.path
.join(self
.bin_root(), "bin/rustc" + self
.exe_suffix())
161 def get_string(self
, line
):
162 start
= line
.find('"')
163 end
= start
+ 1 + line
[start
+1:].find('"')
164 return line
[start
+1:end
]
166 def exe_suffix(self
):
167 if sys
.platform
== 'win32':
172 def parse_nightly_dates(self
):
173 nightlies
= os
.path
.join(self
.rust_root
, "src/nightlies.txt")
174 with
open(nightlies
, 'r') as nightlies
:
175 rustc
, cargo
= nightlies
.read().split("\n")[:2]
176 assert rustc
.startswith("rustc: ")
177 assert cargo
.startswith("cargo: ")
178 self
._rustc
_date
= rustc
[len("rustc: "):]
179 self
._cargo
_date
= cargo
[len("cargo: "):]
181 def build_bootstrap(self
):
182 env
= os
.environ
.copy()
183 env
["CARGO_TARGET_DIR"] = os
.path
.join(self
.build_dir
, "bootstrap")
184 env
["RUSTC"] = self
.rustc()
185 env
["LD_LIBRARY_PATH"] = os
.path
.join(self
.bin_root(), "lib")
186 env
["DYLD_LIBRARY_PATH"] = os
.path
.join(self
.bin_root(), "lib")
187 env
["PATH"] = os
.path
.join(self
.bin_root(), "bin") + \
188 os
.pathsep
+ env
["PATH"]
189 self
.run([self
.cargo(), "build", "--manifest-path",
190 os
.path
.join(self
.rust_root
, "src/bootstrap/Cargo.toml")],
193 def run(self
, args
, env
):
194 proc
= subprocess
.Popen(args
, env
= env
)
199 def build_triple(self
):
200 config
= self
.get_toml('build')
203 config
= self
.get_mk('CFG_BUILD')
207 ostype
= subprocess
.check_output(['uname', '-s']).strip()
208 cputype
= subprocess
.check_output(['uname', '-m']).strip()
209 except FileNotFoundError
:
210 if sys
.platform
== 'win32':
211 return 'x86_64-pc-windows-msvc'
215 # Darwin's `uname -s` lies and always returns i386. We have to use
217 if ostype
== 'Darwin' and cputype
== 'i686':
218 sysctl
= subprocess
.check_output(['sysctl', 'hw.optional.x86_64'])
219 if sysctl
.contains(': 1'):
222 # The goal here is to come up with the same triple as LLVM would,
223 # at least for the subset of platforms we're willing to target.
224 if ostype
== 'Linux':
225 ostype
= 'unknown-linux-gnu'
226 elif ostype
== 'FreeBSD':
227 ostype
= 'unknown-freebsd'
228 elif ostype
== 'DragonFly':
229 ostype
= 'unknown-dragonfly'
230 elif ostype
== 'Bitrig':
231 ostype
= 'unknown-bitrig'
232 elif ostype
== 'OpenBSD':
233 ostype
= 'unknown-openbsd'
234 elif ostype
== 'NetBSD':
235 ostype
= 'unknown-netbsd'
236 elif ostype
== 'Darwin':
237 ostype
= 'apple-darwin'
238 elif ostype
.startswith('MINGW'):
239 # msys' `uname` does not print gcc configuration, but prints msys
240 # configuration. so we cannot believe `uname -m`:
241 # msys1 is always i686 and msys2 is always x86_64.
242 # instead, msys defines $MSYSTEM which is MINGW32 on i686 and
244 ostype
= 'pc-windows-gnu'
246 if os
.environ
.get('MSYSTEM') == 'MINGW64':
248 elif ostype
.startswith('MSYS'):
249 ostype
= 'pc-windows-gnu'
250 elif ostype
.startswith('CYGWIN_NT'):
252 if ostype
.endswith('WOW64'):
254 ostype
= 'pc-windows-gnu'
256 raise ValueError("unknown OS type: " + ostype
)
258 if cputype
in {'i386', 'i486', 'i686', 'i786', 'x86'}:
260 elif cputype
in {'xscale', 'arm'}:
262 elif cputype
== 'armv7l':
265 elif cputype
== 'aarch64':
267 elif cputype
in {'powerpc', 'ppc', 'ppc64'}:
269 elif cputype
in {'amd64', 'x86_64', 'x86-64', 'x64'}:
272 raise ValueError("unknown cpu type: " + cputype
)
274 return cputype
+ '-' + ostype
276 parser
= argparse
.ArgumentParser(description
='Build rust')
277 parser
.add_argument('--config')
278 parser
.add_argument('-v', '--verbose', action
='store_true')
280 args
= [a
for a
in sys
.argv
if a
!= '-h']
281 args
, _
= parser
.parse_known_args(args
)
283 # Configure initial bootstrap
287 rb
.rust_root
= os
.path
.abspath(os
.path
.join(__file__
, '../../..'))
288 rb
.build_dir
= os
.path
.join(os
.getcwd(), "build")
289 rb
.verbose
= args
.verbose
292 with
open(args
.config
or 'config.toml') as config
:
293 rb
.config_toml
= config
.read()
297 rb
.config_mk
= open('config.mk').read()
301 # Fetch/build the bootstrap
302 rb
.build
= rb
.build_triple()
303 rb
.parse_nightly_dates()
304 rb
.download_rust_nightly()
310 args
= [os
.path
.join(rb
.build_dir
, "bootstrap/debug/bootstrap")]
311 args
.extend(sys
.argv
[1:])
313 args
.append(rb
.rust_root
)
314 args
.append('--build')
315 args
.append(rb
.build
)
316 env
= os
.environ
.copy()
317 env
["BOOTSTRAP_PARENT_ID"] = str(os
.getpid())