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 if [ Glob [ FDirName $(HAIKU_TOP) .git ] : index ] { 379 HAIKU_GIT_REVISION_DETERMINED on $(gitIndex) = 1 ; 380 SEARCH on $(gitIndex) = [ FDirName $(HAIKU_TOP) .git ] ; 381 MakeLocate $(revisionFile) : $(HAIKU_BUILD_OUTPUT_DIR) ; 382 Depends $(revisionFile) : $(gitIndex) ; 383 DetermineHaikuRevision1 $(revisionFile) : $(gitIndex) ; 384 } else { 385 revisionFile = ; 386 } 387 } 388 389 return $(revisionFile) ; 390} 391 392 393actions DetermineHaikuRevision1 394{ 395 $(HAIKU_TOP)/build/scripts/determine_haiku_revision $(HAIKU_TOP) $(1) 396} 397 398 399rule DataFileToSourceFile sourceFile : dataFile : dataVariable : sizeVariable 400{ 401 sourceFile = [ FGristFiles $(sourceFile) ] ; 402 MakeLocateCommonPlatform $(sourceFile) ; 403 404 sizeVariable ?= $(dataVariable)Size ; 405 406 DATA_VARIABLE on $(sourceFile) = $(dataVariable) ; 407 SIZE_VARIABLE on $(sourceFile) = $(sizeVariable) ; 408 409 Depends $(sourceFile) : <build>data_to_source $(dataFile) ; 410 DataFileToSourceFile1 $(sourceFile) : <build>data_to_source $(dataFile) ; 411 LocalClean clean : $(sourceFile) ; 412} 413 414actions DataFileToSourceFile1 415{ 416 $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) 417 $(2[1]) $(DATA_VARIABLE) $(SIZE_VARIABLE) $(2[2]) $(1) 418} 419 420rule DownloadLocatedFile target : url : source 421{ 422 # DownloadLocatedFile <target> : <url> [ : <source> ] ; 423 # 424 # <source> is an optional target that <target> will be made dependent on. 425 # Its resolved path can be used in <url> via '$source'. 426 427 URL on $(target) = $(url) ; 428 429 if $(source) { 430 Depends $(target) : $(source) ; 431 } 432 433 DownloadLocatedFile1 $(target) : $(source) ; 434} 435 436actions DownloadLocatedFile1 437{ 438 source="$(2)" 439 wget -O "$(1)" $(URL) || exit 1 440 touch "$(1)" 441} 442 443rule DownloadFile file : url : source 444{ 445 # DownloadFile <file> : <url> [ : <source> ] ; 446 # 447 # <source> is an optional target that the target will be made dependent on. 448 # Its resolved path can be used in <url> via '$source'. 449 450 file = $(file:G=download) ; 451 452 # Request the download only once. 453 if [ on $(file) return $(HAIKU_FILE_DOWNLOAD) ] { 454 return $(file) ; 455 } 456 457 HAIKU_FILE_DOWNLOAD on $(file) = 1 ; 458 459 MakeLocate $(file) : $(HAIKU_DOWNLOAD_DIR) ; 460 DownloadLocatedFile $(file) : $(url) : $(source) ; 461 462 return $(file) ; 463} 464 465 466actions ChecksumFileSHA256 467{ 468 $(HOST_SHA256) $(2) \ 469 | $(HOST_EXTENDED_REGEX_SED) 's,([^[:space:]]*).*,\1,' > $(1) 470 # The sed part is only necessary for sha256sum, but it doesn't harm for 471 # sha256 either. 472} 473 474 475rule StripFile target : source 476{ 477 # Note: The caller is reponsible for matching TARGET_PACKAGING_ARCH with 478 # the architecture the target was built for. 479 STRIP on $(target) = $(HAIKU_STRIP_$(TARGET_PACKAGING_ARCH)) ; 480 481 PropagateContainerUpdateTargetFlags $(target) : $(source) ; 482 483 LocalClean clean : $(target) ; 484 Depends $(target) : $(source) <build>xres <build>copyattr ; 485 StripFile1 $(target) : $(source) <build>xres <build>copyattr ; 486} 487 488 489actions StripFile1 490{ 491 $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) 492 "$(STRIP)" -o "$(1)" "$(2[1])" 493 "$(2[2])" -o "$(1)" "$(2[1])" 494 "$(2[3])" "$(2[1])" "$(1)" 495} 496 497 498rule StripFiles files 499{ 500 # Note: The caller is reponsible for matching TARGET_PACKAGING_ARCH with 501 # the architecture the targets were built for. 502 local strippedFiles ; 503 local file ; 504 for file in $(files) { 505 local strippedFile = $(file:G=stripped_$(file:G)) ; 506 # Place the stripped file in a "stripped" subdirectory of the file's 507 # location. 508 local location = [ on $(file) return $(LOCATE) ] ; 509 if ! $(location) { 510 location 511 = $(TARGET_COMMON_DEBUG_OBJECT_DIR_$(TARGET_PACKAGING_ARCH)) ; 512 } 513 MakeLocateArch $(strippedFile) : [ FDirName $(location) stripped ] ; 514 StripFile $(strippedFile) : $(file) ; 515 strippedFiles += $(strippedFile) ; 516 } 517 518 return $(strippedFiles) ; 519} 520