1 2rule SetupObjectsDir 3{ 4 # SetupObjectsDir 5 # 6 # Internal rule used to set up the *{LOCATE,SEARCH}*_{TARGET,SOURCE} 7 # variables for the current directory. 8 9 local relPath = [ FDirName $(SUBDIR_TOKENS[2-]) ] ; 10 if $(relPath) = . { 11 relPath = ; 12 } 13 COMMON_PLATFORM_LOCATE_TARGET = 14 [ FDirName $(HAIKU_COMMON_PLATFORM_OBJECT_DIR) $(relPath) ] ; 15 16 local var ; 17 for var in COMMON_ARCH COMMON_DEBUG DEBUG_$(HAIKU_DEBUG_LEVELS) { 18 HOST_$(var)_LOCATE_TARGET 19 = [ FDirName $(HOST_$(var)_OBJECT_DIR) $(relPath) ] ; 20 TARGET_$(var)_LOCATE_TARGET 21 = [ FDirName $(TARGET_$(var)_OBJECT_DIR) $(relPath) ] ; 22 } 23 24 LOCATE_TARGET = $(COMMON_PLATFORM_LOCATE_TARGET) ; 25 LOCATE_SOURCE = $(LOCATE_TARGET) ; 26 SEARCH_SOURCE = $(SUBDIR) $(LOCATE_SOURCE) 27 $(HOST_COMMON_DEBUG_LOCATE_TARGET) # Also add the standard output 28 $(TARGET_COMMON_DEBUG_LOCATE_TARGET) # dirs for generated sources. 29 ; 30} 31 32rule SetupFeatureObjectsDir feature 33{ 34 # SetupFeatureObjectsDir <feature> 35 # 36 # Updates the *{LOCATE,SEARCH}*_{TARGET,SOURCE} variables for the current 37 # directory appending a <feature> to each of them. Note that it resets 38 # the LOCATE_TARGET, LOCATE_SOURCE, SEARCH_SOURCE (!) variables. I.e. it 39 # should be invoked before customizing these variables further (e.g. like 40 # adding additional source directories to SEARCH_SOURCE). 41 42 COMMON_PLATFORM_LOCATE_TARGET 43 = [ FDirName $(COMMON_PLATFORM_LOCATE_TARGET) $(feature) ] ; 44 45 local var ; 46 for var in COMMON_ARCH COMMON_DEBUG DEBUG_$(HAIKU_DEBUG_LEVELS) { 47 HOST_$(var)_LOCATE_TARGET 48 = [ FDirName $(HOST_$(var)_LOCATE_TARGET) $(feature) ] ; 49 TARGET_$(var)_LOCATE_TARGET 50 = [ FDirName $(TARGET_$(var)_LOCATE_TARGET) $(feature) ] ; 51 } 52 53 LOCATE_TARGET = [ FDirName $(LOCATE_TARGET) $(feature) ] ; 54 LOCATE_SOURCE = $(LOCATE_TARGET) ; 55 SEARCH_SOURCE = $(SUBDIR) $(LOCATE_SOURCE) 56 $(HOST_COMMON_DEBUG_LOCATE_TARGET) # Also add the standard output 57 $(TARGET_COMMON_DEBUG_LOCATE_TARGET) # dirs for generated sources. 58 ; 59} 60 61rule SubIncludeGPL 62{ 63 # SubInclude rule that can be used to conditionally include GPL licensed 64 # add-ons 65 if $(HAIKU_INCLUDE_GPL_ADDONS) = 1 { 66 SubInclude $(1) ; 67 } 68} 69 70 71# pragma mark - MakeLocate variants 72 73 74rule MakeLocateCommonPlatform 75{ 76 # The file is shared between all target platforms. 77 MakeLocate $(1) : $(COMMON_PLATFORM_LOCATE_TARGET) ; 78} 79 80rule MakeLocatePlatform 81{ 82 # The file is specific for the target platform, but 83 # architecture independent. Usually the right rule for generated 84 # sources, though sometimes sources can be architecture specific. 85 local files = $(1) ; 86 local file ; 87 for file in $(files) { 88 if [ on $(file) return $(PLATFORM) ] = host { 89 MakeLocate $(file) : $(HOST_COMMON_ARCH_LOCATE_TARGET) ; 90 } else { 91 MakeLocate $(file) : $(TARGET_COMMON_ARCH_LOCATE_TARGET) ; 92 } 93 } 94} 95 96rule MakeLocateArch 97{ 98 # The file is platform+architecture specific, but is debug 99 # level independent. This is usually the right rule for generated 100 # architecture specific data or source files. 101 local files = $(1) ; 102 local file ; 103 for file in $(files) { 104 if [ on $(file) return $(PLATFORM) ] = host { 105 MakeLocate $(file) : $(HOST_COMMON_DEBUG_LOCATE_TARGET) ; 106 } else { 107 MakeLocate $(file) : $(TARGET_COMMON_DEBUG_LOCATE_TARGET) ; 108 } 109 } 110} 111 112rule MakeLocateDebug 113{ 114 # The file is platform+architecture+debug level specific. 115 # That's what should be used for compiled code. 116 local files = $(1) ; 117 local file ; 118 for file in $(files) { 119 on $(file) { 120 if $(PLATFORM) = host { 121 MakeLocate $(file) : $(HOST_DEBUG_$(DEBUG)_LOCATE_TARGET) ; 122 } else { 123 MakeLocate $(file) : $(TARGET_DEBUG_$(DEBUG)_LOCATE_TARGET) ; 124 } 125 } 126 } 127} 128 129 130# pragma mark - Deferred SubIncludes 131 132 133# The variable used to collect the deferred SubIncludes. 134HAIKU_DEFERRED_SUB_INCLUDES = ; 135 136rule DeferredSubInclude params : jamfile : scope 137{ 138 # DeferredSubInclude <subdir tokens> [ : <jamfile name> [ : <scope> ] ] ; 139 # 140 # Takes the same directory tokens parameter as SubInclude plus an optional 141 # alternative Jamfile name. The the subdirectory referred to by 142 # <subdir tokens> will be included when ExecuteDeferredSubIncludes is 143 # invoked, i.e. at the end of the root Jamfile. The <jamfile name> parameter 144 # specifies the name of the Jamfile to include. By default it is "Jamfile". 145 # The <scope> parameter can be "global" (default) or "local", specifying 146 # whether the alternative Jamfile name shall also be used for subdirectories. 147 148 HAIKU_DEFERRED_SUB_INCLUDES += "/" $(params) ; 149 if $(jamfile) { 150 SetConfigVar JAMFILE : $(params) : $(jamfile) : $(scope) ; 151 } 152} 153 154rule ExecuteDeferredSubIncludes 155{ 156 # ExecuteDeferredSubIncludes ; 157 # 158 # Performs the deferred SubIncludes scheduled by DeferredSubInclude. 159 160 local tokensList = $(HAIKU_DEFERRED_SUB_INCLUDES) ; 161 while $(tokensList) { 162 # chop off leading "/" 163 tokensList = $(tokensList[2-]) ; 164 165 # get the tokens for the next include 166 local tokens ; 167 while $(tokensList) && $(tokensList[1]) != "/" { 168 tokens += $(tokensList[1]) ; 169 tokensList = $(tokensList[2-]) ; 170 } 171 172 # perform the include 173 if $(tokens) { 174 SubInclude $(tokens) ; 175 } 176 } 177} 178 179rule HaikuSubInclude tokens 180{ 181 # HaikuSubInclude <tokens> ; 182 # 183 # Current subdir relative SubInclude. 184 # <tokens> - subdir tokens specifying the subdirectory to be include 185 # (relative to the current subdir) 186 187 if $(tokens) { 188 SubInclude HAIKU_TOP $(SUBDIR_TOKENS) $(tokens) ; 189 } 190} 191 192 193# pragma mark - Unique IDs/targets 194 195 196# private to NextID; incremented with each NextID invocation 197HAIKU_NEXT_ID = 0 ; 198 199rule NextID 200{ 201 # NextID ; 202 203 local result = $(HAIKU_NEXT_ID:J=) ; 204 HAIKU_NEXT_ID = [ AddNumAbs $(HAIKU_NEXT_ID) : 1 ] ; 205 return $(result) ; 206} 207 208rule NewUniqueTarget basename 209{ 210 # NewUniqueTarget [ basename ] ; 211 212 local id = [ NextID ] ; 213 return $(basename[1]:E=_target:G=unique!target)_$(id) ; 214} 215 216 217# pragma mark - RunCommandLine 218 219 220rule RunCommandLine commandLine 221{ 222 # RunCommandLine <commandLine> 223 # 224 # Creates a pseudo target that, when made by jam, causes the supplied shell 225 # command line to be executed. Elements of <commandLine> with the prefix ":" 226 # are replaced by the rule. After stripping the prefix such a string specifies 227 # a build system target and the finally executed command line will contain 228 # a path to the target instead. 229 # The pseudo target will depend on all targets thus identified. Each 230 # invocation of this rule creates a different pseudo target, which is 231 # returned to the caller. 232 233 # collect the targets in the command line and replace them by $targetX* 234 # variables 235 local substitutedCommandLine ; 236 local targets ; 237 238 local targetVarName = target ; 239 local i ; 240 for i in $(commandLine) { 241 # targets are marked by the ":" prefix 242 local target = [ Match ^:(.*) : $(i) ] ; 243 if $(target) { 244 targets += $(target) ; 245 targetVarName = $(targetVarName)X ; 246 i = "$"$(targetVarName) ; 247 } 248 249 substitutedCommandLine += $(i) ; 250 } 251 252 # define the "run" target 253 local run = [ NewUniqueTarget run ] ; 254 COMMAND_LINE on $(run) = $(substitutedCommandLine) ; 255 NotFile $(run) ; 256 Always $(run) ; 257 Depends $(run) : $(targets) ; 258 RunCommandLine1 $(run) : $(targets) ; 259 260 return $(run) ; 261} 262 263actions RunCommandLine1 { 264 target=target; 265 for t in $(2) ; do 266 target=${target}X 267 eval "${target}=${t}" 268 done 269 $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) 270 "$(COMMAND_LINE)" 271} 272 273 274#pragma mark - DefineBuildProfile 275 276 277rule DefineBuildProfile name : type : path { 278 # DefineBuildProfile <name> : <type> [ : <path> ] 279 # 280 # Makes a build profile known. Build profiles can be used to define 281 # different sets of settings for Haiku images/installations. For each 282 # profile the default actions "build", "update", and "mount" (the latter 283 # only for disks or image types) will be available (i.e. can be specified 284 # as second parameter on the jam command line). They will build an image 285 # or installation, update only given targets, respectively just mount the 286 # image or disk using the bfs_shell. 287 # 288 # <name> - The name of the build profile. 289 # <type> - The type of the build profile. Must be one of "image" (plain 290 # disk image), "anyboot-image" (custom disk image that can be 291 # written to CD or disk device), "cd-image" (ISO CD image), 292 # "vmware-image" (VMware disk image), "disk" (actual partition 293 # or hard disk device), "install" (installation in a directory), 294 # or "custom" (user-defined). 295 # <path> - The path associated with the profile. Depending on the profile 296 # type, this is the path to the disk image/VMware image, hard 297 # disk/partition device, or the installation directory. If the 298 # parameter is omitted, the value of the HAIKU[_VMWARE]_IMAGE_NAME, 299 # HAIKU_IMAGE_DIR, respectively HAIKU_INSTALL_DIR or their default 300 # values will be used instead. 301 302 if [ on $(name) return $(HAIKU_BUILD_PROFILE_SPECIFIED) ] { 303 Exit "ERROR: Build profile \"$(name)\" defined twice!" ; 304 } 305 HAIKU_BUILD_PROFILE_SPECIFIED on $(name) = 1 ; 306 307 if ! $(HAIKU_BUILD_PROFILE) || $(HAIKU_BUILD_PROFILE) != $(name) { 308 return ; 309 } 310 311 HAIKU_BUILD_PROFILE_DEFINED = 1 ; 312 313 # split path into directory path and name 314 local targetDir = $(path:D) ; 315 local targetName = $(path:BS) ; 316 317 # Jam's path splitting produces an empty string, if a component doesn't 318 # exist. That's a little unhandy for checks. 319 if $(targetDir) = "" { 320 targetDir = ; 321 } 322 if $(targetName) = "" { 323 targetName = ; 324 } 325 326 targetDir ?= $(HAIKU_IMAGE_DIR) ; 327 targetDir ?= $(HAIKU_DEFAULT_IMAGE_DIR) ; 328 329 # "disk" is "image" with HAIKU_DONT_CLEAR_IMAGE 330 if $(type) = "disk" { 331 type = "image" ; 332 HAIKU_DONT_CLEAR_IMAGE = 1 ; 333 } 334 335 local buildTarget ; 336 local startOffset ; 337 338 switch $(type) { 339 case "anyboot-image" : { 340 targetName ?= $(HAIKU_ANYBOOT_NAME) ; 341 targetName ?= $(HAIKU_DEFAULT_ANYBOOT_NAME) ; 342 HAIKU_ANYBOOT_DIR = $(targetDir) ; 343 HAIKU_ANYBOOT_NAME = $(targetName) ; 344 buildTarget = haiku-anyboot-image ; 345 } 346 347 case "cd-image" : { 348 targetName ?= $(HAIKU_CD_NAME) ; 349 targetName ?= $(HAIKU_DEFAULT_CD_NAME) ; 350 HAIKU_CD_DIR = $(targetDir) ; 351 HAIKU_CD_NAME = $(targetName) ; 352 buildTarget = haiku-cd ; 353 } 354 355 case "image" : { 356 targetName ?= $(HAIKU_IMAGE_NAME) ; 357 targetName ?= $(HAIKU_DEFAULT_IMAGE_NAME) ; 358 HAIKU_IMAGE_DIR = $(targetDir) ; 359 HAIKU_IMAGE_NAME = $(targetName) ; 360 buildTarget = haiku-image ; 361 } 362 363 case "vmware-image" : { 364 targetName ?= $(HAIKU_VMWARE_IMAGE_NAME) ; 365 targetName ?= $(HAIKU_DEFAULT_VMWARE_IMAGE_NAME) ; 366 HAIKU_IMAGE_DIR = $(targetDir) ; 367 HAIKU_VMWARE_IMAGE_NAME = $(targetName) ; 368 buildTarget = haiku-vmware-image ; 369 startOffset = --start-offset 65536 ; 370 } 371 372 case "install" : { 373 path ?= $(HAIKU_INSTALL_DIR) ; 374 path ?= $(HAIKU_DEFAULT_INSTALL_DIR) ; 375 HAIKU_INSTALL_DIR = $(path) ; 376 buildTarget = install-haiku ; 377 } 378 379 case "custom" : { 380 # user-defined -- don't do anything 381 return 1 ; 382 } 383 384 case * : { 385 Exit "Unsupported build profile type: " $(type) ; 386 } 387 } 388 389 switch $(HAIKU_BUILD_PROFILE_ACTION) { 390 case "build" : { 391 JAM_TARGETS = $(buildTarget) ; 392 } 393 394 case "update" : { 395 JAM_TARGETS = $(buildTarget) ; 396 SetUpdateHaikuImageOnly 1 ; 397 HAIKU_PACKAGES_UPDATE_ONLY = 1 ; 398 HAIKU_INCLUDE_IN_IMAGE on $(HAIKU_BUILD_PROFILE_PARAMETERS) = 1 ; 399 HAIKU_INCLUDE_IN_PACKAGES on $(HAIKU_BUILD_PROFILE_PARAMETERS) = 1 ; 400 } 401 402 case "update-all" : { 403 JAM_TARGETS = $(buildTarget) ; 404 SetUpdateHaikuImageOnly 1 ; 405 HAIKU_PACKAGES_UPDATE_ONLY = 1 ; 406 HAIKU_INCLUDE_IN_IMAGE = 1 ; 407 HAIKU_INCLUDE_IN_PACKAGES = 1 ; 408 } 409 410 case "update-packages" : { 411 JAM_TARGETS = $(buildTarget) ; 412 SetUpdateHaikuImageOnly 1 ; 413 HAIKU_UPDATE_ALL_PACKAGES = 1 ; 414 } 415 416 case "mount" : { 417 if $(type) in "install" "cd-image" { 418 Exit "Build action \"mount\" not supported for profile type" 419 "\"$(type)\"." ; 420 } 421 422 local commandLine = :<build>bfs_shell $(startOffset) 423 \"$(targetName:D=$(targetDir))\" ; 424 JAM_TARGETS = [ RunCommandLine $(commandLine) ] ; 425 } 426 } 427 428 return 1 ; 429} 430 431 432# pragma mark - Build Features 433 434 435rule FIsBuildFeatureEnabled feature 436{ 437 # FIsBuildFeatureEnabled <feature> ; 438 # Returns whether the given build feature <feature> is enabled (if so: "1", 439 # if not: empty list). 440 # 441 # <feature> - The name of the build feature (all lower case). 442 443 if $(feature) in $(HAIKU_BUILD_FEATURES) { 444 return 1 ; 445 } 446 447 return ; 448} 449 450 451rule FMatchesBuildFeatures specification 452{ 453 # FMatchesBuildFeatures <specification> ; 454 # Returns whether the given build feature specification <specification> 455 # holds. <specification> consists of positive and negative build feature 456 # conditions. Conditions can be individual list elements and multiple 457 # conditions can be joined, separated by ",", in a single list element. The 458 # effect is the same; they are considered as single set of conditions. 459 # A positive condition does not start with a "!". It holds when the build 460 # feature named by the element is enabled. 461 # A negative condition starts with a "!". It holds when the build feature 462 # named by the string resulting from removing the leading "!" is not 463 # enabled. 464 # <specification> holds when it is not empty and 465 # * none of the negative conditions it contains hold and 466 # * if it contains any positive conditions, at least one one of them holds. 467 # 468 # <specification> - The build feature specification. A list of individual 469 # conditions or conditions joined by ",". 470 471 local splitSpecification ; 472 local element ; 473 for element in $(specification) { 474 splitSpecification += [ FSplitString $(element) : "," ] ; 475 } 476 return [ FSetConditionsHold $(splitSpecification) 477 : $(HAIKU_BUILD_FEATURES) ] ; 478} 479 480 481rule FFilterByBuildFeatures list 482{ 483 # FFilterByBuildFeatures <list> ; 484 # Filters the list annotated by build feature specifications and returns the 485 # resulting list. The list can be annotated in two different ways: 486 # * A single list element can be annotated by appending "@<specification>" 487 # to it, with <specification> being a build feature specification (a 488 # single comma-separated string). The element appears in the resulting 489 # list, only if <specification> holds. 490 # * A sublist can be annotated by enclosing it in "<specification> @{" (two 491 # separate list elements) and "}@", with <specification> being a build 492 # feature specification (a single comma-separated string). The enclosed 493 # sublist appears in the resulting list, only if <specification> holds. 494 # The sublist annotations can be nested. The annotations themselves don't 495 # appear in the resulting list. 496 # 497 # <list> - A list annotated with build feature specifications. 498 499 local filteredList ; 500 501 # Since we must look ahead one element to be able to decide whether an 502 # element is a regular list element or a features specification for a 503 # subsequent "@{". Hence we always process an element other than "@{" and 504 # "}@" in the next iteration. We append a dummy element to the list so we 505 # don't need special handling for the last element. 506 local evaluationStack = 1 ; 507 local previousElement ; 508 local element ; 509 for element in $(list) dummy { 510 local stackTop = $(evaluationStack[1]) ; 511 local processElement = $(previousElement) ; 512 switch $(element) { 513 case }@ : 514 { 515 # Pop the topmost specificaton off the stack. 516 evaluationStack = $(evaluationStack[2-]) ; 517 if ! $(evaluationStack) { 518 Exit "FFilterByBuildFeatures: Unbalanced @( in: " $(list) ; 519 } 520 521 processElement = $(previousElement) ; 522 previousElement = ; 523 } 524 case @{ : 525 { 526 if ! $(previousElement) { 527 Exit "FFilterByBuildFeatures: No feature specification" 528 "after )@ in: " $(list) ; 529 } 530 531 if $(evaluationStack[1]) = 1 532 && [ FMatchesBuildFeatures $(previousElement) ] { 533 evaluationStack = 1 $(evaluationStack) ; 534 } else { 535 evaluationStack = 0 $(evaluationStack) ; 536 } 537 538 processElement = ; 539 previousElement = ; 540 } 541 case * : 542 { 543 processElement = $(previousElement) ; 544 previousElement = $(element) ; 545 } 546 } 547 548 if $(processElement) && $(stackTop) = 1 { 549 local splitElement = [ Match "(.*)@([^@]*)" : $(processElement) ] ; 550 if $(splitElement) { 551 if [ FMatchesBuildFeatures $(splitElement[2]) ] { 552 filteredList += $(splitElement[1]) ; 553 } 554 } else { 555 filteredList += $(processElement) ; 556 } 557 } 558 } 559 560 if $(evaluationStack[2-]) { 561 Exit "FFilterByBuildFeatures: Unbalanced )@ in: " $(list) ; 562 } 563 564 return $(filteredList) ; 565} 566 567 568rule EnableBuildFeatures features : specification 569{ 570 # EnableBuildFeatures <features> : <specification> ; 571 # Enables the build features <features>, if the build features specification 572 # <specification> holds. If <specification> is omitted, the features are 573 # enabled unconditionally. 574 # The rule enables a build feature by adding its given lower case name to 575 # the build variable HAIKU_BUILD_FEATURES and defining a build variable 576 # HAIKU_BUILD_FEATURE_<FEATURE>_ENABLED (<FEATURE> being the upper case name 577 # of the build feature) to "1". 578 # 579 # <features> - A list of build feature names (lower case). 580 # <specification> - An optional build features specification (cf. 581 # FMatchesBuildFeatures). 582 583 if ! $(specification) 584 || [ FMatchesBuildFeatures $(specification) 585 : $(HAIKU_BUILD_FEATURES) ] { 586 local feature ; 587 for feature in $(features) { 588 HAIKU_BUILD_FEATURES += $(feature) ; 589 HAIKU_BUILD_FEATURE_$(feature:U)_ENABLED = 1 ; 590 } 591 } 592} 593 594 595rule BuildFeatureObject feature 596{ 597 # BuildFeatureObject <feature> ; 598 # Returns a unique object for the given build feature. It is used for 599 # attaching attribute values to it. 600 601 local featureObject = $(HAIKU_BUILD_FEATURE_$(feature:U)) ; 602 if ! $(featureObject) { 603 featureObject = [ NewUniqueTarget ] ; 604 HAIKU_BUILD_FEATURE_$(feature:U) = $(featureObject) ; 605 } 606 607 return $(featureObject) ; 608} 609 610 611rule SetBuildFeatureAttribute feature : attribute : values : package 612{ 613 # SetBuildFeatureAttribute <feature> : <attribute> : <values> 614 # [ : <package> ] ; 615 # Sets attribute <attribute> of a build feature <feature> to value <values>. 616 # If <package> is specified, it names the package the attribute belongs to. 617 618 local featureObject = [ BuildFeatureObject $(feature) ] ; 619 HAIKU_ATTRIBUTE_$(attribute) on $(featureObject) = $(values) ; 620 if $(package) { 621 HAIKU_ATTRIBUTE_$(attribute):package on $(featureObject) = $(package) ; 622 } 623} 624 625 626rule BuildFeatureAttribute feature : attribute : flags 627{ 628 # BuildFeatureAttribute <feature> : <attribute> [ : <flags> ] ; 629 # Returns the value of attribute <attribute> of a build feature <feature>. 630 # Flags can be a list of flags which influence the returned value. Currently 631 # only flag "path" is defined, which will convert the attribute value -- 632 # which is assumed to be a list of (gristed) targets with a path relative to 633 # the extraction directory of the build feature archive files -- to paths. 634 # A typical example is the "headers" attribute, whose value can be used as 635 # dependency, but which must be converted to a path to be a valid headers 636 # search path. 637 638 local featureObject = [ BuildFeatureObject $(feature) ] ; 639 local values 640 = [ on $(featureObject) return $(HAIKU_ATTRIBUTE_$(attribute)) ] ; 641 if path in $(flags) { 642 # get the attribute's package and the corresponding extraction dir 643 local package 644 = [ BuildFeatureAttribute $(feature) : $(attribute):package ] ; 645 local directory ; 646 if $(package) { 647 directory = [ BuildFeatureAttribute $(feature) 648 : $(package):directory ] ; 649 } 650 651 # translate the values 652 local paths ; 653 local value ; 654 for value in $(values:G=) { 655 paths += [ FDirName $(directory) $(value) ] ; 656 } 657 values = $(paths) ; 658 } 659 660 return $(values) ; 661} 662 663 664rule ExtractBuildFeatureArchives feature : list 665{ 666 # ExtractBuildFeatureArchives <feature> : <list> ; 667 # Downloads and extracts one or more archives for build feature <feature> 668 # and sets attributes for the build feature to extracted entries. The syntax 669 # for <list> is: 670 # "file:" <packageName> <url> 671 # <attribute>: <value> ... 672 # ... 673 # "file:" <packageName2> <url2> 674 # ... 675 # 676 # <packageName> specifies a short name for the archive (e.g. "base" for the 677 # base package, "devel" for the development package, etc.), <url> the URL 678 # from which to download the file. <attribute> and be any name and <value> 679 # any relative path in the extraction directory. 680 # 681 # The attribute with the name "depends" will be handled specially. Its 682 # <value> specifies the name of a package the current package depends on 683 # (e.g. "devel" typically depends on "base"). If such a dependency is 684 # specified the current package will be extracted to the same directory as 685 # the package it depends on. The "depends" attribute must precede any other 686 # attribute for the package. 687 # 688 # The rule also sets the build feature attribute "<packageName>:directory" 689 # to the extraction directory for each package. 690 691 while $(list) { 692 if $(list[1]) != file: { 693 Exit "ExtractBuildFeatureArchives: Expected \"file: ...\", got:" 694 $(list) ; 695 } 696 697 local package = $(list[2]) ; 698 local url = $(list[3]) ; 699 local fileName = $(url:BS) ; 700 list = $(list[4-]) ; 701 702 local file = [ DownloadFile $(fileName) : $(url) ] ; 703 704 local directory = [ FDirName $(HAIKU_OPTIONAL_BUILD_PACKAGES_DIR) 705 $(fileName:B) ] ; 706 directory = $(directory:G=$(package)) ; 707 708 while $(list) { 709 local attribute = [ Match "(.*):" : $(list[1]) ] ; 710 if ! $(attribute) { 711 Exit "ExtractBuildFeatureArchives: Expected attribute, got:" 712 $(list) ; 713 } 714 if $(attribute) = file { 715 break ; 716 } 717 718 list = $(list[2-]) ; 719 720 local values ; 721 722 while $(list) { 723 switch $(list[1]) { 724 case *: : 725 { 726 break ; 727 } 728 case * : 729 { 730 values += $(list[1]) ; 731 list = $(list[2-]) ; 732 } 733 } 734 } 735 736 if $(attribute) = depends { 737 # Inherit the extraction directory (with a different grist) and 738 # depend on the extraction directory of the base package. 739 local basePackage = $(values[1]) ; 740 local baseDirectory = [ BuildFeatureAttribute $(feature) 741 : $(basePackage):directory ] ; 742 directory = $(baseDirectory:G=$(package)) ; 743 Depends $(directory) : $(directory:G=$(basePackage)) ; 744 } else { 745 SetBuildFeatureAttribute $(feature) : $(attribute) 746 : [ ExtractArchive $(directory) 747 : $(values) : $(file) 748 : extracted-$(feature)-$(package) ] ; 749 SetBuildFeatureAttribute $(feature) : $(attribute):package 750 : $(package) ; 751 } 752 } 753 754 SetBuildFeatureAttribute $(feature) : $(package):directory 755 : $(directory:G=) ; 756 } 757} 758