Merge pull request #81 from atom/window-native-modules

Fix node native modules support on Windows
This commit is contained in:
Cheng Zhao 2013-09-01 22:31:31 -07:00
Родитель 790c53825b 3b149945bf
Коммит 504f96ae08
7 изменённых файлов: 186 добавлений и 51 удалений

Просмотреть файл

@ -21,7 +21,7 @@ int Start(int argc, char *argv[]);
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
int argc = 0;
wchar_t** wargv = ::CommandLineToArgvW(cmd, &argc);
wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
if (argc > 1 && wcscmp(wargv[1], L"--atom-child_process-fork") == 0) {
// Convert argv to to UTF8
char** argv = new char*[argc];

Просмотреть файл

@ -275,6 +275,7 @@
'destination': '<(PRODUCT_DIR)',
'files': [
'<(libchromiumcontent_library_dir)/chromiumcontent.dll',
'<(libchromiumcontent_library_dir)/ffmpegsumo.dll',
'<(libchromiumcontent_library_dir)/icudt.dll',
'<(libchromiumcontent_library_dir)/libGLESv2.dll',
'<(libchromiumcontent_resources_dir)/content_shell.pak',
@ -469,5 +470,37 @@
}, # target helper
],
}], # OS==Mac
['OS=="win"', {
'targets': [
{
'target_name': 'generate_node_lib',
'type': 'none',
'dependencies': [
'<(project_name)',
],
'actions': [
{
'action_name': 'Create node.lib',
'inputs': [
'<(PRODUCT_DIR)/atom.lib',
'<(libchromiumcontent_library_dir)/chromiumcontent.dll.lib',
],
'outputs': [
'<(PRODUCT_DIR)/node.lib',
],
'action': [
'lib.exe',
'/nologo',
# We can't use <(_outputs) here because that escapes the
# backslash in the path, which confuses lib.exe.
'/OUT:<(PRODUCT_DIR)\\node.lib',
'<@(_inputs)',
],
'msvs_cygwin_shell': 0,
},
],
}, # target generate_node_lib
],
}], # OS==win
],
}

Просмотреть файл

@ -1,12 +1,18 @@
fs = require 'fs'
path = require 'path'
# Redirect node's console to use our own implementations, since node can not
# handle output when running as GUI program.
if process.platform is 'win32'
# Redirect node's console to use our own implementations, since node can not
# handle output when running as GUI program.
console.log = console.error = console.warn = process.log
process.stdout.write = process.stderr.write = process.log
# Always returns EOF for stdin stream.
Readable = require('stream').Readable
stdin = new Readable
stdin.push null
process.__defineGetter__ 'stdin', -> stdin
# Provide default Content API implementations.
atom = {}

Просмотреть файл

@ -20,7 +20,7 @@ def main():
args = parse_args()
for config in args.configuration:
build_path = os.path.join('out', config)
subprocess.call([ninja, '-C', build_path])
subprocess.call([ninja, '-C', build_path, args.target])
def parse_args():
@ -30,6 +30,10 @@ def parse_args():
nargs='+',
default=CONFIGURATIONS,
required=False)
parser.add_argument('-t', '--target',
help='Build specified target',
default='atom',
required=False)
return parser.parse_args()

Просмотреть файл

