Merge pull request #2094 from atom/arm

Add arm build
This commit is contained in:
Cheng Zhao 2015-07-02 16:04:37 +08:00
commit 5ccc909f2f
18 changed files with 446 additions and 77 deletions

2
.gitignore vendored
View file

@ -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/

View file

@ -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

View file

@ -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': [

View file

@ -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': {

View file

@ -23,13 +23,11 @@ $ sudo apt-get install build-essential clang libdbus-1-dev libgtk2.0-dev \
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.
## Getting the code
```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:
@ -75,20 +82,16 @@ 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.

View file

@ -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': [

View file

@ -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')

View file

@ -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,19 +53,14 @@ 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'])
if target_arch == 'x64':
run_script('test.py', ['--ci'])

View file

@ -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,10 +91,12 @@ def main():
if PLATFORM == 'linux':
strip_binaries()
if target_arch != 'arm':
copy_system_libraries()
create_version()
create_dist_zip()
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():

View file

@ -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
script/install-sysroot.py Executable file
View file

@ -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())

View file

@ -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',

View file

@ -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)

View file

@ -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__':

View file

@ -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))

View file

@ -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
tools/linux/sysroot_ld_path.sh Executable file
View file

@ -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

2
vendor/breakpad vendored

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