haiku/build/jam/MiscRules
Ingo Weinhold 161d45feb5 Support for package "update" build profile action
* Add global HAIKU_PACKAGES_UPDATE_ONLY build system variable, which is
  set for the "update" and "update-all" build profile actions.
* Change the HAIKU_INCLUDE_IN_CONTAINER_VAR variable on packages to
  HAIKU_INCLUDE_IN_PACKAGES for all packages. The variable is also
  set for the "update" and "update-all" build profile actions.
* Introduce HAIKU_CONTAINER_INHERIT_UPDATE_VARIABLE on container
  variable. If set, the contained variable will be set on the container
  when one or more files in it are updated. It is set on packages so an
  update of a file in a package causes the package to be updated in the
  image.
* Introduce HAIKU_CONTAINER_ALWAYS_CREATE_DIRECTORIES on container
  variable. If set, directories will be created also in update mode. It
  is set on packages.
2011-07-17 16:54:58 +02:00

424 lines
12 KiB
Plaintext

rule SetupObjectsDir
{
# SetupObjectsDir
#
# Internal rule used to set up the *{LOCATE,SEARCH}*_{TARGET,SOURCE}
# variables for the current directory.
local relPath = [ FDirName $(SUBDIR_TOKENS[2-]) ] ;
if $(relPath) = . {
relPath = ;
}
COMMON_PLATFORM_LOCATE_TARGET =
[ FDirName $(HAIKU_COMMON_PLATFORM_OBJECT_DIR) $(relPath) ] ;
local var ;
for var in COMMON_ARCH COMMON_DEBUG DEBUG_$(HAIKU_DEBUG_LEVELS) {
HOST_$(var)_LOCATE_TARGET
= [ FDirName $(HOST_$(var)_OBJECT_DIR) $(relPath) ] ;
TARGET_$(var)_LOCATE_TARGET
= [ FDirName $(TARGET_$(var)_OBJECT_DIR) $(relPath) ] ;
}
LOCATE_TARGET = $(COMMON_PLATFORM_LOCATE_TARGET) ;
LOCATE_SOURCE = $(LOCATE_TARGET) ;
SEARCH_SOURCE = $(SUBDIR) $(LOCATE_SOURCE)
$(HOST_COMMON_DEBUG_LOCATE_TARGET) # Also add the standard output
$(TARGET_COMMON_DEBUG_LOCATE_TARGET) # dirs for generated sources.
;
}
rule SetupFeatureObjectsDir feature
{
# SetupFeatureObjectsDir <feature>
#
# Updates the *{LOCATE,SEARCH}*_{TARGET,SOURCE} variables for the current
# directory appending a <feature> to each of them. Note that it resets
# the LOCATE_TARGET, LOCATE_SOURCE, SEARCH_SOURCE (!) variables. I.e. it
# should be invoked before customizing these variables further (e.g. like
# adding additional source directories to SEARCH_SOURCE).
COMMON_PLATFORM_LOCATE_TARGET
= [ FDirName $(COMMON_PLATFORM_LOCATE_TARGET) $(feature) ] ;
local var ;
for var in COMMON_ARCH COMMON_DEBUG DEBUG_$(HAIKU_DEBUG_LEVELS) {
HOST_$(var)_LOCATE_TARGET
= [ FDirName $(HOST_$(var)_LOCATE_TARGET) $(feature) ] ;
TARGET_$(var)_LOCATE_TARGET
= [ FDirName $(TARGET_$(var)_LOCATE_TARGET) $(feature) ] ;
}
LOCATE_TARGET = [ FDirName $(LOCATE_TARGET) $(feature) ] ;
LOCATE_SOURCE = $(LOCATE_TARGET) ;
SEARCH_SOURCE = $(SUBDIR) $(LOCATE_SOURCE)
$(HOST_COMMON_DEBUG_LOCATE_TARGET) # Also add the standard output
$(TARGET_COMMON_DEBUG_LOCATE_TARGET) # dirs for generated sources.
;
}
rule SubIncludeGPL
{
# SubInclude rule that can be used to conditionally include GPL licensed
# add-ons
if $(HAIKU_INCLUDE_GPL_ADDONS) = 1 {
SubInclude $(1) ;
}
}
# pragma mark - MakeLocate variants
rule MakeLocateCommonPlatform
{
# The file is shared between all target platforms.
MakeLocate $(1) : $(COMMON_PLATFORM_LOCATE_TARGET) ;
}
rule MakeLocatePlatform
{
# The file is specific for the target platform, but
# architecture independent. Usually the right rule for generated
# sources, though sometimes sources can be architecture specific.
local files = $(1) ;
local file ;
for file in $(files) {
if [ on $(file) return $(PLATFORM) ] = host {
MakeLocate $(file) : $(HOST_COMMON_ARCH_LOCATE_TARGET) ;
} else {
MakeLocate $(file) : $(TARGET_COMMON_ARCH_LOCATE_TARGET) ;
}
}
}
rule MakeLocateArch
{
# The file is platform+architecture specific, but is debug
# level independent. This is usually the right rule for generated
# architecture specific data or source files.
local files = $(1) ;
local file ;
for file in $(files) {
if [ on $(file) return $(PLATFORM) ] = host {
MakeLocate $(file) : $(HOST_COMMON_DEBUG_LOCATE_TARGET) ;
} else {
MakeLocate $(file) : $(TARGET_COMMON_DEBUG_LOCATE_TARGET) ;
}
}
}
rule MakeLocateDebug
{
# The file is platform+architecture+debug level specific.
# That's what should be used for compiled code.
local files = $(1) ;
local file ;
for file in $(files) {
on $(file) {
if $(PLATFORM) = host {
MakeLocate $(file) : $(HOST_DEBUG_$(DEBUG)_LOCATE_TARGET) ;
} else {
MakeLocate $(file) : $(TARGET_DEBUG_$(DEBUG)_LOCATE_TARGET) ;
}
}
}
}
# pragma mark - Deferred SubIncludes
# The variable used to collect the deferred SubIncludes.
HAIKU_DEFERRED_SUB_INCLUDES = ;
rule DeferredSubInclude params : jamfile : scope
{
# DeferredSubInclude <subdir tokens> [ : <jamfile name> [ : <scope> ] ] ;
#
# Takes the same directory tokens parameter as SubInclude plus an optional
# alternative Jamfile name. The the subdirectory referred to by
# <subdir tokens> will be included when ExecuteDeferredSubIncludes is
# invoked, i.e. at the end of the root Jamfile. The <jamfile name> parameter
# specifies the name of the Jamfile to include. By default it is "Jamfile".
# The <scope> parameter can be "global" (default) or "local", specifying
# whether the alternative Jamfile name shall also be used for subdirectories.
HAIKU_DEFERRED_SUB_INCLUDES += "/" $(params) ;
if $(jamfile) {
SetConfigVar JAMFILE : $(params) : $(jamfile) : $(scope) ;
}
}
rule ExecuteDeferredSubIncludes
{
# ExecuteDeferredSubIncludes ;
#
# Performs the deferred SubIncludes scheduled by DeferredSubInclude.
local tokensList = $(HAIKU_DEFERRED_SUB_INCLUDES) ;
while $(tokensList) {
# chop off leading "/"
tokensList = $(tokensList[2-]) ;
# get the tokens for the next include
local tokens ;
while $(tokensList) && $(tokensList[1]) != "/" {
tokens += $(tokensList[1]) ;
tokensList = $(tokensList[2-]) ;
}
# perform the include
if $(tokens) {
SubInclude $(tokens) ;
}
}
}
rule HaikuSubInclude tokens
{
# HaikuSubInclude <tokens> ;
#
# Current subdir relative SubInclude.
# <tokens> - subdir tokens specifying the subdirectory to be include
# (relative to the current subdir)
if $(tokens) {
SubInclude HAIKU_TOP $(SUBDIR_TOKENS) $(tokens) ;
}
}
# pragma mark - Unique IDs/targets
# private to NextID; incremented with each NextID invocation
HAIKU_NEXT_ID = 0 ;
rule NextID
{
# NextID ;
local result = $(HAIKU_NEXT_ID:J=) ;
HAIKU_NEXT_ID = [ AddNumAbs $(HAIKU_NEXT_ID) : 1 ] ;
return $(result) ;
}
rule NewUniqueTarget basename
{
# NewUniqueTarget [ basename ] ;
local id = [ NextID ] ;
return $(basename[1]:E=_target:G=unique!target)_$(id) ;
}
# pragma mark - RunCommandLine
rule RunCommandLine commandLine
{
# RunCommandLine <commandLine>
#
# Creates a pseudo target that, when made by jam, causes the supplied shell
# command line to be executed. Elements of <commandLine> with the prefix ":"
# are replaced by the rule. After stripping the prefix such a string specifies
# a build system target and the finally executed command line will contain
# a path to the target instead.
# The pseudo target will depend on all targets thus identified. Each
# invocation of this rule creates a different pseudo target, which is
# returned to the caller.
# collect the targets in the command line and replace them by $targetX*
# variables
local substitutedCommandLine ;
local targets ;
local targetVarName = target ;
local i ;
for i in $(commandLine) {
# targets are marked by the ":" prefix
local target = [ Match ^:(.*) : $(i) ] ;
if $(target) {
targets += $(target) ;
targetVarName = $(targetVarName)X ;
i = "$"$(targetVarName) ;
}
substitutedCommandLine += $(i) ;
}
# define the "run" target
local run = [ NewUniqueTarget run ] ;
COMMAND_LINE on $(run) = $(substitutedCommandLine) ;
NotFile $(run) ;
Always $(run) ;
Depends $(run) : $(targets) ;
RunCommandLine1 $(run) : $(targets) ;
return $(run) ;
}
actions RunCommandLine1 {
target=target;
for t in $(2) ; do
target=${target}X
eval "${target}=${t}"
done
$(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR)
"$(COMMAND_LINE)"
}
#pragma mark - DefineBuildProfile
rule DefineBuildProfile name : type : path {
# DefineBuildProfile <name> : <type> [ : <path> ]
#
# Makes a build profile known. Build profiles can be used to define
# different sets of settings for Haiku images/installations. For each
# profile the default actions "build", "update", and "mount" (the latter
# only for disks or image types) will be available (i.e. can be specified
# as second parameter on the jam command line). They will build an image
# or installation, update only given targets, respectively just mount the
# image or disk using the bfs_shell.
#
# <name> - The name of the build profile.
# <type> - The type of the build profile. Must be one of "image" (plain
# disk image), "anyboot-image" (custom disk image that can be
# written to CD or disk device), "cd-image" (ISO CD image),
# "vmware-image" (VMware disk image), "disk" (actual partition
# or hard disk device), "install" (installation in a directory),
# or "custom" (user-defined).
# <path> - The path associated with the profile. Depending on the profile
# type, this is the path to the disk image/VMware image, hard
# disk/partition device, or the installation directory. If the
# parameter is omitted, the value of the HAIKU[_VMWARE]_IMAGE_NAME,
# HAIKU_IMAGE_DIR, respectively HAIKU_INSTALL_DIR or their default
# values will be used instead.
if [ on $(name) return $(HAIKU_BUILD_PROFILE_SPECIFIED) ] {
Exit "ERROR: Build profile \"$(name)\" defined twice!" ;
}
HAIKU_BUILD_PROFILE_SPECIFIED on $(name) = 1 ;
if ! $(HAIKU_BUILD_PROFILE) || $(HAIKU_BUILD_PROFILE) != $(name) {
return ;
}
HAIKU_BUILD_PROFILE_DEFINED = 1 ;
# split path into directory path and name
local targetDir = $(path:D) ;
local targetName = $(path:BS) ;
# Jam's path splitting produces an empty string, if a component doesn't
# exist. That's a little unhandy for checks.
if $(targetDir) = "" {
targetDir = ;
}
if $(targetName) = "" {
targetName = ;
}
targetDir ?= $(HAIKU_IMAGE_DIR) ;
targetDir ?= $(HAIKU_DEFAULT_IMAGE_DIR) ;
# "disk" is "image" with HAIKU_DONT_CLEAR_IMAGE
if $(type) = "disk" {
type = "image" ;
HAIKU_DONT_CLEAR_IMAGE = 1 ;
}
local buildTarget ;
local startOffset ;
switch $(type) {
case "anyboot-image" : {
targetName ?= $(HAIKU_ANYBOOT_NAME) ;
targetName ?= $(HAIKU_DEFAULT_ANYBOOT_NAME) ;
HAIKU_ANYBOOT_DIR = $(targetDir) ;
HAIKU_ANYBOOT_NAME = $(targetName) ;
buildTarget = haiku-anyboot-image ;
}
case "cd-image" : {
targetName ?= $(HAIKU_CD_NAME) ;
targetName ?= $(HAIKU_DEFAULT_CD_NAME) ;
HAIKU_CD_DIR = $(targetDir) ;
HAIKU_CD_NAME = $(targetName) ;
buildTarget = haiku-cd ;
}
case "image" : {
targetName ?= $(HAIKU_IMAGE_NAME) ;
targetName ?= $(HAIKU_DEFAULT_IMAGE_NAME) ;
HAIKU_IMAGE_DIR = $(targetDir) ;
HAIKU_IMAGE_NAME = $(targetName) ;
buildTarget = haiku-image ;
}
case "vmware-image" : {
targetName ?= $(HAIKU_VMWARE_IMAGE_NAME) ;
targetName ?= $(HAIKU_DEFAULT_VMWARE_IMAGE_NAME) ;
HAIKU_IMAGE_DIR = $(targetDir) ;
HAIKU_VMWARE_IMAGE_NAME = $(targetName) ;
buildTarget = haiku-vmware-image ;
startOffset = --start-offset 65536 ;
}
case "install" : {
path ?= $(HAIKU_INSTALL_DIR) ;
path ?= $(HAIKU_DEFAULT_INSTALL_DIR) ;
HAIKU_INSTALL_DIR = $(path) ;
buildTarget = install-haiku ;
}
case "custom" : {
# user-defined -- don't do anything
return 1 ;
}
case * : {
Exit "Unsupported build profile type: " $(type) ;
}
}
switch $(HAIKU_BUILD_PROFILE_ACTION) {
case "build" : {
JAM_TARGETS = $(buildTarget) ;
}
case "update" : {
JAM_TARGETS = $(buildTarget) ;
SetUpdateHaikuImageOnly 1 ;
HAIKU_PACKAGES_UPDATE_ONLY = 1 ;
HAIKU_INCLUDE_IN_IMAGE on $(HAIKU_BUILD_PROFILE_PARAMETERS) = 1 ;
HAIKU_INCLUDE_IN_PACKAGES on $(HAIKU_BUILD_PROFILE_PARAMETERS) = 1 ;
}
case "update-all" : {
JAM_TARGETS = $(buildTarget) ;
SetUpdateHaikuImageOnly 1 ;
HAIKU_PACKAGES_UPDATE_ONLY = 1 ;
HAIKU_INCLUDE_IN_IMAGE = 1 ;
HAIKU_INCLUDE_IN_PACKAGES = 1 ;
}
case "mount" : {
if $(type) in "install" "cd-image" {
Exit "Build action \"mount\" not supported for profile type"
"\"$(type)\"." ;
}
local commandLine = :<build>bfs_shell $(startOffset)
\"$(targetName:D=$(targetDir))\" ;
JAM_TARGETS = [ RunCommandLine $(commandLine) ] ;
}
}
return 1 ;
}