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.
This commit is contained in:
Thiago de Arruda 2017-08-11 14:17:55 -03:00
parent b81aab9eae
commit d6fbf5f1bb
7 changed files with 144 additions and 25 deletions

1
.gitignore vendored
View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 @@
Subproject commit 92e2d6a9657444dfbdcb89f986c8705bdda3dccf
Subproject commit 8915338e8cca8679e884efcd6aa5c046b1de57a4