1 # Copyright 2011-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.
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.
18 import distutils.spawn
22 sha_func = hashlib.sha1
29 if sys.version_info >= (3,) and type(b) == bytes:
30 return b.decode('ascii')
34 src_dir = scrub(os.getenv("CFG_SRC_DIR"))
36 raise Exception("missing env var CFG_SRC_DIR")
38 snapshotfile = os.path.join(src_dir, "src", "snapshots.txt")
39 download_url_base = "https://static.rust-lang.org/stage0-snapshots"
40 download_dir_base = "dl"
41 download_unpack_base = os.path.join(download_dir_base, "unpack")
44 "bitrig": ["bin/rustc"],
45 "dragonfly": ["bin/rustc"],
46 "freebsd": ["bin/rustc"],
47 "linux": ["bin/rustc"],
48 "macos": ["bin/rustc"],
49 "netbsd": ["bin/rustc"],
50 "openbsd": ["bin/rustc"],
51 "winnt": ["bin/rustc.exe"],
54 winnt_runtime_deps_32 = ["libgcc_s_dw2-1.dll", "libstdc++-6.dll"]
55 winnt_runtime_deps_64 = ["libgcc_s_seh-1.dll", "libstdc++-6.dll"]
57 def parse_line(n, line):
60 if re.match(r"\s*$", line):
63 if re.match(r"^T\s*$", line):
66 match = re.match(r"\s+([\w_-]+) ([a-fA-F\d]{40})\s*$", line)
68 return {"type": "file",
69 "platform": match.group(1),
70 "hash": match.group(2).lower()}
72 match = re.match(r"([ST]) (\d{4}-\d{2}-\d{2}) ([a-fA-F\d]+)\s*$", line)
74 raise Exception("%s:%d:E syntax error: " % (snapshotfile, n))
75 return {"type": "snapshot",
76 "date": match.group(2),
77 "rev": match.group(3)}
80 def partial_snapshot_name(date, rev, platform):
81 return ("rust-stage0-%s-%s-%s.tar.bz2" %
82 (date, rev, platform))
85 def full_snapshot_name(date, rev, platform, hsh):
86 return ("rust-stage0-%s-%s-%s-%s.tar.bz2" %
87 (date, rev, platform, hsh))
90 def get_kernel(triple):
97 if os_name == "windows":
99 if os_name == "darwin":
101 if os_name == "freebsd":
103 if os_name == "dragonfly":
105 if os_name == "bitrig":
107 if os_name == "netbsd":
109 if os_name == "openbsd":
115 arch = triple.split('-')[0]
121 def get_platform(triple):
122 return "%s-%s" % (get_kernel(triple), get_cpu(triple))
125 def cmd_out(cmdline):
126 p = subprocess.Popen(cmdline, stdout=subprocess.PIPE)
127 return scrub(p.communicate()[0].strip())
130 def local_rev_info(field):
131 return cmd_out(["git", "--git-dir=" + os.path.join(src_dir, ".git"),
133 "--format=%%%s" % field, "HEAD"])
136 def local_rev_full_sha():
137 return local_rev_info("H").split()[0]
140 def local_rev_short_sha():
141 return local_rev_info("h").split()[0]
144 def local_rev_committer_date():
145 return local_rev_info("ci")
148 def get_url_to_file(u, f):
149 # no security issue, just to stop partial download leaving a stale file
153 if distutils.spawn.find_executable("curl"):
154 returncode = subprocess.call(["curl", "-o", tmpf, u])
155 elif distutils.spawn.find_executable("wget"):
156 returncode = subprocess.call(["wget", "-O", tmpf, u])
163 raise Exception("failed to fetch url")
167 def snap_filename_hash_part(snap):
168 match = re.match(r".*([a-fA-F\d]{40}).tar.bz2$", snap)
170 raise Exception("unable to find hash in filename: " + snap)
171 return match.group(1)
176 h.update(open(x, "rb").read())
177 return scrub(h.hexdigest())
180 def get_winnt_runtime_deps(platform):
181 """Returns a list of paths of Rust's system runtime dependencies"""
182 if platform == "winnt-x86_64":
183 deps = winnt_runtime_deps_64
185 deps = winnt_runtime_deps_32
187 path_dirs = os.environ["PATH"].split(os.pathsep)
189 for dir in path_dirs:
190 filepath = os.path.join(dir, name)
191 if os.path.isfile(filepath):
192 runtime_deps.append(filepath)
195 raise Exception("Could not find runtime dependency: %s" % name)
199 def make_snapshot(stage, triple):
200 kernel = get_kernel(triple)
201 platform = get_platform(triple)
202 rev = local_rev_short_sha()
203 date = local_rev_committer_date().split()[0]
205 file0 = partial_snapshot_name(date, rev, platform)
208 cs = re.split(r"[\\/]", fn)
210 return os.sep.join(cs[-2:])
212 tar = tarfile.open(file0, "w:bz2")
214 for name in snapshot_files[kernel]:
216 if stage == "stage1" and re.match(r"^lib/(lib)?std.*", name):
218 fn_glob = os.path.join(triple, dir, name)
219 matches = glob.glob(fn_glob)
221 raise Exception("Not found file with name like " + fn_glob)
222 if len(matches) == 1:
223 tar.add(matches[0], "rust-stage0/" + in_tar_name(matches[0]))
225 raise Exception("Found stale files: \n %s\n"
226 "Please make a clean build." % "\n ".join(matches))
228 if kernel == "winnt":
229 for path in get_winnt_runtime_deps(platform):
230 tar.add(path, "rust-stage0/bin/" + os.path.basename(path))
231 tar.add(os.path.join(os.path.dirname(__file__), "third-party"),
232 "rust-stage0/bin/third-party")
237 file1 = full_snapshot_name(date, rev, platform, h)
239 shutil.move(file0, file1)
244 def curr_snapshot_rev():
250 f = open(snapshotfile)
251 for line in f.readlines():
253 parsed = parse_line(i, line)
257 if parsed["type"] == "snapshot":
258 date = parsed["date"]
264 raise Exception("no snapshot entries in file")
269 def determine_curr_snapshot(triple):
271 platform = get_platform(triple)
279 f = open(snapshotfile)
280 for line in f.readlines():
282 parsed = parse_line(i, line)
286 if found_snap and parsed["type"] == "file":
287 if parsed["platform"] == platform:
291 elif parsed["type"] == "snapshot":
292 date = parsed["date"]
297 raise Exception("no snapshot entries in file")
300 raise Exception("no snapshot file found for platform %s, rev %s" %
303 return full_snapshot_name(date, rev, platform, hsh)