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