⛏️ index : haiku.git

rule AddSharedObjectGlueCode
{
	# AddSharedObjectGlueCode <target> : <isExecutable> ;

	# we link with -nostdlib and add the required libs manually, when building
	# for Haiku
	local platform ;
	on $(1) {
		platform = $(PLATFORM) ;
		if $(platform) = haiku {
			local stdLibs = [ MultiArchDefaultGristFiles libroot.so ]
				[ TargetLibgcc ] ;
			local type = EXECUTABLE ;
			if $(2) != true {
				type = LIBRARY ;

				# special case for libroot: don't link it against itself
				if $(DONT_LINK_AGAINST_LIBROOT) {
					stdLibs = ;
				}
			}

			local beginGlue
				= $(HAIKU_$(type)_BEGIN_GLUE_CODE_$(TARGET_PACKAGING_ARCH)) ;
			local endGlue
				= $(HAIKU_$(type)_END_GLUE_CODE_$(TARGET_PACKAGING_ARCH)) ;

			LINK_BEGIN_GLUE on $(1) = $(beginGlue) ;
			LINK_END_GLUE on $(1) = $(endGlue) ;

			NEEDLIBS on $(1) = [ on $(1) return $(NEEDLIBS) ] $(stdLibs) ;
			Depends $(1) : $(stdLibs) $(beginGlue) $(endGlue) ;
			LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] -nostdlib
				-Xlinker --no-undefined ;
		}
	}

	# link against the compatibility libraries needed for the target
	if $(platform) != host && $(TARGET_HAIKU_COMPATIBILITY_LIBS) {
		LinkAgainst $(1) : $(TARGET_HAIKU_COMPATIBILITY_LIBS) ;
	}
}

rule Application
{
	# Application <name> : <sources> : <libraries> : <res> ;
	#
	if ! [ IsPlatformSupportedForTarget $(1) ] {
		return ;
	}

	AddResources $(1) : $(4) ;
	Main $(1) : $(2) ;
	LinkAgainst $(1) : $(3) ;
	LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ]
		-Xlinker -soname=_APP_ ;

	# we link with -nostdlib and add the required libs manually, when building
	# for Haiku
	AddSharedObjectGlueCode $(1) : true ;
}

rule StdBinCommands
{
	# StdBinCommands <sources> : <libs> : <res> ;
	local libs = $(2) ;
	local ress = $(3) ;
	local source ;
	for source in $(1)
	{
		local target = $(source:S=) ;

		Application $(target) : $(source) : $(libs) : $(ress) ;
	}
}

rule Addon target : sources : libraries : isExecutable
{
	# Addon <target> : <sources> : <is executable> : <libraries> ;
	# <target>: The add-on.
	# <sources>: Source files.
	# <libraries>: Libraries to be linked against.
	# <isExecutable>: true, if the target shall be executable as well.

	if ! [ IsPlatformSupportedForTarget $(target) ] {
		return ;
	}

	Main $(target) : $(sources) ;

	local linkFlags = -Xlinker -soname=\"$(target:G=)\" ;
	if $(isExecutable) != true {
		linkFlags = -shared $(linkFlags) ;
	}
	LINKFLAGS on $(target) = [ on $(target) return $(LINKFLAGS) ] $(linkFlags) ;
	LinkAgainst $(target) : $(libraries) ;

	AddSharedObjectGlueCode $(target) : $(isExecutable) ;
}

rule Translator target : sources : libraries : isExecutable
{
	# Translator <target> : <sources> : <libraries> : <isExecutable> ;
	Addon $(target) : $(sources) : $(libraries) : $(isExecutable) ;
}

rule ScreenSaver target : sources : libraries
{
	# ScreenSaver <target> : <sources> : <libraries> ;
	Addon $(target) : $(sources) : $(libraries) : false ;
}

