Browse Source

Improve development workflow with built libchromiumcontent

- Add `--debug_libchromiumcontent` to build libchromiumcontent for debugging
  (shared library build).
- By default, only invoke `gclient sync` the first time to checkout chromium
  source tree. Add `--force_update_libchromiumcontent` switch to force updating.
- Document new options.

The goal is to allow faster edit/compile cycles when debugging/making changes
to libchromiumcontent.
Thiago de Arruda 7 years ago
parent
commit
d6fbf5f1bb

+ 1 - 0
.gitignore

@@ -41,3 +41,4 @@ node_modules/
 /vendor/node/deps/node-inspect/.npmrc
 /vendor/npm/
 /vendor/python_26/
+.gclient_done

+ 5 - 10
docs/development/build-instructions-linux.md

@@ -156,15 +156,10 @@ To avoid using the prebuilt binaries of `libchromiumcontent`, you can build `lib
   ```bash
   $ git submodule update --init --recursive
   ```
-  4. Copy the .gclient config file
+  4. Pass the `--build_release_libcc` switch to `bootstrap.py` script:
 
   ```bash
-  $ cp vendor/libchromiumcontent/.gclient .
-  ```
-  5. Pass the `--build_libchromiumcontent` switch to `bootstrap.py` script:
-
-  ```bash
-  $ ./script/bootstrap.py -v --build_libchromiumcontent
+  $ ./script/bootstrap.py -v --build_release_libcc
   ```
 
 Note that by default the `shared_library` configuration is not built, so you can
@@ -186,7 +181,7 @@ in `<path>/bin/`.
 For example if you installed `clang` under `/user/local/bin/clang`:
 
 ```bash
-$ ./script/bootstrap.py -v --build_libchromiumcontent --clang_dir /usr/local
+$ ./script/bootstrap.py -v --build_release_libcc --clang_dir /usr/local
 $ ./script/build.py -c R
 ```
 
@@ -199,7 +194,7 @@ variables to the ones you want.
 For example building with GCC toolchain:
 
 ```bash
