1rule SetupObjectsDir 2{ 3 # SetupObjectsDir 4 # 5 # Internal rule used to set up the *{LOCATE,SEARCH}*_{TARGET,SOURCE} 6 # variables for the current directory. 7 8 local relPath = [ FDirName $(SUBDIR_TOKENS[2-]) ] ; 9 if $(relPath) = . { 10 relPath = ; 11 } 12 13 COMMON_PLATFORM_LOCATE_TARGET 14 = [ FDirName $(HAIKU_COMMON_PLATFORM_OBJECT_DIR) $(relPath) ] ; 15 HOST_COMMON_ARCH_LOCATE_TARGET 16 = [ FDirName $(HOST_COMMON_ARCH_OBJECT_DIR) $(relPath) ] ; 17 TARGET_COMMON_ARCH_LOCATE_TARGET 18 = [ FDirName $(TARGET_COMMON_ARCH_OBJECT_DIR) $(relPath) ] ; 19 20 local var ; 21 for var in COMMON_DEBUG DEBUG_$(HAIKU_DEBUG_LEVELS) { 22 HOST_$(var)_LOCATE_TARGET 23 = [ FDirName $(HOST_$(var)_OBJECT_DIR) $(relPath) ] ; 24 TARGET_$(var)_LOCATE_TARGET 25 = [ FDirName $(TARGET_$(var)_OBJECT_DIR_$(TARGET_PACKAGING_ARCH)) 26 $(relPath) ] ; 27 } 28 29 LOCATE_TARGET = $(COMMON_PLATFORM_LOCATE_TARGET) ; 30 LOCATE_SOURCE = $(LOCATE_TARGET) ; 31 SEARCH_SOURCE = $(SUBDIR) $(LOCATE_SOURCE) 32 $(HOST_COMMON_DEBUG_LOCATE_TARGET) # Also add the standard output 33 $(TARGET_COMMON_DEBUG_LOCATE_TARGET) # dirs for generated sources. 34 ; 35} 36 37rule SetupFeatureObjectsDir feature 38{ 39 # SetupFeatureObjectsDir <feature> 40 # 41 # Updates the *{LOCATE,SEARCH}*_{TARGET,SOURCE} variables for the current 42 # directory appending a <feature> to each of them. Note that it resets 43 # the LOCATE_TARGET, LOCATE_SOURCE, SEARCH_SOURCE (!) variables. I.e. it 44 # should be invoked before customizing these variables further (e.g. like 45 # adding additional source directories to SEARCH_SOURCE). 46 47 COMMON_PLATFORM_LOCATE_TARGET 48 = [ FDirName $(COMMON_PLATFORM_LOCATE_TARGET) $(feature) ] ; 49 50 local var ; 51 for var in COMMON_ARCH COMMON_DEBUG DEBUG_$(HAIKU_DEBUG_LEVELS) { 52 HOST_$(var)_LOCATE_TARGET 53 = [ FDirName $(HOST_$(var)_LOCATE_TARGET) $(feature) ] ; 54 TARGET_$(var)_LOCATE_TARGET 55 = [ FDirName $(TARGET_$(var)_LOCATE_TARGET) $(feature) ] ; 56 } 57 58 LOCATE_TARGET = [ FDirName $(LOCATE_TARGET) $(feature) ] ; 59 LOCATE_SOURCE = $(LOCATE_TARGET) ; 60 SEARCH_SOURCE = $(SUBDIR) $(LOCATE_SOURCE) 61 $(HOST_COMMON_DEBUG_LOCATE_TARGET) # Also add the standard output 62 $(TARGET_COMMON_DEBUG_LOCATE_TARGET) # dirs for generated sources. 63 ; 64} 65 66rule SubIncludeGPL 67{ 68 # SubInclude rule that can be used to conditionally include GPL licensed 69 # add-ons 70 if $(HAIKU_INCLUDE_GPL_ADDONS) = 1 { 71 SubInclude $(1) ; 72 } 73} 74 75 76# pragma mark - MakeLocate variants 77 78 79rule MakeLocateCommonPlatform files : subdir 80{ 81 # The file is shared between all target platforms. 82 MakeLocate $(files) 83 : [ FDirName $(COMMON_PLATFORM_LOCATE_TARGET) $(subdir) ] ; 84} 85 86rule MakeLocatePlatform files : subdir 87{ 88 # The file is specific for the target platform, but 89 # architecture independent. Usually the right rule for generated 90 # sources, though sometimes sources can be architecture specific. 91 local file ; 92 for file in $(files) { 93 local directory ; 94 if [ on $(file) return $(PLATFORM) ] = host { 95 directory = $(HOST_COMMON_ARCH_LOCATE_TARGET) ; 96 } else { 97 directory = $(TARGET_COMMON_ARCH_LOCATE_TARGET) ; 98 } 99 MakeLocate $(file) : [ FDirName $(directory) $(subdir) ] ; 100 } 101} 102 103rule MakeLocateArch files : subdir 104{ 105 # The file is platform+architecture specific, but is debug 106 # level independent. This is usually the right rule for generated 107 # architecture specific data or source files. 108 local file ; 109 for file in $(files) { 110 local directory ; 111 if [ on $(file) return $(PLATFORM) ] = host { 112 directory = $(HOST_COMMON_DEBUG_LOCATE_TARGET) ; 113 } else { 114 directory = $(TARGET_COMMON_DEBUG_LOCATE_TARGET) ; 115 } 116 MakeLocate $(file) : [ FDirName $(directory) $(subdir) ] ; 117 } 118} 119 120rule MakeLocateDebug files : subdir 121{ 122 # The file is platform+architecture+debug level specific. 123 # That's what should be used for compiled code. 124 local file ; 125 for file in $(files) { 126 local directory ; 127 on $(file) { 128 if $(PLATFORM) = host { 129 directory = $(HOST_DEBUG_$(DEBUG)_LOCATE_TARGET) ; 130 } else { 131 directory = $(TARGET_DEBUG_$(DEBUG)_LOCATE_TARGET) ; 132 } 133 } 134 MakeLocate $(file) : [ FDirName $(directory) $(subdir) ] ; 135 } 136} 137 138 139# pragma mark - Deferred SubIncludes 140 141 142# The variable used to collect the deferred SubIncludes. 143HAIKU_DEFERRED_SUB_INCLUDES = ; 144 145rule DeferredSubInclude params : jamfile : scope 146{ 147 # DeferredSubInclude <subdir tokens> [ : <jamfile name> [ : <scope> ] ] ; 148 # 149 # Takes the same directory tokens parameter as SubInclude plus an optional 150 # alternative Jamfile name. The the subdirectory referred to by 151 # <subdir tokens> will be included when ExecuteDeferredSubIncludes is 152 # invoked, i.e. at the end of the root Jamfile. The <jamfile name> parameter 153 # specifies the name of the Jamfile to include. By default it is "Jamfile". 154 # The <scope> parameter can be "global" (default) or "local", specifying 155 # whether the alternative Jamfile name shall also be used for subdirectories. 156 157 HAIKU_DEFERRED_SUB_INCLUDES += "/" $(params) ; 158 if $(jamfile) { 159 SetConfigVar JAMFILE : $(params) : $(jamfile) : $(scope) ; 160 } 161} 162 163rule ExecuteDeferredSubIncludes 164{ 165 # ExecuteDeferredSubIncludes ; 166 # 167 # Performs the deferred SubIncludes scheduled by DeferredSubInclude. 168 169 local tokensList = $(HAIKU_DEFERRED_SUB_INCLUDES) ; 170 while $(tokensList) { 171 # chop off leading "/" 172 tokensList = $(tokensList[2-]) ; 173 174 # get the tokens for the next include 175 local tokens ; 176 while $(tokensList) && $(tokensList[1]) != "/" { 177 tokens += $(tokensList[1]) ; 178 tokensList = $(tokensList[2-]) ; 179 } 180 181 # perform the include 182 if $(tokens) { 183 SubInclude $(tokens) ; 184 } 185 } 186} 187 188rule HaikuSubInclude tokens 189{ 190 # HaikuSubInclude <tokens> ; 191 # 192 # Current subdir relative SubInclude. 193 # <tokens> - subdir tokens specifying the subdirectory to be include 194 # (relative to the current subdir) 195 196 if $(tokens) { 197 SubInclude HAIKU_TOP $(SUBDIR_TOKENS) $(tokens) ; 198 } 199} 200 201 202# pragma mark - Unique IDs/targets 203 204 205# private to NextID; incremented with each NextID invocation 206HAIKU_NEXT_ID = 0 ; 207 208rule NextID 209{ 210 # NextID ; 211 212 local result = $(HAIKU_NEXT_ID:J=) ; 213 HAIKU_NEXT_ID = [ AddNumAbs $(HAIKU_NEXT_ID) : 1 ] ; 214 return $(result) ; 215} 216 217rule NewUniqueTarget basename 218{ 219 # NewUniqueTarget [ basename ] ; 220 221 local id = [ NextID ] ; 222 return $(basename[1]:E=_target:G=unique!target)_$(id) ; 223} 224 225 226# pragma mark - RunCommandLine 227 228 229rule RunCommandLine commandLine 230{ 231 # RunCommandLine <commandLine> 232 # 233 # Creates a pseudo target that, when made by jam, causes the supplied shell 234 # command line to be executed. Elements of <commandLine> with the prefix ":" 235 # are replaced by the rule. After stripping the prefix such a string specifies 236 # a build system target and the finally executed command line will contain 237 # a path to the target instead. 238 # The pseudo target will depend on all targets thus identified. Each 239 # invocation of this rule creates a different pseudo target, which is 240 # returned to the caller. 241 242 # collect the targets in the command line and replace them by $targetX* 243 # variables 244 local substitutedCommandLine ; 245 local targets ; 246 247 local targetVarName = target ; 248 local i ; 249 for i in $(commandLine) { 250 # targets are marked by the ":" prefix 251 local target = [ Match ^:(.*) : $(i) ] ; 252 if $(target) { 253 targets += $(target) ; 254 targetVarName = $(targetVarName)X ; 255 i = "$"$(targetVarName) ; 256 } 257 258 substitutedCommandLine += $(i) ; 259 } 260 261 # define the "run" target 262 local run = [ NewUniqueTarget run ] ; 263 COMMAND_LINE on $(run) = $(substitutedCommandLine) ; 264 NotFile $(run) ; 265 Always $(run) ; 266 Depends $(run) : $(targets) ; 267 RunCommandLine1 $(run) : $(targets) ; 268 269 return $(run) ; 270} 271 272actions RunCommandLine1 { 273 target=target; 274 for t in $(2) ; do 275 target=${target}X 276 eval "${target}=${t}" 277 done 278 $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) 279 "$(COMMAND_LINE)" 280} 281 282 283#pragma mark - DefineBuildProfile 284 285 286rule DefineBuildProfile name : type : path { 287 # DefineBuildProfile <name> : <type> [ : <path> ] 288 # 289 # Makes a build profile known. Build profiles can be used to define 290 # different sets of settings for Haiku images/installations. For each 291 # profile the default actions "build", "update", and "mount" (the latter 292 # only for disks or image types) will be available (i.e. can be specified 293 # as second parameter on the jam command line). They will build an image 294 # or installation, update only given targets, respectively just mount the 295 # image or disk using the bfs_shell. 296 # 297 # <name> - The name of the build profile. 298 # <type> - The type of the build profile. Must be one of "image" (plain 299 # disk image), "anyboot-image" (custom disk image that can be 300 # written to CD or disk device), "cd-image" (ISO CD image), 301 # "vmware-image" (VMware disk image), "disk" (actual partition 302 # or hard disk device), "install" (installation in a directory), 303 # or "custom" (user-defined). 304 # <path> - The path associated with the profile. Depending on the profile 305 # type, this is the path to the disk image/VMware image, hard 306 # disk/partition device, or the installation directory. If the 307 # parameter is omitted, the value of the HAIKU[_VMWARE]_IMAGE_NAME, 308 # HAIKU_IMAGE_DIR, respectively HAIKU_INSTALL_DIR or their default 309 # values will be used instead. 310 311 if [ on $(name) return $(HAIKU_BUILD_PROFILE_SPECIFIED) ] { 312 Exit "ERROR: Build profile \"$(name)\" defined twice!" ; 313 } 314 HAIKU_BUILD_PROFILE_SPECIFIED on $(name) = 1 ; 315 316 if ! $(HAIKU_BUILD_PROFILE) || $(HAIKU_BUILD_PROFILE) != $(name) { 317 return ; 318 } 319 320 HAIKU_BUILD_PROFILE_DEFINED = 1 ; 321 322 # split path into directory path and name 323 local targetDir = $(path:D) ; 324 local targetName = $(path:BS) ; 325 326 # Jam's path splitting produces an empty string, if a component doesn't 327 # exist. That's a little unhandy for checks. 328 if $(targetDir) = "" { 329 targetDir = ; 330 } 331 if $(targetName) = "" { 332 targetName = ; 333 } 334 335 targetDir ?= $(HAIKU_IMAGE_DIR) ; 336 targetDir ?= $(HAIKU_DEFAULT_IMAGE_DIR) ; 337 338 # "disk" is "image" with HAIKU_DONT_CLEAR_IMAGE 339 if $(type) = "disk" { 340 type = "image" ; 341 HAIKU_DONT_CLEAR_IMAGE = 1 ; 342 } 343 344 local buildTarget ; 345 local startOffset ; 346 347 switch $(type) { 348 case "anyboot-image" : { 349 targetName ?= $(HAIKU_ANYBOOT_NAME) ; 350 targetName ?= $(HAIKU_DEFAULT_ANYBOOT_NAME) ; 351 HAIKU_ANYBOOT_DIR = $(targetDir) ; 352 HAIKU_ANYBOOT_NAME = $(targetName) ; 353 buildTarget = haiku-anyboot-image ; 354 } 355 356 case "cd-image" : { 357 targetName ?= $(HAIKU_CD_NAME) ; 358 targetName ?= $(HAIKU_DEFAULT_CD_NAME) ; 359 HAIKU_CD_DIR = $(targetDir) ; 360 HAIKU_CD_NAME = $(targetName) ; 361 buildTarget = haiku-cd ; 362 } 363 364 case "image" : { 365 targetName ?= $(HAIKU_IMAGE_NAME) ; 366 targetName ?= $(HAIKU_DEFAULT_IMAGE_NAME) ; 367 HAIKU_IMAGE_DIR = $(targetDir) ; 368 HAIKU_IMAGE_NAME = $(targetName) ; 369 buildTarget = haiku-image ; 370 } 371 372 case "haiku-mmc-image" : { 373 targetName ?= $(HAIKU_MMC_IMAGE_NAME) ; 374 targetName ?= $(HAIKU_DEFAULT_MMC_IMAGE_NAME) ; 375 HAIKU_IMAGE_DIR = $(targetDir) ; 376 HAIKU_IMAGE_NAME = $(targetName) ; 377 buildTarget = haiku-mmc-image ; 378 } 379 380 case "vmware-image" : { 381 targetName ?= $(HAIKU_VMWARE_IMAGE_NAME) ; 382 targetName ?= $(HAIKU_DEFAULT_VMWARE_IMAGE_NAME) ; 383 HAIKU_IMAGE_DIR = $(targetDir) ; 384 HAIKU_VMWARE_IMAGE_NAME = $(targetName) ; 385 buildTarget = haiku-vmware-image ; 386 startOffset = --start-offset 65536 ; 387 } 388 389 case "install" : { 390 path ?= $(HAIKU_INSTALL_DIR) ; 391 path ?= $(HAIKU_DEFAULT_INSTALL_DIR) ; 392 HAIKU_INSTALL_DIR = $(path) ; 393 buildTarget = install-haiku ; 394 } 395 396 case "custom" : { 397 # user-defined -- don't do anything 398 return 1 ; 399 } 400 401 case * : { 402 Exit "Unsupported build profile type: " $(type) ; 403 } 404 } 405 406 switch $(HAIKU_BUILD_PROFILE_ACTION) { 407 case "build" : { 408 # If parameters are specified, only build those targets (under the 409 # influence of the build profile). 410 if $(HAIKU_BUILD_PROFILE_PARAMETERS) { 411 JAM_TARGETS = $(HAIKU_BUILD_PROFILE_PARAMETERS) ; 412 } else { 413 JAM_TARGETS = $(buildTarget) ; 414 } 415 } 416 417 case "update" : { 418 JAM_TARGETS = $(buildTarget) ; 419 SetUpdateHaikuImageOnly 1 ; 420 HAIKU_PACKAGES_UPDATE_ONLY = 1 ; 421 HAIKU_INCLUDE_IN_IMAGE on $(HAIKU_BUILD_PROFILE_PARAMETERS) = 1 ; 422 HAIKU_INCLUDE_IN_PACKAGES on $(HAIKU_BUILD_PROFILE_PARAMETERS) = 1 ; 423 } 424 425 case "update-all" : { 426 JAM_TARGETS = $(buildTarget) ; 427 SetUpdateHaikuImageOnly 1 ; 428 HAIKU_INCLUDE_IN_IMAGE = 1 ; 429 HAIKU_UPDATE_ALL_PACKAGES = 1 ; 430 } 431 432 case "update-packages" : { 433 JAM_TARGETS = $(buildTarget) ; 434 SetUpdateHaikuImageOnly 1 ; 435 HAIKU_UPDATE_ALL_PACKAGES = 1 ; 436 } 437 438 case "build-package-list" : { 439 HAIKU_IMAGE_LIST_PACKAGES_TARGET 440 = $(HAIKU_BUILD_PROFILE_PARAMETERS[1]) ; 441 HAIKU_IMAGE_ADDITIONAL_PACKAGES 442 = $(HAIKU_BUILD_PROFILE_PARAMETERS[2-]) ; 443 JAM_TARGETS = $(HAIKU_IMAGE_LIST_PACKAGES_TARGET) ; 444 } 445 446 case "mount" : { 447 if $(type) in "install" "cd-image" { 448 Exit "Build action \"mount\" not supported for profile type" 449 "\"$(type)\"." ; 450 } 451 452 local commandLine = :<build>bfs_shell $(startOffset) 453 \"$(targetName:D=$(targetDir))\" ; 454 JAM_TARGETS = [ RunCommandLine $(commandLine) ] ; 455 } 456 } 457 458 return 1 ; 459} 460