rule StaticLibrary
{
	# StaticLibrary <lib> : <sources> : <otherObjects> ;
	# Creates a static library from sources.
	# <lib>: The static library to be built.
	# <sources>: List of source files.
	# <otherObjects>: List of additional object files.
	#
	local lib = $(1) ;
	local sources = [ FGristFiles $(2) ] ;
	local otherObjects = $(3) ;
	local objects = $(sources:S=$(SUFOBJ)) ;

	if ! [ IsPlatformSupportedForTarget $(1) ] {
		return ;
	}

	InheritPlatform $(objects) : $(lib) ;

	if $(TARGET_CC_IS_LEGACY_GCC_$(TARGET_PACKAGING_ARCH)) = 0
			&& [ on $(lib) return $(NO_HIDDEN_VISIBILITY) ] != 1 {
		CCFLAGS on $(objects) += -fvisibility=hidden ;
		C++FLAGS on $(objects) += -fvisibility=hidden ;
	}

	StaticLibraryFromObjects $(lib) : $(objects) $(otherObjects) ;
	Objects $(2) ;
}

rule StaticLibraryFromObjects
{
	if ! [ IsPlatformSupportedForTarget $(1) ] {
		return ;
	}

	LibraryFromObjects $(1) : $(2) ;
}

rule AssembleNasm
{
	if ! [ on $(1) return $(NASMFLAGS) ] {
		NASMFLAGS on $(1) = -f elf32 ;
	}

	Depends $(1) : $(2) [ on $(2) return $(PLATFORM) ] ;
}

actions AssembleNasm
{
	if test $(ASFLAGS) ; then
		$(HAIKU_NASM) -d $(ASFLAGS) $(NASMFLAGS) -I$(2:D)/ -o $(1) $(2) ;
	else
		$(HAIKU_NASM) $(NASMFLAGS) -I$(2:D)/ -o $(1) $(2) ;
	fi
}

rule Ld
{
	# Ld <name> : <objs> : <linkerscript> : <flags> ;
	#
	local target = $(1) ;
	local objects = $(2) ;
	local linkerScript = $(3) ;
	local linkerFlags = $(4) ;

	if $(linkerScript) {
		linkerFlags += --script=$(linkerScript) ;
	}

	on $(target) {
		if $(PLATFORM) = host {
			LINK on $(target) = $(HOST_LD) ;
			LINKFLAGS on $(target) = $(HOST_LDFLAGS) $(LINKFLAGS) $(linkerFlags) ;
		} else {
			LINK on $(target) = $(TARGET_LD_$(TARGET_PACKAGING_ARCH)) ;
			LINKFLAGS on $(target) = $(TARGET_LDFLAGS_$(TARGET_PACKAGING_ARCH))
				$(LINKFLAGS) $(linkerFlags) ;
		}

		NEEDLIBS on $(target) = $(NEEDLIBS) ;
		LINKLIBS on $(target) = $(LINKLIBS) ;
	}

	LocalClean clean : $(target) ;
	LocalDepends all : $(target) ;
	Depends $(target) : $(objects) ;

	MakeLocateDebug $(target) ;

	on $(1) XRes $(1) : $(RESFILES) ;
	if ! [ on $(1) return $(DONT_USE_BEOS_RULES) ] {
		SetType $(1) ;
		MimeSet $(1) ;
		SetVersion $(1) ;
	}
}

actions Ld
{
	$(LINK) $(LINKFLAGS) -o "$(1)" "$(2)" "$(NEEDLIBS)" $(LINKLIBS)
}

