Build linux binaries against sid sysroot

Additionally, this requires building against libstdc++ because there's
no libc++ in the sysroot and we aren't currently set up to build libc++
locally. Because this has broken ChromeOS, use libstdc++ for now and
resolve libc++ build later, if necessary.

Unfortunately this doesn't seem to have changed the readelf -d output,
but hopefully it will help CrOS? I'm not sure.

Before:
[(0c5d936b...)] scottmg@around:/work/gn$ readelf -d out/gn

Dynamic section at offset 0x222270 contains 31 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [librt.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libatomic.so.1]

After:
[linux-sysroot] scottmg@around:/work/gn$ readelf -d out/gn

Dynamic section at offset 0x25cc68 contains 31 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [librt.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libatomic.so.1]
 ...

Bug: chromium:855791
Change-Id: I1fd8574cdfa5fd856e0fb27d734d15135a00b99a
Reviewed-on: https://gn-review.googlesource.com/1900
Reviewed-by: Dirk Pranke <dpranke@chromium.org>
Commit-Queue: Scott Graham <scottmg@chromium.org>
diff --git a/.gitignore b/.gitignore
index 4c20aff..455d57f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,6 +39,7 @@
 .gdb_history
 .gdbinit
 .landmines
+.linux-sysroot/
 .metadata
 .project
 .pydevproject
diff --git a/build/gen.py b/build/gen.py
index a0796fb..483d3f0 100755
--- a/build/gen.py
+++ b/build/gen.py
@@ -7,7 +7,6 @@
 
 import contextlib
 import errno
-import logging
 import optparse
 import os
 import platform
@@ -15,6 +14,7 @@
 import subprocess
 import sys
 import tempfile
+import urllib2
 
 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
 REPO_ROOT = os.path.dirname(SCRIPT_DIR)
@@ -30,22 +30,64 @@
   parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
   parser.add_option('-d', '--debug', action='store_true',
                     help='Do a debug build. Defaults to release build.')
-  parser.add_option('-v', '--verbose', action='store_true',
-                    help='Log more details')
   options, args = parser.parse_args(argv)
 
   if args:
     parser.error('Unrecognized command line arguments: %s.' % ', '.join(args))
 
-  logging.basicConfig(level=logging.DEBUG if options.verbose else logging.ERROR)
+  linux_sysroot = UpdateLinuxSysroot() if is_linux else None
 
   out_dir = os.path.join(REPO_ROOT, 'out')
   if not os.path.isdir(out_dir):
     os.makedirs(out_dir)
-  write_gn_ninja(os.path.join(out_dir, 'build.ninja'), options)
+  write_gn_ninja(os.path.join(out_dir, 'build.ninja'), options, linux_sysroot)
   return 0
 
 
+def UpdateLinuxSysroot():
+  # Sysroot revision from:
+  # https://cs.chromium.org/chromium/src/build/linux/sysroot_scripts/sysroots.json
+  server = 'https://commondatastorage.googleapis.com'
+  path = 'chrome-linux-sysroot/toolchain'
+  revision = '1015a998c2adf188813cca60b558b0ea1a0b6ced'
+  filename = 'debian_sid_amd64_sysroot.tar.xz'
+
+  url = '%s/%s/%s/%s' % (server, path, revision, filename)
+
+  sysroot = os.path.join(SCRIPT_DIR, os.pardir, '.linux-sysroot')
+
+  stamp = os.path.join(sysroot, '.stamp')
+  if os.path.exists(stamp):
+    with open(stamp) as s:
+      if s.read() == url:
+        return sysroot
+
+  print 'Installing Debian root image from %s' % url
+
+  if os.path.isdir(sysroot):
+    shutil.rmtree(sysroot)
+  os.mkdir(sysroot)
+  tarball = os.path.join(sysroot, filename)
+  print 'Downloading %s' % url
+
+  for _ in range(3):
+    response = urllib2.urlopen(url)
+    with open(tarball, 'wb') as f:
+      f.write(response.read())
+    break
+  else:
+    raise Exception('Failed to download %s' % url)
+
+  subprocess.check_call(['tar', 'xf', tarball, '-C', sysroot])
+
+  os.remove(tarball)
+
+  with open(stamp, 'w') as s:
+    s.write(url)
+
+  return sysroot
+
+
 def write_generic_ninja(path, static_libraries, executables,
                         cc, cxx, ar, ld, options,
                         cflags=[], cflags_cc=[], ldflags=[], libflags=[],
@@ -149,7 +191,7 @@
             os.path.relpath(template_filename, os.path.dirname(path)) + '\n')
 
 
-def write_gn_ninja(path, options):
+def write_gn_ninja(path, options, linux_sysroot):
   if is_win:
     cc = os.environ.get('CC', 'cl.exe')
     cxx = os.environ.get('CXX', 'cl.exe')
@@ -185,6 +227,18 @@
         '-fno-rtti',
     ])
     cflags_cc.extend(['-std=c++14', '-Wno-c++11-narrowing'])
+
+    if is_linux:
+      # Use the sid sysroot that UpdateLinuxSysroot() downloads. We need to
+      # force the used of libstdc++ for now because libc++ is not in that
+      # sysroot and we don't currently have a local build of that. We should
+      # probably resolve this and (re-)add a way to build against libc++.
+      cflags.extend(['--sysroot=' + linux_sysroot,
+                     '-stdlib=libstdc++'])
+      ldflags.extend(['--sysroot=' + linux_sysroot,
+                      '-rtlib=libgcc',
+                      '-static-libstdc++',
+                      '-stdlib=libstdc++'])
   elif is_win:
     if not options.debug:
       cflags.extend(['/Ox', '/DNDEBUG', '/GL'])