0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-12-24 08:09:16 -05:00

Support binary downloads (#316)

Co-authored-by: Bert Belder <bertbelder@gmail.com>
This commit is contained in:
Ryan Dahl 2020-03-17 17:59:37 -04:00 committed by GitHub
parent 97088f4eb1
commit 51d4e6b740
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 150 additions and 3 deletions

View file

@ -47,6 +47,11 @@ exclude = [
"!v8/tools/testrunner/utils/dump_build_config.py",
]
[features]
# Enable this feature to download and prebuilt V8 binaries from
# https://github.com/denoland/rusty_v8/releases
binary = []
[dependencies]
lazy_static = "1.4.0"
libc = "0.2.67"

View file

@ -29,7 +29,7 @@ V8 Version: 8.2.308, 2020-03-12
Due to the complexity and size of V8's build, this is nontrivial. For example
the crate size must be kept under 10 MiB in order to publish.
## Build
## Build V8 from Source
Use `cargo build -vv` to build the crate.
@ -56,6 +56,20 @@ environmental variable.
Env vars used in build.rs: `SCCACHE`, `GN`, `NINJA`, `CLANG_BASE_PATH`, `GN_ARGS`
## Binary Build
V8 is very large and take a long time to compile. Many users may prefer to use
a prebuilt version of V8. We publish static libs for every version of rusty v8
on [Github](https://github.com/denoland/rusty_v8/releases).
To use these prebuilt binaries use the `binary` feature:
```
cargo build --features="binary"
```
This will cause rusty v8 to download the binaries during the build process.
## FAQ
**Building V8 takes over 30 minutes, this is too slow for me to use this crate.

View file

@ -23,9 +23,12 @@ fn main() {
.map(|s| s.starts_with("rls"))
.unwrap_or(false);
if !(is_trybuild || is_cargo_doc | is_rls) {
if cfg!(feature = "binary") {
download_static_lib_binaries();
} else if !(is_trybuild || is_cargo_doc | is_rls) {
build_v8()
}
if !(is_cargo_doc || is_rls) {
print_link_flags()
}
@ -166,6 +169,70 @@ fn download_ninja_gn_binaries() {
env::set_var("NINJA", ninja);
}
fn static_lib_url() -> (String, String) {
let base = "https://github.com/denoland/rusty_v8/releases/download";
let version = env::var("CARGO_PKG_VERSION").unwrap();
let target = env::var("TARGET").unwrap();
if cfg!(target_os = "windows") {
// Note: we always use the release build on windows.
let url = format!("{}/v{}/rusty_v8_release_{}.lib", base, version, target);
let static_lib_name = "rusty_v8.lib".to_string();
(url, static_lib_name)
} else {
let profile = env::var("PROFILE").unwrap();
assert!(profile == "release" || profile == "debug");
let url =
format!("{}/v{}/librusty_v8_{}_{}.a", base, version, profile, target);
let static_lib_name = "librusty_v8.a".to_string();
(url, static_lib_name)
}
}
fn download_static_lib_binaries() {
let (url, static_lib_name) = static_lib_url();
println!("static lib URL: {}", url);
let root = env::current_dir().unwrap();
// target/debug//build/rusty_v8-d9e5a424d4f96994/out/
let out_dir = env::var_os("OUT_DIR").unwrap();
let out_dir_abs = root.join(out_dir);
// This would be target/debug or target/release
let target_dir = out_dir_abs
.parent()
.unwrap()
.parent()
.unwrap()
.parent()
.unwrap();
let obj_dir = target_dir.join("gn_out").join("obj");
std::fs::create_dir_all(&obj_dir).unwrap();
println!("cargo:rustc-link-search={}", obj_dir.display());
let filename = obj_dir.join(static_lib_name);
if filename.exists() {
println!("static lib already exists {}", filename.display());
println!("To re-download this file, it must be manually deleted.");
} else {
// Using python to do the HTTP download because it's already a dependency
// and so we don't have to add a Rust HTTP client dependency.
println!("Downloading {}", url);
let status = Command::new("python")
.arg("./tools/download_file.py")
.arg("--url")
.arg(url)
.arg("--filename")
.arg(&filename)
.status()
.unwrap();
assert!(status.success());
assert!(filename.exists());
}
}
fn print_link_flags() {
println!("cargo:rustc-link-lib=static=rusty_v8");

62
tools/download_file.py Executable file
View file

@ -0,0 +1,62 @@
#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from __future__ import print_function
import argparse
import os
import sys
try:
from urllib2 import HTTPError, URLError, urlopen
except ImportError: # For Py3 compatibility
from urllib.error import HTTPError, URLError
from urllib.request import urlopen
def DownloadUrl(url, output_file):
"""Download url into output_file."""
CHUNK_SIZE = 4096
num_retries = 3
retry_wait_s = 5 # Doubled at each retry.
while True:
try:
sys.stdout.write('Downloading %s...' % url)
sys.stdout.flush()
response = urlopen(url)
bytes_done = 0
while True:
chunk = response.read(CHUNK_SIZE)
if not chunk:
break
output_file.write(chunk)
bytes_done += len(chunk)
if bytes_done == 0:
raise URLError("empty response")
print(' Done.')
return
except URLError as e:
sys.stdout.write('\n')
print(e)
if num_retries == 0 or isinstance(e, HTTPError) and e.code == 404:
raise e
num_retries -= 1
print('Retrying in %d s ...' % retry_wait_s)
sys.stdout.flush()
time.sleep(retry_wait_s)
retry_wait_s *= 2
def main():
parser = argparse.ArgumentParser(description='Download a file')
parser.add_argument('--filename', help='where to put the file')
parser.add_argument('--url', help='what url to download')
args = parser.parse_args()
with open(args.filename, "wb") as f:
DownloadUrl(args.url, f)
return 0
if __name__ == '__main__':
sys.exit(main())

View file

@ -25,7 +25,6 @@ DIR = None
def DownloadUrl(url, output_file):
"""Download url into output_file."""
CHUNK_SIZE = 4096
TOTAL_DOTS = 10
num_retries = 3
retry_wait_s = 5 # Doubled at each retry.