rule CreateAsmStructOffsetsHeader header : source : architecture
{
	# CreateAsmStructOffsetsHeader header : source : architecture
	#
	# Grist will be added to both header and source.

	header = [ FGristFiles $(header) ] ;
	source = [ FGristFiles $(source) ] ;

	TARGET_PACKAGING_ARCH on $(header) = $(architecture) ;

	# find out which headers, defines, etc. to use
	local headers ;
	local sysHeaders ;
	local defines ;
	local flags ;
	local includesSeparator ;
	local localIncludesOption ;
	local systemIncludesOption ;

	on $(header) { # use on $(1) variable values
		if ! $(PLATFORM) in $(SUPPORTED_PLATFORMS) {
			Echo $(PLATFORM) is not in SUPPORTED_PLATFORMS, cannot make struct-offsets header! ;
			return ;
		}

		# headers and defines
		headers = $(HAIKU_CONFIG_HEADERS) $(SEARCH_SOURCE) $(SUBDIRHDRS)
			$(HDRS) ;
		sysHeaders = $(SUBDIRSYSHDRS) $(SYSHDRS) ;
		defines = $(DEFINES) ;

		if $(PLATFORM) = host {
			sysHeaders += $(HOST_HDRS) ;
			defines += $(HOST_DEFINES) ;

			if $(USES_BE_API) {
				sysHeaders += $(HOST_BE_API_HEADERS) ;
			}
		} else {
			sysHeaders += [ FStandardHeaders $(TARGET_PACKAGING_ARCH) : C++ ]
				$(TARGET_HDRS_$(TARGET_PACKAGING_ARCH)) ;
			defines += $(TARGET_DEFINES_$(TARGET_PACKAGING_ARCH))
				$(TARGET_DEFINES) ;
		}

		# optimization flags
		if $(DEBUG) = 0 {
			flags += $(OPTIM) ;
		} else {
			flags += -O0 ;
		}

		if $(PLATFORM) = host {
			# warning flags
			if $(WARNINGS) != 0 {
				flags += $(HOST_WARNING_C++FLAGS) ;
				if $(WARNINGS) = treatAsErrors {
					flags += -Werror $(HOST_WERROR_FLAGS) ;
				}
			}

			# debug and other flags
			flags += $(HOST_C++FLAGS) $(HOST_DEBUG_$(DEBUG)_C++FLAGS)
				$(SUBDIRC++FLAGS) $(C++FLAGS) ;

			if $(USES_BE_API) {
				flags += $(HOST_BE_API_C++FLAGS) ;
			}

			C++ on $(header) = $(HOST_C++) ;

			includesSeparator = $(HOST_INCLUDES_SEPARATOR) ;
			localIncludesOption = $(HOST_LOCAL_INCLUDES_OPTION) ;
			systemIncludesOption = $(HOST_SYSTEM_INCLUDES_OPTION) ;
		} else {
			# warning flags
			if $(WARNINGS) != 0 {
				flags += $(TARGET_WARNING_C++FLAGS_$(TARGET_PACKAGING_ARCH)) ;
				if $(WARNINGS) = treatAsErrors {
					flags += -Werror
						$(TARGET_WERROR_FLAGS_$(TARGET_PACKAGING_ARCH)) ;
				}
			}

			# debug and other flags
			flags += $(TARGET_C++FLAGS_$(TARGET_PACKAGING_ARCH))
				$(TARGET_DEBUG_$(DEBUG)_C++FLAGS_$(TARGET_PACKAGING_ARCH))
				$(SUBDIRC++FLAGS) $(C++FLAGS) ;

			C++ on $(header) = $(TARGET_C++_$(TARGET_PACKAGING_ARCH)) ;

			includesSeparator
				= $(TARGET_INCLUDES_SEPARATOR_$(TARGET_PACKAGING_ARCH)) ;
			localIncludesOption
				= $(TARGET_LOCAL_INCLUDES_OPTION_$(TARGET_PACKAGING_ARCH)) ;
			systemIncludesOption
				= $(TARGET_SYSTEM_INCLUDES_OPTION_$(TARGET_PACKAGING_ARCH)) ;
		}
	}

	# Turn off "invalid use of offsetof()" macro warning. We use offsetof() also
	# for non-PODs. Since we're using the same compiler for the whole kernel and
	# don't do virtual inheritence, that works well enough.
	flags += -Wno-invalid-offsetof ;
		# TODO: Rather get rid of the respective offsetof() instances.

	# locate object, search for source, and set on target variables

	Depends $(header) : $(source) $(PLATFORM) ;
	SEARCH on $(source) += $(SEARCH_SOURCE) ;
	MakeLocate $(header) : [ FDirName $(TARGET_COMMON_DEBUG_OBJECT_DIR_$(architecture))
		system kernel ] ;
	LocalClean clean : $(header) ;

	HDRRULE on $(source) = HdrRule ;
	HDRSCAN on $(source) = $(HDRPATTERN) ;
	HDRSEARCH on $(source) = $(headers) $(sysHeaders) $(STDHDRS) ;
	HDRGRIST on $(source) = $(HDRGRIST) ;

	C++FLAGS on $(header) = $(flags) ;
	CCHDRS on $(header) = [ FIncludes $(headers) : $(localIncludesOption) ]
		$(includesSeparator)
		[ FSysIncludes $(sysHeaders) : $(systemIncludesOption) ] ;
	CCDEFS on $(header) = [ FDefines $(defines) ] ;

	CreateAsmStructOffsetsHeader1 $(header) : $(source) ;
}

