[e16e8f2] | 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 | */ |
---|