| 1 | ********************************************************************************
|
|---|
| 2 |
|
|---|
| 3 | The Modular Building System (MoBuS)
|
|---|
| 4 |
|
|---|
| 5 | ********************************************************************************
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 | The goal of the build system
|
|---|
| 9 | ----------------------------
|
|---|
| 10 |
|
|---|
| 11 | MoBuS was projected with several goals in mind:
|
|---|
| 12 |
|
|---|
| 13 | - Simplicity of use. Most makefile magic should go in a few relatively
|
|---|
| 14 | complex central makefiles, simplifying the 'end-user' makefiles.
|
|---|
| 15 | In fact, the build system is simple enough for use without even
|
|---|
| 16 | looking into these docs.
|
|---|
| 17 |
|
|---|
| 18 | - Universality. This makefile system can be easily used in any projects,
|
|---|
| 19 | just by copying root makefiles and creating a few .smak files.
|
|---|
| 20 |
|
|---|
| 21 | - Flexibility. Simplicity should not make impossible to write complex
|
|---|
| 22 | building rules, especially since our primary goal is the OS/2 C runtime,
|
|---|
| 23 | which is a very complex thing per se.
|
|---|
| 24 |
|
|---|
| 25 | - Modularity. New building modules should be added and old removed without
|
|---|
| 26 | even having to touch the root makefiles. The build system should adapt
|
|---|
| 27 | automatically to every change.
|
|---|
| 28 |
|
|---|
| 29 | - Multi-option. The ability to build same file with several sets of
|
|---|
| 30 | options (e.g. -Zmt and -pg), which implies a separate output directory for
|
|---|
| 31 | every flavour of output files.
|
|---|
| 32 |
|
|---|
| 33 | - Portability. This is a secondary target, though the build subsystem can
|
|---|
| 34 | be easily used in other operating systems (a few modifications still have
|
|---|
| 35 | to be made first, e.g. including a platform-specific .smak file which
|
|---|
| 36 | would set up every platform-specific aspect).
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 | Glossary of terms used in MoBuS
|
|---|
| 40 | -------------------------------
|
|---|
| 41 |
|
|---|
| 42 | target - a particular executable, library and so on.
|
|---|
| 43 |
|
|---|
| 44 | module - a set of targets, unified by a common functionality
|
|---|
| 45 | (example: targets emxomf.exe, emxomfar.exe, emxomfld.exe,
|
|---|
| 46 | emxaout.exe, listomf.exe are parts of module emxomf).
|
|---|
| 47 |
|
|---|
| 48 | persistent variable - a make variable that does not change its value
|
|---|
| 49 | radically (e.g. some persistent variables can be appended to but never
|
|---|
| 50 | assigned a totally different value). For example CFLAGS is a persistent
|
|---|
| 51 | variable; submakefiles could append something to CFLAGS (which is a bad
|
|---|
| 52 | idea anyways since it will unpredictably affect all modules) but this
|
|---|
| 53 | doesn't change its contents radically.
|
|---|
| 54 |
|
|---|
| 55 | local variable - a temporary variable used in some section of makefile
|
|---|
| 56 | and then can be reused for anything other. For easier reading such
|
|---|
| 57 | variables are prefixed by '.', e.g. ".LOCAL" is a local variable,
|
|---|
| 58 | while "LOCAL" is a persistent variable. When you reference local
|
|---|
| 59 | variables it is highly advised to use the ':=' assignment rather
|
|---|
| 60 | than '=' since when using ':=' the assigned value is expanded
|
|---|
| 61 | immediately.
|
|---|
| 62 |
|
|---|
| 63 | builder - a special submakefile that defines all the rules required
|
|---|
| 64 | to build some target. Their name starts with 'mk', for example mkexe.smak
|
|---|
| 65 | prepares everything needed to build a .exe target and so on.
|
|---|
| 66 |
|
|---|
| 67 |
|
|---|
| 68 | Using MoBuS
|
|---|
| 69 | -----------
|
|---|
| 70 |
|
|---|
| 71 | Every time you start 'make', MoBuS searches all subdirectories for files
|
|---|
| 72 | ending with '.smak' (smak stands for 'Sub-Makefile': I have chosen .smak
|
|---|
| 73 | instead of .mak because EM already used .mak extension for his makefiles
|
|---|
| 74 | and they would conflict with MoBuS).
|
|---|
| 75 |
|
|---|
| 76 | Every submakefile defines a number of special variables that control the
|
|---|
| 77 | build process for a specific target. After they are given values, you usually
|
|---|
| 78 | include one of the builders (we'll list them later) that prepares
|
|---|
| 79 | everything required for the actual building. Most of these variables are
|
|---|
| 80 | cleared to avoid their value to be incidentally passed to another submakefile
|
|---|
| 81 | (which is almost certainly not what you want). If you don't want this to happen,
|
|---|
| 82 | you can assign any value to the special variable .TKEEP. Here is the full list
|
|---|
| 83 | of variables that control the build process:
|
|---|
| 84 |
|
|---|
| 85 | .INSDIR - (optional) directory inside the installation tree for targets.
|
|---|
| 86 | For example, it could be 'bin/' (without quotes), or 'lib/st/' and so on.
|
|---|
| 87 | This variable is NOT cleared after the inclusion of builders since
|
|---|
| 88 | you may want many targets to be placed in the same install directory,
|
|---|
| 89 | and you would have to redefine .INSDIR before every target.
|
|---|
| 90 |
|
|---|
| 91 | .MODULE - The name of current module. As explained above, a module can consist
|
|---|
| 92 | of many submakefiles, and is a minimal build unit.
|
|---|
| 93 |
|
|---|
| 94 | .MDESC - (optional) module description. This is displayed when you type
|
|---|
| 95 | 'make help' in the module list section.
|
|---|
| 96 |
|
|---|
| 97 | .MDEP - (optional) module dependencies. This is useful if current module
|
|---|
| 98 | requires another module to be built first (e.g. a library). It usually
|
|---|
| 99 | contains the name of another module (e.g. .MDEP := os2).
|
|---|
| 100 |
|
|---|
| 101 | .TARGET - The name of target (e.g. executable or library file name without dir).
|
|---|
| 102 | For example: .TARGET := myfile.exe
|
|---|
| 103 |
|
|---|
| 104 | .TKIND - (optional) The kind of target. It can consist of up to three
|
|---|
| 105 | components, the first one defines the object file format (omf or aout,
|
|---|
| 106 | if not defined defaults to omf), the second can be 'prof' to build in
|
|---|
| 107 | profiling mode.
|
|---|
| 108 | Example: .TKIND := omf prof
|
|---|
| 109 |
|
|---|
| 110 | .TKVAR - (optional) The variant of target. This is handy if one need to build
|
|---|
| 111 | the same sources several times with different flags.
|
|---|
| 112 | Exampel: .TKVAR := tcpipv4
|
|---|
| 113 |
|
|---|
| 114 | .TDEP - Dependencies for target (not built from a source file). For example,
|
|---|
| 115 | this could be a library built in another module, or a pre-compiled library.
|
|---|
| 116 | A special sequence @O@ in $(.TDEP) is replaced with the base directory for
|
|---|
| 117 | object files (for example, out/dbg/aout-st-prof/).
|
|---|
| 118 |
|
|---|
| 119 | .TSRC - The list of source files for this target. They should never be
|
|---|
| 120 | absolute paths, since object file names are created by prefixing source
|
|---|
| 121 | file directory with output directory (e.g. src/emxbind/emxbind.c will be
|
|---|
| 122 | compiled to $(OUT)src/emxbind/emxbind.o).
|
|---|
| 123 |
|
|---|
| 124 | .TCF - The C compiler flags for C files listed in .TSRC.
|
|---|
| 125 | .TCF.srcfile - You can define some specific C compiler flags for just one
|
|---|
| 126 | source file (for example .TCF.src/emx/ld/ld.c=-D__SOMETHING)
|
|---|
| 127 |
|
|---|
| 128 | .TSF - Assembler flags for all .s files listed in .TSRC
|
|---|
| 129 | .TSF{.srcfile} - Assembler (.s) flags for GAS for a specific source file.
|
|---|
| 130 |
|
|---|
| 131 | .TAF - Assembler (MASM or ML) flags for all .asm files listed in .TSRC
|
|---|
| 132 | .TAF{.srcfile} - Assembler flags for a specific .asm file listed in .TSRC.
|
|---|
| 133 |
|
|---|
| 134 | .TLDF - Target-specific linker flags (for linked targets such as .exe
|
|---|
| 135 | and .dll files).
|
|---|
| 136 |
|
|---|
| 137 | .TKEEP - If defined, all .XXX variables will be not undefined. This can be
|
|---|
| 138 | used if you want to share some of the .XXX variables between several targets
|
|---|
| 139 | (for example .TSRC). WARNING: Take care they accidentaly to not be passed
|
|---|
| 140 | to another submakefile!
|
|---|
| 141 |
|
|---|
| 142 | After you assign values to above liste variables, you can include one of the
|
|---|
| 143 | following builders:
|
|---|
| 144 |
|
|---|
| 145 | mkexe.smak - this builder treats .TARGET as a executable. It defines all
|
|---|
| 146 | rules required for building all object files and then linking them together
|
|---|
| 147 | to form a executable.
|
|---|
| 148 |
|
|---|
| 149 | mklib.smak - this builder creates a library. It defines all rules required
|
|---|
| 150 | for building all object files and then runs the librarian which binds all
|
|---|
| 151 | object files together in a single library. Besides, if the file format is
|
|---|
| 152 | a.out, it also defines a target called '$(.MODULE)@omf' (e.g. for module
|
|---|
| 153 | zzz it also defines a module called zzz@omf) which will build the OMF
|
|---|
| 154 | library from its a.out counterpart by using emxomf.
|
|---|
| 155 |
|
|---|
| 156 | Here is a simple example of a submakefile that will build a simple helloworld
|
|---|
| 157 | executable:
|
|---|
| 158 |
|
|---|
| 159 | --------8<--------8<--------8<--------8<--------8<--------
|
|---|
| 160 | # $Id: build.txt 885 2003-12-08 05:42:10Z bird $
|
|---|
| 161 |
|
|---|
| 162 | .MODULE := helloworld
|
|---|
| 163 | .MDESC := Build a helloworld executable
|
|---|
| 164 | .INSDIR := bin/
|
|---|
| 165 |
|
|---|
| 166 | .TARGET := helloworld.exe
|
|---|
| 167 | .TSRC := $(wildcard src/helloworld/*.c)
|
|---|
| 168 | include mkexe.smak
|
|---|
| 169 | --------8<--------8<--------8<--------8<--------8<--------
|
|---|
| 170 |
|
|---|
| 171 |
|
|---|
| 172 | Understanding build system
|
|---|
| 173 | --------------------------
|
|---|
| 174 |
|
|---|
| 175 | First of all, it would be nice to have handy the GNU Make manual before
|
|---|
| 176 | starting to look into the makefiles. They use complex expressions, and it
|
|---|
| 177 | would be hard to understand them without knowing how GNU Make works.
|
|---|
| 178 |
|
|---|
| 179 | The core of the build system are: the root Makefile and several .smak files
|
|---|
| 180 | The root makefile does the following:
|
|---|
| 181 |
|
|---|
| 182 | - Defines the build environment (tools, flags and so on)
|
|---|
| 183 | - Searches for all submakefiles (.smak files) and includes them.
|
|---|
| 184 | - Defines the rule for displaying a help (when you run make without
|
|---|
| 185 | arguments).
|
|---|
| 186 | - Defines the rule for re-building the 'build rules file'. The later
|
|---|
| 187 | is a collection of rules of the traditional form:
|
|---|
| 188 |
|
|---|
| 189 | sometarget: somesource
|
|---|
| 190 | commands-to-execute
|
|---|
| 191 |
|
|---|
| 192 | and is placed in a auto-built .smak files in the output directory.
|
|---|
| 193 | - Defines the rule for auto-creating output directories. The
|
|---|
| 194 | submakefiles appends the output directories they need to the
|
|---|
| 195 | variable TARGDIRS.
|
|---|
| 196 | - Defines the install: target which should create a complete
|
|---|
| 197 | distribution tree.
|
|---|
| 198 |
|
|---|
| 199 | The base directory for output files is assigned to the variable OUT.
|
|---|
| 200 | In general, directory names through the makefiles have a forward slash
|
|---|
| 201 | appended (first, for easy visual separation of directory names and second,
|
|---|
| 202 | for simpler usage, e.g. $(OUT)myfile.o rather than $(OUT)/myfile.o).
|
|---|
| 203 |
|
|---|
| 204 | Every target can be of a specific 'kind', e.g. to require a specific
|
|---|
| 205 | pre-defined set of compiler flags. When compiling multiple kinds of object
|
|---|
| 206 | files from a single source file they are put under different output directories
|
|---|
| 207 | (e.g. single-threaded OMF object files go into $(OUT)/omf-st/ directory while
|
|---|
| 208 | multi-threaded a.out object files with profiling go into $(OUT)/aout-prof/
|
|---|
| 209 | directory). This way, you can have several targets that are built from the
|
|---|
| 210 | same source files with different compilation options.
|
|---|