actions CreateAsmStructOffsetsHeader1
{
 	$(C++) -S "$(2)" $(C++FLAGS) $(CCDEFS) $(CCHDRS) -o - \
		| $(SED) 's/@define/#define/g' | grep "#define" \
		| $(SED) -e 's/[\$\#]\([0-9]\)/\1/' > "$(1)"
	grep -q "#define" "$(1)"
}

rule MergeObjectFromObjects
{
	# MergeObjectFromObjects <name> : <objects> : <other objects> ;
	# Merges object files to an object file.
	# <name>: Name of the object file to create. No grist will be added.
	# <objects>: Object files to be merged. Grist will be added.
	# <other objects>: Object files or static libraries to be merged. No grist
	#                  will be added.
	#
	local objects = [ FGristFiles $(2) ] ;

	on $(1) {
		if ! $(PLATFORM) in $(SUPPORTED_PLATFORMS) {
			return ;
		}

		if $(PLATFORM) = host {
			LINK on $(1) = $(HOST_LD) ;
			LINKFLAGS on $(target) = $(HOST_LDFLAGS) ;
		} else {
			LINK on $(1) = $(TARGET_LD_$(TARGET_PACKAGING_ARCH)) ;
			LINKFLAGS on $(target)
				= $(TARGET_LDFLAGS_$(TARGET_PACKAGING_ARCH)) ;
		}
	}

	MakeLocateDebug $(1) ;
	Depends $(1) : $(objects) ;
	Depends $(1) : $(3) ;
	LocalDepends obj : $(1) ;
	MergeObjectFromObjects1 $(1) : $(objects) $(3) ;
}

actions MergeObjectFromObjects1
{
	$(LINK) $(LINKFLAGS) -r $(2) -o $(1)
}

rule MergeObject
{
	# MergeObject <name> : <sources> : <other objects> ;
	# Compiles source files and merges the object files to an object file.
	# <name>: Name of the object file to create. No grist will be added.
	# <sources>: Sources to be compiled. Grist will be added.
	# <other objects>: Object files or static libraries to be merged. No grist
	#                  will be added.
	#
	local target = $(1) ;
	local sources = [ FGristFiles $(2) ] ;
	local otherObjects = $(3) ;
	local objects = $(sources:S=$(SUFOBJ)) ;

	if ! [ IsPlatformSupportedForTarget $(1) ] {
		return ;
	}

	InheritPlatform $(objects) : $(target) ;
	Objects $(sources) ;
	MergeObjectFromObjects $(target) : $(objects) : $(otherObjects) ;
}

rule SharedLibraryFromObjects
{
	# SharedLibraryFromObjects <lib> : <objects> : <libraries> ;
	#
	local _lib = $(1) ;

	if ! [ IsPlatformSupportedForTarget $(1) ] {
		return ;
	}

	local soname = [ on $(_lib) return $(HAIKU_SONAME) ] ;
	soname ?= $(_lib:BS) ;

	MainFromObjects $(_lib) : $(2) ;
	LINKFLAGS on $(_lib) = [ on $(_lib) return $(LINKFLAGS) ]
		-shared -Xlinker -soname=\"$(soname)\" ;
	LinkAgainst $(_lib) : $(3) ;

	AddSharedObjectGlueCode $(_lib) : false ;
}

