1RM_DIR ?= $(RM) -rf ; 2 3actions piecemeal together existing CleanDir 4{ 5 $(RM_DIR) "$(>)" 6} 7 8 9rule Copy 10{ 11 if $(2) { 12 SEARCH on $(2) += $(SEARCH_SOURCE) ; 13 Depends $(1) : <build>copyattr $(2) ; 14 Copy1 $(1) : <build>copyattr $(2) ; 15 } 16} 17 18 19actions Copy1 20{ 21 $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) \ 22 "$(2[1])" -d "$(2[2-])" "$(1)" 23} 24 25 26rule SymLink 27{ 28 # SymLink <target> : <source> : <makeDefaultDependencies> ; 29 # Links <target> to <source>. 30 # <source> is the exact link contents. No binding is done. 31 # <makeDefaultDependencies> If true, <target> will be made a dependency 32 # of the `all' pseudo target, i.e. it will be made by default, and removed 33 # on `jam clean'. 34 35 local target = $(1) ; 36 local source = $(2) ; 37 local makeDefaultDependencies = $(3) ; 38 if ! $(makeDefaultDependencies) { 39 makeDefaultDependencies = true ; 40 } 41 LINKCONTENTS on $(target) = $(source) ; 42 SymLink1 $(target) ; 43 if $(makeDefaultDependencies) = true { 44 LocalDepends files : $(target) ; 45 LocalClean clean : $(target) ; 46 } 47} 48 49actions SymLink1 50{ 51 $(RM) "$(1)" && $(LN) -s "$(LINKCONTENTS)" "$(1)" 52} 53 54rule RelSymLink 55{ 56 # RelSymLink <link> : <link target> : <makeDefaultDependencies> ; 57 # Creates a relative symbolic link from <link> to <link target>. 58 # <link> and <link target> can be usual targets. They may have a grist 59 # and don't need to have any dirname. Their LOCATE variables are used to 60 # find their locations. 61 # <makeDefaultDependencies> If true (which is the default), <link> will be 62 # made a dependency of the `files' pseudo target, i.e. it will be made by 63 # default, and removed on `jam clean'. 64 65 local target = $(1) ; 66 local source = $(2) ; 67 local makeDefaultDependencies = $(3) ; 68 local targetDir = [ on $(target) FDirName $(LOCATE[1]) $(target:D) ] ; 69 local sourceDir = [ on $(source) FDirName $(LOCATE[1]) $(source:D) ] ; 70 local sourcePath = $(source:G=) ; 71 sourcePath = $(sourcePath:D=$(sourceDir)) ; 72 local targetDirComponents = [ FSplitPath $(targetDir) ] ; 73 local sourceComponents = [ FSplitPath $(sourcePath) ] ; 74 75 SymLink $(target) 76 : [ FRelPath $(targetDirComponents) : $(sourceComponents) ] 77 : $(makeDefaultDependencies) ; 78 NOUPDATE $(target) ; 79 Depends $(target) : $(source) ; 80} 81 82rule AbsSymLink 83{ 84 # AbsSymLink <link> : <link target> : <link dir> 85 # : <makeDefaultDependencies> ; 86 # Creates an absolute symbolic link from <link> to <link target>. 87 # <link> and <link target> must be usual targets. If <link dir> is 88 # given, then it is set as LOCATE directory on <link>. 89 # <makeDefaultDependencies> If true (which is the default), <link> will be 90 # made a dependency of the `files' pseudo target, i.e. it will be made by 91 # default, and removed on `jam clean'. 92 93 local makeDefaultDependencies = $(4) ; 94 if ! $(makeDefaultDependencies) { 95 makeDefaultDependencies = true ; 96 } 97 98 Depends $(1) : $(2) ; 99 if $(3) { 100 MakeLocate $(1) : $(3) ; 101 } 102 SEARCH on $(2) += $(SEARCH_SOURCE) ; 103 if $(makeDefaultDependencies) = true { 104 LocalDepends files : $(1) ; 105 LocalClean clean : $(1) ; 106 } 107} 108 109actions AbsSymLink 110{ 111 target="$(2)" 112 case "$target" in 113 /*) ;; 114 *) target=`pwd`/"$target";; 115 esac 116 $(RM) "$(1)" && $(LN) -s "$target" "$(1)" 117} 118 119rule HaikuInstall installAndUninstall : dir : sources : installgrist 120 : installRule : targets 121{ 122 # Usage: HaikuInstall <[ install [ and uninstall ] pseudotarget ]> 123 # : <directory> : <sources to install> : [ <installgrist> ] 124 # : [ <install rule> ] : [ <targets> ] ; 125 126 local install = $(installAndUninstall[1]) ; 127 install ?= install ; 128 local uninstall = $(installAndUninstall[2]) ; 129 uninstall ?= un$(install) ; 130 installgrist ?= $(INSTALLGRIST) ; 131 installRule ?= Install ; 132 133 targets ?= $(sources) ; 134 targets = $(targets:G=$(installgrist)) ; 135 136 NotFile $(install) ; 137 NotFile $(uninstall) ; 138 Depends $(install) : $(targets) ; 139 Clean $(uninstall) : $(targets) ; 140 141 SEARCH on $(sources) += $(SEARCH_SOURCE) ; 142 MakeLocate $(targets) : $(dir) ; 143 144 local source ; 145 for source in $(sources) { 146 local target = $(targets[1]) ; 147 targets = $(targets[2-]) ; 148 149 Depends $(target) : $(source) ; 150 $(installRule) $(target) : $(source) ; 151 152 if [ on $(target) return $(MODE) ] { 153 Chmod $(target) ; 154 } 155 156 if $(OWNER) && $(CHOWN) { 157 Chown $(target) ; 158 OWNER on $(target) = $(OWNER) ; 159 } 160 161 if $(GROUP) && $(CHGRP) { 162 Chgrp $(target) ; 163 GROUP on $(target) = $(GROUP) ; 164 } 165 } 166} 167 168rule InstallAbsSymLinkAdapter 169{ 170 # InstallAbsSymLinkAdapter <link> : <link target> 171 if ! [ on $(2) return $(TARGET) ] { 172 TARGET on $(2) = [ on $(2) return $(SEARCH) ] ; 173 } 174 AbsSymLink $(1) : $(2) : : false ; 175} 176 177rule HaikuInstallAbsSymLink 178{ 179 # Usage: HaikuInstallAbsSymLink <[ install [ and uninstall ] pseudotarget ]> 180 # : <directory> : <sources to install> 181 # : [ <installgrist> ] ; 182 HaikuInstall $(1) : $(2) : $(3) : $(4) : InstallAbsSymLinkAdapter ; 183} 184 185rule InstallRelSymLinkAdapter 186{ 187 # InstallRelSymLinkAdapter <link> : <link target> 188 if ! [ on $(2) return $(TARGET) ] { 189 TARGET on $(2) = [ on $(2) return $(SEARCH) ] ; 190 } 191 RelSymLink $(1) : $(2) : false ; 192} 193 194rule HaikuInstallRelSymLink 195{ 196 # Usage: HaikuInstallRelSymLink <[ install [ and uninstall ] pseudotarget ]> 197 # : <directory> : <sources to install> 198 # : [ <installgrist> ] ; 199 HaikuInstall $(1) : $(2) : $(3) : $(4) : InstallRelSymLinkAdapter ; 200} 201 202 203rule UnarchiveObjects 204{ 205 # UnarchiveObjects <target objects> : <static object> 206 207 MakeLocateArch $(1) ; 208 Depends $(1) : $(2) ; 209 SEARCH on $(2) = $(SEARCH_SOURCE) ; 210} 211 212actions UnarchiveObjects 213{ 214 ( cd $(1[1]:D) && $(TARGET_AR_$(TARGET_PACKAGING_ARCH)) \ 215 $(TARGET_UNARFLAGS_$(TARGET_PACKAGING_ARCH)) "$(2)" $(1:BS) ) 216} 217 218 219rule ExtractArchive directory : entries : archiveFile : grist 220{ 221 # ExtractArchive <directory> : <entries> : <archiveFile> [ : <grist> ] 222 # 223 # Extract the archive file target <archiveFile> to directory <directory>. 224 # The rule can be called multiple times for different <entries> for the same 225 # <directory> and <archiveFile> combo. 226 # 227 # <directory> - The directory into which to extract the archive file. The 228 # directory is created by this rule and it is the target 229 # that the extract action is associated with. 230 # <entries> - The entries of the archive file one is interested in. The 231 # rule always extracts the complete archive file, from the 232 # given entries the rule creates targets (using <grist>) 233 # representing the extracted entries. Those targets are 234 # returned by the rule. 235 # <archiveFile> - The archive file target to extract. 236 # <grist> - The grist used to create targets from <entries>. Defaults to 237 # "extracted". 238 239 grist ?= extracted ; 240 241 # Turn the entries into targets to build. 242 local targets ; 243 local entry ; 244 for entry in $(entries) { 245 local target = $(entry:G=$(grist)) ; 246 targets += $(target) ; 247 } 248 249 LOCATE on $(targets) = $(directory:G=) ; 250 Depends $(targets) : $(directory) $(archiveFile) ; 251 NoUpdate $(targets) ; 252 253 # one-time initialization for the main target (the directory) 254 if ! [ on $(directory) return $(INITIALIZED) ] { 255 # make sure the parent dir exists 256 local parentDir = $(directory:PG=dir) ; 257 Depends $(directory) : $(parentDir) ; 258 MkDir $(parentDir) ; 259 260 NoUpdate $(directory) ; 261 Depends $(directory) : $(archiveFile) ; 262 switch $(archiveFile:S) 263 { 264 case .zip : 265 ExtractZipArchive1 $(directory) : $(archiveFile) ; 266 267 case .tgz : 268 ExtractTarArchive1 $(directory) : $(archiveFile) ; 269 270 case .hpkg : 271 Depends $(directory) : <build>package ; 272 ExtractHPKGArchive1 $(directory) 273 : <build>package $(archiveFile) ; 274 275 case "" : 276 Exit "ExtractArchive: No archive passed" ; 277 278 case * : 279 Exit "ExtractArchive: Unhandled archive extension:" 280 "$(archiveFile:S)" ; 281 } 282 INITIALIZED on $(directory) = 1 ; 283 } 284 285 return $(targets) ; 286} 287 288 289actions ExtractZipArchive1 290{ 291 mkdir -p $(1) 292 unzip -q -u -o -d $(1) $(2) 293} 294 295 296actions ExtractTarArchive1 297{ 298 mkdir -p $(1) 299 tar -C $(1) -xf $(2) 300} 301 302 303actions ExtractHPKGArchive1 304{ 305 mkdir -p "$(1)" 306 $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) \ 307 $(2[1]) extract -C "$(1)" "$(2[2])" 308} 309 310 311rule ObjectReference 312{ 313 # ObjectReference <reference object> : <source object> 314 # Makes <reference object> refer to the same file as <source object>. 315 # The filenames must of course be identical. 316 # <source object> must have already been LOCATEd. 317 318 local ref = $(1) ; 319 local source = $(2) ; 320 if $(ref) != $(source) { 321 Depends $(ref) : $(source) ; 322 LOCATE on $(ref) = [ on $(source) return $(LOCATE) ] ; 323 } 324} 325 326rule ObjectReferences 327{ 328 # ObjectReferences <source objects> 329 # Creates local references to <source objects>, i.e. identifiers with the 330 # current grist referring to the same files. <source objects> must have 331 # already been LOCATEd. 332 333 local source ; 334 for source in $(1) { 335 ObjectReference [ FGristFiles $(source) ] : $(source) ; 336 } 337} 338 339 340rule CopySetHaikuRevision target : source 341{ 342 # CopySetHaikuRevision <target> : <source> 343 # 344 # Copy <source> to <target>, writing the Git revision of the working 345 # directory into the haiku revision section of <target>. 346 # 347 # <target> - Output file target. Gristed and located target. 348 # <source> - ELF object to be copied. Gristed and located target. 349 350 PropagateContainerUpdateTargetFlags $(target) : $(source) ; 351 352 HAIKU_TARGET_IS_EXECUTABLE on $(target) = [ on $(source) 353 return $(HAIKU_TARGET_IS_EXECUTABLE) ] ; 354 355 local revisionFile = [ DetermineHaikuRevision ] ; 356 357 Depends $(target) 358 : <build>copyattr <build>set_haiku_revision $(source) $(revisionFile) ; 359 CopySetHaikuRevision1 $(target) 360 : <build>copyattr <build>set_haiku_revision $(source) $(revisionFile) ; 361} 362 363 364actions CopySetHaikuRevision1 365{ 366 export $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) 367 368 $(2[1]) --data $(2[3]) $(1) || exit 1 369 370 revision=0 371 if [ -n "$(2[4]:E=)" ]; then 372 revision="`cat $(2[4]:E=)`" 373 fi 374 $(2[2]) $(1) "$revision" 375} 376 377 378rule DetermineHaikuRevision 379{ 380 # If existing, make the target depend on the .git/index file in the 381 # root directory, so it gets updated when the revision changes due to 382 # commits or merges. 383 local gitIndex = <haiku-rootdir-git>index ; 384 local revisionFile = <haiku-rootdir>haiku-revision ; 385 if ! [ on $(gitIndex) return $(HAIKU_GIT_REVISION_DETERMINED) ] { 386 HAIKU_GIT_REVISION_DETERMINED on $(gitIndex) = 1 ; 387 MakeLocate $(revisionFile) : $(HAIKU_BUILD_OUTPUT_DIR) ; 388 LocalClean clean : $(revisionFile) ; 389 if $(HAIKU_REVISION) { 390 DetermineHaikuRevision2 $(revisionFile) ; 391 } else if [ Glob [ FDirName $(HAIKU_TOP) .git ] : index ] { 392 SEARCH on $(gitIndex) = [ FDirName $(HAIKU_TOP) .git ] ; 393 Depends $(revisionFile) : $(gitIndex) ; 394 DetermineHaikuRevision1 $(revisionFile) : $(gitIndex) ; 395 } else { 396 revisionFile = ; 397 } 398 } 399 400 return $(revisionFile) ; 401} 402 403 404actions DetermineHaikuRevision1 405{ 406 $(HAIKU_TOP)/build/scripts/determine_haiku_revision $(HAIKU_TOP) $(1) 407} 408 409 410actions DetermineHaikuRevision2 411{ 412 echo $(HAIKU_REVISION) > $(1) 413} 414 415 416rule DataFileToSourceFile sourceFile : dataFile : dataVariable : sizeVariable 417{ 418 sourceFile = [ FGristFiles $(sourceFile) ] ; 419 MakeLocateCommonPlatform $(sourceFile) ; 420 421 sizeVariable ?= $(dataVariable)Size ; 422 423 DATA_VARIABLE on $(sourceFile) = $(dataVariable) ; 424 SIZE_VARIABLE on $(sourceFile) = $(sizeVariable) ; 425 426 Depends $(sourceFile) : <build>data_to_source $(dataFile) ; 427 DataFileToSourceFile1 $(sourceFile) : <build>data_to_source $(dataFile) ; 428 LocalClean clean : $(sourceFile) ; 429} 430 431actions DataFileToSourceFile1 432{ 433 $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) \ 434 $(2[1]) $(DATA_VARIABLE) $(SIZE_VARIABLE) $(2[2]) $(1) 435} 436 437rule DownloadLocatedFile target : url : source 438{ 439 # DownloadLocatedFile <target> : <url> [ : <source> ] ; 440 # 441 # <source> is an optional target that <target> will be made dependent on. 442 # Its resolved path can be used in <url> via '$source'. 443 444 URL on $(target) = $(url) ; 445 446 if $(source) { 447 Depends $(target) : $(source) ; 448 } 449 450 DownloadLocatedFile1 $(target) : $(source) ; 451} 452 453if $(HAIKU_NO_DOWNLOADS) = 1 { 454 actions DownloadLocatedFile1 455 { 456 source="$(2)" 457 echo "ERROR: Would need to download $(URL), but HAIKU_NO_DOWNLOADS is set!" 458 exit 1 459 } 460} else { 461 actions DownloadLocatedFile1 462 { 463 source="$(2)" 464 wget --retry-connrefused --retry-on-host-error --timeout 30 -O "$(1)" $(URL) || exit 1 465 touch "$(1)" 466 } 467} 468 469rule DownloadFile file : url : source 470{ 471 # DownloadFile <file> : <url> [ : <source> ] ; 472 # 473 # <source> is an optional target that the target will be made dependent on. 474 # Its resolved path can be used in <url> via '$source'. 475 476 file = $(file:G=download) ; 477 478 # Request the download only once. 479 if [ on $(file) return $(HAIKU_FILE_DOWNLOAD) ] { 480 return $(file) ; 481 } 482 483 HAIKU_FILE_DOWNLOAD on $(file) = 1 ; 484 485 MakeLocate $(file) : $(HAIKU_DOWNLOAD_DIR) ; 486 DownloadLocatedFile $(file) : $(url) : $(source) ; 487 488 return $(file) ; 489} 490 491 492actions ChecksumFileSHA256 493{ 494 $(HOST_SHA256) $(2) \ 495 | $(HOST_EXTENDED_REGEX_SED) 's,([^[:space:]]*).*,\1,' > $(1) 496 # The sed part is only necessary for sha256sum, but it doesn't harm for 497 # sha256 either. 498} 499 500 501rule Sed target : source : substitutions : targetMap 502{ 503 # Sed <target> : [ <source> ] : <substitutions> [ : <targetMap> ] ; 504 # 505 # Performs substitutions in a text file. If <source> is given, that is the 506 # input, otherwise the substitutions are performed in place on <target>. The 507 # caller is responsible for locating <target>, <source>, and any other used 508 # target. 509 # 510 # <target> - The target file. 511 # <source> - The source file. If not given, the substitutions are performed 512 # in place on <target>. If given, a dependency of <target> to <source> 513 # will be established. 514 # <substitutions> - List of substitutions to be performed. Each element 515 # specifies a substitution. It's a partial sed "s" command of the form 516 # "<pattern>,<replacement>". 517 # <targetMap> - A list of elements of the form "<variable>=<mappedTarget>". 518 # <variable> specifies a name of a shell variable, <mappedTarget> a jam 519 # target whose bound name will be assigned to the shell variable. The 520 # variable can be used in <substitutions>. A dependency of <target> to 521 # <mappedTarget> will be established. 522 523 # We need a temporary (shell) file to which we write the target variable 524 # mappings and the sed invocations. This is necessary, since multiple rule 525 # invocations are allowed for a target, so that we cannot use on-target 526 # variables. 527 local script = [ NextID ] ; 528 script = temp-sed-script-$(target:BS)-$(script) ; 529 530 # process the target variable mappings 531 local mappedTargets ; 532 local targetMapElement ; 533 for targetMapElement in $(targetMap) { 534 local split = [ Match ([^=]+)=(.*) : $(targetMapElement) ] ; 535 HAIKU_SED_SCRIPT_VARIABLE on $(script) += $(split[1]) ; 536 local mappedTarget = $(split[2]) ; 537 mappedTargets += $(mappedTarget) ; 538 } 539 540 HAIKU_SED_SCRIPT_SUBSTITUTIONS on $(script) 541 = "-e \"s,$(substitutions),g\"" ; 542 HAIKU_SED_SCRIPT_SOURCE on $(script) = $(source) ; 543 if $(source) { 544 HAIKU_SED_SCRIPT_SOURCE_ARGUMENTS on $(script) = ">" ; 545 } else { 546 HAIKU_SED_SCRIPT_SOURCE_ARGUMENTS on $(script) = -i ; 547 } 548 549 # build the script 550 MakeLocate $(script) : $(HAIKU_TMP_DIR) ; 551 Depends $(script) : $(mappedTargets) $(source) ; 552 SedCreateScript $(script) : $(mappedTargets) ; 553 554 # build the target 555 Depends $(target) : $(script) ; 556 Sed1 $(target) : $(script) ; 557 RmTemps $(target) : $(script) ; 558} 559 560 561actions SedCreateScript bind HAIKU_SED_SCRIPT_SOURCE 562{ 563 set -o errexit 564 565 $(RM) "$(1)" 566 touch "$(1)" 567 568 set -- $(2) 569 for variable in "$(HAIKU_SED_SCRIPT_VARIABLE)" ; do 570 echo "$variable=\"$1\"" >> "$(1)" 571 shift 572 done 573 574 echo sed '$(HAIKU_SED_SCRIPT_SUBSTITUTIONS)' \ 575 '"$(HAIKU_SED_SCRIPT_SOURCE)"' "$(HAIKU_SED_SCRIPT_SOURCE_ARGUMENTS)" \ 576 '"$target"' >> "$(1)" 577} 578 579 580actions Sed1 581{ 582 set -o errexit 583 584 target="$(1)" 585 . "$(2)" 586} 587 588 589rule StripFile target : source 590{ 591 # Note: The caller is reponsible for matching TARGET_PACKAGING_ARCH with 592 # the architecture the target was built for. 593 STRIP on $(target) = $(HAIKU_STRIP_$(TARGET_PACKAGING_ARCH)) ; 594 595 PropagateContainerUpdateTargetFlags $(target) : $(source) ; 596 597 LocalClean clean : $(target) ; 598 Depends $(target) : $(source) <build>xres <build>copyattr ; 599 StripFile1 $(target) : $(source) <build>xres <build>copyattr ; 600} 601 602 603actions StripFile1 604{ 605 export $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) 606 "$(STRIP)" -o "$(1)" "$(2[1])" 607 "$(2[2])" -o "$(1)" "$(2[1])" 608 "$(2[3])" "$(2[1])" "$(1)" 609} 610 611 612rule StripFiles files 613{ 614 # Note: The caller is reponsible for matching TARGET_PACKAGING_ARCH with 615 # the architecture the targets were built for. 616 local strippedFiles ; 617 local file ; 618 for file in $(files) { 619 local strippedFile = $(file:G=stripped_$(file:G)) ; 620 # Place the stripped file in a "stripped" subdirectory of the file's 621 # location. 622 local location = [ on $(file) return $(LOCATE) ] ; 623 if ! $(location) { 624 location 625 = $(TARGET_COMMON_DEBUG_OBJECT_DIR_$(TARGET_PACKAGING_ARCH)) ; 626 } 627 MakeLocateArch $(strippedFile) : [ FDirName $(location) stripped ] ; 628 StripFile $(strippedFile) : $(file) ; 629 strippedFiles += $(strippedFile) ; 630 } 631 632 return $(strippedFiles) ; 633} 634