diff --git a/.gitignore b/.gitignore index faa00c4501..bde008c04b 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ node_modules/ /vendor/node/deps/node-inspect/.npmrc /vendor/npm/ /vendor/python_26/ +.gclient_done diff --git a/docs/development/build-instructions-linux.md b/docs/development/build-instructions-linux.md index e1e65aeca7..7cb484a570 100644 --- a/docs/development/build-instructions-linux.md +++ b/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 `/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. \ No newline at end of file +script, it won't work in the `build.py` script. diff --git a/docs/development/chromium-development.md b/docs/development/chromium-development.md index 23506ae918..6804f3482e 100644 --- a/docs/development/chromium-development.md +++ b/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 diff --git a/script/bootstrap.py b/script/bootstrap.py index 41ee7de5ee..9345bd8ac5 100755 --- a/script/bootstrap.py +++ b/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: diff --git a/script/build-libchromiumcontent.py b/script/build-libchromiumcontent.py index 63d7514de7..409e22262b 100755 --- a/script/build-libchromiumcontent.py +++ b/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() diff --git a/script/build.py b/script/build.py index 1a7378bf97..741340da43 100755 --- a/script/build.py +++ b/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() diff --git a/vendor/libchromiumcontent b/vendor/libchromiumcontent index 92e2d6a965..8915338e8c 160000 --- a/vendor/libchromiumcontent +++ b/vendor/libchromiumcontent @@ -1 +1 @@ -Subproject commit 92e2d6a9657444dfbdcb89f986c8705bdda3dccf +Subproject commit 8915338e8cca8679e884efcd6aa5c046b1de57a4