โ›๏ธ index : haiku.git

##	Haiku Generic Jamfile Engine v1.0.2
##	Does all the hard work for the Generic Jamfile
##	which simply defines the project parameters.
##	Most of the real work is done in the Jambase
##	embedded into the jam executable.
##	
##	Inspired by the Be Makefile Engine
##
##	Supports Generic Jamfile v1.0.1
##
##	Copyright (c) 2002-2010 Ryan Leavengood
##	Copyright (c) 2011 Peter Polรกฤik
##	Released under the Terms of the MIT License, see
##	http://www.opensource.org/licenses/mit-license.html

##-------------------------------------------------------------------
## Define some utility rules
##-------------------------------------------------------------------

# AddResources <Application Name> : <Resource Files> ;
#   Adds the given resources to the given application.
rule AddResources
{
	Depends $(<) : $(>) ;
}

actions AddResources
{
	$(XRES) -o "$(<)" $(>)
}

# MimeSet <Application Name> ;
#   Sets the mime type of the given application to be an application.
actions MimeSet
{
	$(MIMESET) -f "$(<)"
}

# ProcessLibs <List of Library Names> ;
#   Prepends -l to any library names that aren't _APP_ or _KERNEL_ or
#   that don't have .a or .so file extensions.  The result will be given
#   to the linker so that it links to the right libraries.
rule ProcessLibs
{
	local result ;
	for i in $(1)
	{
		if ( ( $(i) in _APP_ _KERNEL_ ) || ( $(i:S) in .so .a ) )
		{
			result += $(i) ;
		}
		else
		{
			result += -l$(i) ;
		}
	}
	return $(result) ;
}

# MkObjectDirs <List of Source Files> ;
#   Makes the necessary sub-directories in the object target directory based
#   on the sub-directories used for the source files.
rule MkObjectDirs
{
	local dir ;
	for i in $(1)
	{
		dir = [ FDirName $(LOCATE_TARGET) $(i:D) ] ;
		Depends $(i:S=$(SUFOBJ)) : $(dir) ;
		MkDir $(dir) ;
	}
}

# CollectCatKeys <Pseudotarget Name> : <Source Files> ;
#   Collects catalog keys for localization from sources into per-locale files
rule CollectCatKeys
{
	Depends $(<) : $(>) ;
	Depends $(<) : $(LOCATE_TARGET) ;
	#Depends $(<) : $(SRCS) ;
	Depends $(CATKEYS_DIR)/en.catkeys : $(<) ;
}

actions CollectCatKeys
{
	cat $(SRCS) | gcc -E -x c++ $(HDRS) $(CCFLAGS) \
		-DB_COLLECTING_CATKEYS - > $(LOCATE_TARGET)/$(NAME).pre
	mkdir -p "$(CATKEYS_DIR)"
	collectcatkeys -s $(APP_MIME_SIG) $(LOCATE_TARGET)/$(NAME).pre \
		-o $(CATKEYS_DIR)/en.catkeys
}

# Catalogs <Pseudotarget Name> : <CollectCatKeys Target> ;
#    Compiles .catkeys files into .catalog files, one per locale
rule Catalogs
{
	Depends $(<) : $(>) ;
	Depends $(<) : $(SRCS) ;
	for lng in $(LOCALES)
	{
		Depends $(<) : $(CATKEYS_DIR)/$(lng:S=.catkeys) ;
		Depends $(CATKEYS_DIR)/$(lng:S=.catkeys) : $(>) ;
		#Clean clean : $(CATKEYS_DIR)/$(lng:S=.catkeys) ;
		Clean clean : 
			$(LOCATE_TARGET)/$(APP_MIME_SIG)/$(lng:S=.catalog) ;
	}
	Clean clean : $(LOCATE_TARGET)/$(NAME).pre ;
}

