Browse Source

Merge pull request #2094 from atom/arm

Add arm build
Cheng Zhao 9 years ago
parent
commit
5ccc909f2f

+ 2 - 0
.gitignore

@@ -4,6 +4,8 @@
 /external_binaries/
 /out/
 /vendor/brightray/vendor/download/
+/vendor/debian_wheezy_arm-sysroot/
+/vendor/debian_wheezy_i386-sysroot/
 /vendor/python_26/
 /vendor/npm/
 /vendor/llvm/

+ 13 - 7
.travis.yml

@@ -1,15 +1,21 @@
+git:
+  depth: 10
+notifications:
+  email: false
+
 language: cpp
 compiler: clang
 os:
   - linux
   - osx
+env:
+  - TARGET_ARCH=x64
 
-notifications:
-  email:
-    on_success: never
-    on_failure: change
+matrix:
+  include:
+    - os: linux
+      env: TARGET_ARCH=arm
+    - os: linux
+      env: TARGET_ARCH=ia32
 
 script: './script/cibuild'
-
-git:
-  depth: 10

+ 5 - 4
atom.gyp

@@ -5,8 +5,6 @@
     'company_name%': 'GitHub, Inc',
     'company_abbr%': 'github',
     'version%': '0.28.3',
-
-    'atom_source_root': '<!(["python", "tools/atom_source_root.py"])',
   },
   'includes': [
     'filenames.gypi',
@@ -18,7 +16,7 @@
       'ATOM_PROJECT_NAME="<(project_name)"',
     ],
     'mac_framework_dirs': [
-      '<(atom_source_root)/external_binaries',
+      '<(source_root)/external_binaries',
     ],
   },
   'targets': [
@@ -45,7 +43,6 @@
           'dependencies': [
             '<(project_name)_framework',
             '<(project_name)_helper',
-            'vendor/breakpad/breakpad.gyp:dump_syms',
           ],
           'xcode_settings': {
             'ATOM_BUNDLE_ID': 'com.<(company_abbr).<(project_name)',
@@ -157,6 +154,10 @@
               ]
             },
           ],
