33
33
'''
34
34
35
35
import argparse
36
+ import base64
36
37
import collections
37
38
import hashlib
39
+ import json
38
40
import platform
39
41
import os
40
42
import pipes
41
43
import shutil
42
44
import string
43
45
import subprocess
44
46
import sys
47
+ import urllib
45
48
46
49
from pathlib import Path
47
50
51
54
'scripts' ))
52
55
53
56
from build import (AddCMakeToPath , AddOpenSSLToEnv , AddZlibToPath ,
54
- GetLibXml2Dirs , RunCommand )
55
- from update import (CLANG_REVISION , CLANG_SUB_REVISION , LLVM_BUILD_DIR ,
56
- GetDefaultHostOs , RmTree , UpdatePackage )
57
+ CheckoutGitRepo , GetLibXml2Dirs , LLVM_BUILD_TOOLS_DIR ,
58
+ RunCommand )
59
+ from update import (CLANG_REVISION , CLANG_SUB_REVISION , DownloadAndUnpack ,
60
+ LLVM_BUILD_DIR , GetDefaultHostOs , RmTree , UpdatePackage )
57
61
import build
58
62
59
63
from update_rust import (CHROMIUM_DIR , RUST_REVISION , RUST_SUB_REVISION ,
60
64
RUST_TOOLCHAIN_OUT_DIR , STAGE0_JSON_SHA256 ,
61
65
THIRD_PARTY_DIR , VERSION_STAMP_PATH ,
62
66
GetPackageVersionForBuild )
63
67
64
- RUST_GIT_URL = 'https://github.com/rust-lang/rust/'
68
+ RUST_GIT_URL = ('https://chromium.googlesource.com/external/' +
69
+ 'github.com/rust-lang/rust' )
65
70
66
71
RUST_SRC_DIR = os .path .join (THIRD_PARTY_DIR , 'rust_src' , 'src' )
67
72
STAGE0_JSON_PATH = os .path .join (RUST_SRC_DIR , 'src' , 'stage0.json' )
68
73
# Download crates.io dependencies to rust-src subdir (rather than $HOME/.cargo)
69
74
CARGO_HOME_DIR = os .path .join (RUST_SRC_DIR , 'cargo-home' )
70
- RUST_SRC_VERSION_FILE_PATH = os .path .join (RUST_SRC_DIR , 'version' )
75
+ RUST_SRC_VERSION_FILE_PATH = os .path .join (RUST_SRC_DIR , 'src' , ' version' )
71
76
RUST_SRC_GIT_COMMIT_INFO_FILE_PATH = os .path .join (RUST_SRC_DIR ,
72
77
'git-commit-info' )
73
78
RUST_TOOLCHAIN_LIB_DIR = os .path .join (RUST_TOOLCHAIN_OUT_DIR , 'lib' )
77
82
'vendor' )
78
83
RUST_CONFIG_TEMPLATE_PATH = os .path .join (
79
84
os .path .dirname (os .path .abspath (__file__ )), 'config.toml.template' )
85
+ RUST_CARGO_CONFIG_TEMPLATE_PATH = os .path .join (
86
+ os .path .dirname (os .path .abspath (__file__ )), 'cargo-config.toml.template' )
80
87
RUST_SRC_VENDOR_DIR = os .path .join (RUST_SRC_DIR , 'vendor' )
81
88
82
89
if sys .platform == 'win32' :
93
100
# Which test suites to run. Any failure will fail the build.
94
101
TEST_SUITES = [
95
102
'library/std' ,
96
- 'src/test /codegen' ,
97
- 'src/test /ui' ,
103
+ 'tests /codegen' ,
104
+ 'tests /ui' ,
98
105
]
99
106
100
107
EXCLUDED_TESTS = [
@@ -142,6 +149,82 @@ def quote_string(s: str):
142
149
output .write (template .substitute (subs ))
143
150
144
151
152
+ def FetchCargo (rust_git_hash ):
153
+ '''Downloads the beta Cargo package specified for the compiler build
154
+
155
+ Unpacks the package and returns the path to the binary itself.
156
+ '''
157
+ if sys .platform == 'win32' :
158
+ target = 'cargo-beta-x86_64-pc-windows-msvc'
159
+ elif sys .platform == 'darwin' :
160
+ if platform .machine () == 'arm64' :
161
+ target = 'rust-std-beta-aarch64-apple-darwin'
162
+ else :
163
+ target = 'cargo-beta-x86_64-apple-darwin'
164
+ else :
165
+ target = 'cargo-beta-x86_64-unknown-linux-gnu'
166
+
167
+ # Pull the stage0 JSON to find the Cargo binary intended to be used to
168
+ # build this version of the Rust compiler.
169
+ STAGE0_JSON_URL = (
170
+ 'https://chromium.googlesource.com/external/github.com/'
171
+ 'rust-lang/rust/+/{GIT_HASH}/src/stage0.json?format=TEXT' )
172
+ base64_text = urllib .request .urlopen (
173
+ STAGE0_JSON_URL .format (GIT_HASH = rust_git_hash )).read ().decode ("utf-8" )
174
+ stage0 = json .loads (base64 .b64decode (base64_text ))
175
+
176
+ # The stage0 JSON contains the path to all tarballs it uses binaries from,
177
+ # including cargo.
178
+ for k in stage0 ['checksums_sha256' ].keys ():
179
+ if k .endswith (target + '.tar.gz' ):
180
+ cargo_tgz = k
181
+
182
+ server = stage0 ['config' ]['dist_server' ]
183
+ DownloadAndUnpack (f'{ server } /{ cargo_tgz } ' , LLVM_BUILD_TOOLS_DIR )
184
+
185
+ bin_path = os .path .join (LLVM_BUILD_TOOLS_DIR , target , 'cargo' , 'bin' )
186
+ if sys .platform == 'win32' :
187
+ return os .path .join (bin_path , 'cargo.exe' )
188
+ else :
189
+ return os .path .join (bin_path , 'cargo' )
190
+
191
+
192
+ def CargoVendor (cargo_bin ):
193
+ '''Runs `cargo vendor` to pull down dependencies.'''
194
+ os .chdir (RUST_SRC_DIR )
195
+
196
+ # Some Submodules are part of the workspace and need to exist (so we can
197
+ # read their Cargo.toml files) before we can vendor their deps.
198
+ RunCommand ([
199
+ 'git' , 'submodule' , 'update' , '--init' , '--recursive' , '--depth' , '1'
200
+ ])
201
+
202
+ # From https://github.com/rust-lang/rust/blob/master/src/bootstrap/dist.rs#L986-L995
203
+ # The additional `--sync` Cargo.toml files are not part of the top level
204
+ # workspace.
205
+ RunCommand ([
206
+ cargo_bin ,
207
+ 'vendor' ,
208
+ '--locked' ,
209
+ '--versioned-dirs' ,
210
+ '--sync' ,
211
+ 'src/tools/rust-analyzer/Cargo.toml' ,
212
+ '--sync' ,
213
+ 'compiler/rustc_codegen_cranelift/Cargo.toml' ,
214
+ '--sync' ,
215
+ 'src/bootstrap/Cargo.toml' ,
216
+ ])
217
+
218
+ # Make a `.cargo/config.toml` the points to the `vendor` directory for all
219
+ # dependency crates.
220
+ try :
221
+ os .mkdir (os .path .join (RUST_SRC_DIR , '.cargo' ))
222
+ except FileExistsError :
223
+ pass
224
+ shutil .copyfile (RUST_CARGO_CONFIG_TEMPLATE_PATH ,
225
+ os .path .join (RUST_SRC_DIR , '.cargo' , 'config.toml' ))
226
+
227
+
145
228
def RunXPy (sub , args , llvm_bins_path , zlib_path , libxml2_dirs , build_mac_arm ,
146
229
gcc_toolchain_path , verbose ):
147
230
''' Run x.py, Rust's build script'''
@@ -152,6 +235,7 @@ def RunXPy(sub, args, llvm_bins_path, zlib_path, libxml2_dirs, build_mac_arm,
152
235
'LDFLAGS' ,
153
236
'RUSTFLAGS_BOOTSTRAP' ,
154
237
'RUSTFLAGS_NOT_BOOTSTRAP' ,
238
+ 'RUSTDOCFLAGS' ,
155
239
]
156
240
157
241
RUSTENV = collections .defaultdict (str , os .environ )
@@ -220,6 +304,10 @@ def RunXPy(sub, args, llvm_bins_path, zlib_path, libxml2_dirs, build_mac_arm,
220
304
RUSTENV ['RUSTFLAGS_NOT_BOOTSTRAP' ] += (
221
305
f' -L native={ gcc_toolchain_path } /lib64' )
222
306
307
+ # Rustdoc should use our clang linker as well, as we pass flags that
308
+ # the system linker may not understand.
309
+ RUSTENV ['RUSTDOCFLAGS' ] += f' -Clinker={ RUSTENV ["CC" ]} '
310
+
223
311
# Cargo normally stores files in $HOME. Override this.
224
312
RUSTENV ['CARGO_HOME' ] = CARGO_HOME_DIR
225
313
@@ -243,16 +331,27 @@ def GetTestArgs():
243
331
return args
244
332
245
333
246
- def GetVersionStamp ():
247
- # We must generate a version stamp that contains the expected `rustc
248
- # --version` output. This contains the Rust release version, git commit data
249
- # that the nightly tarball was generated from, and chromium-specific package
250
- # information.
334
+ def MakeVersionStamp (git_hash ):
335
+ # We must generate a version stamp that contains the full version of the
336
+ # built Rust compiler:
337
+ # * The version number returned from `rustc --version`.
338
+ # * The git hash.
339
+ # * The chromium revision name of the compiler build, which includes the
340
+ # associated clang/llvm version.
251
341
with open (RUST_SRC_VERSION_FILE_PATH ) as version_file :
252
342
rust_version = version_file .readline ().rstrip ()
343
+ return (f'rustc { rust_version } { git_hash } '
344
+ f' ({ GetPackageVersionForBuild ()} chromium)\n ' )
345
+
253
346
254
- return ('rustc %s (%s chromium)\n ' %
255
- (rust_version , GetPackageVersionForBuild ()))
347
+ def GetLatestRustCommit ():
348
+ """Get the latest commit hash in the LLVM monorepo."""
349
+ main = json .loads (
350
+ urllib .request .urlopen ('https://chromium.googlesource.com/external/' +
351
+ 'github.com/rust-lang/rust/' +
352
+ '+/refs/heads/main?format=JSON' ).read ().decode (
353
+ "utf-8" ).replace (")]}'" , "" ))
354
+ return main ['commit' ]
256
355
257
356
258
357
def main ():
@@ -271,6 +370,9 @@ def main():
271
370
help =
272
371
'checkout Rust, verify the stage0 hash, then quit without building. '
273
372
'Will print the actual hash if different than expected.' )
373
+ parser .add_argument ('--skip-checkout' ,
374
+ action = 'store_true' ,
375
+ help = 'do not create or update any checkouts' )
274
376
parser .add_argument ('--skip-clean' ,
275
377
action = 'store_true' ,
276
378
help = 'skip x.py clean step' )
@@ -280,6 +382,9 @@ def main():
280
382
parser .add_argument ('--skip-install' ,
281
383
action = 'store_true' ,
282
384
help = 'do not install to RUST_TOOLCHAIN_OUT_DIR' )
385
+ parser .add_argument ('--rust-force-head-revision' ,
386
+ action = 'store_true' ,
387
+ help = 'build the latest revision' )
283
388
parser .add_argument (
284
389
'--fetch-llvm-libs' ,
285
390
action = 'store_true' ,
@@ -324,6 +429,14 @@ def main():
324
429
else :
325
430
llvm_bins_path = os .path .join (build .LLVM_BOOTSTRAP_DIR , 'bin' )
326
431
432
+ if args .rust_force_head_revision :
433
+ checkout_revision = GetLatestRustCommit ()
434
+ else :
435
+ checkout_revision = RUST_REVISION
436
+
437
+ if not args .skip_checkout :
438
+ CheckoutGitRepo ('Rust' , RUST_GIT_URL , checkout_revision , RUST_SRC_DIR )
439
+
327
440
VerifyStage0JsonHash ()
328
441
if args .verify_stage0_hash :
329
442
# The above function exits and prints the actual hash if verification
@@ -344,6 +457,9 @@ def main():
344
457
# Set up config.toml in Rust source tree to configure build.
345
458
Configure (llvm_bins_path , llvm_libs_root )
346
459
460
+ cargo_bin = FetchCargo (checkout_revision )
461
+ CargoVendor (cargo_bin )
462
+
347
463
AddCMakeToPath ()
348
464
349
465
# Require zlib compression.
@@ -404,19 +520,18 @@ def main():
404
520
shutil .rmtree (RUST_TOOLCHAIN_OUT_DIR )
405
521
406
522
RunXPy ('install' , DISTRIBUTION_ARTIFACTS , llvm_bins_path , zlib_path ,
407
- libxml2_dirs , args .gcc_toolchain , args .verbose )
523
+ libxml2_dirs , args .build_mac_arm , args .gcc_toolchain , args .verbose )
524
+
525
+ # Copy additional sources required for building stdlib out of
526
+ # RUST_TOOLCHAIN_SRC_DIST_DIR.
527
+ print (f'Copying vendored dependencies to { RUST_TOOLCHAIN_OUT_DIR } ...' )
528
+ shutil .copytree (RUST_SRC_VENDOR_DIR , RUST_TOOLCHAIN_SRC_DIST_VENDOR_DIR )
408
529
409
530
with open (VERSION_STAMP_PATH , 'w' ) as stamp :
410
- stamp .write (GetVersionStamp ( ))
531
+ stamp .write (MakeVersionStamp ( checkout_revision ))
411
532
412
533
return 0
413
534
414
- # TODO(crbug.com/1342708): fix vendoring and re-enable.
415
- # x.py installed library sources to our toolchain directory. We also need to
416
- # copy the vendor directory so Chromium checkouts have all the deps needed
417
- # to build std.
418
- # shutil.copytree(RUST_SRC_VENDOR_DIR, RUST_TOOLCHAIN_SRC_DIST_VENDOR_DIR)
419
-
420
535
421
536
if __name__ == '__main__' :
422
537
sys .exit (main ())
0 commit comments