Nightly Node.js and Big Endian cross compilation Node.js (#1590)
This PR adds support for `./emsdk install node-nightly-64bit` which finds the latest nightly node.js version and installs that. It is a moving target, so the next day when a new nightly is produced, reissuing `./emsdk install node-nightly-64bit` will install the newer published version. Also, this PR adds a fixed 22.18.0 version for the cross compilation s390x Node.js target as well. On an x64 Linux system, this allows running `./emsdk install node-big-endian-crosscompile-22.16.0-64bit` to install the big endian Node.js. This greatly simplifies the steps at https://github.com/emscripten-core/emscripten/compare/main...juj:emscripten:bigendian_test_suite#diff-c36b90121be240017fa490a1c00e63e47fa3235f5c1be0593e2b7502d017c778R9985-R10000 and enables a trivial way to switch between LE and BE Node.js versions for testing. CC @slavek-kucera
This commit is contained in:
100
emsdk.py
100
emsdk.py
@@ -1477,6 +1477,77 @@ def find_emscripten_root(active_tools):
|
||||
return root
|
||||
|
||||
|
||||
def fetch_nightly_node_versions():
|
||||
url = "https://nodejs.org/download/nightly/"
|
||||
with urlopen(url) as response:
|
||||
html = response.read().decode("utf-8")
|
||||
|
||||
# Regex to capture href values like v7.0.0-nightly2016080175c6d9dd95/
|
||||
pattern = re.compile(r'<a href="(v[0-9]+\.[0-9]+\.[0-9]+-nightly[0-9a-f]+)/">')
|
||||
matches = pattern.findall(html)
|
||||
return matches
|
||||
|
||||
|
||||
def dir_installed_nightly_node_versions():
|
||||
path = os.path.abspath('node')
|
||||
return [name for name in os.listdir(path) if os.path.isdir(os.path.join(path, name)) and name.startswith("nightly-")]
|
||||
|
||||
|
||||
def extract_newest_node_nightly_version(versions):
|
||||
def parse(v):
|
||||
# example: v7.0.0-nightly2016080175c6d9dd95
|
||||
m = re.match(r'v(\d+)\.(\d+)\.(\d+)-nightly(\d+)', v)
|
||||
if m:
|
||||
major, minor, patch, nightly = m.groups()
|
||||
return [int(major), int(minor), int(patch), int(nightly)]
|
||||
else:
|
||||
return []
|
||||
|
||||
try:
|
||||
return max(versions, key=lambda v: parse(v))
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def download_node_nightly(tool):
|
||||
nightly_versions = fetch_nightly_node_versions()
|
||||
latest_nightly = extract_newest_node_nightly_version(nightly_versions)
|
||||
print('Latest Node.js Nightly download available is "' + latest_nightly + '"')
|
||||
|
||||
output_dir = os.path.abspath('node/nightly-' + latest_nightly)
|
||||
# Node.js zip structure quirk: Linux and macOS archives have a /bin,
|
||||
# Windows does not. Unify the file structures.
|
||||
if WINDOWS:
|
||||
output_dir += '/bin'
|
||||
|
||||
if os.path.isdir(output_dir):
|
||||
return True
|
||||
|
||||
url = tool.url.replace('%version%', latest_nightly)
|
||||
if WINDOWS:
|
||||
os_ = 'win'
|
||||
elif LINUX:
|
||||
os_ = 'linux'
|
||||
elif MACOS:
|
||||
os_ = 'darwin'
|
||||
else:
|
||||
os_ = ''
|
||||
if platform.machine().lower() in ["x86_64", "amd64"]:
|
||||
arch = 'x64'
|
||||
elif platform.machine().lower() in ["arm64", "aarch64"]:
|
||||
arch = 'arm64'
|
||||
if WINDOWS:
|
||||
zip_suffix = 'zip'
|
||||
else:
|
||||
zip_suffix = 'tar.gz'
|
||||
url = url.replace('%os%', os_)
|
||||
url = url.replace('%arch%', arch)
|
||||
url = url.replace('%zip_suffix%', zip_suffix)
|
||||
download_and_extract(url, output_dir)
|
||||
open(tool.get_version_file_path(), 'w').write('node-nightly-64bit')
|
||||
return True
|
||||
|
||||
|
||||
# returns a tuple (string,string) of config files paths that need to used
|
||||
# to activate emsdk env depending on $SHELL, defaults to bash.
|
||||
def get_emsdk_shell_env_configs():
|
||||
@@ -1511,7 +1582,10 @@ def generate_em_config(active_tools, permanently_activate, system):
|
||||
activated_config['NODE_JS'] = node_fallback
|
||||
|
||||
for name, value in activated_config.items():
|
||||
cfg += name + " = '" + value + "'\n"
|
||||
if value.startswith('['):
|
||||
cfg += name + " = " + value + "\n"
|
||||
else:
|
||||
cfg += name + " = '" + value + "'\n"
|
||||
|
||||
emroot = find_emscripten_root(active_tools)
|
||||
if emroot:
|
||||
@@ -1606,6 +1680,11 @@ class Tool(object):
|
||||
str = str.replace('%.exe%', '.exe' if WINDOWS else '')
|
||||
if '%llvm_build_bin_dir%' in str:
|
||||
str = str.replace('%llvm_build_bin_dir%', llvm_build_bin_dir(self))
|
||||
if '%latest_downloaded_node_nightly_dir%' in str:
|
||||
installed_node_nightlys = dir_installed_nightly_node_versions()
|
||||
latest_node_nightly = extract_newest_node_nightly_version(installed_node_nightlys)
|
||||
if latest_node_nightly:
|
||||
str = str.replace('%latest_downloaded_node_nightly_dir%', latest_node_nightly)
|
||||
|
||||
return str
|
||||
|
||||
@@ -1727,10 +1806,11 @@ class Tool(object):
|
||||
return False
|
||||
|
||||
if self.download_url() is None:
|
||||
# This tool does not contain downloadable elements, so it is installed by default.
|
||||
debug_print(str(self) + ' has no files to download, so is installed by default.')
|
||||
return True
|
||||
|
||||
content_exists = is_nonempty_directory(self.installation_path())
|
||||
debug_print(str(self) + ' installation path is ' + self.installation_path() + ', exists: ' + str(content_exists) + '.')
|
||||
|
||||
# For e.g. fastcomp clang from git repo, the activated PATH is the
|
||||
# directory where the compiler is built to, and installation_path is
|
||||
@@ -1876,12 +1956,14 @@ class Tool(object):
|
||||
print("Installing tool '" + str(self) + "'..")
|
||||
url = self.download_url()
|
||||
|
||||
if hasattr(self, 'custom_install_script') and self.custom_install_script == 'build_llvm':
|
||||
success = build_llvm(self)
|
||||
elif hasattr(self, 'custom_install_script') and self.custom_install_script == 'build_ninja':
|
||||
success = build_ninja(self)
|
||||
elif hasattr(self, 'custom_install_script') and self.custom_install_script == 'build_ccache':
|
||||
success = build_ccache(self)
|
||||
custom_install_scripts = {
|
||||
'build_llvm': build_llvm,
|
||||
'build_ninja': build_ninja,
|
||||
'build_ccache': build_ccache,
|
||||
'download_node_nightly': download_node_nightly
|
||||
}
|
||||
if hasattr(self, 'custom_install_script') and self.custom_install_script in custom_install_scripts:
|
||||
success = custom_install_scripts[self.custom_install_script](self)
|
||||
elif hasattr(self, 'git_branch'):
|
||||
success = git_clone_checkout_and_pull(url, self.installation_path(), self.git_branch, getattr(self, 'remote_name', 'origin'))
|
||||
elif url.endswith(ARCHIVE_SUFFIXES):
|
||||
@@ -1896,7 +1978,7 @@ class Tool(object):
|
||||
if hasattr(self, 'custom_install_script'):
|
||||
if self.custom_install_script == 'emscripten_npm_install':
|
||||
success = emscripten_npm_install(self, self.installation_path())
|
||||
elif self.custom_install_script in ('build_llvm', 'build_ninja', 'build_ccache'):
|
||||
elif self.custom_install_script in ('build_llvm', 'build_ninja', 'build_ccache', 'download_node_nightly'):
|
||||
# 'build_llvm' is a special one that does the download on its
|
||||
# own, others do the download manually.
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user