haiku/build/jam/ImageRules
Ingo Weinhold afed18de79 New build system feature to shorten the turn-around times when working
with image files. E.g.

  jam -q update-image libbe.so kernel_x86

will only build libbe.so and the kernel (if necessary) and copy them
onto the already existing Haiku image. The MIME DB will not be
reinstalled, and only those source directories will be copied for which
the AddSourceDirectoryToHaikuImage rule is given a second argument
(e.g. "1"). The image will otherwise remain unchanged.

The "update-vmware-image" and "update-install" work similarly for the
VMWare image and the directory installation respectively. Note that, due
to the way the VMWare image is created (prepending a header to the
standard image), the file itself is fully rebuilt, i.e. changes made
during the emulation will be lost after updating the VMWare image.

The feature requires Haiku's jam. With other jam versions a similar
effect can be reached by accordingly setting the HAIKU_IMAGE_UPDATE_ONLY
and HAIKU_INCLUDE_IN_IMAGE in the UserBuildConfig file.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20602 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-04-06 21:13:35 +00:00

449 lines
11 KiB
Plaintext

rule FSameTargetWithPrependedGrist
{
# SameTargetWithPrependedGrist <target> : <grist to prepend> ;
#
local target = $(1) ;
local gristToPrepend = $(2) ;
local grist = $(target:G) ;
if $(grist) {
grist = $(gristToPrepend)!$(grist) ;
} else {
grist = $(gristToPrepend) ;
}
return $(target:G=$(grist)) ;
}
rule InitScript
{
# Note: The script must have been LOCATEd before.
local script = $(1) ;
local initScript
= [ FSameTargetWithPrependedGrist $(script) : init-script ] ;
if ! [ on $(script) return $(__is_initialized) ] {
__is_initialized on $(script) = true ;
MakeLocate $(initScript) : [ on $(script) return $(LOCATE) ] ;
Always $(initScript) ;
Depends $(script) : $(initScript) ;
InitScript1 $(initScript) ;
}
return $(initScript) ;
}
actions InitScript1
{
rm -f $(1)
echo -n > $(1)
}
rule AddVariableToScript script : variable : value
{
# AddVariableToScript <script> : <variable> : <value> ;
# interpret an empty variable value as empty string
if ! $(value) {
value = "" ;
}
InitScript $(script) ;
VARIABLE_DEFS on $(script) += "echo $(variable)=\\\"$(value[1])\\\" >> " ;
# if the value is an array, add the other array elements
value = $(value[2-]) ;
while $(value) {
VARIABLE_DEFS on $(script)
+= "echo $(variable)+=\\\" $(value[1])\\\" >> " ;
value = $(value[2-]) ;
}
AddVariableToScript1 $(script) ;
}
actions together AddVariableToScript1
{
$(VARIABLE_DEFS)$(1);
}
rule AddTargetVariableToScript
{
# AddTargetVariableToScript <script> : <target> [ : <variable> ] ;
#
local script = $(1) ;
local target = $(2) ;
local variable = $(3:E=$(target:BS)) ;
InitScript $(script) ;
# That's not completely save, if one has more than on target with the
# same base name. A unique pseudo target would have to be introduced
# to do it more correctly.
VARIABLE_NAME($(target:BS)) on $(script) = $(variable) ;
Depends $(script) : $(target) ;
AddTargetVariableToScript1 $(script) : $(target) ;
}
actions AddTargetVariableToScript1
{
echo "$(VARIABLE_NAME($(2:BS)))=\"$(2)\"" >> $(1)
}
rule AddDirectoryToHaikuImage directoryTokens
{
# AddDirectoryToHaikuImage <directoryTokens>
local directory = [ FDirName $(directoryTokens) ] ;
directory = $(directory:G=HaikuImage) ;
if ! [ on $(directory) return $(__is_on_image) ] {
INSTALL_DIRECTORIES on haiku-image-contents += $(directory) ;
__is_on_image on $(directory) = true ;
NotFile $(directory) ;
# mark the parent dir as not to be created
local parent = [ FReverse $(directoryTokens) ] ;
parent = [ FReverse $(parent[2-]) ] ;
if $(parent) {
parent = [ FDirName $(parent) ] ;
parent = $(parent:G=HaikuImage) ;
DONT_CREATE on $(parent) = true ;
}
}
return $(directory) ;
}
rule FilterImageUpdateTargets targets
{
# FilterImageUpdateTargets targets
local filteredTargets ;
local target ;
for target in $(targets) {
if [ on $(target) return $(HAIKU_INCLUDE_IN_IMAGE) ] {
filteredTargets += $(target) ;
}
}
return $(filteredTargets) ;
}
rule AddFilesToHaikuImage
{
# AddFilesToHaikuImage <directory> : <targets> [ : dest name ]
#
local directory = [ AddDirectoryToHaikuImage $(1) ] ;
local targets = $(2) ;
local destName = $(3) ;
# If the image shall only be updated, we filter out all targets not marked
# accordingly.
if $(HAIKU_IMAGE_UPDATE_ONLY) {
targets = [ FilterImageUpdateTargets $(targets) ] ;
}
# We create a unique dummy target per target to install.
local target ;
for target in $(targets) {
local name ;
if $(destName) {
name = $(destName) ;
} else {
name = $(target:G=:D=) ;
}
local destTarget = $(name:G=HaikuImage__$(directory:G=)) ;
TARGET on $(destTarget) = $(target) ;
INSTALL_DIR on $(destTarget) = $(directory) ;
INSTALL_TARGETS on $(target) += $(destTarget) ;
TARGETS_TO_INSTALL on $(directory) += $(destTarget) ;
}
}
rule AddSymlinkToHaikuImage directoryTokens : linkTarget : linkName
{
# AddSymlinkToHaikuImage <directory> : <link target> [ : <link name> ] ;
#
# If the image shall only be updated, we don't add any symlinks.
if $(HAIKU_IMAGE_UPDATE_ONLY) {
return ;
}
local directory = [ AddDirectoryToHaikuImage $(directoryTokens) ] ;
if ! $(linkName) {
local path = [ FReverse [ FSplitPath $(linkTarget) ] ] ;
linkName = $(path[1]) ;
}
local link = $(directory)/$(linkName) ;
SYMLINK_TARGET on $(link) = $(linkTarget) ;
SYMLINKS_TO_INSTALL on $(directory) += $(link) ;
}
rule AddSourceDirectoryToHaikuImage dirTokens : alwaysUpdate
{
# AddSourceDirectoryToHaikuImage <dirTokens> : <alwaysUpdate> ;
# If the image shall only be updated, we update sources only, if explicitely
# requested.
if ! $(HAIKU_IMAGE_UPDATE_ONLY) || $(alwaysUpdate) {
HAIKU_INSTALL_SOURCE_DIRS += [ FDirName $(HAIKU_TOP) $(dirTokens) ] ;
}
}
rule AddDriversToHaikuImage
{
# AddDriversToHaikuImage <relative directory> : <targets> ;
#
local relativeDirectoryTokens = $(1) ;
local targets = $(2) ;
local directoryTokens = beos system add-ons kernel drivers dev
$(relativeDirectoryTokens) ;
AddFilesToHaikuImage beos system add-ons kernel drivers bin : $(targets) ;
# If the image shall only be updated, we don't add any symlinks.
if $(HAIKU_IMAGE_UPDATE_ONLY) {
return ;
}
# get the relative symlink path prefix
local linkPrefix = ;
for i in $(relativeDirectoryTokens) {
linkPrefix += .. ;
}
linkPrefix += .. bin ;
# add the symlinks
local name ;
for name in $(targets:BS) {
AddSymlinkToHaikuImage $(directoryTokens)
: [ FDirName $(linkPrefix) $(name) ] : $(name) ;
}
}
rule AddDriverRegistrationToHaikuImage
{
# AddDriverRegistrationToHaikuImage <directory> : <link target> : <link names> ] ;
#
local relativeDirectoryTokens = $(1) ;
local target = $(2) ;
local links = $(3) ;
local directoryTokens = beos system add-ons kernel registration
$(relativeDirectoryTokens) ;
# get the relative symlink path prefix
local linkPrefix = ;
for i in $(relativeDirectoryTokens) {
linkPrefix += .. ;
}
linkPrefix += .. drivers bin ;
# add the symlink
AddSymlinkToHaikuImage $(directoryTokens)
: [ FDirName $(linkPrefix) $(target:BS) ] : $(links) ;
}
rule AddBootModuleSymlinks targets
{
# AddBootModuleSymlinks <targets> ;
#
# If the image shall only be updated, we don't add any symlinks.
if $(HAIKU_IMAGE_UPDATE_ONLY) {
return ;
}
# add the symlinks
local target ;
for target in $(targets) {
# Symlink to the first place where the target has been installed.
local destTarget = [ on $(target) return $(INSTALL_TARGETS[1]) ] ;
local installDir = [ on $(destTarget) return $(INSTALL_DIR) ] ;
if ! $(installDir) {
Echo "ERROR: AddBootModuleSymlinks: Can't create a symlink to"
"target" \"$(target)"\"." ;
Exit "ERROR: Add*ToHaikuImage has not been invoked for it yet." ;
}
local name = $(target:BS) ;
local linkTarget = [ FDirName /boot $(installDir:G=) $(name) ] ;
AddSymlinkToHaikuImage beos system add-ons kernel boot
: $(linkTarget) : $(name) ;
}
}
rule CreateHaikuImageMakeDirectoriesScript
{
local script = $(1) ;
MakeLocate $(script) : $(HAIKU_OUTPUT_DIR) ;
Always $(script) ;
local initScript = [ InitScript $(script) ] ;
local scriptBody
= [ FSameTargetWithPrependedGrist $(script) : script-body ] ;
LOCATE on $(scriptBody) = [ on $(script) return $(LOCATE) ] ;
Depends $(scriptBody) : $(initScript) ;
Depends $(script) : $(scriptBody) ;
local dirsToCreate ;
local dir ;
for dir in [ on haiku-image-contents return $(INSTALL_DIRECTORIES) ] {
if ! [ on $(dir) return $(DONT_CREATE) ] {
dirsToCreate += $(dir) ;
}
}
Depends $(scriptBody) : $(dirsToCreate) ;
# If the image shall only be updated, we don't create directories.
if $(dirsToCreate) && ! $(HAIKU_IMAGE_UPDATE_ONLY) {
CreateHaikuImageMakeDirectoriesScript1 $(scriptBody) : $(dirsToCreate) ;
}
}
actions piecemeal CreateHaikuImageMakeDirectoriesScript1
{
echo \$mkdir -p "\"\${tPrefix}$(2:G=)\"" >> $(1)
}
rule CreateHaikuImageCopyFilesScript
{
local script = $(1) ;
MakeLocate $(script) : $(HAIKU_OUTPUT_DIR) ;
Always $(script) ;
local initScript = [ InitScript $(script) ] ;
local scriptBody
= [ FSameTargetWithPrependedGrist $(script) : script-body ] ;
LOCATE on $(scriptBody) = [ on $(script) return $(LOCATE) ] ;
Depends $(scriptBody) : $(initScript) ;
Depends $(script) : $(scriptBody) ;
local dir ;
for dir in [ on haiku-image-contents return $(INSTALL_DIRECTORIES) ] {
# filter the targets that shall be renamed; they have to be copied
# individually
local destTargets = [ on $(dir) return $(TARGETS_TO_INSTALL) ] ;
local remainingTargets ;
local destTarget ;
for destTarget in $(destTargets) {
local target = [ on $(destTarget) return $(TARGET) ] ;
local name = $(destTarget:BS) ;
if $(name) != $(target:BS) {
# use a unique dummy target for this file, on which we
# can define the TARGET_DIR variable
local dummyTarget = $(script)-dummy-$(dir:G=)-$(target) ;
NotFile $(dummyTarget) ;
TARGET_DIR on $(dummyTarget) = $(dir:G=) ;
INSTALL_TARGET_NAME on $(dummyTarget) = $(name) ;
Depends $(dummyTarget) : $(initScript) $(target) ;
Depends $(script) : $(dummyTarget) ;
AppendToHaikuImageCopyFilesScriptSingleFile $(dummyTarget)
: $(initScript) $(target) ;
} else {
remainingTargets += $(target) ;
}
}
targets = $(remainingTargets) ;
if $(targets) {
# use a unique dummy target for this directory, on which we
# can define the TARGET_DIR variable
local dummyTarget = $(script)-dummy-$(dir:G=) ;
NotFile $(dummyTarget) ;
TARGET_DIR on $(dummyTarget) = $(dir:G=) ;
Depends $(dummyTarget) : $(initScript) $(targets) ;
Depends $(script) : $(dummyTarget) ;
OUTPUT_SCRIPT on $(dummyTarget) = $(initScript) ;
AppendToHaikuImageCopyFilesScript $(dummyTarget) : $(targets) ;
}
local symlinks = [ on $(dir) return $(SYMLINKS_TO_INSTALL) ] ;
local symlink ;
for symlink in $(symlinks) {
NotFile $(symlink) ;
Depends $(script) : $(symlink) ;
Depends $(symlink) : $(initScript) ;
AddSymlinkToHaikuImageCopyFilesScript $(symlink) : $(initScript) ;
}
}
}
actions piecemeal AppendToHaikuImageCopyFilesScript bind OUTPUT_SCRIPT
{
echo \$cp "\"\${sPrefix}$(2)\"" "\"\${tPrefix}$(TARGET_DIR)\"" >> $(OUTPUT_SCRIPT)
}
actions AppendToHaikuImageCopyFilesScriptSingleFile
{
echo \$cp "\"\${sPrefix}$(2[2])\"" \
"\"\${tPrefix}$(TARGET_DIR)/$(INSTALL_TARGET_NAME)\"" >> $(2[1])
}
actions AddSymlinkToHaikuImageCopyFilesScript
{
echo \$ln -sfn "\"$(SYMLINK_TARGET)\"" "\"\${tPrefix}$(1:G=)\"" >> $(2[1])
}
rule BuildHaikuImage
{
# BuildHaikuImage <haiku image> : <scripts> : <is image> ;
#
local haikuImage = $(1) ;
local scripts = $(2) ;
local isImage = $(3) ;
if $(isImage) = 1 || $(isImage) = true {
IS_IMAGE on $(haikuImage) = 1 ;
} else {
IS_IMAGE on $(haikuImage) = "" ;
}
local mainScript = build_haiku_image ;
SEARCH on $(mainScript) = [ FDirName $(HAIKU_TOP) build scripts ] ;
Depends $(haikuImage) : $(mainScript) $(scripts) ;
BuildHaikuImage1 $(haikuImage) : $(mainScript) $(scripts) ;
}
actions BuildHaikuImage1
{
export isImage="$(IS_IMAGE)"
$(2[1]) $(2[2-])
}
rule BuildVMWareImage vmwareImage : plainImage : imageSize
{
# BuildVMWareImage <vmware image> : <plain image> : <image size in MB>
IMAGE_SIZE on $(vmwareImage) = $(imageSize) ;
Depends $(vmwareImage) : <build>vmdkheader $(plainImage) ;
BuildVMWareImage1 $(vmwareImage) : <build>vmdkheader $(plainImage) ;
}
actions BuildVMWareImage1
{
rm -f $(1)
$(2[1]) -h 64k -i$(IMAGE_SIZE)M $(1) &&
cat $(2[2]) >> $(1)
}