feat: vendor GYP and libuv dependencies directly into repository for offline builds

Remove dynamic dependency download during build by checking in libuv source and GYP build tooling. Update .gitignore to exclude intermediate build artifacts from the vendored deps directory, adjust Makefile to remove the now-unnecessary cleanall target and deps folder cleanup, and add the full libuv project tree including its own .gitignore, .mailmap, AUTHORS, CONTRIBUTING.md, ChangeLog, and LICENSE files.
This commit is contained in:
Bob Nystrom
2017-04-09 16:31:44 +00:00
parent 5916a401de
commit f25778d874
184 changed files with 83315 additions and 208 deletions
+93
View File
@@ -0,0 +1,93 @@
#!/usr/bin/env python
# Runs GYP to generate the right project then uses that to build libuv.
from __future__ import print_function
import os
import platform
import shutil
import sys
from util import ensure_dir, python2_binary, run
LIB_UV_VERSION = "v1.10.0"
LIB_UV_DIR = "deps/libuv"
def build_libuv_mac():
# Create the XCode project.
run([
python2_binary(), LIB_UV_DIR + "/gyp_uv.py", "-f", "xcode"
])
# Compile it.
# TODO: Support debug builds too.
run([
"xcodebuild",
# Build a 32-bit + 64-bit universal binary:
"ARCHS=i386 x86_64", "ONLY_ACTIVE_ARCH=NO",
"BUILD_DIR=out",
"-project", LIB_UV_DIR + "/uv.xcodeproj",
"-configuration", "Release",
"-target", "libuv"
])
def build_libuv_linux(arch):
# Set up the Makefile to build for the right architecture.
args = [python2_binary(), "gyp_uv.py", "-f", "make"]
if arch == "-32":
args.append("-Dtarget_arch=ia32")
elif arch == "-64":
args.append("-Dtarget_arch=x64")
run(args, cwd=LIB_UV_DIR)
run(["make", "-C", "out", "BUILDTYPE=Release"], cwd=LIB_UV_DIR)
def build_libuv_windows(arch):
args = ["cmd", "/c", "vcbuild.bat", "release"]
if arch == "-32":
args.append("x86")
elif arch == "-64":
args.append("x64")
run(args, cwd=LIB_UV_DIR)
def build_libuv(arch, out):
if platform.system() == "Darwin":
build_libuv_mac()
elif platform.system() == "Linux":
build_libuv_linux(arch)
elif platform.system() == "Windows":
build_libuv_windows(arch)
else:
print("Unsupported platform: " + platform.system())
sys.exit(1)
# Copy the build library to the build directory for Mac and Linux where we
# support building for multiple architectures.
if platform.system() != "Windows":
ensure_dir(os.path.dirname(out))
shutil.copyfile(
os.path.join(LIB_UV_DIR, "out", "Release", "libuv.a"), out)
def main(args):
expect_usage(len(args) >= 1 and len(args) <= 2)
arch = "" if len(args) < 2 else args[2]
out = os.path.join("build", "libuv" + arch + ".a")
build_libuv(arch, out)
def expect_usage(condition):
if (condition): return
print("Usage: build_libuv.py [-32|-64]")
sys.exit(1)
main(sys.argv)
-188
View File
@@ -1,188 +0,0 @@
#!/usr/bin/env python
# Downloads and compiles libuv.
from __future__ import print_function
import os
import os.path
import platform
import shutil
import subprocess
import sys
LIB_UV_VERSION = "v1.10.0"
LIB_UV_DIR = "deps/libuv"
def python2_binary():
"""Tries to find a python 2 executable."""
# Using [0] instead of .major here to support Python 2.6.
if sys.version_info[0] == 2:
return sys.executable or "python"
else:
return "python2"
def ensure_dir(dir):
"""Creates dir if not already there."""
if os.path.isdir(dir):
return
os.makedirs(dir)
def remove_dir(dir):
"""Recursively removes dir."""
if platform.system() == "Windows":
# rmtree gives up on readonly files on Windows
# rd doesn't like paths with forward slashes
subprocess.check_call(
['cmd', '/c', 'rd', '/s', '/q', dir.replace('/', '\\')])
else:
shutil.rmtree(dir)
def download_libuv():
"""Clones libuv into deps/libuv and checks out the right version."""
# Delete it if already there so we ensure we get the correct version if the
# version number in this script changes.
if os.path.isdir(LIB_UV_DIR):
print("Cleaning output directory...")
remove_dir(LIB_UV_DIR)
ensure_dir("deps")
print("Cloning libuv...")
run([
"git", "clone", "--quiet", "--depth=1",
"https://github.com/libuv/libuv.git",
LIB_UV_DIR
])
print("Getting tags...")
run([
"git", "fetch", "--quiet", "--depth=1", "--tags"
], cwd=LIB_UV_DIR)
print("Checking out libuv " + LIB_UV_VERSION + "...")
run([
"git", "checkout", "--quiet", LIB_UV_VERSION
], cwd=LIB_UV_DIR)
# TODO: Pin gyp to a known-good commit. Update a previously downloaded gyp
# if it doesn't match that commit.
print("Downloading gyp...")
run([
"git", "clone", "--quiet", "--depth=1",
"https://chromium.googlesource.com/external/gyp.git",
LIB_UV_DIR + "/build/gyp"
])
def build_libuv_mac():
# Create the XCode project.
run([
python2_binary(), LIB_UV_DIR + "/gyp_uv.py", "-f", "xcode"
])
# Compile it.
# TODO: Support debug builds too.
run([
"xcodebuild",
# Build a 32-bit + 64-bit universal binary:
"ARCHS=i386 x86_64", "ONLY_ACTIVE_ARCH=NO",
"BUILD_DIR=out",
"-project", LIB_UV_DIR + "/uv.xcodeproj",
"-configuration", "Release",
"-target", "All"
])
def build_libuv_linux(arch):
# Set up the Makefile to build for the right architecture.
args = [python2_binary(), "gyp_uv.py", "-f", "make"]
if arch == "-32":
args.append("-Dtarget_arch=ia32")
elif arch == "-64":
args.append("-Dtarget_arch=x64")
run(args, cwd=LIB_UV_DIR)
run(["make", "-C", "out", "BUILDTYPE=Release"], cwd=LIB_UV_DIR)
def build_libuv_windows(arch):
args = ["cmd", "/c", "vcbuild.bat", "release"]
if arch == "-32":
args.append("x86")
elif arch == "-64":
args.append("x64")
run(args, cwd=LIB_UV_DIR)
def build_libuv(arch, out):
if platform.system() == "Darwin":
build_libuv_mac()
elif platform.system() == "Linux":
build_libuv_linux(arch)
elif platform.system() == "Windows":
build_libuv_windows(arch)
else:
print("Unsupported platform: " + platform.system())
sys.exit(1)
# Copy the build library to the build directory for Mac and Linux where we
# support building for multiple architectures.
if platform.system() != "Windows":
ensure_dir(os.path.dirname(out))
shutil.copyfile(
os.path.join(LIB_UV_DIR, "out", "Release", "libuv.a"), out)
def run(args, cwd=None):
"""Spawn a process to invoke [args] and mute its output."""
try:
# check_output() was added in Python 2.7.
has_check_output = (sys.version_info[0] > 2 or
(sys.version_info[0] == 2 and sys.version_info[1] >= 7))
if has_check_output:
subprocess.check_output(args, cwd=cwd, stderr=subprocess.STDOUT)
else:
proc = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE)
proc.communicate()[0].split()
except subprocess.CalledProcessError as error:
print(error.output)
sys.exit(error.returncode)
def main():
expect_usage(len(sys.argv) >= 2)
if sys.argv[1] == "download":
download_libuv()
elif sys.argv[1] == "build":
expect_usage(len(sys.argv) <= 3)
arch = ""
if len(sys.argv) == 3:
arch = sys.argv[2]
out = os.path.join("build", "libuv" + arch + ".a")
build_libuv(arch, out)
else:
expect_usage(false)
def expect_usage(condition):
if (condition): return
print("Usage: libuv.py download")
print(" libuv.py build [-32|-64]")
sys.exit(1)
main()
+73
View File
@@ -0,0 +1,73 @@
#!/usr/bin/env python
# Downloads GYP and libuv into deps/.
#
# Run this manually to update the vendored copies of GYP and libuv that are
# committed in the Wren repo.
from __future__ import print_function
import sys
from util import clean_dir, remove_dir, replace_in_file, run
LIB_UV_VERSION = "v1.10.0"
LIB_UV_DIR = "deps/libuv"
def main(args):
# Delete it if already there so we ensure we get the correct version if the
# version number in this script changes.
clean_dir("deps")
print("Cloning libuv...")
run([
"git", "clone", "--quiet", "--depth=1",
"https://github.com/libuv/libuv.git",
LIB_UV_DIR
])
print("Getting tags...")
run([
"git", "fetch", "--quiet", "--depth=1", "--tags"
], cwd=LIB_UV_DIR)
print("Checking out libuv " + LIB_UV_VERSION + "...")
run([
"git", "checkout", "--quiet", LIB_UV_VERSION
], cwd=LIB_UV_DIR)
# TODO: Pin gyp to a known-good commit. Update a previously downloaded gyp
# if it doesn't match that commit.
print("Downloading gyp...")
run([
"git", "clone", "--quiet", "--depth=1",
"https://chromium.googlesource.com/external/gyp.git",
LIB_UV_DIR + "/build/gyp"
])
# We don't need all of libuv and gyp's various support files.
print("Deleting unneeded files...")
remove_dir("deps/libuv/build/gyp/buildbot")
remove_dir("deps/libuv/build/gyp/infra")
remove_dir("deps/libuv/build/gyp/samples")
remove_dir("deps/libuv/build/gyp/test")
remove_dir("deps/libuv/build/gyp/tools")
remove_dir("deps/libuv/docs")
remove_dir("deps/libuv/img")
remove_dir("deps/libuv/samples")
remove_dir("deps/libuv/test")
# We are going to commit libuv and GYP in the main Wren repo, so we don't
# want them to be their own repos.
remove_dir("deps/libuv/.git")
remove_dir("deps/libuv/build/gyp/.git")
# Libuv's .gitignore ignores GYP, but we want to commit it.
replace_in_file("deps/libuv/.gitignore",
"/build/gyp",
"# /build/gyp (We do want to commit GYP in Wren's repo)")
main(sys.argv)
+77
View File
@@ -0,0 +1,77 @@
# Utility functions used by other Python files in this directory.
from __future__ import print_function
import os
import os.path
import platform
import shutil
import subprocess
import sys
def python2_binary():
"""Tries to find a python 2 executable."""
# Using [0] instead of .major here to support Python 2.6.
if sys.version_info[0] == 2:
return sys.executable or "python"
else:
return "python2"
def clean_dir(dir):
"""If dir exists, deletes it and recreates it, otherwise creates it."""
if os.path.isdir(dir):
remove_dir(dir)
os.makedirs(dir)
def ensure_dir(dir):
"""Creates dir if not already there."""
if os.path.isdir(dir):
return
os.makedirs(dir)
def remove_dir(dir):
"""Recursively removes dir."""
if platform.system() == "Windows":
# rmtree gives up on readonly files on Windows
# rd doesn't like paths with forward slashes
subprocess.check_call(
['cmd', '/c', 'rd', '/s', '/q', dir.replace('/', '\\')])
else:
shutil.rmtree(dir)
def replace_in_file(path, text, replace):
"""Replaces all occurrences of `text` in the file at `path` with `replace`."""
with open(path) as file:
contents = file.read()
contents = contents.replace(text, replace)
with open(path, "w") as file:
file.write(contents)
def run(args, cwd=None):
"""Spawn a process to invoke [args] and mute its output."""
try:
# check_output() was added in Python 2.7.
has_check_output = (sys.version_info[0] > 2 or
(sys.version_info[0] == 2 and sys.version_info[1] >= 7))
if has_check_output:
subprocess.check_output(args, cwd=cwd, stderr=subprocess.STDOUT)
else:
proc = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE)
proc.communicate()[0].split()
except subprocess.CalledProcessError as error:
print(error.output)
sys.exit(error.returncode)
+3 -6
View File
@@ -213,13 +213,10 @@ $(BUILD_DIR)/test/%.o: test/api/%.c $(OPT_HEADERS) $(MODULE_HEADERS) \
$(V) mkdir -p $(dir $@)
$(V) $(CC) -c $(CFLAGS) $(CLI_FLAGS) -o $@ $(FILE_FLAG) $<
# Download libuv.
$(LIBUV_DIR)/build/gyp/gyp: util/libuv.py
$(V) ./util/libuv.py download
# Build libuv to a static library.
$(LIBUV): $(LIBUV_DIR)/build/gyp/gyp util/libuv.py
$(V) ./util/libuv.py build $(LIBUV_ARCH)
$(LIBUV): $(LIBUV_DIR)/build/gyp/gyp util/update_deps.py
@ printf "%10s %-30s %s\n" run util/build_libuv.py
$(V) ./util/build_libuv.py $(LIBUV_ARCH)
# Wren modules that get compiled into the binary as C strings.
src/optional/wren_opt_%.wren.inc: src/optional/wren_opt_%.wren util/wren_to_c_string.py