1 | /** @page build_sys Build system |
---|
2 | |
---|
3 | @section overview Overview |
---|
4 | |
---|
5 | Building an Etherboot image consists of three stages: |
---|
6 | |
---|
7 | -# @ref compilation : Compiling all the source files into object files |
---|
8 | -# @ref linking : Linking a particular image from selected object files |
---|
9 | -# @ref finalisation : Producing the final output binary |
---|
10 | |
---|
11 | Though this is a remarkably complex process, it is important to note |
---|
12 | that it all happens automatically. Whatever state your build tree is |
---|
13 | in, you can always type, for example |
---|
14 | |
---|
15 | @code |
---|
16 | |
---|
17 | make bin/rtl8139.dsk |
---|
18 | |
---|
19 | @endcode |
---|
20 | |
---|
21 | and know that you will get a floppy disk image with an RTL8139 driver |
---|
22 | built from the current sources. |
---|
23 | |
---|
24 | @section compilation Compilation |
---|
25 | |
---|
26 | @subsection comp_overview Overview |
---|
27 | |
---|
28 | Each source file (a @c .c or a @c .S file) is compiled into a @c .o |
---|
29 | file in the @c bin/ directory. Etherboot makes minimal use of |
---|
30 | conditional compilation (see @ref ifdef_harmful), and so you will find |
---|
31 | that all objects get built, even the objects that correspond to |
---|
32 | features that you are not intending to include in your image. For |
---|
33 | example, all network card drivers will be compiled even if you are |
---|
34 | just building a ROM for a 3c509 card. This is a deliberate design |
---|
35 | decision; please do @b not attempt to "fix" the build system to avoid |
---|
36 | doing this. |
---|
37 | |
---|
38 | Source files are defined to be any @c .c or @c .S files found in a |
---|
39 | directory listed in the Makefile variable #SRCDIRS. You therefore do |
---|
40 | @b not need to edit the Makefile just because you have added a new |
---|
41 | source file (although you will need to edit the Makefile if you have |
---|
42 | added a new source directory). To see a list of all source |
---|
43 | directories and source files that the build system currently knows |
---|
44 | about, you can use the commands |
---|
45 | |
---|
46 | @code |
---|
47 | |
---|
48 | make srcdirs |
---|
49 | make srcs |
---|
50 | |
---|
51 | @endcode |
---|
52 | |
---|
53 | Rules for compiling @c .c and @c .S files are defined in the Makefile |
---|
54 | variables #RULE_c and #RULE_S. Makefile rules are automatically |
---|
55 | generated for each source file using these rules. The generated rules |
---|
56 | can be found in the @c .d file corresponding to each source file; |
---|
57 | these are located in <tt>bin/deps/</tt>. For example, the rules |
---|
58 | generated for <tt>drivers/net/rtl8139.c</tt> can be found in |
---|
59 | <tt>bin/deps/drivers/net/rtl8139.c.d</tt>. These rules allow you to |
---|
60 | type, for example |
---|
61 | |
---|
62 | @code |
---|
63 | |
---|
64 | make bin/rtl8139.o |
---|
65 | |
---|
66 | @endcode |
---|
67 | |
---|
68 | and have <tt>rtl8139.o</tt> be built from |
---|
69 | <tt>drivers/net/rtl8139.c</tt> using the generic rule #RULE_c for |
---|
70 | compiling @c .c files. |
---|
71 | |
---|
72 | You can see the full list of object files that will be built using |
---|
73 | |
---|
74 | @code |
---|
75 | |
---|
76 | make bobjs |
---|
77 | |
---|
78 | @endcode |
---|
79 | |
---|
80 | @subsection comp_ar After compilation |
---|
81 | |
---|
82 | Once all objects have been compiled, they will be collected into a |
---|
83 | build library ("blib") in <tt>bin/blib.a</tt>. |
---|
84 | |
---|
85 | @subsection comp_custom Customising compilation |
---|
86 | |
---|
87 | The Makefile rules for a particular object can be customised to a |
---|
88 | certain extent by defining the Makefile variable CFLAGS_@<object@>. |
---|
89 | For example, if you were to set |
---|
90 | |
---|
91 | @code |
---|
92 | |
---|
93 | CFLAGS_rtl8139 = -DFOO |
---|
94 | |
---|
95 | @endcode |
---|
96 | |
---|
97 | then <tt>bin/rtl8139.o</tt> would be compiled with the additional |
---|
98 | flags <tt>-DFOO</tt>. To see the flags that will be used when |
---|
99 | compiling a particular object, you can use e.g. |
---|
100 | |
---|
101 | @code |
---|
102 | |
---|
103 | make bin/rtl8139.flags |
---|
104 | |
---|
105 | @endcode |
---|
106 | |
---|
107 | If you need more flexibility than the CFLAGS_@<object@> mechanism |
---|
108 | provides, then you can exclude source files from the automatic rule |
---|
109 | generation process by listing them in the Makefile variable |
---|
110 | #NON_AUTO_SRCS. The command |
---|
111 | |
---|
112 | @code |
---|
113 | |
---|
114 | make autosrcs |
---|
115 | |
---|
116 | @endcode |
---|
117 | |
---|
118 | will show you which files are currently part of the automatic rule |
---|
119 | generation process. |
---|
120 | |
---|
121 | @subsection comp_multiobj Multiple objects |
---|
122 | |
---|
123 | A single source file can be used to generate multiple object files. |
---|
124 | This is used, for example, to generate the decompressing and the |
---|
125 | non-decompressing prefixes from the same source files. |
---|
126 | |
---|
127 | By default, a single object will be built from each source file. To |
---|
128 | override the list of objects for a source file, you can define the |
---|
129 | Makefile variable OBJS_@<object@>. For example, the |
---|
130 | <tt>arch/i386/prefix/dskprefix.S</tt> source file is built into two |
---|
131 | objects, <tt>bin/dskprefix.o</tt> and <tt>zdskprefix.o</tt> by |
---|
132 | defining the Makefile variable |
---|
133 | |
---|
134 | @code |
---|
135 | |
---|
136 | OBJS_dskprefix = dskprefix zdskprefix |
---|
137 | |
---|
138 | @endcode |
---|
139 | |
---|
140 | Since there would be little point in building two identical objects, |
---|
141 | customised compilation flags (see @ref comp_custom) are defined as |
---|
142 | |
---|
143 | @code |
---|
144 | |
---|
145 | CFLAGS_zdskprefix = -DCOMPRESS |
---|
146 | |
---|
147 | @endcode |
---|
148 | |
---|
149 | Thus, <tt>arch/i386/prefix/dskprefix.S</tt> is built into @c |
---|
150 | dskprefix.o using the normal set of flags, and into @c zdskprefix.o |
---|
151 | using the normal set of flags plus <tt>-DCOMPRESS</tt>. |
---|
152 | |
---|
153 | @subsection comp_debug Special debugging targets |
---|
154 | |
---|
155 | In addition to the basic rules #RULE_c and #RULE_S for compiling |
---|
156 | source files into object files, there are various other rules that can |
---|
157 | be useful for debugging. |
---|
158 | |
---|
159 | @subsubsection comp_debug_c_to_c Preprocessed C |
---|
160 | |
---|
161 | You can see the results of preprocessing a @c .c file (including the |
---|
162 | per-object flags defined via CFLAGS_@<object@> if applicable) using |
---|
163 | e.g. |
---|
164 | |
---|
165 | @code |
---|
166 | |
---|
167 | make bin/rtl8139.c |
---|
168 | |
---|
169 | @endcode |
---|
170 | |
---|
171 | and examining the resulting file (<tt>bin/rtl8139.c</tt> in this |
---|
172 | case). |
---|
173 | |
---|
174 | @subsubsection comp_debug_x_to_s Assembler |
---|
175 | |
---|
176 | You can see the results of assembling a @c .c file, or of |
---|
177 | preprocessing a @c .S file, using e.g. |
---|
178 | |
---|
179 | @code |
---|
180 | |
---|
181 | make bin/rtl8139.s |
---|
182 | make bin/zdskprefix.s |
---|
183 | |
---|
184 | @endcode |
---|
185 | |
---|
186 | @subsubsection comp_debug_dbg Debugging-enabled targets |
---|
187 | |
---|
188 | You can build targets with debug messages (DBG()) enabled using e.g. |
---|
189 | |
---|
190 | @code |
---|
191 | |
---|
192 | make bin/rtl8139.dbg.o |
---|
193 | make bin/rtl8139.dbg2.o |
---|
194 | |
---|
195 | @endcode |
---|
196 | |
---|
197 | You will probably not need to use these targets directly, since a |
---|
198 | mechanism exists to select debugging levels at build time; see @ref |
---|
199 | debug. |
---|
200 | |
---|
201 | @section linking Linking |
---|
202 | |
---|
203 | @subsection link_overview Overview |
---|
204 | |
---|
205 | Etherboot is designed to be small and extremely customisable. This is |
---|
206 | achieved by linking in only the features that are really wanted in any |
---|
207 | particular build. |
---|
208 | |
---|
209 | There are two places from which the list of desired features is |
---|
210 | obtained: |
---|
211 | |
---|
212 | -# @ref link_config_h |
---|
213 | -# @ref link_cmdline |
---|
214 | |
---|
215 | @subsection link_config_h config.h |
---|
216 | |
---|
217 | The config.h file is used to define global build options that are |
---|
218 | likely to apply to all images that you build, such as the console |
---|
219 | types, supported download protocols etc. See the documentation for |
---|
220 | config.h for more details. |
---|
221 | |
---|
222 | @subsection link_cmdline The make command line |
---|
223 | |
---|
224 | When you type a command such as |
---|
225 | |
---|
226 | @code |
---|
227 | |
---|
228 | make bin/dfe538.zrom |
---|
229 | |
---|
230 | @endcode |
---|
231 | |
---|
232 | it is used to derive the following information: |
---|
233 | |
---|
234 | - We are building a compressed ROM image |
---|
235 | - The DFE538 is a PCI NIC, so we need the decompressing PCI ROM prefix |
---|
236 | - The PCI IDs for the DFE538 are 1186:1300 |
---|
237 | - The DFE538 is an rtl8139-based card, therefore we need the rtl8139 driver |
---|
238 | |
---|
239 | You can see this process in action using the command |
---|
240 | |
---|
241 | @code |
---|
242 | |
---|
243 | make bin/dfe538.zrom.info |
---|
244 | |
---|
245 | @endcode |
---|
246 | |
---|
247 | which will print |
---|
248 | |
---|
249 | @code |
---|
250 | |
---|
251 | Elements : dfe538 |
---|
252 | Prefix : zrom |
---|
253 | Drivers : rtl8139 |
---|
254 | ROM name : dfe538 |
---|
255 | Media : rom |
---|
256 | |
---|
257 | ROM type : pci |
---|
258 | PCI vendor : 0x1186 |
---|
259 | PCI device : 0x1300 |
---|
260 | |
---|
261 | LD driver symbols : obj_rtl8139 |
---|
262 | LD prefix symbols : obj_zpciprefix |
---|
263 | LD ID symbols : pci_vendor_id=0x1186 pci_device_id=0x1300 |
---|
264 | |
---|
265 | LD target flags : -u obj_zpciprefix --defsym check_obj_zpciprefix=obj_zpciprefix -u obj_rtl8139 --defsym check_obj_rtl8139=obj_rtl8139 -u obj_config --defsym check_obj_config=obj_config --defsym pci_vendor_id=0x1186 --defsym pci_device_id=0x1300 |
---|
266 | |
---|
267 | @endcode |
---|
268 | |
---|
269 | This should be interpreted as follows: |
---|
270 | |
---|
271 | @code |
---|
272 | |
---|
273 | Elements : dfe538 |
---|
274 | Prefix : zrom |
---|
275 | |
---|
276 | @endcode |
---|
277 | |
---|
278 | "Elements" is the list of components preceding the first dot in the |
---|
279 | target name. "Prefix" is the component following the first dot in the |
---|
280 | target name. (It's called a "prefix" because the code that makes it a |
---|
281 | @c .zrom (rather than a @c .dsk, @c .zpxe or any other type of target) |
---|
282 | usually ends up at the start of the resulting binary image.) |
---|
283 | |
---|
284 | @code |
---|
285 | |
---|
286 | Drivers : rtl8139 |
---|
287 | |
---|
288 | @endcode |
---|
289 | |
---|
290 | "Drivers" is the list of drivers corresponding to the "Elements". |
---|
291 | Most drivers support several network cards. The PCI_ROM() and |
---|
292 | ISA_ROM() macros are used in the driver source files to list the cards |
---|
293 | that a particular driver can support. |
---|
294 | |
---|
295 | @code |
---|
296 | |
---|
297 | ROM name : dfe538 |
---|
298 | |
---|
299 | @endcode |
---|
300 | |
---|
301 | "ROM name" is the first element in the "Elements" list. It is used to |
---|
302 | select the PCI IDs for a PCI ROM. |
---|
303 | |
---|
304 | @code |
---|
305 | |
---|
306 | Media : rom |
---|
307 | |
---|
308 | @endcode |
---|
309 | |
---|
310 | "Media" is the "Prefix" minus the leading @c z, if any. |
---|
311 | |
---|
312 | @code |
---|
313 | |
---|
314 | ROM type : pci |
---|
315 | PCI vendor : 0x1186 |
---|
316 | PCI device : 0x1300 |
---|
317 | |
---|
318 | @endcode |
---|
319 | |
---|
320 | These are derived from the "ROM name" and the PCI_ROM() or ISA_ROM() |
---|
321 | macros in the driver source files. |
---|
322 | |
---|
323 | @code |
---|
324 | |
---|
325 | LD driver symbols : obj_rtl8139 |
---|
326 | LD prefix symbols : obj_zpciprefix |
---|
327 | |
---|
328 | @endcode |
---|
329 | |
---|
330 | This is the interesting part. At this point, we have established that |
---|
331 | we need the rtl8139 driver (i.e. @c rtl8139.o) and the decompressing |
---|
332 | PCI prefix (i.e. @c zpciprefix.o). Our build system (via the |
---|
333 | compiler.h header file) arranges that every object exports a symbol |
---|
334 | obj_@<object@>; this can be seen by e.g. |
---|
335 | |
---|
336 | @code |
---|
337 | |
---|
338 | objdump -t bin/rtl8139.o |
---|
339 | |
---|
340 | @endcode |
---|
341 | |
---|
342 | which will show the line |
---|
343 | |
---|
344 | @code |
---|
345 | |
---|
346 | 00000000 g *ABS* 00000000 obj_rtl8139 |
---|
347 | |
---|
348 | @endcode |
---|
349 | |
---|
350 | By instructing the linker that we need the symbols @c obj_rtl8139 and |
---|
351 | @c obj_zpciprefix, we can therefore ensure that these two objects are |
---|
352 | included in our build. (The linker will also include any objects that |
---|
353 | these two objects require, since that's the whole purpose of the |
---|
354 | linker.) |
---|
355 | |
---|
356 | In a similar way, we always instruct the linker that we need the |
---|
357 | symbol @c obj_config, in order to include the object @c config.o. @c |
---|
358 | config.o is used to drag in the objects that were specified via |
---|
359 | config.h; see @ref link_config_h. |
---|
360 | |
---|
361 | @code |
---|
362 | |
---|
363 | LD target flags : -u obj_zpciprefix --defsym check_obj_zpciprefix=obj_zpciprefix -u obj_rtl8139 --defsym check_obj_rtl8139=obj_rtl8139 -u obj_config --defsym check_obj_config=obj_config --defsym pci_vendor_id=0x1186 --defsym pci_device_id=0x1300 |
---|
364 | |
---|
365 | @endcode |
---|
366 | |
---|
367 | These are the flags that we pass to the linker in order to include the |
---|
368 | objects that we want in our build, and to check that they really get |
---|
369 | included. (This latter check is needed to work around what seems to |
---|
370 | be a bug in @c ld). |
---|
371 | |
---|
372 | The linker does its job of linking all the required objects together |
---|
373 | into a coherent build. The best way to see what is happening is to |
---|
374 | look at one of the resulting linker maps; try, for example |
---|
375 | |
---|
376 | @code |
---|
377 | |
---|
378 | make bin/dfe538.dsk.map |
---|
379 | |
---|
380 | @endcode |
---|
381 | |
---|
382 | The linker map includes, amongst others: |
---|
383 | |
---|
384 | - A list of which objects are included in the build, and why. |
---|
385 | - The results of processing the linker script, line-by-line. |
---|
386 | - A complete symbol table of the resulting build. |
---|
387 | |
---|
388 | It is worth spending time examining the linker map to see how an |
---|
389 | Etherboot image is assembled. |
---|
390 | |
---|
391 | Whatever format is selected, the Etherboot image is built into an ELF |
---|
392 | file, simply because this is the default format used by @c ld. |
---|
393 | |
---|
394 | @section finalisation Finalisation |
---|
395 | |
---|
396 | @subsection final_overview Overview |
---|
397 | |
---|
398 | The ELF file resulting from @ref linking "linking" needs to be |
---|
399 | converted into the final binary image. Usually, this is just a case |
---|
400 | of running |
---|
401 | |
---|
402 | @code |
---|
403 | |
---|
404 | objcopy -O binary <elf file> <output file> |
---|
405 | |
---|
406 | @endcode |
---|
407 | |
---|
408 | to convert the ELF file into a raw binary image. Certain image |
---|
409 | formats require special additional treatment. |
---|
410 | |
---|
411 | @subsection final_rom ROM images |
---|
412 | |
---|
413 | ROM images must be rounded up to a suitable ROM size (e.g. 16kB or |
---|
414 | 32kB), and certain header information such as checksums needs to be |
---|
415 | filled in. This is done by the @c makerom.pl program. |
---|
416 | |
---|
417 | @section debug Debugging-enabled builds |
---|
418 | |
---|
419 | */ |
---|