rule SharedLibrary
{
	# SharedLibrary <lib> : <sources> : <libraries> : <abiVersion> ;
	local lib = $(1) ;
	local sources = [ FGristFiles $(2) ] ;
	local objects = $(sources:S=$(SUFOBJ)) ;
	local libs = $(3) ;
	local abiVersion = $(4) ;	# major ABI (soname) version for lib (if any)

	if ! [ IsPlatformSupportedForTarget $(1) ] {
		return ;
	}

	if $(abiVersion) {
		HAIKU_SONAME on $(lib) = $(lib:BS).$(abiVersion) ;
		HAIKU_LIB_ABI_VERSION on $(lib) = $(abiVersion) ;
	}

	InheritPlatform $(objects) : $(lib) ;
	Objects $(sources) ;
	SharedLibraryFromObjects $(lib) : $(objects) : $(libs) ;
}

rule LinkAgainst
{
	# LinkAgainst <name> : <libs> [ : <mapLibs> ] ;
	# Valid elements for <libs> are e.g. "be" or "libtranslation.so" or
	# "/boot/.../libfoo.so". If the basename starts with "lib" or the thingy
	# has a dirname or grist, it is added to the NEEDLIBS variable (i.e. the
	# file will be bound!), otherwise it is prefixed "-l" and added to
	# LINKLIBS. If you want to specify a target that isn't a library and
	# also has neither grist nor a dirname, you can prepend "<nogrist>" as
	# grist; it will be stripped by this rule.
	# <mapLibs> specifies whether the to translate library names (e.g. "be"
	# to "libbe.so" in case of target platform "haiku"). Defaults to "true".
	#
	local target = $(1) ;
	local libs = $(2) ;
	local mapLibs = $(3:E=true) ;

	local linkLibs ;
	local needLibs ;

	on $(target) {
		local i ;

		# map libraries, if desired and target platform is Haiku
		local map = $(TARGET_LIBRARY_NAME_MAP_$(TARGET_PACKAGING_ARCH)) ;
		if $(PLATFORM) != host && $(mapLibs) = true && $(map) {
			local mappedLibs ;

			for i in $(libs) {
				local mapped = $($(map)_$(i)) ;
				mapped ?= $(i) ;
				mappedLibs += $(mapped) ;
			}

			libs = $(mappedLibs) ;
		}

		for i in $(libs) {
			local isfile = ;
			if $(i:D) || $(i:G) {
				isfile = true ;
				if $(i:G) = <nogrist> {
					i = $(i:G=) ;
				}
			} else {
				switch $(i:B)
				{
					# XXX: _APP_ and _KERNEL_ should not be needed for ELF.
					case _APP_ : isfile = true ;
					case _KERNEL_ : isfile = true ;
					case lib*	: isfile = true ;
					case *	: isfile = ;
				}
				if ! $(isfile) && ( $(i:S) = .so || $(i:S) = .a ) {
					isfile = true ;
				}
			}

			if $(isfile) {
				needLibs += $(i) ;
			} else {
				linkLibs += $(i) ;
			}
		}
	}

	# Copy in the library dependencies from any static libraries first.
	# (We have to do the [ on ... ] outside the on { } block. )
	for i in $(needLibs) {
		if $(i:S) = .a  {
			needLibs += [ on $(i) return $(NEEDLIBS) ] ;
			linkLibs += [ on $(i) return $(LINKLIBS) ] ;
		}
	}

	on $(target) {
		NEEDLIBS on $(1) = $(NEEDLIBS) $(needLibs) ;
		LINKLIBS on $(1) = $(LINKLIBS) -l$(linkLibs) ;

		if $(needLibs) && ! $(NO_LIBRARY_DEPENDENCIES) {
			Depends $(1) : $(needLibs) ;
		}
	}
}