+        }, {
+          'dependencies': [
+            'vendor/breakpad/breakpad.gyp:dump_syms#host',
+          ],
         }],  # OS=="win"
         ['OS=="linux"', {
           'copies': [

+ 1 - 2
common.gypi

@@ -6,6 +6,7 @@
   'variables': {
     # Required by breakpad.
     'os_bsd': 0,
+    'chromeos': 0,
     # Reflects node's config.gypi.
     'component%': 'static_library',
     'python': 'python',
@@ -32,8 +33,6 @@
     'V8_BASE': '',
     'v8_postmortem_support': 'false',
     'v8_enable_i18n_support': 'false',
-    # Required by Linux (empty for now, should support it in future).
-    'sysroot': '',
   },
   # Settings to compile node under Windows.
   'target_defaults': {

+ 22 - 19
docs/development/build-instructions-linux.md

@@ -4,9 +4,9 @@
 
 * Python 2.7.x. Some distributions like CentOS still use Python 2.6.x
 so you may need to check your Python version with `python -V`.
-* Node.js v0.12.x. There are various ways to install Node. One can download 
-source code from [Node.js] (http://nodejs.org) and compile from source. 
-Doing so permits installing Node to your own home directory as a standard user.  
+* Node.js v0.12.x. There are various ways to install Node. One can download
+source code from [Node.js] (http://nodejs.org) and compile from source.
+Doing so permits installing Node to your own home directory as a standard user.
 Or try repositories such as [NodeSource] (https://nodesource.com/blog/nodejs-v012-iojs-and-the-nodesource-linux-repositories)
 * Clang 3.4 or later
 * Development headers of GTK+ and libnotify
@@ -20,15 +20,13 @@ $ sudo apt-get install build-essential clang libdbus-1-dev libgtk2.0-dev \
                        libxss1 gcc-multilib g++-multilib
 ```
 
-Other distributions may offer similar packages for installation via package 
+Other distributions may offer similar packages for installation via package
 managers such as yum. Or one can compile from source code.
 
-
 ## If You Use Virtual Machines For Building
 
 If you plan to build electron on a virtual machine, you will need a fixed-size
-device container of at least 25 gigabytes in size. 
-
+device container of at least 25 gigabytes in size.
 
 ## Getting the code
 
@@ -39,8 +37,8 @@ $ git clone https://github.com/atom/electron.git
 ## Bootstrapping
 
 The bootstrap script will download all necessary build dependencies and create
-build project files. You must have Python 2.7.x for the script to succeed. 
-Downloading certain files could take a long time. Notice that we are using 
+build project files. You must have Python 2.7.x for the script to succeed.
+Downloading certain files could take a long time. Notice that we are using
 `ninja` to build Electron so there is no `Makefile` generated.
 
 ```bash
@@ -48,6 +46,15 @@ $ cd electron
 $ ./script/bootstrap.py -v
 ```
 
+### Cross compilation
+
+If you want to cross compile for `arm` or `ia32` targets, you can pass the
+`--target_arch` parameter to the `bootstrap.py` script:
+
+```bash
+$ ./script/bootstrap.py -v --target_arch=arm
+```
+
 ## Building
 
 If you would like to build both `Release` and `Debug` targets:
@@ -57,16 +64,16 @@ $ ./script/build.py
 ```
 
 This script will cause a very large Electron executable to be placed in
-the directory `out/R`. The file size is in excess of 1.3 gigabytes. This 
-happens because the Release target binary contains debugging symbols. 
+the directory `out/R`. The file size is in excess of 1.3 gigabytes. This
+happens because the Release target binary contains debugging symbols.
 To reduce the file size, run the `create-dist.py` script:
 
 ```bash
 $ ./script/create-dist.py
 ```
 
-This will put a working distribution with much smaller file sizes in 
-the `dist` directory. After running the create-dist.py script, you 
+This will put a working distribution with much smaller file sizes in
+the `dist` directory. After running the create-dist.py script, you
 may want to remove the 1.3+ gigabyte binary which is still in out/R.
 
 You can also build the `Debug` target only:
@@ -75,23 +82,19 @@ You can also build the `Debug` target only:
 $ ./script/build.py -c D
 ```
 
-After building is done, you can find the `electron` debug binary 
-under `out/D`.
-
+After building is done, you can find the `electron` debug binary under `out/D`.
 
 ## Cleaning
 
-
 To clean the build files:
 
 ```bash
 $ ./script/clean.py
 ```
 
-
 ## Troubleshooting
 
-Make sure you have installed all the build dependencies. 
+Make sure you have installed all the build dependencies.
 
 ## Tests
 

+ 0 - 1
filenames.gypi

@@ -416,7 +416,6 @@
       'sk', 'sl', 'sr', 'sv', 'sw', 'ta', 'te', 'th', 'tr', 'uk',
       'vi', 'zh-CN', 'zh-TW',
     ],
-    'atom_source_root': '<!(["python", "tools/atom_source_root.py"])',
     'conditions': [
       ['OS=="win"', {
         'app_sources': [

+ 19 - 2
script/bootstrap.py

@@ -25,12 +25,16 @@ def main():
     enable_verbose_mode()
   if sys.platform == 'cygwin':
     update_win32_python()
+
+  if PLATFORM != 'win32':
+    update_clang()
+
   update_submodules()
   update_node_modules('.')
   bootstrap_brightray(args.dev, args.url, args.target_arch)
 
-  if PLATFORM != 'win32':
-    update_clang()
+  if args.target_arch in ['arm', 'ia32'] and PLATFORM == 'linux':
+    download_sysroot(args.target_arch)
 
   create_chrome_version_h()
   touch_config_gypi()
@@ -88,6 +92,12 @@ def bootstrap_brightray(is_dev, url, target_arch):
 def update_node_modules(dirname, env=None):
   if env is None:
     env = os.environ
+  if PLATFORM == 'linux':
+    llvm_dir = os.path.join(SOURCE_ROOT, 'vendor', 'llvm-build',
+                            'Release+Asserts', 'bin')
+    env['CC']  = os.path.join(llvm_dir, 'clang')
+    env['CXX'] = os.path.join(llvm_dir, 'clang++')
+    env['npm_config_clang'] = '1'
   with scoped_cwd(dirname):
     if is_verbose_mode():
       execute_stdout([NPM, 'install', '--verbose'], env)
@@ -113,6 +123,13 @@ def update_clang():
   execute_stdout([os.path.join(SOURCE_ROOT, 'script', 'update-clang.sh')])
 
 
+def download_sysroot(target_arch):
+  if target_arch == 'ia32':
+    target_arch = 'i386'
+  execute_stdout([os.path.join(SOURCE_ROOT, 'script', 'install-sysroot.py'),
+                  '--arch', target_arch])
+
+
 def create_chrome_version_h():
   version_file = os.path.join(SOURCE_ROOT, 'vendor', 'brightray', 'vendor',
                               'libchromiumcontent', 'VERSION')

+ 17 - 12
script/cibuild

@@ -15,22 +15,32 @@ LINUX_DEPS = [
   'libgnome-keyring-dev',
   'libgtk2.0-dev',
   'libnotify-dev',
-  'gcc-4.8',
-  'g++-4.8',
   'gcc-multilib',
   'g++-multilib',
 ]
 
+LINUX_DEPS_ARM = [
+  'libc6-dev-armhf-cross',
+  'linux-libc-dev-armhf-cross',
+  'g++-arm-linux-gnueabihf',
+]
+
 
 def main():
   os.environ['CI'] = '1'
 
+  target_arch = 'x64'
+  if os.environ.has_key('TARGET_ARCH'):
+    target_arch = os.environ['TARGET_ARCH']
+
   is_travis = (os.getenv('TRAVIS') == 'true')
   if is_travis and sys.platform == 'linux2':
     print 'Setup travis CI'
-    execute(['sudo', 'add-apt-repository', '-y', 'ppa:ubuntu-toolchain-r/test'])
     execute(['sudo', 'apt-get', 'update'])
-    execute(['sudo', 'apt-get', 'install'] + LINUX_DEPS)
+    deps = LINUX_DEPS
+    if target_arch == 'arm':
+      deps += LINUX_DEPS_ARM
+    execute(['sudo', 'apt-get', 'install'] + deps)
 
     os.environ['DISPLAY'] = ':99.0'
     execute(['sh', '-e', '/etc/init.d/xvfb', 'start'])
@@ -43,20 +53,15 @@ def main():
   rm_rf(os.path.join(SOURCE_ROOT, 'vendor', 'brightray', 'vendor', 'download',
                      'libchromiumcontent'))
 
-  if is_travis and sys.platform == 'linux2':
-    with scoped_env('CXX', 'g++-4.8'):
-      with scoped_env('CC', 'gcc-4.8'):
-        run_script('bootstrap.py', ['--dev'])
-    run_script('update.py')
-  else:
-    run_script('bootstrap.py', ['--dev'])
+  run_script('bootstrap.py', ['--dev', '--target_arch=' + target_arch])
 
   run_script('cpplint.py')
   if sys.platform != 'win32':
     run_script('pylint.py')
   run_script('coffeelint.py')
   run_script('build.py', ['-c', 'Debug'])
-  run_script('test.py', ['--ci'])
+  if target_arch == 'x64':
+    run_script('test.py', ['--ci'])
 
 
 def run_script(script, args=[]):

+ 11 - 3
script/create-dist.py

@@ -80,6 +80,8 @@ def main():
   rm_rf(DIST_DIR)
   os.makedirs(DIST_DIR)
 
+  target_arch = get_target_arch()
+
   force_build()
   create_symbols()
   copy_binaries()
@@ -89,11 +91,13 @@ def main():
 
   if PLATFORM == 'linux':
     strip_binaries()
-    copy_system_libraries()
+    if target_arch != 'arm':
+      copy_system_libraries()
 
   create_version()
   create_dist_zip()
-  create_chrome_binary_zip('chromedriver', get_chromedriver_version())
+  if target_arch != 'arm':
+    create_chrome_binary_zip('chromedriver', get_chromedriver_version())
   create_chrome_binary_zip('mksnapshot', ATOM_SHELL_VERSION)
   create_symbols_zip()
 
@@ -129,9 +133,13 @@ def copy_license():
 
 
 def strip_binaries():
+  if get_target_arch() == 'arm':
+    strip = 'arm-linux-gnueabihf-strip'
+  else:
+    strip = 'strip'
   for binary in TARGET_BINARIES[PLATFORM]:
     if binary.endswith('.so') or '.' not in binary:
-      execute(['strip', os.path.join(DIST_DIR, binary)])
+      execute([strip, os.path.join(DIST_DIR, binary)])
 
 
 def copy_system_libraries():

+ 0 - 4
script/dump-symbols.py

@@ -22,10 +22,6 @@ def main(destination):
   (project_name, product_name) = get_names_from_gyp()
 
   if PLATFORM in ['darwin', 'linux']:
-    # Generate the dump_syms tool.
-    build = os.path.join(SOURCE_ROOT, 'script', 'build.py')
-    execute([sys.executable, build, '-c', 'R', '-t', 'dump_syms'])
-
     generate_breakpad_symbols = os.path.join(SOURCE_ROOT, 'tools', 'posix',
                                              'generate_breakpad_symbols.py')
     if PLATFORM == 'darwin':

+ 177 - 0
script/install-sysroot.py

@@ -0,0 +1,177 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Script to install a Debian Wheezy sysroot for making official Google Chrome
+# Linux builds.
+# The sysroot is needed to make Chrome work for Debian Wheezy.
+# This script can be run manually but is more often run as part of gclient
+# hooks. When run from hooks this script should be a no-op on non-linux
+# platforms.
+
+# The sysroot image could be constructed from scratch based on the current
+# state or Debian Wheezy but for consistency we currently use a pre-built root
+# image. The image will normally need to be rebuilt every time chrome's build
+# dependancies are changed.
+
+import hashlib
+import platform
+import optparse
+import os
+import re
+import shutil
+import subprocess
+import sys
+
+from lib.util import get_host_arch
+
+
+SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+URL_PREFIX = 'https://github.com'
+URL_PATH = 'atom/debian-sysroot-image-creator/releases/download'
+REVISION_AMD64 = 264817
+REVISION_I386 = 'v0.2.0'
+REVISION_ARM = 'v0.1.0'
+TARBALL_AMD64 = 'debian_wheezy_amd64_sysroot.tgz'
+TARBALL_I386 = 'debian_wheezy_i386_sysroot.tgz'
+TARBALL_ARM = 'debian_wheezy_arm_sysroot.tgz'
+TARBALL_AMD64_SHA1SUM = '74b7231e12aaf45c5c5489d9aebb56bd6abb3653'
+TARBALL_I386_SHA1SUM = 'f5b2ceaeb3f7e6bc2058733585fe877d002b5fa7'
+TARBALL_ARM_SHA1SUM = '72e668c57b8591e108759584942ddb6f6cee1322'
+SYSROOT_DIR_AMD64 = 'debian_wheezy_amd64-sysroot'
+SYSROOT_DIR_I386 = 'debian_wheezy_i386-sysroot'
+SYSROOT_DIR_ARM = 'debian_wheezy_arm-sysroot'
+
+valid_archs = ('arm', 'i386', 'amd64')
+
+
+def GetSha1(filename):
+  sha1 = hashlib.sha1()
+  with open(filename, 'rb') as f:
+    while True:
+      # Read in 1mb chunks, so it doesn't all have to be loaded into memory.
+      chunk = f.read(1024*1024)
+      if not chunk:
+        break
+      sha1.update(chunk)
+  return sha1.hexdigest()
+
+
+def DetectArch(gyp_defines):
+  # Check for optional target_arch and only install for that architecture.
+  # If target_arch is not specified, then only install for the host
+  # architecture.
+  if 'target_arch=x64' in gyp_defines:
+    return 'amd64'
+  elif 'target_arch=ia32' in gyp_defines:
+    return 'i386'
+  elif 'target_arch=arm' in gyp_defines:
+    return 'arm'
+
+  detected_host_arch = get_host_arch()
+  if detected_host_arch == 'x64':
+    return 'amd64'
+  elif detected_host_arch == 'ia32':
+    return 'i386'
+  elif detected_host_arch == 'arm':
+    return 'arm'
+  else:
+    print "Unknown host arch: %s" % detected_host_arch
+
+  return None
+
+
+def main():
+  if options.linux_only:
+    # This argument is passed when run from the gclient hooks.
+    # In this case we return early on non-linux platforms.
+    if not sys.platform.startswith('linux'):
+      return 0
+
+  gyp_defines = os.environ.get('GYP_DEFINES', '')
+
+  if options.arch:
+    target_arch = options.arch
+  else:
+    target_arch = DetectArch(gyp_defines)
+    if not target_arch:
+      print 'Unable to detect host architecture'
+      return 1
+
+  if options.linux_only and target_arch != 'arm':
+    # When run from runhooks, only install the sysroot for an Official Chrome
+    # Linux build, except on ARM where we always use a sysroot.
+    defined = ['branding=Chrome', 'buildtype=Official']
+    undefined = ['chromeos=1']
+    for option in defined:
+      if option not in gyp_defines:
+        return 0
+    for option in undefined:
+      if option in gyp_defines:
+        return 0
+
+  # The sysroot directory should match the one specified in build/common.gypi.
+  # TODO(thestig) Consider putting this else where to avoid having to recreate
+  # it on every build.
+  linux_dir = os.path.join(SCRIPT_DIR, '..', 'vendor')
+  if target_arch == 'amd64':
+    sysroot = os.path.join(linux_dir, SYSROOT_DIR_AMD64)
+    tarball_filename = TARBALL_AMD64
+    tarball_sha1sum = TARBALL_AMD64_SHA1SUM
+    revision = REVISION_AMD64
+  elif target_arch == 'arm':
+    sysroot = os.path.join(linux_dir, SYSROOT_DIR_ARM)
+    tarball_filename = TARBALL_ARM
+    tarball_sha1sum = TARBALL_ARM_SHA1SUM
+    revision = REVISION_ARM
+  elif target_arch == 'i386':
+    sysroot = os.path.join(linux_dir, SYSROOT_DIR_I386)
+    tarball_filename = TARBALL_I386
+    tarball_sha1sum = TARBALL_I386_SHA1SUM
+    revision = REVISION_I386
+  else:
+    print 'Unknown architecture: %s' % target_arch
+    assert(False)
+
+  url = '%s/%s/%s/%s' % (URL_PREFIX, URL_PATH, revision, tarball_filename)
+
+  stamp = os.path.join(sysroot, '.stamp')
+  if os.path.exists(stamp):
+    with open(stamp) as s:
+      if s.read() == url:
+        print 'Debian Wheezy %s root image already up-to-date: %s' % \
+            (target_arch, sysroot)
+        return 0
+
+  print 'Installing Debian Wheezy %s root image: %s' % (target_arch, sysroot)
+  if os.path.isdir(sysroot):
+    shutil.rmtree(sysroot)
+  os.mkdir(sysroot)
+  tarball = os.path.join(sysroot, tarball_filename)
+  print 'Downloading %s' % url
+  sys.stdout.flush()
+  sys.stderr.flush()
+  subprocess.check_call(['curl', '--fail', '-L', url, '-o', tarball])
+  sha1sum = GetSha1(tarball)
+  if sha1sum != tarball_sha1sum:
+    print 'Tarball sha1sum is wrong.'
+    print 'Expected %s, actual: %s' % (tarball_sha1sum, sha1sum)
+    return 1
+  subprocess.check_call(['tar', 'xf', tarball, '-C', sysroot])
+  os.remove(tarball)
+
+  with open(stamp, 'w') as s:
+    s.write(url)
+  return 0
+
+
+if __name__ == '__main__':
+  parser = optparse.OptionParser('usage: %prog [OPTIONS]')
+  parser.add_option('--linux-only', action='store_true',
+                    default=False, help='Only install sysroot for official '
+                                        'Linux builds')
+  parser.add_option('--arch', type='choice', choices=valid_archs,
+                    help='Sysroot architecture: %s' % ', '.join(valid_archs))
+  options, _ = parser.parse_args()
+  sys.exit(main())

+ 1 - 1
script/lib/config.py

@@ -7,7 +7,7 @@ import sys
 
 
 BASE_URL = 'http://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent'
-LIBCHROMIUMCONTENT_COMMIT = '3bfdfa28d2361c2242b89603b98f2509d3ebb859'
+LIBCHROMIUMCONTENT_COMMIT = 'a4410de75315f3ecc00db2314bfab184dcd914f8'
 
 PLATFORM = {
   'cygwin': 'win32',

+ 25 - 0
script/lib/util.py

@@ -3,6 +3,8 @@
 import atexit
 import contextlib
 import errno
+import platform
+import re
 import shutil
 import ssl
 import subprocess
@@ -15,6 +17,29 @@ import zipfile
 
 from config import is_verbose_mode
 
+
+def get_host_arch():
+  """Returns the host architecture with a predictable string."""
+  host_arch = platform.machine()
+
+  # Convert machine type to format recognized by gyp.
+  if re.match(r'i.86', host_arch) or host_arch == 'i86pc':
+    host_arch = 'ia32'
+  elif host_arch in ['x86_64', 'amd64']:
+    host_arch = 'x64'
+  elif host_arch.startswith('arm'):
+    host_arch = 'arm'
+
+  # platform.machine is based on running kernel. It's possible to use 64-bit
+  # kernel with 32-bit userland, e.g. to give linker slightly more memory.
+  # Distinguish between different userland bitness by querying
+  # the python binary.
+  if host_arch == 'x64' and platform.architecture()[0] == '32bit':
+    host_arch = 'ia32'
+
+  return host_arch
+
+
 def tempdir(prefix=''):
   directory = tempfile.mkdtemp(prefix=prefix)
   atexit.register(shutil.rmtree, directory)

+ 11 - 10
script/update.py

@@ -5,7 +5,8 @@ import platform
 import subprocess
 import sys
 
-from lib.config import get_target_arch
+from lib.config import get_target_arch, PLATFORM
+from lib.util import get_host_arch
 
 
 SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
@@ -14,6 +15,10 @@ SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
 def main():
   os.chdir(SOURCE_ROOT)
 
+  if platform.architecture()[0] != '64bit':
+    print 'Electron is required to be built on a 64bit machine'
+    return 1
+
   update_external_binaries()
   return update_gyp()
 
@@ -36,6 +41,9 @@ def update_gyp():
 
 
 def run_gyp(target_arch, component):
+  env = os.environ.copy()
+  if PLATFORM == 'linux' and target_arch != get_host_arch():
+    env['GYP_CROSSCOMPILE'] = '1'
   python = sys.executable
   if sys.platform == 'cygwin':
     # Force using win32 python on cygwin.
@@ -44,18 +52,11 @@ def run_gyp(target_arch, component):
   defines = [
     '-Dlibchromiumcontent_component={0}'.format(component),
     '-Dtarget_arch={0}'.format(target_arch),
-    '-Dhost_arch=x64',
+    '-Dhost_arch={0}'.format(get_host_arch()),
     '-Dlibrary=static_library',
   ]
   return subprocess.call([python, gyp, '-f', 'ninja', '--depth', '.',
-                          'atom.gyp', '-Icommon.gypi'] + defines)
-
-
-def get_host_arch():
-  if platform.architecture()[0] == '32bit':
-    return 'ia32'
-  else:
-    return 'x64'
+                          'atom.gyp', '-Icommon.gypi'] + defines, env=env)
 
 
 if __name__ == '__main__':

+ 4 - 6
script/upload.py

@@ -15,7 +15,6 @@ from lib.github import GitHub
 
 ATOM_SHELL_REPO = 'atom/electron'
 ATOM_SHELL_VERSION = get_atom_shell_version()
-CHROMEDRIVER_VERSION = get_chromedriver_version()
 
 PROJECT_NAME = atom_gyp()['project_name%']
 PRODUCT_NAME = atom_gyp()['product_name%']
@@ -31,9 +30,6 @@ SYMBOLS_NAME = '{0}-{1}-{2}-{3}-symbols.zip'.format(PROJECT_NAME,
                                                     ATOM_SHELL_VERSION,
                                                     PLATFORM,
                                                     get_target_arch())
-CHROMEDRIVER_NAME = 'chromedriver-{0}-{1}-{2}.zip'.format(CHROMEDRIVER_VERSION,
-                                                          PLATFORM,
-                                                          get_target_arch())
 MKSNAPSHOT_NAME = 'mksnapshot-{0}-{1}-{2}.zip'.format(ATOM_SHELL_VERSION,
                                                       PLATFORM,
                                                       get_target_arch())
@@ -78,9 +74,11 @@ def main():
   upload_atom_shell(github, release_id, os.path.join(DIST_DIR, SYMBOLS_NAME))
 
   # Upload chromedriver and mksnapshot for minor version update.
-  if parse_version(args.version)[2] == '0':
+  if get_target_arch() != 'arm' and parse_version(args.version)[2] == '0':
+    chromedriver = 'chromedriver-{0}-{1}-{2}.zip'.format(
+        get_chromedriver_version(), PLATFORM, get_target_arch())
     upload_atom_shell(github, release_id,
-                      os.path.join(DIST_DIR, CHROMEDRIVER_NAME))
+                      os.path.join(DIST_DIR, chromedriver))
     upload_atom_shell(github, release_id,
                       os.path.join(DIST_DIR, MKSNAPSHOT_NAME))
 

+ 37 - 5
toolchain.gypi

@@ -1,10 +1,16 @@
 {
   'variables': {
+    # The abosulte version of <(DEPTH).
+    'source_root': '<!(cd <(DEPTH) && pwd -P)',
+
     # Clang stuff.
     'make_clang_dir%': 'vendor/llvm-build/Release+Asserts',
     # Set this to true when building with Clang.
     'clang%': 1,
 
+    # Path to sysroot dir.
+    'sysroot%': '',
+
     'variables': {
       # Set ARM architecture version.
       'arm_version%': 7,
@@ -51,6 +57,7 @@
     ],
   },
   'conditions': [
+    # Setup building with clang.
     ['clang==1', {
       'make_global_settings': [
         ['CC', '<(make_clang_dir)/bin/clang'],
@@ -85,6 +92,36 @@
       },
     }],  # clang==1
 
+    # Setup sysroot environment.
+    ['OS=="linux" and target_arch in ["arm", "ia32"]', {
+      'variables': {
+        'conditions': [
+          ['target_arch=="arm"', {
+            # sysroot needs to be an absolute path otherwise it generates
+            # incorrect results when passed to pkg-config
+            'sysroot': '<(source_root)/vendor/debian_wheezy_arm-sysroot',
+          }],
+          ['target_arch=="ia32"', {
+            'sysroot': '<(source_root)/vendor/debian_wheezy_i386-sysroot',
+          }],
+        ],
+      },
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'cflags': [
+              '--sysroot=<(sysroot)',
+            ],
+            'ldflags': [
+              '--sysroot=<(sysroot)',
+              '<!(<(source_root)/tools/linux/sysroot_ld_path.sh <(sysroot))',
+            ],
+          }]
+        ],
+      },
+    }],  # target_arch==arm
+
+    # Setup cross-compilation on Linux.
     ['OS=="linux"', {
       'target_defaults': {
         'target_conditions': [
@@ -138,11 +175,6 @@
                   }],
                 ],
               }],
-              ['clang==1', {
-                'cflags': [
-                  '-no-integrated-as',
-                ],
-              }],
               ['arm_tune!=""', {
                 'cflags': [
                   '-mtune=<(arm_tune)',

+ 100 - 0
tools/linux/sysroot_ld_path.sh

@@ -0,0 +1,100 @@
+#!/bin/sh
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Reads etc/ld.so.conf and/or etc/ld.so.conf.d/*.conf and returns the
+# appropriate linker flags.
+#
+#  sysroot_ld_path.sh /abspath/to/sysroot
+#
+
+log_error_and_exit() {
+  echo $0: $@
+  exit 1
+}
+
+process_entry() {
+  if [ -z "$1" ] || [ -z "$2" ]; then
+    log_error_and_exit "bad arguments to process_entry()"
+  fi
+  local root="$1"
+  local localpath="$2"
+
+  echo $localpath | grep -qs '^/'
+  if [ $? -ne 0 ]; then
+    log_error_and_exit $localpath does not start with /
+  fi
+  local entry="$root$localpath"
+  echo -L$entry
+  echo -Wl,-rpath-link=$entry
+}
+
+process_ld_so_conf() {
+  if [ -z "$1" ] || [ -z "$2" ]; then
+    log_error_and_exit "bad arguments to process_ld_so_conf()"
+  fi
+  local root="$1"
+  local ld_so_conf="$2"
+
+  # ld.so.conf may include relative include paths. pushd is a bashism.
+  local saved_pwd=$(pwd)
+  cd $(dirname "$ld_so_conf")
+
+  cat "$ld_so_conf" | \
+    while read ENTRY; do
+      echo "$ENTRY" | grep -qs ^include
+      if [ $? -eq 0 ]; then
+        local included_files=$(echo "$ENTRY" | sed 's/^include //')
+        echo "$included_files" | grep -qs ^/
+        if [ $? -eq 0 ]; then
+          if ls $root$included_files >/dev/null 2>&1 ; then
+            for inc_file in $root$included_files; do
+              process_ld_so_conf "$root" "$inc_file"
+            done
+          fi
+        else
+          if ls $(pwd)/$included_files >/dev/null 2>&1 ; then
+            for inc_file in $(pwd)/$included_files; do
+              process_ld_so_conf "$root" "$inc_file"
+            done
+          fi
+        fi
+        continue
+      fi
+
+      echo "$ENTRY" | grep -qs ^/
+      if [ $? -eq 0 ]; then
+        process_entry "$root" "$ENTRY"
+      fi
+    done
+
+  # popd is a bashism
+  cd "$saved_pwd"
+}
+
+# Main
+
+if [ $# -ne 1 ]; then
+  echo Usage $0 /abspath/to/sysroot
+  exit 1
+fi
+
+echo $1 | grep -qs ' '
+if [ $? -eq 0 ]; then
+  log_error_and_exit $1 contains whitespace.
+fi
+
+LD_SO_CONF="$1/etc/ld.so.conf"
+LD_SO_CONF_D="$1/etc/ld.so.conf.d"
+
+if [ -e "$LD_SO_CONF" ]; then
+  process_ld_so_conf "$1" "$LD_SO_CONF" | xargs echo
+elif [ -e "$LD_SO_CONF_D" ]; then
+  find "$LD_SO_CONF_D" -maxdepth 1 -name '*.conf' -print -quit > /dev/null
+  if [ $? -eq 0 ]; then
+    for entry in $LD_SO_CONF_D/*.conf; do
+      process_ld_so_conf "$1" "$entry"
+    done | xargs echo
+  fi
+fi

+ 1 - 1
vendor/breakpad

@@ -1 +1 @@
-Subproject commit 4427c1170387afe46eb3fad259436f1f9f5efa86
+Subproject commit 4ee7e1a703d066861b7bf6fce28526f8ed07dcd6