8 import simplejson as json
16 node_prefix = '/usr/local' # PREFIX variable from Makefile
17 install_path = None # base target directory (DESTDIR + PREFIX from Makefile)
18 target_defaults = None
22 path = os.path.join(*args)
23 return os.path.abspath(path)
26 s = open('config.gypi').read()
27 s = re.sub(r'#.*?\n', '', s) # strip comments
28 s = re.sub(r'\'', '"', s) # convert quotes
35 if e.errno != errno.ENOENT: raise
37 def try_symlink(source_path, link_path):
38 print 'symlinking %s -> %s' % (source_path, link_path)
40 os.symlink(source_path, link_path)
42 def try_mkdir_r(path):
46 if e.errno != errno.EEXIST: raise
48 def try_rmdir_r(path):
50 while path.startswith(install_path):
54 if e.errno == errno.ENOTEMPTY: return
55 if e.errno == errno.ENOENT: return
57 path = abspath(path, '..')
59 def mkpaths(path, dst):
61 target_path = abspath(install_path, dst, os.path.basename(path))
63 target_path = abspath(install_path, dst)
64 return path, target_path
66 def try_copy(path, dst):
67 source_path, target_path = mkpaths(path, dst)
68 print 'installing %s' % target_path
69 try_mkdir_r(os.path.dirname(target_path))
70 try_unlink(target_path) # prevent ETXTBSY errors
71 return shutil.copy2(source_path, target_path)
73 def try_remove(path, dst):
74 source_path, target_path = mkpaths(path, dst)
75 print 'removing %s' % target_path
76 try_unlink(target_path)
77 try_rmdir_r(os.path.dirname(target_path))
79 def install(paths, dst): map(lambda path: try_copy(path, dst), paths)
80 def uninstall(paths, dst): map(lambda path: try_remove(path, dst), paths)
82 def update_shebang(path, shebang):
83 print 'updating shebang of %s to %s' % (path, shebang)
84 s = open(path, 'r').read()
85 s = re.sub(r'#!.*\n', '#!' + shebang + '\n', s)
86 open(path, 'w').write(s)
88 def npm_files(action):
89 target_path = 'lib/node_modules/npm/'
91 # don't install npm if the target path is a symlink, it probably means
92 # that a dev version of npm is installed there
93 if os.path.islink(abspath(install_path, target_path)): return
95 # npm has a *lot* of files and it'd be a pain to maintain a fixed list here
96 # so we walk its source directory instead...
97 for dirname, subdirs, basenames in os.walk('deps/npm', topdown=True):
98 subdirs[:] = filter('test'.__ne__, subdirs) # skip test suites
99 paths = [os.path.join(dirname, basename) for basename in basenames]
100 action(paths, target_path + dirname[9:] + '/')
102 # create/remove symlink
103 link_path = abspath(install_path, 'bin/npm')
104 if action == uninstall:
105 action([link_path], 'bin/npm')
106 elif action == install:
107 try_symlink('../lib/node_modules/npm/bin/npm-cli.js', link_path)
108 if os.environ.get('PORTABLE'):
109 # This crazy hack is necessary to make the shebang execute the copy
110 # of node relative to the same directory as the npm script. The precompiled
111 # binary tarballs use a prefix of "/" which gets translated to "/bin/node"
112 # in the regular shebang modifying logic, which is incorrect since the
113 # precompiled bundle should be able to be extracted anywhere and "just work"
114 shebang = '/bin/sh\n// 2>/dev/null; exec "`dirname "$0"`/node" "$0" "$@"'
116 shebang = os.path.join(node_prefix or '/', 'bin/node')
117 update_shebang(link_path, shebang)
119 assert(0) # unhandled action type
121 def subdir_files(path, dest, action):
123 for dirpath, dirnames, filenames in os.walk(path):
124 files = [dirpath + '/' + f for f in filenames if f.endswith('.h')]
125 ret[dest + dirpath.replace(path, '')] = files
126 for subdir, files in ret.items():
127 action(files, subdir + '/')
130 is_windows = sys.platform == 'win32'
132 exeext = '.exe' if is_windows else ''
133 action(['out/Release/node' + exeext], 'bin/node' + exeext)
135 if 'true' == variables.get('node_use_dtrace'):
136 action(['out/Release/node.d'], 'lib/dtrace/node.d')
138 # behave similarly for systemtap
139 action(['src/node.stp'], 'share/systemtap/tapset/')
141 action(['deps/v8/tools/gdbinit'], 'share/doc/node/')
143 if 'freebsd' in sys.platform or 'openbsd' in sys.platform:
144 action(['doc/node.1'], 'man/man1/')
146 action(['doc/node.1'], 'share/man/man1/')
148 if 'true' == variables.get('node_install_npm'): npm_files(action)
158 'src/node_internals.h',
159 'src/node_object_wrap.h',
160 'src/node_version.h',
163 subdir_files('deps/cares/include', 'include/node/', action)
164 subdir_files('deps/v8/include', 'include/node/', action)
166 if 'false' == variables.get('node_shared_libuv'):
167 subdir_files('deps/uv/include', 'include/node/', action)
169 if 'false' == variables.get('node_shared_openssl'):
170 subdir_files('deps/openssl/openssl/include/openssl', 'include/node/openssl/', action)
171 subdir_files('deps/openssl/config/archs', 'include/node/openssl/archs', action)
172 action(['deps/openssl/config/opensslconf.h'], 'include/node/openssl/')
174 if 'false' == variables.get('node_shared_zlib'):
181 global node_prefix, install_path, target_defaults, variables
183 # chdir to the project's top-level directory
184 os.chdir(abspath(os.path.dirname(__file__), '..'))
187 variables = conf['variables']
188 target_defaults = conf['target_defaults']
190 # argv[2] is a custom install prefix for packagers (think DESTDIR)
191 # argv[3] is a custom install prefix (think PREFIX)
192 # Difference is that dst_dir won't be included in shebang lines etc.
193 dst_dir = args[2] if len(args) > 2 else ''
196 node_prefix = args[3]
198 # install_path thus becomes the base target directory.
199 install_path = dst_dir + node_prefix + '/'
201 cmd = args[1] if len(args) > 1 else 'install'
203 if os.environ.get('HEADERS_ONLY'):
204 if cmd == 'install': return headers(install)
205 if cmd == 'uninstall': return headers(uninstall)
207 if cmd == 'install': return files(install)
208 if cmd == 'uninstall': return files(uninstall)
210 raise RuntimeError('Bad command: %s\n' % cmd)
212 if __name__ == '__main__':