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