Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(919)

Side by Side Diff: docs/component_build.md

Issue 2205573006: Correct formatting of component build documentation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # The Chrome Component Build 1 # The Chrome Component Build
2 2
3 ## Introduction 3 ## Introduction
4 4
5 Release builds are “static” builds which compile to one executable and 5 Release builds are “static” builds which compile to one executable and
6 zero-to-two shared libraries (depending on the platform). This is efficient at 6 zero-to-two shared libraries (depending on the platform). This is efficient at
7 runtime, but can take a long time to link because so much code goes into a 7 runtime, but can take a long time to link because so much code goes into a
8 single binary. When you set the GN build variable 8 single binary. When you set the GN build variable
9 9
10 ```python 10 ```python
11 is_component_build = true 11 is_component_build = true
12 ``` 12 ```
13 13
14 the build will generate many smaller shared libraries. This speeds up link 14 the build will generate many smaller shared libraries. This speeds up link
15 times, and means that many changes only require that the local shared library 15 times, and means that many changes only require that the local shared library
16 be linked rather than the full executable, but at the expense of program 16 be linked rather than the full executable, but at the expense of program
17 load-time performance. 17 load-time performance.
18 18
19 ### How to make a component 19 ### How to make a component
20 20
21 Defining a component just means using the GN “component” template instead 21 Defining a component just means using the GN “component” template instead
22 of a shared library, static library, or source set. The template will 22 of a shared library, static library, or source set. The template will
23 generate a shared library when `is_component_build` is enabled, and a static 23 generate a shared library when `is_component_build` is enabled, and a static
24 library otherwise. 24 library otherwise.
25 25
26 ```python 26 ```python
27 component("browser") { 27 component("browser") {
28 output_name = "chrome_browser" 28 output_name = "chrome_browser"
29 sources = ... 29 sources = ...
30 ... 30 ...
31 } 31 }
32 ``` 32 ```
33 33
34 Shared libraries in GN must have globally unique output names. According to GN 34 Shared libraries in GN must have globally unique output names. According to GN
35 style, your target should be named something simple and convenient (often 35 style, your target should be named something simple and convenient (often
36 matching your directory name). If this is non-unique, override it with the 36 matching your directory name). If this is non-unique, override it with the
37 output_name variable. 37 `output_name` variable.
38 38
39 ### Dependencies between targets 39 ### Dependencies between targets
40 40
41 When a component directly or indirectly depends on a static library or source 41 When a component directly or indirectly depends on a static library or source
42 set, it will be linked into this component. If other components do the same, 42 set, it will be linked into this component. If other components do the same,
43 the static library or source set’s code will be duplicated. 43 the static library or source set’s code will be duplicated.
44 44
45 In a few cases (for defining some constants) this duplication is OK, but in 45 In a few cases (for defining some constants) this duplication is OK, but in
46 general this is a bad idea. Globals and singletons will get duplicated which 46 general this is a bad idea. Globals and singletons will get duplicated which
47 will wreak havoc. Therefore, you should normally ensure that components only 47 will wreak havoc. Therefore, you should normally ensure that components only
(...skipping 12 matching lines...) Expand all
60 60
61 When a shared library or executable uses a symbol from a shared library, it is 61 When a shared library or executable uses a symbol from a shared library, it is
62 “imported” by the user of the symbol, and “exported” from the shared library 62 “imported” by the user of the symbol, and “exported” from the shared library
63 that defines the symbol. Don’t confuse exported symbols with the public API of 63 that defines the symbol. Don’t confuse exported symbols with the public API of
64 a component. For example, unit tests will often require implementation details 64 a component. For example, unit tests will often require implementation details
65 to be exported. Export symbols to make the build link the way you need it, and 65 to be exported. Export symbols to make the build link the way you need it, and
66 use GN’s public headers and visibility restrictions to define your public API. 66 use GN’s public headers and visibility restrictions to define your public API.
67 67
68 ### Chrome’s pattern for exports 68 ### Chrome’s pattern for exports
69 69
70 Write a header with the name <component_name>_export.h. Copy an [existing 70 Write a header with the name `<component_name>_export.h`. Copy an [existing
71 one](https://cs.chromium.org/chromium/src/ipc/ipc_export.h) 71 one](https://cs.chromium.org/chromium/src/ipc/ipc_export.h)
72 and update the macro names. It will key off of two macros: 72 and update the macro names. It will key off of two macros:
73 73
74 * `COMPONENT_BUILD`: A globally defined preprocessor definition set when the 74 * `COMPONENT_BUILD`: A globally defined preprocessor definition set when the
75 component build is on. 75 component build is on.
76 * `<component_name>_IMPLEMENTATION`: A macro you define for code inside your 76 * `<component_name>_IMPLEMENTATION`: A macro you define for code inside your
77 component, and leave undefined for code outside of your component. The 77 component, and leave undefined for code outside of your component. The
78 naming should match your `*_export.h` header. 78 naming should match your `*_export.h` header.
79 79
80 It will define a macro `<component_name>_EXPORT`. This will use the 80 It will define a macro `<component_name>_EXPORT`. This will use the
81 `*_IMPLEMENTATION` macro to know whether code is being compiled inside or outsid e 81 `*_IMPLEMENTATION` macro to know whether code is being compiled inside or outsid e
82 of your component, and the `*_EXPORT` macro will set it to being exported or 82 of your component, and the `*_EXPORT` macro will set it to being exported or
83 imported, respectively. You should copy an existing file and update the 83 imported, respectively. You should copy an existing file and update the
84 `*_EXPORT` macro naming for your component. 84 `*_EXPORT` macro naming for your component.
85 85
86 When defining the target for your component, set: 86 When defining the target for your component, set:
87 87
88 ```python 88 ```python
89 defines = [ "FOO_IMPLEMENTATION" ] 89 defines = [ "FOO_IMPLEMENTATION" ]
90 ``` 90 ```
91 91
92 In your BUILD.gn file. If you have source sets that also make up your 92 In your BUILD.gn file. If you have source sets that also make up your
93 component, set this on them also. A good way to share this is to put the 93 component, set this on them also. A good way to share this is to put the
94 definition in a GN config: 94 definition in a GN config:
95 95
96 ```python 96 ```python
97 config("foo_implementation") { 97 config("foo_implementation") {
98 defines = [ "FOO_IMPLEMENTATION" ] 98 defines = [ "FOO_IMPLEMENTATION" ]
99 } 99 }
100 ``` 100 ```
101 101
102 and set the config on the targets that use it: 102 and set the config on the targets that use it:
103 103
104 ```python 104 ```python
105 configs += [ ":foo_implementation" ] 105 configs += [ ":foo_implementation" ]
106 ``` 106 ```
107 107
108 The component build is only reason to use the `*_IMPLEMENTATION` macros. If 108 The component build is only reason to use the `*_IMPLEMENTATION` macros. If
109 your code is not being compiled into a component, don’t define such a macro 109 your code is not being compiled into a component, don’t define such a macro
110 (sometimes people do this by copying other targets without understanding). 110 (sometimes people do this by copying other targets without understanding).
111 111
112 ### Marking symbols for export 112 ### Marking symbols for export
113 113
114 Use the `*_EXPORT` macros on function and class declarations (don’t annotate 114 Use the `*_EXPORT` macros on function and class declarations (don’t annotate
115 the implementations) as follows: 115 the implementations) as follows:
116 116
117 ```c++ 117 ```c++
118 #include "yourcomponent/yourcomponent_export.h" 118 #include "yourcomponent/yourcomponent_export.h"
119 119
120 class YOURCOMPONENT_EXPORT YourClass { ... }; 120 class YOURCOMPONENT_EXPORT YourClass { ... };
121 121
122 YOURCOMPONENT_EXPORT void SomeFunction(); 122 YOURCOMPONENT_EXPORT void SomeFunction();
123 ``` 123 ```
124 124
125 Sometimes you have an internal helper class used as the base for an exported 125 Sometimes you have an internal helper class used as the base for an exported
126 class. Visual C++ will complain if the base class is not exported: 126 class. Visual C++ will complain if the base class is not exported:
127 127
128 warning C4275: non dll-interface class 'YourClass' used as base for dll-inte rface class 'Base' 128 warning C4275: non dll-interface class 'YourClass' used as base for dll-inte rface class 'Base'
129 129
130 If you don’t use the base class outside of the component, Chrome supplies the NO N_EXPORTED_BASE macro in base/compiler_specific.h to disable the warning. For ex ample: 130 If you don’t use the base class outside of the component, Chrome supplies the
131 `NON_EXPORTED_BASE` macro in `base/compiler_specific.h` to disable the warning.
132 For example:
131 133
132 ```c++ 134 ```c++
133 class YourClass : public NON_EXPORTED_BASE(Base) { ... }; 135 class YourClass : public NON_EXPORTED_BASE(Base) { ... };
134 ``` 136 ```
135 137
136 ## Creating components from multiple targets 138 ## Creating components from multiple targets
137 139
138 ### Static library symbol export issues 140 ### Static library symbol export issues
139 141
140 Components can be made up of static libraries and GN source sets. A source set 142 Components can be made up of static libraries and GN source sets. A source set
141 results in all object files from that compilation being linked into the 143 results in all object files from that compilation being linked into the
142 component. But when code is in a static library, only those object files needed 144 component. But when code is in a static library, only those object files needed
143 to define undefined symbols will be pulled in to the link. If an object file is 145 to define undefined symbols will be pulled in to the link. If an object file is
144 not needed to link the component itself, it won’t be pulled into the link, even 146 not needed to link the component itself, it won’t be pulled into the link, even
(...skipping 22 matching lines...) Expand all
167 169
168 In the static build the structure will be: `//external/thing` ➜ `//foo:browser` 170 In the static build the structure will be: `//external/thing` ➜ `//foo:browser`
169 ➜ `//foo:browser_impl` 171 ➜ `//foo:browser_impl`
170 172
171 In the component build the structure will be: `//external/thing` ➜ 173 In the component build the structure will be: `//external/thing` ➜
172 `//foo:browser` ➜ `//foo:mycomponent` ➜ `//foo:browser_impl` 174 `//foo:browser` ➜ `//foo:mycomponent` ➜ `//foo:browser_impl`
173 175
174 Set GN visibility so that the targets with the code can only be depended on by 176 Set GN visibility so that the targets with the code can only be depended on by
175 targets inside your component. 177 targets inside your component.
176 178
177 ```python 179 ```python
178 if (is_component_build) { 180 if (is_component_build) {
179 component("mycomponent") { 181 component("mycomponent") {
180 public_deps = [ ":browser_impl", ":renderer_impl" ] 182 public_deps = [ ":browser_impl", ":renderer_impl" ]
181 } 183 }
182 } 184 }
183 185
184 # External targets always depend on this or the equivalent “renderer” target . 186 # External targets always depend on this or the equivalent “renderer” target.
185 group("browser") { 187 group("browser") {
186 if (is_component_build) { 188 if (is_component_build) {
187 public_deps = [ ":mycomponent" ] 189 public_deps = [ ":mycomponent" ]
188 } else { 190 } else {
189 public_deps = [ ":browser_impl" ] 191 public_deps = [ ":browser_impl" ]
190 } 192 }
191 } 193 }
192 194
193 source_set("browser_impl") { 195 source_set("browser_impl") {
194 visibility = [ ":*" ] # Prevent accidental dependencies. 196 visibility = [ ":*" ] # Prevent accidental dependencies.
195 defines = [ "MYCOMPONENT_IMPLEMENTATION" ] 197 defines = [ "MYCOMPONENT_IMPLEMENTATION" ]
196 sources = [ ... ] 198 sources = [ ... ]
197 } 199 }
198 ``` 200 ```
199 201
200 ## Common mistakes 202 ## Common mistakes
201 203
202 ### Forgetting to mark a symbol with `*_EXPORT` 204 ### Forgetting to mark a symbol with `*_EXPORT`
203 205
204 If a function is not marked with your `*_EXPORT` annotation, other components 206 If a function is not marked with your `*_EXPORT` annotation, other components
205 won’t see the symbol when linking and you’ll get undefined symbols during 207 won’t see the symbol when linking and you’ll get undefined symbols during
206 linking: 208 linking:
207 209
208 some_file.obj : error LNK2001: unresolved external symbol <some definition> 210 some_file.obj : error LNK2001: unresolved external symbol <some definition>
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 cases above where `_IMPLEMENTATION` is inappropriately defined or inappropriatel y 242 cases above where `_IMPLEMENTATION` is inappropriately defined or inappropriatel y
241 undefined. Use GN visibility to make sure callers don’t screw up. 243 undefined. Use GN visibility to make sure callers don’t screw up.
242 244
243 ### Putting exported symbols in static libraries 245 ### Putting exported symbols in static libraries
244 246
245 As discussed above, exported symbols should not be in static libraries because 247 As discussed above, exported symbols should not be in static libraries because
246 the object file might not be brought into the link. Even if it is brought in 248 the object file might not be brought into the link. Even if it is brought in
247 today, it might not be brought in due to completely unrelated changes in the 249 today, it might not be brought in due to completely unrelated changes in the
248 future. The result will be undefined symbol errors from other components. Use 250 future. The result will be undefined symbol errors from other components. Use
249 source sets if your component is made up of more than one target. 251 source sets if your component is made up of more than one target.
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698