rule AddResources
{
	# AddResources <name> : <resourcefiles> ;

	# add grist to the resource files which don't have any yet
	local resfiles ;
	local file ;
	for file in $(2) {
		if ! $(file:G) {
			file = [ FGristFiles $(file) ] ;
		}
		resfiles += $(file) ;
	}

	SEARCH on $(resfiles) += $(SEARCH_SOURCE) ;

	for file in $(resfiles) {
		if $(file:S) = .rdef {
			local rdef = $(file) ;
			file = $(rdef:S=.rsrc) ;
			ResComp $(file) : $(rdef) ;
		}
		InheritPlatform $(file) : $(1) ;
		RESFILES on $(1) += $(file) ;
	}
}

rule SetVersionScript target : versionScript
{
	# SetVersionScript <target> : <versionScript>
	#
	# Sets the version script for <target>. Grist will be added to
	# <versionScript> and SEARCH will be set on it.

	versionScript = [ FGristFiles $(versionScript) ] ;

	SEARCH on $(versionScript) += $(SEARCH_SOURCE) ;

	VERSION_SCRIPT on $(target) = $(versionScript) ;
	Depends $(target) : $(versionScript) ;
}

rule BuildPlatformObjects
{
	# Usage BuildPlatformObjects <sources> ;
	# <sources> The sources.
	#
	local sources = [ FGristFiles $(1) ] ;
	local objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;

	PLATFORM on $(objects) = host ;
	SUPPORTED_PLATFORMS on $(objects) = host ;

	Objects $(sources) ;
}

rule BuildPlatformMain
{
	# Usage BuildPlatformMain <target> : <sources> : <libraries> ;
	# <target> The executable/library.
	# <sources> The sources.
	# <libraries> Libraries to link against.
	#
	local target = $(1) ;
	local sources = $(2) ;
	local libs = $(3) ;
	local objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;

	PLATFORM on $(target) = host ;
	SUPPORTED_PLATFORMS on $(target) = host ;
	DONT_USE_BEOS_RULES on $(target) = true ;

	local usesBeAPI = [ on $(target) return $(USES_BE_API) ] ;
	if $(usesBeAPI) {
		# propagate the flag to the objects
		USES_BE_API on $(objects) = $(usesBeAPI) ;

		# add the build libroot
		local libroot = [ on $(target) return $(HOST_LIBROOT) ] ;
		Depends $(target) : $(libroot) ;
		NEEDLIBS on $(target) += $(libroot) ;
	}

	Main $(target) : $(sources) ;
	LinkAgainst $(target) : $(libs) ;
}

rule BuildPlatformSharedLibrary
{
	# Usage BuildPlatformSharedLibrary <target> : <sources> : <libraries> ;
	# <target> The library.
	# <sources> The sources.
	# <libraries> Libraries to link against.
	#
	local target = $(1) ;
	local sources = $(2) ;
	local libs = $(3) ;

	BuildPlatformMain $(target) : $(sources) : $(libs) ;

	if $(HOST_PLATFORM) = darwin {
		LINKFLAGS on $(target) = [ on $(target) return $(LINKFLAGS) ]
			-dynamic -dynamiclib -Xlinker -flat_namespace ;
	} else {
		LINKFLAGS on $(target) = [ on $(target) return $(LINKFLAGS) ]
			-shared -Xlinker -soname=\"$(target:G=)\" ;
	}

	local objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;
	CCFLAGS on $(objects) += $(HOST_PIC_CCFLAGS) ;
	C++FLAGS on $(objects) += $(HOST_PIC_C++FLAGS) ;
}

