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