1rule SymLink 2{ 3 # SymLink <target> : <source> : <makeDefaultDependencies> ; 4 # Links <target> to <source>. 5 # <source> is the exact link contents. No binding is done. 6 # <makeDefaultDependencies> If true, <target> will be made a dependency 7 # of the `all' pseudo target, i.e. it will be made by default, and removed 8 # on `jam clean'. 9 10 local target = $(1) ; 11 local source = $(2) ; 12 local makeDefaultDependencies = $(3) ; 13 if ! $(makeDefaultDependencies) { 14 makeDefaultDependencies = true ; 15 } 16 LINKCONTENTS on $(target) = $(source) ; 17 SymLink1 $(target) ; 18 if $(makeDefaultDependencies) = true { 19 LocalDepends files : $(target) ; 20 LocalClean clean : $(target) ; 21 } 22} 23 24actions SymLink1 25{ 26 $(RM) "$(1)" && $(LN) -s "$(LINKCONTENTS)" "$(1)" 27} 28 29rule RelSymLink 30{ 31 # RelSymLink <link> : <link target> : <makeDefaultDependencies> ; 32 # Creates a relative symbolic link from <link> to <link target>. 33 # <link> and <link target> can be usual targets. They may have a grist 34 # and don't need to have any dirname. Their LOCATE variables are used to 35 # find their locations. 36 # <makeDefaultDependencies> If true (which is the default), <link> will be 37 # made a dependency of the `files' pseudo target, i.e. it will be made by 38 # default, and removed on `jam clean'. 39 40 local target = $(1) ; 41 local source = $(2) ; 42 local makeDefaultDependencies = $(3) ; 43 local targetDir = [ on $(target) FDirName $(LOCATE[1]) $(target:D) ] ; 44 local sourceDir = [ on $(source) FDirName $(LOCATE[1]) $(source:D) ] ; 45 local sourcePath = $(source:G=) ; 46 sourcePath = $(sourcePath:D=$(sourceDir)) ; 47 local targetDirComponents = [ FSplitPath $(targetDir) ] ; 48 local sourceComponents = [ FSplitPath $(sourcePath) ] ; 49 50 SymLink $(target) 51 : [ FRelPath $(targetDirComponents) : $(sourceComponents) ] 52 : $(makeDefaultDependencies) ; 53 NOUPDATE $(target) ; 54 Depends $(target) : $(source) ; 55} 56 57rule AbsSymLink 58{ 59 # AbsSymLink <link> : <link target> : <link dir> 60 # : <makeDefaultDependencies> ; 61 # Creates an absolute symbolic link from <link> to <link target>. 62 # <link> and <link target> must be usual targets. If <link dir> is 63 # given, then it is set as LOCATE directory on <link>. 64 # <makeDefaultDependencies> If true (which is the default), <link> will be 65 # made a dependency of the `files' pseudo target, i.e. it will be made by 66 # default, and removed on `jam clean'. 67 68 local makeDefaultDependencies = $(4) ; 69 if ! $(makeDefaultDependencies) { 70 makeDefaultDependencies = true ; 71 } 72 73 Depends $(1) : $(2) ; 74 if $(3) { 75 MakeLocate $(1) : $(3) ; 76 } 77 SEARCH on $(2) += $(SEARCH_SOURCE) ; 78 if $(makeDefaultDependencies) = true { 79 LocalDepends files : $(1) ; 80 LocalClean clean : $(1) ; 81 } 82} 83 84actions AbsSymLink 85{ 86 target="$(2)" 87 case "$target" in 88 /*) ;; 89 *) target=`pwd`/"$target";; 90 esac 91 $(RM) "$(1)" && $(LN) -s "$target" "$(1)" 92} 93 94rule HaikuInstall installAndUninstall : dir : sources : installgrist 95 : installRule : targets 96{ 97 # Usage: HaikuInstall <[ install [ and uninstall ] pseudotarget ]> 98 # : <directory> : <sources to install> : [ <installgrist> ] 99 # : [ <install rule> ] : [ <targets> ] ; 100 101 local install = $(installAndUninstall[1]) ; 102 install ?= install ; 103 local uninstall = $(installAndUninstall[2]) ; 104 uninstall ?= un$(install) ; 105 installgrist ?= $(INSTALLGRIST) ; 106 installRule ?= Install ; 107 108 targets ?= $(sources) ; 109 targets = $(targets:G=$(installgrist)) ; 110 111 NotFile $(install) ; 112 NotFile $(uninstall) ; 113 Depends $(install) : $(targets) ; 114 Clean $(uninstall) : $(targets) ; 115 116 SEARCH on $(sources) += $(SEARCH_SOURCE) ; 117 MakeLocate $(targets) : $(dir) ; 118 119 local source ; 120 for source in $(sources) { 121 local target = $(targets[1]) ; 122 targets = $(targets[2-]) ; 123 124 Depends $(target) : $(source) ; 125 $(installRule) $(target) : $(source) ; 126 127 if [ on $(target) return $(MODE) ] { 128 Chmod $(target) ; 129 } 130 131 if $(OWNER) && $(CHOWN) { 132 Chown $(target) ; 133 OWNER on $(target) = $(OWNER) ; 134 } 135 136 if $(GROUP) && $(CHGRP) { 137 Chgrp $(target) ; 138 GROUP on $(target) = $(GROUP) ; 139 } 140 } 141} 142 143rule InstallAbsSymLinkAdapter 144{ 145 # InstallAbsSymLinkAdapter <link> : <link target> 146 if ! [ on $(2) return $(TARGET) ] { 147 TARGET on $(2) = [ on $(2) return $(SEARCH) ] ; 148 } 149 AbsSymLink $(1) : $(2) : : false ; 150} 151 152rule HaikuInstallAbsSymLink 153{ 154 # Usage: HaikuInstallAbsSymLink <[ install [ and uninstall ] pseudotarget ]> 155 # : <directory> : <sources to install> 156 # : [ <installgrist> ] ; 157 HaikuInstall $(1) : $(2) : $(3) : $(4) : InstallAbsSymLinkAdapter ; 158} 159 160rule InstallRelSymLinkAdapter 161{ 162 # InstallRelSymLinkAdapter <link> : <link target> 163 if ! [ on $(2) return $(TARGET) ] { 164 TARGET on $(2) = [ on $(2) return $(SEARCH) ] ; 165 } 166 RelSymLink $(1) : $(2) : false ; 167} 168 169rule HaikuInstallRelSymLink 170{ 171 # Usage: HaikuInstallRelSymLink <[ install [ and uninstall ] pseudotarget ]> 172 # : <directory> : <sources to install> 173 # : [ <installgrist> ] ; 174 HaikuInstall $(1) : $(2) : $(3) : $(4) : InstallRelSymLinkAdapter ; 175} 176 177 178rule UnarchiveObjects 179{ 180 # UnarchiveObjects <target objects> : <static object> 181 182 MakeLocateArch $(1) ; 183 Depends $(1) : $(2) ; 184 SEARCH on $(2) = $(SEARCH_SOURCE) ; 185} 186 187actions UnarchiveObjects 188{ 189 ( cd $(1[1]:D) && $(TARGET_AR) $(TARGET_UNARFLAGS) "$(2)" $(1:BS) ) 190} 191 192 193rule ExtractArchive directory : entries : archiveFile : grist 194{ 195 # ExtractArchive <directory> : <entries> : <archiveFile> [ : <grist> ] 196 # 197 # Extract the archive file target <archiveFile> to directory <directory>. 198 # The rule can be called multiple times for different <entries> for the same 199 # <directory> and <archiveFile> combo. 200 # 201 # <directory> - The directory into which to extract the archive file. The 202 # directory is created is by this rule and it is the target 203 # that the extract action is associated with. 204 # <entries> - The entries of the archive file one is interested in. The 205 # rule always extracts the complete archive file, from the 206 # given entries the rule creates targets (using <grist>) 207 # representing the extracted entries. Those targets are 208 # returned by the rule. 209 # <archiveFile> - The archive file target to extract. 210 # <grist> - The grist used to create targets from <entries>. Defaults to 211 # "extracted". 212 213 grist ?= extracted ; 214 215 # Turn the entries into targets to build. 216 local targets ; 217 local entry ; 218 for entry in $(entries) { 219 local target = $(entry:G=$(grist)) ; 220 targets += $(target) ; 221 } 222 223 LOCATE on $(targets) = $(directory) ; 224 Depends $(targets) : $(directory) $(archiveFile) ; 225 NoUpdate $(targets) ; 226 227 # one-time initialization for the main target (the directory) 228 if ! [ on $(directory) return $(INITIALIZED) ] { 229 # make sure the parent dir exists 230 local parentDir = $(directory:PG=dir) ; 231 Depends $(directory) : $(parentDir) ; 232 MkDir $(parentDir) ; 233 234 NoUpdate $(directory) ; 235 Depends $(directory) : $(archiveFile) ; 236 switch $(archiveFile:S) 237 { 238 case .zip : ExtractZipArchive1 $(targets) : $(directory) 239 $(archiveFile) ; 240 case .tgz : ExtractTarArchive1 $(targets) : $(directory) 241 $(archiveFile) ; 242 case * : Exit "ExtractArchive: Unhandled archive extension: 243 $(archiveFile:S)" ; 244 } 245 INITIALIZED on $(directory) = 1 ; 246 } 247 248 # Use a dummy rule so that it looks to jam like the targets are actually 249 # built from the directory target. 250 ExtractArchiveDummy $(targets) : $(directory) ; 251 252 return $(targets) ; 253} 254 255actions ExtractZipArchive1 256{ 257 mkdir -p $(2[1]) 258 unzip -q -u -o -d $(2[1]) $(2[2]) 259} 260 261actions ExtractTarArchive1 262{ 263 mkdir -p $(2[1]) 264 tar -C $(2[1]) -xf $(2[2]) 265} 266 267actions ExtractArchiveDummy 268{ 269} 270 271rule ObjectReference 272{ 273 # ObjectReference <reference object> : <source object> 274 # Makes <reference object> refer to the same file as <source object>. 275 # The filenames must of course be identical. 276 # <source object> must have already been LOCATEd. 277 278 local ref = $(1) ; 279 local source = $(2) ; 280 if $(ref) != $(source) { 281 Depends $(ref) : $(source) ; 282 LOCATE on $(ref) = [ on $(source) return $(LOCATE) ] ; 283 } 284} 285 286rule ObjectReferences 287{ 288 # ObjectReferences <source objects> 289 # Creates local references to <source objects>, i.e. identifiers with the 290 # current grist referring to the same files. <source objects> must have 291 # already been LOCATEd. 292 293 local source ; 294 for source in $(1) { 295 ObjectReference [ FGristFiles $(source) ] : $(source) ; 296 } 297} 298 299rule CopySetHaikuRevision target : source 300{ 301 # CopySetHaikuRevision <target> : <source> 302 # 303 # Copy <source> to <target>, writing the SVN revision of the working root 304 # directory into the haiku revision section of <target>. 305 # 306 # <target> - Output file target. Gristed and located target. 307 # <source> - ELF object to be copied. Gristed and located target. 308 309 # If existent, make the target depend on the .svn/entries file in the 310 # root directory, so it gets updated when the revision changes due to 311 # "svn up". 312 if [ Glob [ FDirName $(HAIKU_TOP) .svn ] : entries ] { 313 local svnEntries = <haiku-rootdir-svn>entries ; 314 SEARCH on $(svnEntries) = [ FDirName $(HAIKU_TOP) .svn ] ; 315 Depends $(target) : $(svnEntries) ; 316 } else if [ Glob [ FDirName $(HAIKU_TOP) .git ] : index ] { 317 local gitIndex = <haiku-rootdir-git>index ; 318 SEARCH on $(gitIndex) = [ FDirName $(HAIKU_TOP) .git ] ; 319 Depends $(target) : $(gitIndex) ; 320 } else if [ Glob [ FDirName $(HAIKU_TOP) .hg ] : store ] { 321 local hgStore = <haiku-rootdir-hg>store ; 322 SEARCH on $(hgStore) = [ FDirName $(HAIKU_TOP) .hg ] ; 323 Depends $(target) : $(hgStore) ; 324 } 325 326 HAIKU_INCLUDE_IN_IMAGE on $(target) 327 = [ on $(source) return $(HAIKU_INCLUDE_IN_IMAGE) ] ; 328 329 Depends $(target) : <build>copyattr <build>set_haiku_revision $(source) ; 330 CopySetHaikuRevision1 $(target) 331 : <build>copyattr <build>set_haiku_revision $(source) ; 332} 333 334actions CopySetHaikuRevision1 335{ 336 $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) 337 # Try svn or git-svn 338 # Extract from "Revision: 12345" line 339 revision=`(LC_ALL=C LANG=C svn info $(HAIKU_TOP) || 340 (cd $(HAIKU_TOP) && [ -d .git/svn ] && LC_ALL=C LANG=C git svn info)) 2> /dev/null | 341 grep Revision | awk '{printf $2}'` 342 if [ "$revision" = 0 -o "$revision" = "" ]; then 343 # git-svn not present or not configured for this repository 344 # Try searching git logs for last git-svn commit 345 # Extract from " git-svn-id: .../haiku/trunk@12345 ..." line 346 revision=`cd $(HAIKU_TOP) && 347 git log --max-count=1 --grep="git-svn-id:" 2> /dev/null | 348 grep "git-svn-id:" | cut -d '@' -f 2 | 349 awk '{printf $1}'` 350 fi 351 if [ "$revision" = 0 -o "$revision" = "" ]; then 352 # Try searching hg log for last svn commit 353 # Extract from "(svn r12345) ..." line 354 revision=`(cd $(HAIKU_TOP) && 355 hg log --no-merges --template "{desc|firstline}\n") 2> /dev/null | 356 grep --max-count=1 "(svn r" | 357 sed -n -e 's,(svn r\(.*\)).*,\1,p'` 358 fi 359 if [ "$revision" = "" ]; then 360 revision=0 361 fi 362 $(2[1]) --data $(2[3]) $(1) && 363 $(2[2]) $(1) ${revision} 364} 365 366rule DataFileToSourceFile sourceFile : dataFile : dataVariable : sizeVariable 367{ 368 sourceFile = [ FGristFiles $(sourceFile) ] ; 369 MakeLocateCommonPlatform $(sourceFile) ; 370 371 sizeVariable ?= $(dataVariable)Size ; 372 373 DATA_VARIABLE on $(sourceFile) = $(dataVariable) ; 374 SIZE_VARIABLE on $(sourceFile) = $(sizeVariable) ; 375 376 Depends $(sourceFile) : <build>data_to_source $(dataFile) ; 377 DataFileToSourceFile1 $(sourceFile) : <build>data_to_source $(dataFile) ; 378 LocalClean clean : $(sourceFile) ; 379} 380 381actions DataFileToSourceFile1 382{ 383 $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) 384 $(2[1]) $(DATA_VARIABLE) $(SIZE_VARIABLE) $(2[2]) $(1) 385} 386 387rule DownloadLocatedFile target : url 388{ 389 URL on $(target) = $(url) ; 390 391 DownloadLocatedFile1 $(target) ; 392} 393 394actions DownloadLocatedFile1 395{ 396 wget -O $(1) $(URL) 397} 398 399rule DownloadFile file : url 400{ 401 file = $(file:G=download) ; 402 403 # Request the download only once. 404 if [ on $(file) return $(HAIKU_FILE_DOWNLOAD) ] { 405 return $(file) ; 406 } 407 408 HAIKU_FILE_DOWNLOAD on $(file) = 1 ; 409 410 MakeLocate $(file) : $(HAIKU_DOWNLOAD_DIR) ; 411 DownloadLocatedFile $(file) : $(url) ; 412 413 return $(file) ; 414} 415 416