actions Catalogs
{
	mkdir -p $(LOCATE_TARGET)/$(APP_MIME_SIG)
	TMP=`echo "$(LOCALES)" | tr ';' ' '`
	
	for lang in $TMP ; do
		if [ ! -f $(CATKEYS_DIR)/$lang.catkeys ]; then 
			cp $(CATKEYS_DIR)/en.catkeys \
				$(CATKEYS_DIR)/$lang.catkeys; fi
		linkcatkeys \
	       	-o $(LOCATE_TARGET)/$(APP_MIME_SIG)/$lang.catalog \
		-s $(APP_MIME_SIG) \
		-l `basename $(LOCATE_TARGET)/$(APP_MIME_SIG)/$lang.catalog` \
		$(CATKEYS_DIR)/$lang.catkeys
	done
}

# CatalogsInstall <Pseudotarget Name> : <Catalog Files> ;
#    Copies .catalog files into system locale directory
rule CatalogsInstall
{
	Depends $(<) : $(>) ;
	Depends $(>) : catalogs ;
}

actions CatalogsInstall
{
	mkdir -p "/boot/home/config/data/locale/catalogs/$(APP_MIME_SIG)" ;
	cp $(LOCATE_TARGET)/$(APP_MIME_SIG)/*.catalog \
	/boot/home/config/data/locale/catalogs/$(APP_MIME_SIG)
}

# BindCatalogs <Pseudotarget Name> : <Catalog Files> ;
#    Binds .catalog files into program executable
rule BindCatalogs
{
	Depends $(<) : $(>) ;
	Depends $(<) : $(NAME) ;
	Depends $(<) : $(LOCATE_TARGET)/$(NAME) ;
	Depends $(LOCATE_TARGET)/$(NAME) : $(NAME) ;
	Clean clean : $(<) ;
}

actions BindCatalogs
{
	TMP=`echo $(LOCALES) | tr ';' ' '`
	for lc in $TMP; do 
		linkcatkeys -o $(LOCATE_TARGET)/$(NAME) \
	       	-s $(APP_MIME_SIG) -tr \
	       	-l $lc $(CATKEYS_DIR)/$lc.catkeys
	done
}

# RmApp <Pseudotarget Name> : <Application Name> ;
#   Removes the given application file when the given pseudotarget 
#   is specified.
rule RmApp
{
	Depends $(<) : $(>) ;
}

actions RmApp
{
	rm -rf "$(>)"
}

# RunApp <Pseudotarget Name> : <Application Name> ;
#   Runs the given application in the background when the given pseudotarget
#   is specified.
rule RunApp
{
	Depends $(<) : $(>) ;
}

actions RunApp
{
	"$(>)" &
}

# InstallDriver1 <Pseudotarget Name> : <Driver File> ;
#   Installs the given driver in the correct location when the given pseudotarget
#   is specified.
rule InstallDriver1
{
	Depends $(<) : $(>) ;
	USER_BIN_PATH = /boot/home/config/add-ons/kernel/drivers/bin ;
	USER_DEV_PATH = /boot/home/config/add-ons/kernel/drivers/dev ;
}

actions InstallDriver1
{
	copyattr --data "$(>)" "$(USER_BIN_PATH)/$(>:B)"
	mkdir -p $(USER_DEV_PATH)/$(DRIVER_PATH)
	ln -sf "$(USER_BIN_PATH)/$(>:B)" "$(USER_DEV_PATH)/$(DRIVER_PATH)/$(>:B)"
}

# InstallDriver <Pseudotarget Name> : <Driver File> ;
#   Installs the given driver in the correct location when the given pseudotarget
#   is specified, after making sure that this is actually a driver.
rule InstallDriver
{
	if ( $(TYPE) = DRIVER )
	{
		InstallDriver1 $(<) : $(>) ;
	}
}

# Link <Application Name> : <List of Object Files> ;
#   Replaces the actions for the default Jam Link rule with one that handles spaces 
#   in application names.
actions Link bind NEEDLIBS
{
	$(LINK) $(LINKFLAGS) -o "$(<)" $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
}

# BeMain <Application Name> : <List of Source Files> ;
#   This is the main rule that builds the project.
rule BeMain
{
	MkObjectDirs $(>) ;
	
	if ( $(TYPE) = STATIC )
	{
		Library $(<) : $(>) ;
	}
	else
	{
		Main $(<) : $(>) ;
	}
	
	if ( $(RSRCS) ) 
	{
		AddResources $(<) : $(RSRCS) ;
	}

	if ( $(LOCALES) )
	{
		CollectCatKeys ;
	}

	MimeSet $(<) ;
}

##-------------------------------------------------------------------
## Now all the needed variables are defined
##-------------------------------------------------------------------

# Set the directory where object files and binaries will be created.
# The pre-defined Jam variable OSPLAT will indicate what platform we 
# are on (X86 vs PPC, etc.)
LOCATE_TARGET = obj.$(OSPLAT) ;

# Set some defaults
if ( ! $(NAME) )
{
	ECHO "No NAME defined!" ;
	NAME = NameThisApp ;
}

if ( ! $(TYPE) )
{
	ECHO "No TYPE defined...defaulting to APP" ;
	TYPE = APP ;
}

if ( ! $(SRCS) )
{
	ECHO "NO SRCS defined...defaulting to *.cpp in current directory" ;
	SRCS = [ GLOB . : *.cpp ] ;
}

if ( ! $(DRIVER_PATH) )
{
	DRIVER_PATH = misc ;
}

# Now handle platform-specific settings
if ( $(OSPLAT) = X86 )
{
	if ( $(TYPE) = DRIVER )
	{
		CCFLAGS += -D_KERNEL_MODE=1 -no-fpic ;
		C++FLAGS += -D_KERNEL_MODE=1 -no-fpic ;
	}
	
	switch $(OPTIMIZE)
	{
		case FULL : OPTIMIZER = -O3 ;
		case SOME : OPTIMIZER = -O1 ;
		case NONE : OPTIMIZER = -O0 ;
		# Default to FULL
		case * : OPTIMIZER = -O3 ;
	}
	
	DEBUG = ;
	
	if ( $(DEBUGGER) = TRUE )
	{
		DEBUG += -g ;
		OPTIMIZER = -O0 ;
	}
	
	CCFLAGS += $(OPTIMIZER) $(DEBUG) ;
	C++FLAGS += $(OPTIMIZER) $(DEBUG) ;
	
	if ( $(WARNINGS) = ALL )
	{		
		CCFLAGS += -Wall -Wno-multichar -Wno-ctor-dtor-privacy ;
		C++FLAGS += -Wall -Wno-multichar -Wno-ctor-dtor-privacy ;
	}
	else if ( $(WARNINGS) = NONE )
	{
		CCFLAGS += -w ;
		C++FLAGS += -w ;
	}
	
	LINKFLAGS += $(DEBUG) ;
	
	# Set linker flags
	switch $(TYPE)
	{
		case APP : LINKFLAGS += -Xlinker -soname=_APP_ ;
		case SHARED : LINKFLAGS += -shared -Xlinker -soname=$(NAME) ;
		case DRIVER : LINKFLAGS += -nostdlib /boot/develop/lib/x86/_KERNEL_ ;
	}
} 
else if ( $(OSPLAT) = PPC ) 
{
	switch $(OPTIMIZE)
	{
		case FULL : OPTIMIZER = -O7 ;
		case SOME : OPTIMIZER = -O3 ;
		case NONE : OPTIMIZER = -O0 ;
		# Default to FULL
		case * : OPTIMIZER = -O7 ;
	}
	
	DEBUG = ;
	
	if ( $(DEBUGGER) = TRUE )
	{
		DEBUG += -g ;
	}
	
	CCFLAGS += $(OPTIMIZER) $(DEBUG) ;
	C++FLAGS += $(OPTIMIZER) $(DEBUG) ;
	
	if ( $(WARNINGS) = ALL )
	{		
		CCFLAGS += -w on -requireprotos ;
		C++FLAGS += -w on -requireprotos ;
	}
	else if ( $(WARNINGS) = NONE )
	{
		CCFLAGS += -w off ;
		C++FLAGS += -w off ;
	}
	
	# Clear the standard environment variable
	# Now there are no standard libraries to link against
	BELIBFILES = ;
	
	# Set linker flags
	if ( $(TYPE) = SHARED )
	{
		LINKFLAGS += -xms ;
	}
	
	if ( $(TYPE) = DRIVER )
	{
		LINKFLAGS += -nodefaults -export all -G 
			/boot/develop/lib/ppc/glue-noinit.a 
			/boot/develop/lib/ppc/_KERNEL_ ;
	}
	else
	{
		LINKFLAGS += -export pragma -init _init_routine_ 
			-term _term_routine_ -lroot 
			/boot/develop/lib/ppc/glue-noinit.a 
			/boot/develop/lib/ppc/init_term_dyn.o 
			/boot/develop/lib/ppc/start_dyn.o ;
	}
	
	if ( $(SYMBOLS) = TRUE )
	{
		LINKFLAGS += -map $(NAME).xMAP ;
	}	

	if ( $(DEBUGGER) = TRUE )
	{
		LINKFLAGS += -g -osym $(NAME).SYM ;
	}
} 
else 
{
	EXIT "Your platform is unsupported" ;
}

# Handle the other settings
LINKLIBS += [ ProcessLibs $(LIBS) ] ;
for i in $(LIBPATHS)
{
	LINKFLAGS += -L$(i) ;
} 
HDRS += $(SYSTEM_INCLUDE_PATHS) ;
HDRS += $(LOCAL_INCLUDE_PATHS) ;
CCFLAGS += $(COMPILER_FLAGS) ;
C++FLAGS += $(COMPILER_FLAGS) ;
LINKFLAGS += $(LINKER_FLAGS) ;

# Localization specific variables

if ( ! $(APP_MIME_SIG) )
{
	ECHO "No mime signature defined! Defaulting to x.vnd-Haiku-$(NAME)" ;
	APP_MIME_SIG = x.vnd-Haiku-$(NAME) ;
}

CATKEYS_DIR = locales ;
if ( $(APP_MIME_SIG) )
{
	CATALOGS_DIR = $(LOCATE_TARGET)/$(APP_MIME_SIG) ;
	CATALOGS = $(LOCALES:D=$(CATALOGS_DIR):S=.catalog) ;
}

# Define some tools
XRES = xres ;
MIMESET = mimeset ;

# Defining this variable keeps objects from being deleted by the Library
# rule.  By default the objects are deleted after being archived into 
# the library.  I prefer they not be.
KEEPOBJS = true ;

# Set up the driverinstall target...this makes it easy to install drivers 
# for testing
Always driverinstall ;
NotFile driverinstall ;
InstallDriver driverinstall : $(NAME) ;

# Set up the rmapp target...this removes only the application
Always rmapp ;
NotFile rmapp ;
RmApp rmapp : $(NAME) ;

# Set up the test target...this runs the application in the background
#Always test ;
NotFile test ;
RunApp test : $(NAME) ;

Always catkeys ;
NotFile catkeys ;
CollectCatKeys catkeys : $(SRCS) ;

#Always catalogs ;
NotFile catalogs ;
Catalogs catalogs : catkeys ;

#Always catalogsinstall ;
NotFile catalogsinstall ;
CatalogsInstall catalogsinstall : $(CATALOGS_DIR)/$(LOCALES:S=.catalog) ;

#Always bindcatalogs ;
NotFile bindcatalogs ;
BindCatalogs bindcatalogs : $(CATALOGS_DIR)/$(LOCALES:S=.catalog) ;

##-------------------------------------------------------------------
## OK, let's build
##-------------------------------------------------------------------

BeMain $(NAME) : $(SRCS) ;