mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
Restores functionality from v0.8 where module authors may not be relying on gyp for building their modules.
193 lines
5.9 KiB
Python
Executable File
193 lines
5.9 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
import errno
|
|
|
|
try:
|
|
import json
|
|
except ImportError:
|
|
import simplejson as json
|
|
|
|
import os
|
|
import re
|
|
import shutil
|
|
import sys
|
|
|
|
# set at init time
|
|
dst_dir = None
|
|
node_prefix = None # dst_dir without DESTDIR prefix
|
|
target_defaults = None
|
|
variables = None
|
|
|
|
def abspath(*args):
|
|
path = os.path.join(*args)
|
|
return os.path.abspath(path)
|
|
|
|
def load_config():
|
|
s = open('config.gypi').read()
|
|
s = re.sub(r'#.*?\n', '', s) # strip comments
|
|
s = re.sub(r'\'', '"', s) # convert quotes
|
|
return json.loads(s)
|
|
|
|
def try_unlink(path):
|
|
try:
|
|
os.unlink(path)
|
|
except OSError, 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)
|
|
os.symlink(source_path, link_path)
|
|
|
|
def try_mkdir_r(path):
|
|
try:
|
|
os.makedirs(path)
|
|
except OSError, e:
|
|
if e.errno != errno.EEXIST: raise
|
|
|
|
def try_rmdir_r(path):
|
|
path = abspath(path)
|
|
while path.startswith(dst_dir):
|
|
try:
|
|
os.rmdir(path)
|
|
except OSError, 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(dst_dir, dst, os.path.basename(path))
|
|
else:
|
|
target_path = abspath(dst_dir, 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): map(lambda path: try_copy(path, dst), paths)
|
|
def uninstall(paths, dst): map(lambda path: try_remove(path, dst), paths)
|
|
|
|
def update_shebang(path, shebang):
|
|
print 'updating shebang of %s to %s' % (path, shebang)
|
|
s = open(path, 'r').read()
|
|
s = re.sub(r'#!.*\n', '#!' + shebang + '\n', s)
|
|
open(path, 'w').write(s)
|
|
|
|
def npm_files(action):
|
|
target_path = 'lib/node_modules/npm/'
|
|
|
|
# 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(dst_dir, 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...
|
|
for dirname, subdirs, basenames in os.walk('deps/npm', topdown=True):
|
|
subdirs[:] = filter('test'.__ne__, subdirs) # skip test suites
|
|
paths = [os.path.join(dirname, basename) for basename in basenames]
|
|
action(paths, target_path + dirname[9:] + '/')
|
|
|
|
# create/remove symlink
|
|
link_path = abspath(dst_dir, 'bin/npm')
|
|
if action == uninstall:
|
|
action([link_path], 'bin/npm')
|
|
elif action == install:
|
|
try_symlink('../lib/node_modules/npm/bin/npm-cli.js', link_path)
|
|
if os.environ.get('PORTABLE'):
|
|
# This crazy hack is necessary to make the shebang execute the copy
|
|
# of node relative to the same directory as the npm script. The precompiled
|
|
# binary tarballs use a prefix of "/" which gets translated to "/bin/node"
|
|
# in the regular shebang modifying logic, which is incorrect since the
|
|
# precompiled bundle should be able to be extracted anywhere and "just work"
|
|
shebang = '/bin/sh\n// 2>/dev/null; exec "`dirname "$0"`/node" "$0" "$@"'
|
|
else:
|
|
shebang = os.path.join(node_prefix, 'bin/node')
|
|
update_shebang(link_path, shebang)
|
|
else:
|
|
assert(0) # unhandled action type
|
|
|
|
def subdir_files(path, dest, action):
|
|
ret = {}
|
|
for dirpath, dirnames, filenames in os.walk(path):
|
|
files = [dirpath + '/' + f for f in filenames if f.endswith('.h')]
|
|
ret[dest + dirpath.replace(path, '')] = files
|
|
for subdir, files in ret.items():
|
|
action(files, subdir + '/')
|
|
|
|
def files(action):
|
|
action(['out/Release/node'], 'bin/node')
|
|
|
|
# install unconditionally, checking if the platform supports dtrace doesn't
|
|
# work when cross-compiling and besides, there's at least one linux flavor
|
|
# with dtrace support now (oracle's "unbreakable" linux)
|
|
action(['src/node.d'], 'lib/dtrace/')
|
|
|
|
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)
|
|
|
|
action([
|
|
'config.gypi',
|
|
'src/node.h',
|
|
'src/node_buffer.h',
|
|
'src/node_internals.h',
|
|
'src/node_object_wrap.h',
|
|
'src/node_version.h',
|
|
], 'include/node/')
|
|
|
|
if 'false' == variables.get('node_shared_cares'):
|
|
subdir_files('deps/cares/include', 'include/node/', action)
|
|
|
|
if 'false' == variables.get('node_shared_libuv'):
|
|
subdir_files('deps/uv/include', 'include/node/', action)
|
|
|
|
if 'false' == variables.get('node_shared_openssl'):
|
|
action(['deps/openssl/config/opensslconf.h'], 'include/node/openssl/')
|
|
subdir_files('deps/openssl/include/openssl', 'include/node/openssl/', action)
|
|
|
|
if 'false' == variables.get('node_shared_v8'):
|
|
subdir_files('deps/v8/include', 'include/node/', action)
|
|
|
|
if 'false' == variables.get('node_shared_zlib'):
|
|
action([
|
|
'deps/zlib/zconf.h',
|
|
'deps/zlib/zlib.h',
|
|
], 'include/node/')
|
|
|
|
def run(args):
|
|
global dst_dir, node_prefix, 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)
|
|
dst_dir = node_prefix = variables.get('node_prefix') or '/usr/local'
|
|
if len(args) > 2: dst_dir = abspath(args[2] + '/' + dst_dir)
|
|
|
|
cmd = args[1] if len(args) > 1 else 'install'
|
|
if cmd == 'install': return files(install)
|
|
if cmd == 'uninstall': return files(uninstall)
|
|
raise RuntimeError('Bad command: %s\n' % cmd)
|
|
|
|
if __name__ == '__main__':
|
|
run(sys.argv[:])
|