mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
ed7b6764c2
The shared libraries will now be stores in lib.target as opposed to obj.target, libnode.version.so, libnode.x (for npm backwards compat and testing), and libnode.version.x (for builds). The install will also include libnode.so link that points to libnode.version.so (this will be used by native npms for backwards compat). PR-URL: https://github.com/nodejs/node/pull/42256 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com> Co-authored-by: Gaby Baghdadi <baghdadi@ca.ibm.com> Co-authored-by: Wayne Zhang <shuowang.zhang@ibm.com>
347 lines
11 KiB
Python
Executable File
347 lines
11 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
from __future__ import print_function
|
|
|
|
import ast
|
|
import errno
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import re
|
|
|
|
# set at init time
|
|
node_prefix = '/usr/local' # PREFIX variable from Makefile
|
|
install_path = '' # base target directory (DESTDIR + PREFIX from Makefile)
|
|
target_defaults = None
|
|
variables = None
|
|
|
|
def abspath(*args):
|
|
path = os.path.join(*args)
|
|
return os.path.abspath(path)
|
|
|
|
def load_config():
|
|
with open('config.gypi') as f:
|
|
return ast.literal_eval(f.read())
|
|
|
|
def try_unlink(path):
|
|
try:
|
|
os.unlink(path)
|
|
except OSError as e:
|
|
if e.errno != errno.ENOENT: raise
|
|
|
|
def try_symlink(source_path, link_path):
|
|
print('symlinking %s -> %s' % (source_path, link_path))
|
|
try_unlink(link_path)
|
|
try_mkdir_r(os.path.dirname(link_path))
|
|
os.symlink(source_path, link_path)
|
|
|
|
def try_mkdir_r(path):
|
|
try:
|
|
os.makedirs(path)
|
|
except OSError as e:
|
|
if e.errno != errno.EEXIST: raise
|
|
|
|
def try_rmdir_r(path):
|
|
path = abspath(path)
|
|
while path.startswith(install_path):
|
|
try:
|
|
os.rmdir(path)
|
|
except OSError as e:
|
|
if e.errno == errno.ENOTEMPTY: return
|
|
if e.errno == errno.ENOENT: return
|
|
raise
|
|
path = abspath(path, '..')
|
|
|
|
def mkpaths(path, dst):
|
|
if dst.endswith('/'):
|
|
target_path = abspath(install_path, dst, os.path.basename(path))
|
|
else:
|
|
target_path = abspath(install_path, dst)
|
|
return path, target_path
|
|
|
|
def try_copy(path, dst):
|
|
source_path, target_path = mkpaths(path, dst)
|
|
print('installing %s' % target_path)
|
|
try_mkdir_r(os.path.dirname(target_path))
|
|
try_unlink(target_path) # prevent ETXTBSY errors
|
|
return shutil.copy2(source_path, target_path)
|
|
|
|
def try_remove(path, dst):
|
|
source_path, target_path = mkpaths(path, dst)
|
|
print('removing %s' % target_path)
|
|
try_unlink(target_path)
|
|
try_rmdir_r(os.path.dirname(target_path))
|
|
|
|
def install(paths, dst):
|
|
for path in paths:
|
|
try_copy(path, dst)
|
|
|
|
def uninstall(paths, dst):
|
|
for path in paths:
|
|
try_remove(path, dst)
|
|
|
|
def package_files(action, name, bins):
|
|
target_path = 'lib/node_modules/' + name + '/'
|
|
|
|
# don't install npm if the target path is a symlink, it probably means
|
|
# that a dev version of npm is installed there
|
|
if os.path.islink(abspath(install_path, target_path)): return
|
|
|
|
# npm has a *lot* of files and it'd be a pain to maintain a fixed list here
|
|
# so we walk its source directory instead...
|
|
root = 'deps/' + name
|
|
for dirname, subdirs, basenames in os.walk(root, topdown=True):
|
|
subdirs[:] = [subdir for subdir in subdirs if subdir != 'test']
|
|
paths = [os.path.join(dirname, basename) for basename in basenames]
|
|
action(paths, target_path + dirname[len(root) + 1:] + '/')
|
|
|
|
# create/remove symlinks
|
|
for bin_name, bin_target in bins.items():
|
|
link_path = abspath(install_path, 'bin/' + bin_name)
|
|
if action == uninstall:
|
|
action([link_path], 'bin/' + bin_name)
|
|
elif action == install:
|
|
try_symlink('../lib/node_modules/' + name + '/' + bin_target, link_path)
|
|
else:
|
|
assert 0 # unhandled action type
|
|
|
|
def npm_files(action):
|
|
package_files(action, 'npm', {
|
|
'npm': 'bin/npm-cli.js',
|
|
'npx': 'bin/npx-cli.js',
|
|
})
|
|
|
|
def corepack_files(action):
|
|
package_files(action, 'corepack', {
|
|
'corepack': 'dist/corepack.js',
|
|
# Not the default just yet:
|
|
# 'yarn': 'dist/yarn.js',
|
|
# 'yarnpkg': 'dist/yarn.js',
|
|
# 'pnpm': 'dist/pnpm.js',
|
|
# 'pnpx': 'dist/pnpx.js',
|
|
})
|
|
|
|
# On z/OS, we install node-gyp for convenience, as some vendors don't have
|
|
# external access and may want to build native addons.
|
|
if sys.platform == 'zos':
|
|
link_path = abspath(install_path, 'bin/node-gyp')
|
|
if action == uninstall:
|
|
action([link_path], 'bin/node-gyp')
|
|
elif action == install:
|
|
try_symlink('../lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js', link_path)
|
|
else:
|
|
assert 0 # unhandled action type
|
|
|
|
def subdir_files(path, dest, action):
|
|
ret = {}
|
|
for dirpath, dirnames, filenames in os.walk(path):
|
|
files_in_path = [dirpath + '/' + f for f in filenames if f.endswith('.h')]
|
|
ret[dest + dirpath.replace(path, '')] = files_in_path
|
|
for subdir, files_in_path in ret.items():
|
|
action(files_in_path, subdir + '/')
|
|
|
|
def files(action):
|
|
is_windows = sys.platform == 'win32'
|
|
output_file = 'node'
|
|
output_prefix = 'out/Release/'
|
|
|
|
if is_windows:
|
|
output_file += '.exe'
|
|
action([output_prefix + output_file], 'bin/' + output_file)
|
|
|
|
if 'true' == variables.get('node_shared'):
|
|
if is_windows:
|
|
action([output_prefix + 'libnode.dll'], 'bin/libnode.dll')
|
|
action([output_prefix + 'libnode.lib'], 'lib/libnode.lib')
|
|
elif sys.platform == 'zos':
|
|
# GYP will output to lib.target; see _InstallableTargetInstallPath
|
|
# function in tools/gyp/pylib/gyp/generator/make.py
|
|
output_prefix += 'lib.target/'
|
|
|
|
output_lib = 'libnode.' + variables.get('shlib_suffix')
|
|
action([output_prefix + output_lib], 'lib/' + output_lib)
|
|
|
|
# create libnode.x that references libnode.so (C++ addons compat)
|
|
os.system(os.path.dirname(os.path.realpath(__file__)) +
|
|
'/zos/modifysidedeck.sh ' +
|
|
abspath(install_path, 'lib/' + output_lib) + ' ' +
|
|
abspath(install_path, 'lib/libnode.x') + ' libnode.so')
|
|
|
|
# install libnode.version.so
|
|
so_name = 'libnode.' + re.sub(r'\.x$', '.so', variables.get('shlib_suffix'))
|
|
action([output_prefix + so_name], 'lib/' + so_name)
|
|
|
|
# create symlink of libnode.so -> libnode.version.so (C++ addons compat)
|
|
link_path = abspath(install_path, 'lib/libnode.so')
|
|
try_symlink(so_name, link_path)
|
|
else:
|
|
output_lib = 'libnode.' + variables.get('shlib_suffix')
|
|
action([output_prefix + output_lib], 'lib/' + output_lib)
|
|
|
|
action(['deps/v8/tools/gdbinit'], 'share/doc/node/')
|
|
action(['deps/v8/tools/lldb_commands.py'], 'share/doc/node/')
|
|
|
|
if 'freebsd' in sys.platform or 'openbsd' in sys.platform:
|
|
action(['doc/node.1'], 'man/man1/')
|
|
else:
|
|
action(['doc/node.1'], 'share/man/man1/')
|
|
|
|
if 'true' == variables.get('node_install_npm'):
|
|
npm_files(action)
|
|
|
|
if 'true' == variables.get('node_install_corepack'):
|
|
corepack_files(action)
|
|
|
|
headers(action)
|
|
|
|
def headers(action):
|
|
def wanted_v8_headers(files_arg, dest):
|
|
v8_headers = [
|
|
'deps/v8/include/cppgc/common.h',
|
|
'deps/v8/include/libplatform/libplatform.h',
|
|
'deps/v8/include/libplatform/libplatform-export.h',
|
|
'deps/v8/include/libplatform/v8-tracing.h',
|
|
'deps/v8/include/v8.h',
|
|
'deps/v8/include/v8-array-buffer.h',
|
|
'deps/v8/include/v8-callbacks.h',
|
|
'deps/v8/include/v8-container.h',
|
|
'deps/v8/include/v8-context.h',
|
|
'deps/v8/include/v8-data.h',
|
|
'deps/v8/include/v8-date.h',
|
|
'deps/v8/include/v8-debug.h',
|
|
'deps/v8/include/v8-embedder-heap.h',
|
|
'deps/v8/include/v8-embedder-state-scope.h',
|
|
'deps/v8/include/v8-exception.h',
|
|
'deps/v8/include/v8-extension.h',
|
|
'deps/v8/include/v8-external.h',
|
|
'deps/v8/include/v8-forward.h',
|
|
'deps/v8/include/v8-function-callback.h',
|
|
'deps/v8/include/v8-function.h',
|
|
'deps/v8/include/v8-initialization.h',
|
|
'deps/v8/include/v8-internal.h',
|
|
'deps/v8/include/v8-isolate.h',
|
|
'deps/v8/include/v8-json.h',
|
|
'deps/v8/include/v8-local-handle.h',
|
|
'deps/v8/include/v8-locker.h',
|
|
'deps/v8/include/v8-maybe.h',
|
|
'deps/v8/include/v8-memory-span.h',
|
|
'deps/v8/include/v8-message.h',
|
|
'deps/v8/include/v8-microtask-queue.h',
|
|
'deps/v8/include/v8-microtask.h',
|
|
'deps/v8/include/v8-object.h',
|
|
'deps/v8/include/v8-persistent-handle.h',
|
|
'deps/v8/include/v8-platform.h',
|
|
'deps/v8/include/v8-primitive-object.h',
|
|
'deps/v8/include/v8-primitive.h',
|
|
'deps/v8/include/v8-profiler.h',
|
|
'deps/v8/include/v8-promise.h',
|
|
'deps/v8/include/v8-proxy.h',
|
|
'deps/v8/include/v8-regexp.h',
|
|
'deps/v8/include/v8-script.h',
|
|
'deps/v8/include/v8-snapshot.h',
|
|
'deps/v8/include/v8-statistics.h',
|
|
'deps/v8/include/v8-template.h',
|
|
'deps/v8/include/v8-traced-handle.h',
|
|
'deps/v8/include/v8-typed-array.h',
|
|
'deps/v8/include/v8-unwinder.h',
|
|
'deps/v8/include/v8-value-serializer.h',
|
|
'deps/v8/include/v8-value.h',
|
|
'deps/v8/include/v8-version.h',
|
|
'deps/v8/include/v8-wasm.h',
|
|
'deps/v8/include/v8-weak-callback-info.h',
|
|
'deps/v8/include/v8config.h',
|
|
]
|
|
files_arg = [name for name in files_arg if name in v8_headers]
|
|
action(files_arg, dest)
|
|
|
|
def wanted_zoslib_headers(files_arg, dest):
|
|
import glob
|
|
zoslib_headers = glob.glob(zoslibinc + '/*.h')
|
|
files_arg = [name for name in files_arg if name in zoslib_headers]
|
|
action(files_arg, dest)
|
|
|
|
action([
|
|
'common.gypi',
|
|
'config.gypi',
|
|
'src/node.h',
|
|
'src/node_api.h',
|
|
'src/js_native_api.h',
|
|
'src/js_native_api_types.h',
|
|
'src/node_api_types.h',
|
|
'src/node_buffer.h',
|
|
'src/node_object_wrap.h',
|
|
'src/node_version.h',
|
|
], 'include/node/')
|
|
|
|
# Add the expfile that is created on AIX
|
|
if sys.platform.startswith('aix'):
|
|
action(['out/Release/node.exp'], 'include/node/')
|
|
|
|
subdir_files('deps/v8/include', 'include/node/', wanted_v8_headers)
|
|
|
|
if 'false' == variables.get('node_shared_libuv'):
|
|
subdir_files('deps/uv/include', 'include/node/', action)
|
|
|
|
if 'true' == variables.get('node_use_openssl') and \
|
|
'false' == variables.get('node_shared_openssl'):
|
|
subdir_files('deps/openssl/openssl/include/openssl', 'include/node/openssl/', action)
|
|
subdir_files('deps/openssl/config/archs', 'include/node/openssl/archs', action)
|
|
subdir_files('deps/openssl/config', 'include/node/openssl', action)
|
|
|
|
if 'false' == variables.get('node_shared_zlib'):
|
|
action([
|
|
'deps/zlib/zconf.h',
|
|
'deps/zlib/zlib.h',
|
|
], 'include/node/')
|
|
|
|
if sys.platform == 'zos':
|
|
zoslibinc = os.environ.get('ZOSLIB_INCLUDES')
|
|
if not zoslibinc:
|
|
raise RuntimeError('Environment variable ZOSLIB_INCLUDES is not set\n')
|
|
if not os.path.isfile(zoslibinc + '/zos-base.h'):
|
|
raise RuntimeError('ZOSLIB_INCLUDES is not set to a valid location\n')
|
|
subdir_files(zoslibinc, 'include/node/zoslib/', wanted_zoslib_headers)
|
|
|
|
def run(args):
|
|
global node_prefix, install_path, target_defaults, variables
|
|
|
|
# chdir to the project's top-level directory
|
|
os.chdir(abspath(os.path.dirname(__file__), '..'))
|
|
|
|
conf = load_config()
|
|
variables = conf['variables']
|
|
target_defaults = conf['target_defaults']
|
|
|
|
# argv[2] is a custom install prefix for packagers (think DESTDIR)
|
|
# argv[3] is a custom install prefix (think PREFIX)
|
|
# Difference is that dst_dir won't be included in shebang lines etc.
|
|
dst_dir = args[2] if len(args) > 2 else ''
|
|
|
|
if len(args) > 3:
|
|
node_prefix = args[3]
|
|
|
|
# install_path thus becomes the base target directory.
|
|
install_path = dst_dir + node_prefix + '/'
|
|
|
|
cmd = args[1] if len(args) > 1 else 'install'
|
|
|
|
if os.environ.get('HEADERS_ONLY'):
|
|
if cmd == 'install':
|
|
headers(install)
|
|
return
|
|
if cmd == 'uninstall':
|
|
headers(uninstall)
|
|
return
|
|
else:
|
|
if cmd == 'install':
|
|
files(install)
|
|
return
|
|
if cmd == 'uninstall':
|
|
files(uninstall)
|
|
return
|
|
|
|
raise RuntimeError('Bad command: %s\n' % cmd)
|
|
|
|
if __name__ == '__main__':
|
|
run(sys.argv[:])
|