-$ env CC=gcc CXX=g++ ./script/bootstrap.py -v --build_libchromiumcontent --disable_clang
+$ env CC=gcc CXX=g++ ./script/bootstrap.py -v --build_release_libcc --disable_clang
 $ ./script/build.py -c R
 ```
 
@@ -223,4 +218,4 @@ custom the building configurations:
 * `LDFLAGS`
 
 The environment variables have to be set when executing the `bootstrap.py`
-script, it won't work in the `build.py` script.
+script, it won't work in the `build.py` script.

+ 61 - 0
docs/development/chromium-development.md

@@ -12,3 +12,64 @@
 - [Discussion Groups](http://www.chromium.org/developers/discussion-groups)
 
 See also [V8 Development](v8-development.md)
+
+# Chromium development with Electron
+
+It is possible to debug Chromium with Electron by passing
+`--build_debug_libcc` to the bootstrap script:
+
+    $ ./script/bootstrap.py -d --build_debug_libcc
+
+This will download and build libchromiumcontent locally, similarly to the
+`--build_release_libcc`, but it will create a shared library build of
+libchromiumcontent and won't strip any symbols, making it ideal for debugging.
+
+When built like this, you can make changes to files in
+`vendor/libchromiumcontent/src` and rebuild quickly with:
+
+    $ ./script/build.py -c D --libcc
+
+When developing on linux with gdb, it is recommended to add a gdb index to speed
+up loading symbols. This doesn't need to be executed on every build, but it is
+recommended to do it at least once to index most shared libraries: 
+
+    $ ./vendor/libchromiumcontent/src/build/gdb-add-index ./out/D/electron
+
+Building libchromiumcontent requires a powerful machine and takes a long time
+(though incremental rebuilding the shared library component is fast). With an
+8-core/16-thread Ryzen 1700 CPU clocked at 3ghz, fast SSD and 32GB of RAM, it
+should take about 40 minutes. It is not recommended to build with less than 16GB
+of RAM.
+
+## Chromium git cache
+
+`depot_tools` has an undocumented option that allows the developer to set a
+global cache for all git objects of Chromium + dependencies. This option uses
+`git clone --shared` to save bandwidth/space on multiple clones of the same
+repositories.
+
+On electron/libchromiumcontent, this option is exposed through the
+`LIBCHROMIUMCONTENT_GIT_CACHE` environment variable. If you intend to have
+several libchromiumcontent build trees on the same machine(to work on different
+branches for example), it is recommended to set the variable to speed up the
+download of Chromium source. For example:
+
+    $ mkdir ~/.chromium-git-cache
+    $ LIBCHROMIUMCONTENT_GIT_CACHE=~/.chromium-git-cache ./script/bootstrap.py -d --build_debug_libcc
+
+If the bootstrap script is interrupted while using the git cache, it will leave
+the cache locked. To remove the lock, delete the files ending in `.lock`:
+
+    $ find ~/.chromium-git-cache/ -type f -name '*.lock' -delete
+
+It is possible to share this directory with other machines by exporting it as
+SMB share on linux, but only one process/machine can be using the cache at a
+time. The locks created by git-cache script will try to prevent this, but it may
+not work perfectly in a network.
+
+On Windows, SMBv2 has a directory cache that will cause problems with the git
+cache script, so it is necessary to disable it by setting the registry key
+
+    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Lanmanworkstation\Parameters\DirectoryCacheLifetime
+
+to 0. More information: https://stackoverflow.com/a/9935126

+ 17 - 5
script/bootstrap.py

@@ -38,8 +38,9 @@ def main():
   libcc_static_library_path = args.libcc_static_library_path
 
   # Redirect to use local libchromiumcontent build.
-  if args.build_libchromiumcontent:
-    build_libchromiumcontent(args.verbose, args.target_arch, defines)
+  if args.build_release_libcc or args.build_debug_libcc:
+    build_libchromiumcontent(args.verbose, args.target_arch, defines,
+                             args.build_debug_libcc, args.update_libcc)
     dist_dir = os.path.join(VENDOR_DIR, 'libchromiumcontent', 'dist', 'main')
     libcc_source_path = os.path.join(dist_dir, 'src')
     libcc_shared_library_path = os.path.join(dist_dir, 'shared_library')
@@ -88,8 +89,14 @@ def parse_args():
   parser.add_argument('--clang_dir', default='', help='Path to clang binaries')
   parser.add_argument('--disable_clang', action='store_true',
                       help='Use compilers other than clang for building')
-  parser.add_argument('--build_libchromiumcontent', action='store_true',
-                      help='Build local version of libchromiumcontent')
+  build_libcc = parser.add_mutually_exclusive_group()
+  build_libcc.add_argument('--build_release_libcc', action='store_true',
+                           help='Build release version of libchromiumcontent')
+  build_libcc.add_argument('--build_debug_libcc', action='store_true',
+                           help='Build debug version of libchromiumcontent')
+  parser.add_argument('--update_libcc', default=False,
+                      action='store_true', help=('force gclient invocation to '
+                      'update libchromiumcontent'))
   parser.add_argument('--libcc_source_path', required=False,
                       help='The source path of libchromiumcontent. ' \
                            'NOTE: All options of libchromiumcontent are ' \
@@ -162,9 +169,14 @@ def update_win32_python():
       execute_stdout(['git', 'clone', PYTHON_26_URL])
 
 
-def build_libchromiumcontent(verbose, target_arch, defines):
+def build_libchromiumcontent(verbose, target_arch, defines, debug,
+                             force_update):
   args = [sys.executable,
           os.path.join(SOURCE_ROOT, 'script', 'build-libchromiumcontent.py')]
+  if debug:
+    args += ['-d']
+  if force_update:
+    args += ['--force-update']
   if verbose:
     args += ['-v']
   if defines:

+ 36 - 9
script/build-libchromiumcontent.py

@@ -6,13 +6,29 @@ import sys
 
 from lib.config import enable_verbose_mode, get_target_arch
 from lib.util import execute_stdout
+from bootstrap import get_libchromiumcontent_commit 
 
 
 SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
+LIBCC_DIR = os.path.join(SOURCE_ROOT, 'vendor', 'libchromiumcontent')
+GCLIENT_DONE_MARKER = os.path.join(SOURCE_ROOT, '.gclient_done')
+LIBCC_COMMIT = get_libchromiumcontent_commit()
+
+
+def update_gclient_done_marker():
+  with open(GCLIENT_DONE_MARKER, 'wb') as f:
+    f.write(LIBCC_COMMIT)
+
+
+def libchromiumcontent_outdated():
+  if not os.path.exists(GCLIENT_DONE_MARKER):
+    return True
+  with open(GCLIENT_DONE_MARKER, 'rb') as f:
+    return f.read() != LIBCC_COMMIT
 
 
 def main():
-  os.chdir(SOURCE_ROOT)
+  os.chdir(LIBCC_DIR)
 
   args = parse_args()
   if args.verbose:
@@ -22,18 +38,25 @@ def main():
   # ./script/update -t x64 --defines=''
   # ./script/build --no_shared_library -t x64
   # ./script/create-dist -c static_library -t x64 --no_zip
-  script_dir = os.path.join(SOURCE_ROOT, 'vendor', 'libchromiumcontent',
-                            'script')
+  script_dir = os.path.join(LIBCC_DIR, 'script')
   bootstrap = os.path.join(script_dir, 'bootstrap')
   update = os.path.join(script_dir, 'update')
   build = os.path.join(script_dir, 'build')
   create_dist = os.path.join(script_dir, 'create-dist')
-  execute_stdout([sys.executable, bootstrap])
-  execute_stdout([sys.executable, update, '-t', args.target_arch,
-                  '--defines', args.defines])
-  execute_stdout([sys.executable, build, '-R', '-t', args.target_arch])
-  execute_stdout([sys.executable, create_dist, '-c', 'static_library',
-                  '--no_zip', '-t', args.target_arch])
+  if args.force_update or libchromiumcontent_outdated():
+    execute_stdout([sys.executable, bootstrap])
+    execute_stdout([sys.executable, update, '-t', args.target_arch,
+                    '--defines', args.defines])
+    update_gclient_done_marker()
+  if args.debug:
+    execute_stdout([sys.executable, build, '-D', '-t', args.target_arch])
+    execute_stdout([sys.executable, create_dist, '-c', 'shared_library',
+                    '--no_zip', '--keep-debug-symbols',
+                    '-t', args.target_arch])
+  else:
+    execute_stdout([sys.executable, build, '-R', '-t', args.target_arch])
+    execute_stdout([sys.executable, create_dist, '-c', 'static_library',
+                    '--no_zip', '-t', args.target_arch])
 
 
 def parse_args():
@@ -44,6 +67,10 @@ def parse_args():
                       help='The definetions passed to gyp')
   parser.add_argument('-v', '--verbose', action='store_true',
                       help='Prints the output of the subprocesses')
+  parser.add_argument('-d', '--debug', action='store_true',
+                      help='Build libchromiumcontent for debugging')
+  parser.add_argument('--force-update', default=False, action='store_true',
+                      help='Force gclient to update libchromiumcontent')
   return parser.parse_args()
 
 

+ 23 - 0
script/build.py

@@ -11,6 +11,9 @@ from lib.util import electron_gyp, import_vs_env
 
 CONFIGURATIONS = ['Release', 'Debug']
 SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
+LIBCC_SOURCE_ROOT = os.path.join(SOURCE_ROOT, 'vendor', 'libchromiumcontent')
+LIBCC_DIST_MAIN = os.path.join(LIBCC_SOURCE_ROOT, 'dist', 'main')
+GCLIENT_DONE = os.path.join(SOURCE_ROOT, '.gclient_done')
 
 
 def main():
@@ -24,6 +27,19 @@ def main():
     ninja += '.exe'
 
   args = parse_args()
+  if args.libcc:
+    if ('D' not in args.configuration
+        or not os.path.exists(GCLIENT_DONE)
+        or not os.path.exists(os.path.join(LIBCC_DIST_MAIN, 'build.ninja'))):
+      sys.stderr.write('--libcc should only be used when '
+                       'libchromiumcontent was built with bootstrap.py -d '
+                       '--debug_libchromiumcontent' + os.linesep)
+      sys.exit(1)
+    script = os.path.join(LIBCC_SOURCE_ROOT, 'script', 'build')
+    subprocess.check_call([sys.executable, script, '-D', '-t',
+                           get_target_arch()])
+    subprocess.check_call([ninja, '-C', LIBCC_DIST_MAIN])
+
   for config in args.configuration:
     build_path = os.path.join('out', config[0])
     ret = subprocess.call([ninja, '-C', build_path, args.target])
@@ -42,6 +58,13 @@ def parse_args():
                       help='Build specified target',
                       default=electron_gyp()['project_name%'],
                       required=False)
+  parser.add_argument('--libcc',
+                      help=(
+                        'Build libchromiumcontent first. Should be used only '
+                        'when libchromiumcontent as built with boostrap.py '
+                        '-d --debug_libchromiumcontent.'
+                      ),
+                      action='store_true', default=False)
   return parser.parse_args()
 
 

+ 1 - 1
vendor/libchromiumcontent

@@ -1 +1 @@
-Subproject commit 92e2d6a9657444dfbdcb89f986c8705bdda3dccf
+Subproject commit 8915338e8cca8679e884efcd6aa5c046b1de57a4