@ -11,14 +11,42 @@ import tarfile
from lib.util import *
ATOM_SHELL_VRESION = get_atom_shell_version()
NODE_VERSION = 'v0.10.15'
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
DIST_DIR = os.path.join(SOURCE_ROOT, 'dist')
NODE_DIR = os.path.join(SOURCE_ROOT, 'vendor', 'node')
DIST_HEADERS_NAME = 'node-{0}'.format(get_atom_shell_version())
DIST_HEADERS_NAME = 'node-{0}'.format(NODE_VERSION)
DIST_HEADERS_DIR = os.path.join(DIST_DIR, DIST_HEADERS_NAME)
BUNDLE_NAME = 'Atom.app'
BUNDLE_DIR = os.path.join(SOURCE_ROOT, 'out', 'Release', BUNDLE_NAME)
TARGET_PLATFORM = {
'cygwin': 'win32',
'darwin': 'darwin',
'linux2': 'linux',
'win32': 'win32',
}[sys.platform]
TARGET_BINARIES = {
'darwin': [
],
'win32': [
'atom.exe',
'chromiumcontent.dll',
'content_shell.pak',
'ffmpegsumo.dll',
'icudt.dll',
'libGLESv2.dll',
],
}
TARGET_DIRECTORIES = {
'darwin': [
'Atom.app',
],
'win32': [
'resources',
],
}
HEADERS_SUFFIX = [
'.h',
@ -27,7 +55,6 @@ HEADERS_SUFFIX = [
HEADERS_DIRS = [
'src',
'deps/http_parser',
'deps/v8',
'deps/zlib',
'deps/uv',
]
@ -56,12 +83,20 @@ def force_build():
def copy_binaries():
shutil.copytree(BUNDLE_DIR, os.path.join(DIST_DIR, BUNDLE_NAME),
symlinks=True)
out_dir = os.path.join(SOURCE_ROOT, 'out', 'Release')
for binary in TARGET_BINARIES[TARGET_PLATFORM]:
shutil.copy2(os.path.join(out_dir, binary), DIST_DIR)
for directory in TARGET_DIRECTORIES[TARGET_PLATFORM]:
shutil.copytree(os.path.join(out_dir, directory),
os.path.join(DIST_DIR, directory),
symlinks=True)
def copy_headers():
os.mkdir(DIST_HEADERS_DIR)
# Copy standard node headers from node. repository.
for include_path in HEADERS_DIRS:
abs_path = os.path.join(NODE_DIR, include_path)
for dirpath, dirnames, filenames in os.walk(abs_path):
@ -71,7 +106,19 @@ def copy_headers():
continue
copy_source_file(os.path.join(dirpath, filename))
for other_file in HEADERS_FILES:
copy_source_file(os.path.join(NODE_DIR, other_file))
copy_source_file(source = os.path.join(NODE_DIR, other_file))
# Copy V8 headers from chromium's repository.
src = os.path.join(SOURCE_ROOT, 'vendor', 'brightray', 'vendor', 'download',
'libchromiumcontent', 'src')
for dirpath, dirnames, filenames in os.walk(os.path.join(src, 'v8')):
for filename in filenames:
extension = os.path.splitext(filename)[1]
if extension not in HEADERS_SUFFIX:
continue
copy_source_file(source=os.path.join(dirpath, filename),
start=src,
destination=os.path.join(DIST_HEADERS_DIR, 'deps'))
def copy_license():
@ -82,17 +129,19 @@ def copy_license():
def create_version():
version_path = os.path.join(SOURCE_ROOT, 'dist', 'version')
with open(version_path, 'w') as version_file:
version_file.write(get_atom_shell_version())
version_file.write(ATOM_SHELL_VRESION)
def create_zip():
print "Zipping distribution..."
zip_file = os.path.join(SOURCE_ROOT, 'dist', 'atom-shell.zip')
safe_unlink(zip_file)
dist_name = 'atom-shell-{0}-{1}.zip'.format(ATOM_SHELL_VRESION,
TARGET_PLATFORM)
zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name)
with scoped_cwd(DIST_DIR):
files = ['Atom.app', 'LICENSE', 'version']
subprocess.check_call(['zip', '-r', '-y', zip_file] + files)
files = TARGET_BINARIES[TARGET_PLATFORM] + \
TARGET_DIRECTORIES[TARGET_PLATFORM] + \
['LICENSE', 'version']
make_zip(zip_file, files)
def create_header_tarball():
@ -102,11 +151,11 @@ def create_header_tarball():
tarball.close()
def copy_source_file(source):
relative = os.path.relpath(source, start=NODE_DIR)
destination = os.path.join(DIST_HEADERS_DIR, relative)
safe_mkdir(os.path.dirname(destination))
shutil.copy2(source, destination)
def copy_source_file(source, start=NODE_DIR, destination=DIST_HEADERS_DIR):
relative = os.path.relpath(source, start=start)
final_destination = os.path.join(destination, relative)
safe_mkdir(os.path.dirname(final_destination))
shutil.copy2(source, final_destination)
if __name__ == '__main__':

Просмотреть файл

@ -64,6 +64,16 @@ def extract_zip(zip_path, destination):
with zipfile.ZipFile(zip_path) as z:
z.extractall(destination)
def make_zip(zip_file_path, files):
safe_unlink(zip_file_path)
if sys.platform == 'darwin':
subprocess.check_call(['zip', '-r', '-y', zip_file_path] + files)
else:
zip_file = zipfile.ZipFile(zip_file_path, "w")
for filename in files:
zip_file.write(filename, filename)
zip_file.close()
def rm_rf(path):
try:

Просмотреть файл

@ -1,5 +1,6 @@
#!/usr/bin/env python
import argparse
import errno
import glob
import os
@ -10,29 +11,41 @@ import tempfile
from lib.util import *
TARGET_PLATFORM = {
'cygwin': 'win32',
'darwin': 'darwin',
'linux2': 'linux',
'win32': 'win32',
}[sys.platform]
ATOM_SHELL_VRESION = get_atom_shell_version()
NODE_VERSION = 'v0.10.15'
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
OUT_DIR = os.path.join(SOURCE_ROOT, 'out', 'Release')
DIST_DIR = os.path.join(SOURCE_ROOT, 'dist')
DIST_NAME = 'atom-shell-{0}-{1}.zip'.format(ATOM_SHELL_VRESION, TARGET_PLATFORM)
def main():
try:
ensure_s3put()
if not dist_newer_than_head():
create_dist = os.path.join(SOURCE_ROOT, 'script', 'create-dist.py')
subprocess.check_call([sys.executable, create_dist])
upload()
except AssertionError as e:
return e.message
args = parse_args()
if not dist_newer_than_head():
create_dist = os.path.join(SOURCE_ROOT, 'script', 'create-dist.py')
subprocess.check_call([sys.executable, create_dist])
bucket, access_key, secret_key = s3_config()
upload(bucket, access_key, secret_key)
if not args.no_update_version:
update_version(bucket, access_key, secret_key)
def ensure_s3put():
output = ''
try:
output = subprocess.check_output(['s3put', '--help'])
except OSError as e:
if e.errno != errno.ENOENT:
raise
assert 'multipart' in output, 'Error: Please install boto and filechunkio'
def parse_args():
parser = argparse.ArgumentParser(description='upload distribution file')
parser.add_argument('-n', '--no-update-version',
help='Do not update the latest version file',
action='store_false')
return parser.parse_args()
def dist_newer_than_head():
@ -40,7 +53,7 @@ def dist_newer_than_head():
try:
head_time = subprocess.check_output(['git', 'log', '--pretty=format:%at',
'-n', '1']).strip()
dist_time = os.path.getmtime(os.path.join(DIST_DIR, 'atom-shell.zip'))
dist_time = os.path.getmtime(os.path.join(DIST_DIR, DIST_NAME))
except OSError as e:
if e.errno != errno.ENOENT:
raise
@ -49,17 +62,36 @@ def dist_newer_than_head():
return dist_time > int(head_time)
def upload():
def upload(bucket, access_key, secret_key, version=ATOM_SHELL_VRESION):
os.chdir(DIST_DIR)
bucket, access_key, secret_key = s3_config()
version = get_atom_shell_version()
s3put(bucket, access_key, secret_key, DIST_DIR,
'atom-shell/{0}'.format(version), ['atom-shell.zip'])
'atom-shell/{0}'.format(version), [DIST_NAME])
s3put(bucket, access_key, secret_key, DIST_DIR,
'atom-shell/dist/{0}'.format(version), glob.glob('node-*.tar.gz'))
'atom-shell/dist/{0}'.format(NODE_VERSION), glob.glob('node-*.tar.gz'))
update_version(bucket, access_key, secret_key)
if TARGET_PLATFORM == 'win32':
# Generate the node.lib.
build = os.path.join(SOURCE_ROOT, 'script', 'build.py')
subprocess.check_call([sys.executable, build, '-c', 'Release',
'-t', 'generate_node_lib'])
# Upload the 32bit node.lib.
node_lib = os.path.join(OUT_DIR, 'node.lib')
s3put(bucket, access_key, secret_key, OUT_DIR,
'atom-shell/dist/{0}'.format(NODE_VERSION), [node_lib])
# Upload the fake 64bit node.lib.
touch_x64_node_lib()
node_lib = os.path.join(OUT_DIR, 'x64', 'node.lib')
s3put(bucket, access_key, secret_key, OUT_DIR,
'atom-shell/dist/{0}'.format(NODE_VERSION), [node_lib])
def update_version(bucket, access_key, secret_key):
prefix = os.path.join(SOURCE_ROOT, 'dist')
version = os.path.join(prefix, 'version')
s3put(bucket, access_key, secret_key, prefix, 'atom-shell', [version])
def s3_config():
@ -73,12 +105,6 @@ def s3_config():
return config
def update_version(bucket, access_key, secret_key):
prefix = os.path.join(SOURCE_ROOT, 'dist')
version = os.path.join(prefix, 'version')
s3put(bucket, access_key, secret_key, prefix, 'atom-shell', [ version ])
def s3put(bucket, access_key, secret_key, prefix, key_prefix, files):
args = [
's3put',
@ -93,6 +119,13 @@ def s3put(bucket, access_key, secret_key, prefix, key_prefix, files):
subprocess.check_call(args)
def touch_x64_node_lib():
x64_dir = os.path.join(OUT_DIR, 'x64')
safe_mkdir(x64_dir)
with open(os.path.join(x64_dir, 'node.lib'), 'w+') as node_lib:
node_lib.write('Invalid library')
if __name__ == '__main__':
import sys
sys.exit(main())