| The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 1 | # This file is used to build the Bionic library with the Jam build | 
|  | 2 | # tool. For info, see www.perforce.com/jam/jam.html | 
|  | 3 | # | 
|  | 4 |  | 
|  | 5 | BIONIC_TOP ?= $(DOT) ; | 
|  | 6 |  | 
|  | 7 | DEBUG = 1 ; | 
|  | 8 |  | 
|  | 9 | # pattern used for automatic heade inclusion detection | 
|  | 10 | HDRPATTERN = "^[ 	]*#[ 	]*include[ 	]*[<\"]([^\">]*)[\">].*$" ; | 
|  | 11 |  | 
|  | 12 |  | 
|  | 13 | # debugging support, simply define the DEBUG variable to activate verbose output | 
|  | 14 | rule Debug | 
|  | 15 | { | 
|  | 16 | if $(DEBUG) { | 
|  | 17 | Echo $(1) ; | 
|  | 18 | } | 
|  | 19 | } | 
|  | 20 |  | 
|  | 21 | # return all elements from $(1) that are not in $(2) | 
|  | 22 | rule Filter  list : filter | 
|  | 23 | { | 
|  | 24 | local result = ; | 
|  | 25 | local item ; | 
|  | 26 | for item in $(list) { | 
|  | 27 | if ! $(item) in $(filter) { | 
|  | 28 | result += $(item) ; | 
|  | 29 | } | 
|  | 30 | } | 
|  | 31 | return $(result) ; | 
|  | 32 | } | 
|  | 33 |  | 
|  | 34 |  | 
|  | 35 | # reverse a list of elements | 
|  | 36 | rule Reverse  list | 
|  | 37 | { | 
|  | 38 | local  result = ; | 
|  | 39 | local  item ; | 
|  | 40 |  | 
|  | 41 | for item in $(list) { | 
|  | 42 | result = $(item) $(result) ; | 
|  | 43 | } | 
|  | 44 | return $(result) ; | 
|  | 45 | } | 
|  | 46 |  | 
|  | 47 |  | 
|  | 48 | # decompose a path into a list of elements | 
|  | 49 | rule PathDecompose  dir | 
|  | 50 | { | 
|  | 51 | local  result ; | 
|  | 52 |  | 
|  | 53 | while $(dir:D) | 
|  | 54 | { | 
|  | 55 | if ! $(dir:BS) {  # for rooted paths like "/foo" | 
|  | 56 | break ; | 
|  | 57 | } | 
|  | 58 | result = $(dir:BS) $(result) ; | 
|  | 59 | dir    = $(dir:D) ; | 
|  | 60 | } | 
|  | 61 | result = $(dir) $(result) ; | 
|  | 62 | return $(result) ; | 
|  | 63 | } | 
|  | 64 |  | 
|  | 65 |  | 
|  | 66 | # simply a file path, i.e. get rid of . or .. when possible | 
|  | 67 | rule _PathSimplify  dir | 
|  | 68 | { | 
|  | 69 | local  result = ; | 
|  | 70 | local  dir2 d ; | 
|  | 71 |  | 
|  | 72 | dir  = [ PathDecompose $(dir) ] ; | 
|  | 73 |  | 
|  | 74 | # get rid of any single dot | 
|  | 75 | dir2 = ; | 
|  | 76 | for d in $(dir) { | 
|  | 77 | if $(d) = "." { | 
|  | 78 | continue ; | 
|  | 79 | } | 
|  | 80 | dir2 += $(d) ; | 
|  | 81 | } | 
|  | 82 |  | 
|  | 83 | # get rid of .. when possible | 
|  | 84 | for d in $(dir2) { | 
|  | 85 | if $(d) = ".." && $(result) { | 
|  | 86 | result = $(result[2-]) ; | 
|  | 87 | } | 
|  | 88 | else | 
|  | 89 | result = $(d) $(result) ; | 
|  | 90 | } | 
|  | 91 |  | 
|  | 92 | # now invert the result | 
|  | 93 | result = [ Reverse $(result) ] ; | 
|  | 94 | if ! $(result) { | 
|  | 95 | result = "." ; | 
|  | 96 | } | 
|  | 97 | return $(result:J="/") ; | 
|  | 98 | } | 
|  | 99 |  | 
|  | 100 |  | 
|  | 101 | rule PathSimplify  dirs | 
|  | 102 | { | 
|  | 103 | local result ; | 
|  | 104 | local d ; | 
|  | 105 | for d in $(dirs) { | 
|  | 106 | result += [ _PathSimplify $(d) ] ; | 
|  | 107 | } | 
|  | 108 | return $(result) ; | 
|  | 109 | } | 
|  | 110 |  | 
|  | 111 |  | 
|  | 112 | # retrieve list of subdirectories | 
|  | 113 | rule ListSubDirs  paths | 
|  | 114 | { | 
|  | 115 | local  result  = ; | 
|  | 116 | local  entry ; | 
|  | 117 | for entry in [ Glob $(paths) : * ] { | 
|  | 118 | if ! $(entry:S) { | 
|  | 119 | result += $(entry) ; | 
|  | 120 | } | 
|  | 121 | } | 
|  | 122 | return [ PathSimplify $(result) ] ; | 
|  | 123 | } | 
|  | 124 |  | 
|  | 125 |  | 
|  | 126 | # retrieve list of sources in a given directory | 
|  | 127 | rule ListSources  path | 
|  | 128 | { | 
|  | 129 | return [ Glob $(path) : *.S *.c ] ; | 
|  | 130 | } | 
|  | 131 |  | 
|  | 132 |  | 
|  | 133 | # find the prebuilt directory | 
|  | 134 | # | 
|  | 135 | if ! $(TOP) { | 
|  | 136 | Echo "Please define TOP as the root of your device build tree" ; | 
|  | 137 | Exit ; | 
|  | 138 | } | 
|  | 139 |  | 
|  | 140 | Debug "OS is" $(OS) ; | 
|  | 141 | Debug "CPU is" $(CPU) ; | 
|  | 142 |  | 
|  | 143 | if $(OS) = LINUX | 
|  | 144 | { | 
|  | 145 | PREBUILT = $(TOP)/prebuilt/Linux ; | 
|  | 146 | } | 
|  | 147 | else if $(OS) = MACOSX | 
|  | 148 | { | 
|  | 149 | switch $(CPU) { | 
|  | 150 | case i386 : PREBUILT = $(TOP)/prebuilt/darwin-x86 ; break ; | 
|  | 151 | case ppc  : PREBUILT = $(TOP)/prebuilt/darwin-ppc ; break ; | 
|  | 152 | case *    : Echo "unsupported CPU" "$(CPU) !!" ; | 
|  | 153 | Echo "Please contact digit@google.com for help" ; | 
|  | 154 | Exit ; | 
|  | 155 | } | 
|  | 156 | } | 
|  | 157 | else | 
|  | 158 | { | 
|  | 159 | Echo "Unsupported operating system" $(OS) ; | 
|  | 160 | Echo "Please contact digit@google.com for help" ; | 
|  | 161 | Exit ; | 
|  | 162 | } | 
|  | 163 |  | 
|  | 164 | Debug "TOP is" $(TOP) ; | 
|  | 165 | Debug "PREBUILT is" $(PREBUILT) ; | 
|  | 166 |  | 
|  | 167 |  | 
|  | 168 | # check architectures and setup toolchain variables | 
|  | 169 | # | 
|  | 170 | SUPPORTED_ARCHS = x86 arm ; | 
|  | 171 |  | 
|  | 172 | ARCH ?= $(SUPPORTED_ARCHS) ; | 
|  | 173 |  | 
|  | 174 | if ! $(ARCH) in $(SUPPORTED_ARCHS) { | 
|  | 175 | Echo "The variable ARCH contains an unsupported value, use one or more of these instead" ; | 
|  | 176 | Echo "separated by spaces:" $(SUPPORTED_ARCHS) ; | 
|  | 177 | Exit ; | 
|  | 178 | } | 
|  | 179 |  | 
|  | 180 | x86_TOOLSET_PREFIX ?= "" ; | 
|  | 181 | arm_TOOLSET_PREFIX ?= $(TOP)/prebuilt/Linux/toolchain-4.1.1/bin/arm-elf- ; | 
|  | 182 |  | 
|  | 183 | for arch in $(ARCH) { | 
|  | 184 | CC_$(arch)  = $($(arch)_TOOLSET_PREFIX)gcc ; | 
|  | 185 | C++_$(arch) = $($(arch)_TOOLSET_PREFIX)g++ ; | 
|  | 186 | AR_$(arch)  = $($(arch)_TOOLSET_PREFIX)ar ; | 
|  | 187 | } | 
|  | 188 |  | 
|  | 189 |  | 
|  | 190 | # the list of arch-independent source subdirectories | 
|  | 191 | BIONIC_SRC_SUBDIRS = string ; | 
|  | 192 | BIONIC_x86_SUBDIRS = ; | 
|  | 193 | BIONIC_arm_SUBDIRS = ; | 
|  | 194 |  | 
|  | 195 | CFLAGS   = -O0 -g -W ; | 
|  | 196 |  | 
|  | 197 |  | 
|  | 198 |  | 
|  | 199 | # find sources in a given list of subdirectories | 
|  | 200 | rule FindSources  dirs | 
|  | 201 | { | 
|  | 202 | local dir ; | 
|  | 203 |  | 
|  | 204 | for dir in $(dirs) | 
|  | 205 | { | 
|  | 206 | local LOCAL_SRC NO_LOCAL_SRC ; | 
|  | 207 |  | 
|  | 208 | if [ Glob $(dir) : rules.jam ] { | 
|  | 209 | include $(dir)/rules.jam ; | 
|  | 210 | if $(LOCAL_SRC) { | 
|  | 211 | _sources = $(LOCAL_SRC) ; | 
|  | 212 | } | 
|  | 213 | else { | 
|  | 214 | _sources = [ Glob $(dir) : *.S *.c ] ; | 
|  | 215 | _sources = $(_sources:BS) ; | 
|  | 216 | } | 
|  | 217 | if $(NO_LOCAL_SRC) { | 
|  | 218 | _sources = [ Filter $(_sources) : $(NO_LOCAL_SRC) ] ; | 
|  | 219 | } | 
|  | 220 | sources += $(dir)/$(_sources) ; | 
|  | 221 | } | 
|  | 222 | else | 
|  | 223 | sources += [ ListSources $(dir) ] ; | 
|  | 224 | } | 
|  | 225 | } | 
|  | 226 |  | 
|  | 227 | # Compile a given object file from a source | 
|  | 228 | rule Compile  object : source | 
|  | 229 | { | 
|  | 230 | Depends $(object) : $(source) ; | 
|  | 231 | Depends bionic : $(object) ; | 
|  | 232 | Clean clean : $(object) ; | 
|  | 233 |  | 
|  | 234 | MakeLocate $(object) : $(OUT) ; | 
|  | 235 |  | 
|  | 236 |  | 
|  | 237 | CC on $(object)       = $(CC_$(arch)) ; | 
|  | 238 | CFLAGS on $(object)   = $(CFLAGS) ; | 
|  | 239 | INCLUDES on $(object) = $(INCLUDES) ; | 
|  | 240 | DEFINES on $(object)  = $(DEFINES) ; | 
|  | 241 |  | 
|  | 242 | HDRRULE on $(>) = HdrRule ; | 
|  | 243 | HDRSCAN on $(>) = $(HDRPATTERN) ; | 
|  | 244 | HDRSEARCH on $(>) = $(INCLUDES) ; | 
|  | 245 | HDRGRIST on $(>) = $(HDRGRIST) ; | 
|  | 246 | } | 
|  | 247 |  | 
|  | 248 |  | 
|  | 249 | actions Compile | 
|  | 250 | { | 
|  | 251 | $(CC) -c -o $(1) $(CFLAGS) -I$(INCLUDES) -D$(DEFINES) $(2) | 
|  | 252 | } | 
|  | 253 |  | 
|  | 254 |  | 
|  | 255 | rule RmTemps | 
|  | 256 | { | 
|  | 257 | Temporary $(2) ; | 
|  | 258 | } | 
|  | 259 |  | 
|  | 260 | actions quietly updated piecemeal together RmTemps | 
|  | 261 | { | 
|  | 262 | rm -f $(2) | 
|  | 263 | } | 
|  | 264 |  | 
|  | 265 | actions Archive | 
|  | 266 | { | 
|  | 267 | $(AR) ru $(1) $(2) | 
|  | 268 | } | 
|  | 269 |  | 
|  | 270 | rule Library  library : objects | 
|  | 271 | { | 
|  | 272 | local  obj ; | 
|  | 273 |  | 
|  | 274 | if ! $(library:S) { | 
|  | 275 | library = $(library:S=.a) ; | 
|  | 276 | } | 
|  | 277 | library = $(library:G=<$(arch)>) ; | 
|  | 278 |  | 
|  | 279 | Depends all : $(library) ; | 
|  | 280 |  | 
|  | 281 | if ! $(library:D) { | 
|  | 282 | MakeLocate $(library) $(library)($(objects:BS)) : $(OUT) ; | 
|  | 283 | } | 
|  | 284 |  | 
|  | 285 | Depends $(library) : $(library)($(objects:BS)) ; | 
|  | 286 | for obj in $(objects) { | 
|  | 287 | Depends $(library)($(obj:BS)) : $(obj) ; | 
|  | 288 | } | 
|  | 289 |  | 
|  | 290 | Clean clean : $(library) ; | 
|  | 291 |  | 
|  | 292 | AR on $(library) = $(AR_$(arch)) ; | 
|  | 293 | Archive $(library) : $(objects) ; | 
|  | 294 |  | 
|  | 295 | RmTemps $(library) : $(objects) ; | 
|  | 296 | } | 
|  | 297 |  | 
|  | 298 |  | 
|  | 299 | rule  ProcessDir | 
|  | 300 | { | 
|  | 301 | local CFLAGS   = $(CFLAGS) ; | 
|  | 302 | local DEFINES  = $(DEFINES) ; | 
|  | 303 | local INCLUDES = $(INCLUDES) ; | 
|  | 304 | local local_rules = [ Glob $(1) : rules.jam ] ; | 
|  | 305 | local source sources ; | 
|  | 306 |  | 
|  | 307 | if $(local_rules) { | 
|  | 308 | local LOCAL_CFLAGS LOCAL_DEFINES LOCAL_INCLUDES LOCAL_SRC NO_LOCAL_SRC ; | 
|  | 309 |  | 
|  | 310 | include $(local_rules) ; | 
|  | 311 | CFLAGS   += $(LOCAL_CFLAGS) ; | 
|  | 312 | DEFINES  += $(LOCAL_DEFINES) ; | 
|  | 313 | INCLUDES += $(LOCAL_INCLUDES) ; | 
|  | 314 |  | 
|  | 315 | if $(LOCAL_SRC) { | 
|  | 316 | sources = $(LOCAL_SRC) ; | 
|  | 317 | } | 
|  | 318 | else { | 
|  | 319 | sources = [ Glob $(1) : *.S *.c ] ; | 
|  | 320 | sources = $(sources:BS) ; | 
|  | 321 | } | 
|  | 322 |  | 
|  | 323 | if $(NO_LOCAL_SRC) { | 
|  | 324 | sources = [ Filter $(sources) : $(NO_LOCAL_SRC) ] ; | 
|  | 325 | } | 
|  | 326 |  | 
|  | 327 | sources = $(1)/$(sources) ; | 
|  | 328 | } | 
|  | 329 | else | 
|  | 330 | sources = [ Glob $(1) : *.S *.c ] ; | 
|  | 331 |  | 
|  | 332 | for source in $(sources) { | 
|  | 333 | local name = $(source:B) ; | 
|  | 334 |  | 
|  | 335 | if $(source:S) = ".S" { | 
|  | 336 | # record the list of assembler sources | 
|  | 337 | ASSEMBLER_SOURCES += $(name) ; | 
|  | 338 | } | 
|  | 339 | else if $(source:S) = ".c" && $(name) in $(ASSEMBLER_SOURCES) { | 
|  | 340 | # skip C source file if corresponding assembler exists | 
|  | 341 | continue ; | 
|  | 342 | } | 
|  | 343 |  | 
|  | 344 | objname = <$(arch)>$(name).o  ; | 
|  | 345 |  | 
|  | 346 | Compile $(objname) : $(source) ; | 
|  | 347 | ALL_OBJECTS += $(objname) ; | 
|  | 348 | } | 
|  | 349 | } | 
|  | 350 |  | 
|  | 351 | rule ProcessDirs | 
|  | 352 | { | 
|  | 353 | local  dir ; | 
|  | 354 | for dir in $(1) { | 
|  | 355 | ProcessDir $(dir) ; | 
|  | 356 | } | 
|  | 357 | } | 
|  | 358 |  | 
|  | 359 | INCLUDES_x86 = /usr/src/linux/include ; | 
|  | 360 |  | 
|  | 361 | INCLUDES_arm = ../kernel_headers | 
|  | 362 | include/arch/arm | 
|  | 363 | include/bits32 | 
|  | 364 | ; | 
|  | 365 |  | 
|  | 366 | INCLUDES = include stdio string stdlib . | 
|  | 367 | ../msun/include | 
|  | 368 | ; | 
|  | 369 |  | 
|  | 370 | DEFINES  = ANDROID_CHANGES | 
|  | 371 | USE_LOCKS | 
|  | 372 | REALLOC_ZERO_BYTES_FREES | 
|  | 373 | _LIBC=1 | 
|  | 374 | SOFTFLOAT | 
|  | 375 | FLOATING_POINT | 
|  | 376 | NEED_PSELECT=1 | 
|  | 377 | ANDROID | 
|  | 378 | ; | 
|  | 379 |  | 
|  | 380 | CFLAGS_x86 = ; | 
|  | 381 |  | 
|  | 382 |  | 
|  | 383 | for arch in $(ARCH) | 
|  | 384 | { | 
|  | 385 | local ARCH_DIR = $(BIONIC_TOP)/arch-$(arch) ; | 
|  | 386 | local INCLUDES = $(INCLUDES_$(arch)) $(ARCH_DIR)/include $(INCLUDES) ; | 
|  | 387 | local DEFINES  = $(DEFINES_$(arch)) $(DEFINES) ARCH=$(arch)  ; | 
|  | 388 | local CFLAGS   = $(CFLAGS) $(CFLAGS_$(arch)) ; | 
|  | 389 | local OUT      = out/$(arch) ; | 
|  | 390 | local ASSEMBLER_SOURCES ALL_OBJECTS ; | 
|  | 391 |  | 
|  | 392 | ProcessDirs [ ListSubDirs $(ARCH_DIR) ] ; | 
|  | 393 | ProcessDirs stdlib stdio unistd string tzcode inet ; | 
|  | 394 | ProcessDirs [ ListSubDirs netbsd ] ; | 
|  | 395 | ProcessDirs bionic ; | 
|  | 396 |  | 
|  | 397 | Library bionic : $(ALL_OBJECTS) ; | 
|  | 398 | } | 
|  | 399 |  | 
|  | 400 | BIONIC_SEARCH = $(BIONIC_TOP)/include ; | 
|  | 401 |  | 
|  | 402 |  | 
|  | 403 |  | 
|  | 404 | # /HdrRule source : headers ; | 
|  | 405 | # | 
|  | 406 | # Arranges the proper dependencies when the file _source_ includes the files | 
|  | 407 | # _headers_ through the #include C preprocessor directive | 
|  | 408 | # | 
|  | 409 | # this rule is not intendend to be called explicitely. It is called | 
|  | 410 | # automatically during header scanning on sources handled by the @Object | 
|  | 411 | # rule (e.g. sources in @Main or @Library rules) | 
|  | 412 | # | 
|  | 413 | rule HdrRule | 
|  | 414 | { | 
|  | 415 | # HdrRule source : headers ; | 
|  | 416 |  | 
|  | 417 | # N.B.  This rule is called during binding, potentially after | 
|  | 418 | # the fate of many targets has been determined, and must be | 
|  | 419 | # used with caution: don't add dependencies to unrelated | 
|  | 420 | # targets, and don't set variables on $(<). | 
|  | 421 |  | 
|  | 422 | # Tell Jam that anything depending on $(<) also depends on $(>), | 
|  | 423 | # set SEARCH so Jam can find the headers, but then say we don't | 
|  | 424 | # care if we can't actually find the headers (they may have been | 
|  | 425 | # within ifdefs), | 
|  | 426 |  | 
|  | 427 | local s = $(>:G=$(HDRGRIST:E)) ; | 
|  | 428 |  | 
|  | 429 | Includes $(<) : $(s) ; | 
|  | 430 | SEARCH on $(s) = $(HDRSEARCH) ; | 
|  | 431 | NoCare $(s) ; | 
|  | 432 |  | 
|  | 433 | # Propagate on $(<) to $(>) | 
|  | 434 |  | 
|  | 435 | HDRSEARCH on $(s) = $(HDRSEARCH) ; | 
|  | 436 | HDRSCAN on $(s) = $(HDRSCAN) ; | 
|  | 437 | HDRRULE on $(s) = $(HDRRULE) ; | 
|  | 438 | HDRGRIST on $(s) = $(HDRGRIST) ; | 
|  | 439 | } | 
|  | 440 |  | 
|  | 441 |  |