# Rules for Jamfile.jam

if ( $(toolset:I=^mingw) )
{
	if ( $(configuration) = "debug" )
	{
		CCFLAGS += -D_DEBUG ;
	}
	else
	{
		CCFLAGS += -DNDEBUG -O3 ;
	}

	actions ObjectAction
	{
		%$(toolset)_PATH%\bin\gcc -W -Wall -Wextra -Werror -pedantic -c $(>) -o $(<) $(CCFLAGS)
	}
	
	actions LibraryAction
	{
		%$(toolset)_PATH%\bin\ar rc $(<) $(>)
	}
	
	actions LinkAction
	{
		%$(toolset)_PATH%\bin\g++ $(>) -o $(<) $(LDFLAGS) 
	}
	
	actions CoverageAction
	{
		%$(toolset)_PATH%\bin\gcov $(>:\\) $(GCOVFLAGS) | perl tests/gcov-filter.pl
	}
}
else if ( $(toolset:I^=msvc) )
{
	if ( $(configuration) = "debug" )
	{
		CCFLAGS += /D_DEBUG /MTd ;
	}
	else
	{
		CCFLAGS += /DNDEBUG /Ox /MT ;
	}

	if ( $(toolset) != msvc6 )
	{
		CCFLAGS += /Wp64 /W4 ;
	}
	else
	{
		CCFLAGS += /W3 ; # lots of warnings at W4 in standard library
	}

	actions ObjectAction
	{
		%$(toolset)_PATH%\bin\cl.exe /EHsc /WX /I%$(toolset)_PATH%\include /c $(>) /Fo$(<) /nologo $(CCFLAGS)
	}
	
	actions LibraryAction
	{
		%$(toolset)_PATH%\bin\lib.exe /NOLOGO /OUT:$(<) $(>)
	}
	
	actions LinkAction
	{
		%$(toolset)_PATH%\bin\link.exe /SUBSYSTEM:CONSOLE /NOLOGO /OUT:$(<) $(>) /LIBPATH:%$(toolset)_PATH%\lib /LIBPATH:%$(toolset)_PATH%\PlatformSDK\lib $(LDFLAGS)
	}
	
	actions CoverageAction
	{
	}
}

actions RunAction
{
	$(>:\\)
}

actions quietly ignore MakeDirAction
{
	mkdir $(<:\\) >nul 2>&1
}

actions quietly ignore DeleteAction
{
	del /F $(>:\\) >nul 2>&1
}

rule MakeFileDir TARGET
{
	local DIR = $(TARGET:D) ;

	MakeDirAction $(DIR) ;
	Needs $(TARGET) : $(DIR) ;
}

rule Alias TARGET : SOURCE
{
	NotFile $(TARGET) ;
	Always $(TARGET) ;
	Depends $(TARGET) : $(SOURCE) ;
}

rule Object TARGET : SOURCE
{
	HDRRULE on $(SOURCE) = C.HdrRule ;
	HDRSCAN on $(SOURCE) = $(C.HDRPATTERN) ;

	MakeFileDir $(TARGET) ;
	ObjectAction $(TARGET) : $(SOURCE) ;
	Depends $(TARGET) : $(SOURCE) ;
}

rule Objects SOURCES
{
	local OBJECTS ;

	for SOURCE in $(SOURCES)
	{
		local OBJECT = $(BUILD)/$(SOURCE:S=.o) ;

		Object $(OBJECT) : $(SOURCE) ;
		OBJECTS += $(OBJECT) ;
	}

	return $(OBJECTS) ;
}

rule Library TARGET : SOURCES
{
	# build object files
	local OBJECTS = [ Objects $(SOURCES) ] ;

	# build library
	local LIBRARY = $(BUILD)/$(TARGET).a ;

	MakeFileDir $(LIBRARY) ;
	LibraryAction $(LIBRARY) : $(OBJECTS) ;
	Depends $(LIBRARY) : $(OBJECTS) ;

	# make alias
	Alias $(TARGET) : $(LIBRARY) ;

	# remember library path for linking
	$(TARGET)_path = $(LIBRARY) ;

	# remember library objects for coverage
	$(TARGET)_objects = $(OBJECTS) ;
}

rule Application TARGET : SOURCES : LIBRARIES
{
	# build object files
	local OBJECTS = [ Objects $(SOURCES) ] ;

	# get binary path
	local EXECUTABLE = $(BUILD)/$(TARGET).exe ;

	# set libraries
	LDFLAGS on $(EXECUTABLE) = $(LDFLAGS) $($(LIBRARIES)_path) ;

	# build application
	MakeFileDir $(EXECUTABLE) ;
	LinkAction $(EXECUTABLE) : $(OBJECTS) ;
	Depends $(EXECUTABLE) : $(OBJECTS) $($(LIBRARIES)_path) ;
	
	# make alias
	Alias $(TARGET) : $(EXECUTABLE) ;

	# remember executable path for running
	$(TARGET)_path = $(EXECUTABLE) ;
	
	# remember executable objects for coverage
	$(TARGET)_objects = $(OBJECTS) $($(LIBRARIES)_objects) ;
}

rule CleanCoverage TARGET 
{
	# make target
	local CLEAN_TARGET = $(TARGET)_clean_coverage ;

	NotFile $(CLEAN_TARGET) ;
	Always $(CLEAN_TARGET) ;
	Depends $(TARGET) : $(CLEAN_TARGET) ;
	
	# clean object files
	local FILES = $($(SOURCE)_objects:S=.gcda) ;

	DeleteAction $(CLEAN_TARGET) : $(FILES) ;
}

rule Test TARGET : SOURCE
{
	# make alias
	Alias $(TARGET) : $(SOURCE) ;

	# run tests
	RunAction $(TARGET) : $($(SOURCE)_path) ;

	# remember executable objects for coverage
	$(TARGET)_objects = $($(SOURCE)_objects) ;

	# clean coverage files before run
	CleanCoverage $(TARGET) ;
}

rule Coverage TARGET : SOURCE
{
	local FILES = $($(SOURCE)_objects:S=.gcda) ;

	# disable "independent target" warnings
	NotFile $(FILES) ;

	CoverageAction $(TARGET) : $(FILES) ;
	Depends $(TARGET) : $(SOURCE) ;
}