Add component build documentation.
This will replace this page: https://www.chromium.org/developers/how-tos/component-build This patch also removes some out-of-date GYP references from a few other places (but not all of them). Review-Url: https://codereview.chromium.org/2206383002 Cr-Commit-Position: refs/heads/master@{#409607}
This commit is contained in:
@ -52,56 +52,16 @@ gclient sync --nohooks -r <lkgr-sha1>
|
||||
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.
|
||||
|
@ -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.
|
||||
|
249
docs/component_build.md
Normal file
249
docs/component_build.md
Normal file
@ -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 <component_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.
|
||||
* `<component_name>_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 `<component_name>_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 <some definition>
|
||||
|
||||
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
|
||||
<horrendous mangled name> imported in function <some definition>
|
||||
|
||||
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 <some definition>
|
||||
|
||||
### 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.
|
@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user