diff --git a/docs/android_build_instructions.md b/docs/android_build_instructions.md index 8340291cd6337a..5dd04a9f057401 100644 --- a/docs/android_build_instructions.md +++ b/docs/android_build_instructions.md @@ -52,56 +52,16 @@ gclient sync --nohooks -r This is not needed for a typical developer workflow; only for one-time builds of Chromium. -## Configure your build +## Configure GN -Android builds can be run with GN or GYP, though GN incremental builds -are the fastest option and GN will soon be the only supported option. -They are both meta-build systems that generate nina files for the -Android build. Both builds are regularly tested on the build waterfall. - -### Configure GYP (deprecated -- use GN instead) - -If you are using GYP, next to the .gclient file, create a a file called -'chromium.gyp_env' with the following contents: - -```shell -echo "{ 'GYP_DEFINES': 'OS=android target_arch=arm', }" > chromium.gyp_env -``` - -Note that "arm" is the default architecture and can be omitted. If -building for x86 or MIPS devices, change `target_arch` to "ia32" or -"mipsel". - - **NOTE:** If you are using the `GYP_DEFINES` environment variable, it -will override any settings in this file. Either clear it or set it to -the values above before running `gclient runhooks`. - - See -[build/android/developer\_recommended\_flags.gypi](https://code.google.com/p/chromium/codesearch#chromium/src/build/android/developer_recommended_flags.gypi&sq=package:chromium&type=cs&q=file:android/developer_recommended_flags.gypi&l=1) -for other recommended GYP settings. - Once chromium.gyp_env is ready, you need to run the following command -to update projects from gyp files. You may need to run this again when -you have added new files, updated gyp files, or sync'ed your -repository. - -```shell -gclient runhooks -``` - -#### This will download more things and prompt you to accept Terms of Service for Android SDK packages. - -## Configure GN (recommended) - -If you are using GN, create a build directory and set the build flags -with: +Create a build directory and set the build flags with: ```shell gn args out/Default ``` You can replace out/Default with another name you choose inside the out -directory. Do not use GYP's out/Debug or out/Release directories, as -they may conflict with GYP builds. +directory. Also be aware that some scripts (e.g. tombstones.py, adb_gdb.py) require you to set `CHROMIUM_OUTPUT_DIR=out/Default`. @@ -191,9 +151,6 @@ unplugging and reattaching your device. ### Build the full browser -**Note: When adding new resource files or java files in gyp builds, you -need to run 'gclient runhooks' again to get them in the build.** - ```shell ninja -C out/Release chrome_public_apk ``` @@ -201,7 +158,6 @@ ninja -C out/Release chrome_public_apk And deploy it to your Android device: ```shell -build/android/adb_install_apk.py out/Release/apks/ChromePublic.apk # For gyp. CHROMIUM_OUTPUT_DIR=$gndir build/android/adb_install_apk.py $gndir/apks/ChromePublic.apk # for gn. ``` @@ -219,9 +175,8 @@ build/android/adb_install_apk.py out/Release/apks/ContentShell.apk ``` this will build and install an Android apk under -`out/Release/apks/ContentShell.apk`. For GYP, replace `Release` with `Debug` -above if you want to generate a Debug app. If you are using GN, substitute the -name you initially gave to your build directory. +`out/Release/apks/ContentShell.apk`. (Where `Release` is the name of your build +directory.) If you use custom out dir instead of standard out/ dir, use CHROMIUM_OUT_DIR env. diff --git a/docs/clang.md b/docs/clang.md index 7f9da04d69df90..d9c818a94dea32 100644 --- a/docs/clang.md +++ b/docs/clang.md @@ -24,9 +24,7 @@ by `gclient runhooks`. Regenerate the ninja build files with Clang enabled. Again, on Linux and Mac, Clang is the default compiler. -If you use gyp: `GYP_DEFINES=clang=1 build/gyp_chromium` - -If you use gn, run `gn args` and add `is_clang = true` to your args.gn file. +Run `gn args` and add `is_clang = true` to your args.gn file. Build: `ninja -C out/Debug chrome` @@ -59,8 +57,10 @@ To test the FindBadConstructs plugin, run: ./test.py ../../../../third_party/llvm-build/Release+Asserts/bin/clang \ ../../../../third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so) -To run [other plugins](writing_clang_plugins.md), add these to your -`GYP_DEFINES` (this is not currently set up in GN): +These instructions are for GYP which no longer works. Something similar needs +to be set up for the GN build if you want to do this. For reference, here are +the old instructions: To run [other plugins](writing_clang_plugins.md), add +these to your `GYP_DEFINES`: * `clang_load`: Absolute path to a dynamic library containing your plugin * `clang_add_plugin`: tells clang to run a specific PluginASTAction @@ -85,10 +85,7 @@ http://build.chromium.org/p/chromium.fyi/console?category=win%20clang ``` shell python tools\clang\scripts\update.py -set GYP_DEFINES=clang=1 -python build\gyp_chromium - -# or, if you use gn, run `gn args` and add `is_clang = true` to your args.gn +# run `gn args` and add `is_clang = true` to your args.gn, then... ninja -C out\Debug chrome ``` @@ -103,6 +100,10 @@ Current brokenness: ## Using a custom clang binary +These instructions are for GYP which no longer works. Something similar needs +to be set up for the GN build if you want to do this. For reference, here are +the old instructions: + If you want to try building Chromium with your own clang binary that you've already built, set `make_clang_dir` to the directory containing `bin/clang` (i.e. the directory you ran cmake in, or your `Release+Asserts` folder if you @@ -138,6 +139,5 @@ Linux support, where it can link Chrome approximately twice as fast as gold and MSVC's link.exe as of this writing. LLD does not yet support generating PDB files, which makes it hard to debug Chrome while using LLD. -If you use gyp, you can enable it with `GYP_DEFINES=lld=1`. If you use gn, set -`use_lld = true` in args.gn. Currently this configuration is only supported on -Windows. +Set `use_lld = true` in args.gn. Currently this configuration is only supported +on Windows. diff --git a/docs/component_build.md b/docs/component_build.md new file mode 100644 index 00000000000000..f5468153d32457 --- /dev/null +++ b/docs/component_build.md @@ -0,0 +1,249 @@ +# The Chrome Component Build + +## Introduction + +Release builds are “static” builds which compile to one executable and +zero-to-two shared libraries (depending on the platform). This is efficient at +runtime, but can take a long time to link because so much code goes into a +single binary. When you set the GN build variable + + ```python + is_component_build = true + ``` + +the build will generate many smaller shared libraries. This speeds up link +times, and means that many changes only require that the local shared library +be linked rather than the full executable, but at the expense of program +load-time performance. + +### How to make a component + +Defining a component just means using the GN “component” template instead +of a shared library, static library, or source set. The template will +generate a shared library when `is_component_build` is enabled, and a static +library otherwise. + + ```python + component("browser") { + output_name = "chrome_browser" + sources = ... + ... + } + ``` + +Shared libraries in GN must have globally unique output names. According to GN +style, your target should be named something simple and convenient (often +matching your directory name). If this is non-unique, override it with the +output_name variable. + +### Dependencies between targets + +When a component directly or indirectly depends on a static library or source +set, it will be linked into this component. If other components do the same, +the static library or source set’s code will be duplicated. + +In a few cases (for defining some constants) this duplication is OK, but in +general this is a bad idea. Globals and singletons will get duplicated which +will wreak havoc. Therefore, you should normally ensure that components only +depend on other components. + +### Component granularity + +Creating lots of small components isn’t desirable. Some code can easily get +duplicated, it takes extra time to create the shared libraries themselves, load +time will get worse, and the build and code can get complicated. On the other +extreme, very large components negate the benefits of the component build. A +good rule of thumb is that components should be medium sized, somewhere in the +range of several dozen to several hundred files. + +## Exporting and importing symbols + +When a shared library or executable uses a symbol from a shared library, it is +“imported” by the user of the symbol, and “exported” from the shared library +that defines the symbol. Don’t confuse exported symbols with the public API of +a component. For example, unit tests will often require implementation details +to be exported. Export symbols to make the build link the way you need it, and +use GN’s public headers and visibility restrictions to define your public API. + +### Chrome’s pattern for exports + +Write a header with the name _export.h. Copy an [existing +one](https://cs.chromium.org/chromium/src/ipc/ipc_export.h) +and update the macro names. It will key off of two macros: + + * `COMPONENT_BUILD`: A globally defined preprocessor definition set when the + component build is on. + * `_IMPLEMENTATION`: A macro you define for code inside your + component, and leave undefined for code outside of your component. The + naming should match your `*_export.h` header. + +It will define a macro `_EXPORT`. This will use the +`*_IMPLEMENTATION` macro to know whether code is being compiled inside or outside +of your component, and the `*_EXPORT` macro will set it to being exported or +imported, respectively. You should copy an existing file and update the +`*_EXPORT` macro naming for your component. + +When defining the target for your component, set: + + ```python + defines = [ "FOO_IMPLEMENTATION" ] + ``` + +In your BUILD.gn file. If you have source sets that also make up your +component, set this on them also. A good way to share this is to put the +definition in a GN config: + + ```python + config("foo_implementation") { + defines = [ "FOO_IMPLEMENTATION" ] + } + ``` + +and set the config on the targets that use it: + + ```python + configs += [ ":foo_implementation" ] + ``` + +The component build is only reason to use the `*_IMPLEMENTATION` macros. If +your code is not being compiled into a component, don’t define such a macro +(sometimes people do this by copying other targets without understanding). + +### Marking symbols for export + +Use the `*_EXPORT` macros on function and class declarations (don’t annotate +the implementations) as follows: + + ```c++ + #include "yourcomponent/yourcomponent_export.h" + + class YOURCOMPONENT_EXPORT YourClass { ... }; + + YOURCOMPONENT_EXPORT void SomeFunction(); + ``` + +Sometimes you have an internal helper class used as the base for an exported +class. Visual C++ will complain if the base class is not exported: + + warning C4275: non dll-interface class 'YourClass' used as base for dll-interface class 'Base' + +If you don’t use the base class outside of the component, Chrome supplies the NON_EXPORTED_BASE macro in base/compiler_specific.h to disable the warning. For example: + + ```c++ + class YourClass : public NON_EXPORTED_BASE(Base) { ... }; + ``` + +## Creating components from multiple targets + +### Static library symbol export issues + +Components can be made up of static libraries and GN source sets. A source set +results in all object files from that compilation being linked into the +component. But when code is in a static library, only those object files needed +to define undefined symbols will be pulled in to the link. If an object file is +not needed to link the component itself, it won’t be pulled into the link, even +though it might have exported symbols needed by other components. + +Therefore, all code with exported symbols should be either on the component +target itself or in source sets it depends on. + +### Splitting targets differently in static and component builds + +Sometimes you might have something consisting of multiple sub-targets. For +example: a browser, a renderer, and a common directory, each with their own +target. In the static build, they would all be linked into different places. In +the component build, you may want to have these be in a single component for +performance and sanity reasons. Content is such an example. + +The important thing is that the sub-projects not be depended on directly from +outside of the component in the component build. This will duplicate the code +and the import/export of symbols will get confused (see “Common mistakes” +below). + +Generally the way to do this is to create browser and renderer group targets +that forward to the right place. In static builds these would forward to +internal targets with the actual code in them. In component builds, these would +forward to the component. + +In the static build the structure will be: `//external/thing` ➜ `//foo:browser` +➜ `//foo:browser_impl` + +In the component build the structure will be: `//external/thing` ➜ +`//foo:browser` ➜ `//foo:mycomponent` ➜ `//foo:browser_impl` + +Set GN visibility so that the targets with the code can only be depended on by +targets inside your component. + + ```python + if (is_component_build) { + component("mycomponent") { + public_deps = [ ":browser_impl", ":renderer_impl" ] + } + } + + # External targets always depend on this or the equivalent “renderer” target. + group("browser") { + if (is_component_build) { + public_deps = [ ":mycomponent" ] + } else { + public_deps = [ ":browser_impl" ] + } + } + + source_set("browser_impl") { + visibility = [ ":*" ] # Prevent accidental dependencies. + defines = [ "MYCOMPONENT_IMPLEMENTATION" ] + sources = [ ... ] + } + ``` + +## Common mistakes + +### Forgetting to mark a symbol with `*_EXPORT` + +If a function is not marked with your `*_EXPORT` annotation, other components +won’t see the symbol when linking and you’ll get undefined symbols during +linking: + + some_file.obj : error LNK2001: unresolved external symbol + +This will only happen on Windows component builds, which makes the error more +difficult to debug. However, if you see such an error only for Windows +component builds, you know it’s this problem. + +### Not defining `*_IMPLEMENTATION` for code in your component + +When code is compiled that sees a symbol marked with `__declspec(dllimport)`, +it will expect to find that symbol in another shared library. If that symbol +ends up in the same shared library, you’ll see the error: + + some_file.obj : warning LNK4217: locally defined symbol + imported in function + +The solution is to make sure your `*_IMPLEMENTATION` define is set consistently +for all code in the component. If your component links in source sets or static +libraries, the `*_IMPLEMENTATION` macro must be set on those as well. + +### Defining `*_IMPLEMENTATION` for code outside your component + +If your `*_IMPLEMENTATION` macro is set for code compiled outside of the +component, that code will expect the symbol to be in the current shared +library, but it won’t be found. It won’t even go looking in other libraries and +the result will be an undefined symbol: + + some_file.obj : error LNK2001: unresolved external symbol + +### Depending on a source set or static library from both inside and outside a component + +If the source set or static library has any `*_EXPORT` macros and ends up both +inside and outside of the component boundary, those symbols will fall under the +cases above where `_IMPLEMENTATION` is inappropriately defined or inappropriately +undefined. Use GN visibility to make sure callers don’t screw up. + +### Putting exported symbols in static libraries + +As discussed above, exported symbols should not be in static libraries because +the object file might not be brought into the link. Even if it is brought in +today, it might not be brought in due to completely unrelated changes in the +future. The result will be undefined symbol errors from other components. Use +source sets if your component is made up of more than one target. diff --git a/docs/ninja_build.md b/docs/ninja_build.md index 7cca2e2d6d6523..39b9072a710a15 100644 --- a/docs/ninja_build.md +++ b/docs/ninja_build.md @@ -16,8 +16,7 @@ Read more about Ninja at [the Ninja home page](https://ninja-build.org/). #### Install -Ninja is included in `depot_tools` as well as `gyp`, so there's nothing to -install. +Ninja is included in `depot_tools` so there's nothing to install. ## Build instructions