rule BuildPlatformMergeObject
{
	# BuildPlatformMergeObject <name> : <sources> : <other objects> ;
	# Compiles source files and merges the object files to an object file.
	# <name>: Name of the object file to create. No grist will be added.
	# <sources>: Sources to be compiled. Grist will be added.
	# <other objects>: Object files or static libraries to be merged. No grist
	#                  will be added.
	#
	local target = $(1) ;
	local sources = $(2) ;
	local otherObjects = $(3) ;
	local objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;

	PLATFORM on $(target) = host ;
	SUPPORTED_PLATFORMS on $(target) = host ;

	local usesBeAPI = [ on $(target[1]) return $(USES_BE_API) ] ;
	if $(usesBeAPI) {
		# propagate the flag to the objects
		USES_BE_API on $(objects) = $(usesBeAPI) ;
	}

	MergeObject $(target) : $(sources) : $(otherObjects) ;
}

rule BuildPlatformMergeObjectPIC target : sources : otherObjects
{
	# BuildPlatformMergeObjectPIC <name> : <sources> : <other objects> ;
	# Compiles source files and merges the object files to an object file.
	# Same as BuildPlatformMergeObject rule but adds position-independent
	# flags to the compiler (if any).
	# <name>: Name of the object file to create. No grist will be added.
	# <sources>: Sources to be compiled. Grist will be added.
	# <other objects>: Object files or static libraries to be merged. No grist
	#                  will be added.
	#
	ObjectCcFlags $(sources) : $(HOST_PIC_CCFLAGS) ;
	ObjectC++Flags $(sources) : $(HOST_PIC_C++FLAGS) ;

	BuildPlatformMergeObject $(target) : $(sources) : $(otherObjects) ;
}

rule BuildPlatformStaticLibrary lib : sources : otherObjects
{
	# BuildPlatformStaticLibrary <lib> : <sources> ;
	# Creates a static library from sources.
	# <lib>: The static library to be built.
	# <sources>: List of source files.
	# <otherObjects>: List of additional object files.
	#

	local objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;

	PLATFORM on $(lib) = host ;
	SUPPORTED_PLATFORMS on $(lib) = host ;

	local usesBeAPI = [ on $(lib) return $(USES_BE_API) ] ;
	if $(usesBeAPI) {
		# propagate the flag to the objects
		USES_BE_API on $(objects) = $(usesBeAPI) ;
	}

	StaticLibrary $(lib) : $(sources) : $(otherObjects) ;
}

rule BuildPlatformStaticLibraryPIC target : sources : otherObjects
{
	# Like BuildPlatformStaticLibrary, but producing position independent code.

	ObjectCcFlags $(sources) : $(HOST_PIC_CCFLAGS) ;
	ObjectC++Flags $(sources) : $(HOST_PIC_C++FLAGS) ;

	BuildPlatformStaticLibrary $(target) : $(sources) : $(otherObjects) ;
}

rule BootstrapStage0PlatformObjects sources : separateFromStandardSiblings
{
	# BootstrapStage0PlatformObjects <sources> : <separateFromStandardSiblings>
	# Builds objects from the given sources for stage0 of the bootstrap process.
	# <sources> The sources from which objects should be created.
	# <separateFromStandardSiblings> Pass 'true' if the same objects are built
	# in a different context, too, so that a separate grist and target location
	# is required. This defaults to ''.
	local source ;
	for source in $(sources) {
		local objectGrist ;
		if $(separateFromStandardSiblings) = true {
			objectGrist = "bootstrap!$(SOURCE_GRIST)" ;
		} else {
			objectGrist = $(SOURCE_GRIST) ;
		}
		local object = $(source:S=$(SUFOBJ):G=$(objectGrist)) ;
		PLATFORM on $(object) = bootstrap_stage0 ;
		SUPPORTED_PLATFORMS on $(object) = bootstrap_stage0 ;
		if $(separateFromStandardSiblings) = true {
			MakeLocate $(object) : [
				FDirName $(TARGET_DEBUG_$(DEBUG)_LOCATE_TARGET) bootstrap
			] ;
		}
		Object $(object) : $(source) ;
	}
}