You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
586 lines
24 KiB
586 lines
24 KiB
![]()
4 years ago
|
#====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
|
||
|
#
|
||
|
# Purpose: Syncs, builds and runs tests on the steam code in
|
||
|
# the currently active p4 clientspec
|
||
|
#
|
||
|
#=============================================================================
|
||
|
|
||
|
# INSTALLATION INSTRUCTIONS:
|
||
|
#
|
||
|
# 1. add the vc compiler solution compiler devenv.exe to the path (defaults to being in "C:\\Program Files\\Microsoft Visual Studio .NET 2003\\Common7\\IDE\\devenv.exe")
|
||
|
# 2. create a P4 clientspec that contains the steam code, eg. //steam/main/...
|
||
|
# 3. make that the default clientspec
|
||
|
# 4. sync to it
|
||
|
# 5. run this build script from inside that directory
|
||
|
|
||
|
|
||
|
import sys, os, string, re, time, smtplib, getopt, P4, SystemHelpers
|
||
|
|
||
|
# config options
|
||
|
g_bTest = 0 # 1: disables reporting to SRCDEV; only reports to admin
|
||
|
g_bRunTests = 0 # 1: enables testing after build is complete
|
||
|
g_bSync = 0 # 1: enables syncing to perforce
|
||
|
g_bLockMutex = 0 # 1: require mutex to be free before proceeding to build
|
||
|
g_bBuild = 0 # 1: build binaries
|
||
|
g_bDebug = 0 # 1: enables debug output
|
||
|
g_bDev = 0 # 1: script builds immediately upon start, regardless of presence of perforce state
|
||
|
g_bShaders = 0
|
||
|
g_bXBOX = 0
|
||
|
|
||
|
g_szEmailAlias = "" # email alias of users interested in build failures
|
||
|
g_szAdministrator = "" # address to auto-email if the script fails for some reason, test output
|
||
|
g_szMailhost = "" # set to hostname of machine running an SMTP server
|
||
|
g_szSenderEmail = "" # email address that the failure mails come from; TODO: Get buildmachine email
|
||
|
|
||
|
g_szBuildExe = "" # executable for compilation; devenv: .Net, BuildConsole: IncrediBuild
|
||
|
#g_szBuildExe = "devenv" # executable for compilation; devenv: .Net, BuildConsole: IncrediBuild
|
||
|
g_szBuildType = "" # build type; /rebuild or /build
|
||
|
g_szBuildFlags = "" # should be empty for devenv, /all for buildconsole
|
||
|
|
||
|
g_szTestingFile = "" # name of testing file, located in .\Build Machine Tests\
|
||
|
g_szLocalLogFile = "" # name of generated log file; currently not used
|
||
|
g_szPublishedErrorsDir = "" # place to copy log file to reference in failure email
|
||
|
g_szTestDirectory = "" # directory where the testing files are located
|
||
|
|
||
|
g_szBaseDir = os.getcwd() # directory from which the script is launched
|
||
|
|
||
|
g_szP4SrcFilesToWatch = "" # path to src files to watch
|
||
|
g_szP4ForceFilesToWatch = "" # path to bin files to watch
|
||
|
g_szP4SyncFilesToWatch = ""
|
||
|
g_szP4Mutex = "" # name of perforce mutex to wait for
|
||
|
g_szP4ChangeCounter = "" # perforce counter containg the changelist number we're verifying
|
||
|
g_szP4VerifiedCounter = "" # perforce counter the last changelist number we have verified
|
||
|
|
||
|
g_nP4MostRecentCheckin = 0 # used to keep track of current checkin
|
||
|
g_nP4LastVerifiedCheckin = 0 # used to keep track of last verified checkin
|
||
|
|
||
|
g_nSleepTimeBetweenChecks = 10 # number of seconds to wait before checking for a free mutex
|
||
|
|
||
|
g_szBuildName = ""
|
||
|
|
||
|
|
||
|
# mails off a success checkin
|
||
|
def SendSuccessEmail( _szEmail, _szChangeNumber ):
|
||
|
cMailport = smtplib.SMTP(g_szMailhost)
|
||
|
szTestString = ""
|
||
|
if g_bTest:
|
||
|
szTestString = "TEST"
|
||
|
print "sending success email to: " + _szEmail
|
||
|
|
||
|
szMessage = 'From: ' + g_szBuildName + ' Builder ' + ' <' + g_szSenderEmail + '>\n' +\
|
||
|
'To: ' + szTestString + _szEmail + '\n' +\
|
||
|
'Subject: [ ' + g_szBuildName + ' build successful ]' +\
|
||
|
'\n' +\
|
||
|
'\n' +\
|
||
|
'Your checkin:\n\n' +\
|
||
|
_szChangeNumber +\
|
||
|
'\n\n' +\
|
||
|
'has been successfully built and verified against all tests.\n'
|
||
|
|
||
|
if ( g_bTest | g_bDev ):
|
||
|
cMailport.sendmail( g_szSenderEmail, g_szAdministrator, szMessage )
|
||
|
else:
|
||
|
cMailport.sendmail( g_szSenderEmail, _szEmail, szMessage )
|
||
|
cMailport.quit()
|
||
|
|
||
|
# print of debugging messages
|
||
|
def dPrint( _szText ):
|
||
|
if g_bDebug:
|
||
|
print _szText
|
||
|
|
||
|
# mails off the current error string
|
||
|
def SendFailureEmail( _szErr ):
|
||
|
cMailport = smtplib.SMTP( g_szMailhost )
|
||
|
szTestString = ""
|
||
|
if g_bTest:
|
||
|
szTestString = "TEST"
|
||
|
print "sending failure email to: " + g_szEmailAlias
|
||
|
print "failure reason: " + _szErr
|
||
|
|
||
|
szMessage = 'From: ' + g_szBuildName + ' Builder' + ' <' + g_szSenderEmail + '>\n' +\
|
||
|
'To: ' + szTestString + g_szEmailAlias + '\n' +\
|
||
|
'Subject: [ ' + g_szBuildName + ' branch broken ]' +\
|
||
|
'\n' +\
|
||
|
'\n' +\
|
||
|
_szErr +\
|
||
|
'\n' +\
|
||
|
P4.GetUnverifiedCheckins( g_szP4SrcFilesToWatch, g_szP4VerifiedCounter, g_szP4ChangeCounter )
|
||
|
|
||
|
if g_bTest | g_bDev:
|
||
|
cMailport.sendmail( g_szSenderEmail, g_szAdministrator, szMessage )
|
||
|
else:
|
||
|
cMailport.sendmail( g_szSenderEmail, szTestString + g_szEmailAlias, szMessage )
|
||
|
cMailport.quit()
|
||
|
|
||
|
# use to email the admin about any unexpected errors that occur
|
||
|
def ComplainToAdmin( _szErr ):
|
||
|
cMailport = smtplib.SMTP(g_szMailhost)
|
||
|
print "sending script failure email to: " + g_szAdministrator
|
||
|
print "failure reason: |" + _szErr + "|"
|
||
|
|
||
|
szMessage = 'From: ' + g_szBuildName + " Builder" + ' <' + g_szSenderEmail + '>\n' +\
|
||
|
'To: ' + g_szAdministrator + '\n' +\
|
||
|
'Subject: [ ' + g_szBuildName + ' builder build script error ]' +\
|
||
|
'\n' +\
|
||
|
'\n' +\
|
||
|
'error reason:\n' +\
|
||
|
_szErr +\
|
||
|
'\n'
|
||
|
|
||
|
cMailport.sendmail(g_szSenderEmail, g_szAdministrator, szMessage)
|
||
|
cMailport.quit()
|
||
|
|
||
|
# parses out the reason for failure from a test
|
||
|
def GetTestFailureReason( _nBuild ):
|
||
|
|
||
|
# start our error message
|
||
|
szMsg = "Test log file:\n"
|
||
|
|
||
|
# make a directory to copy the error files into, based on the build config and the p4 changelist number
|
||
|
nBuildNum = P4.GetCounter(g_szP4ChangeCounter)
|
||
|
szErrDir = g_szPublishedErrorsDir + nBuildNum + "\\" + _nBuild
|
||
|
os.popen("mkdir " + szErrDir, "r").read()
|
||
|
|
||
|
# copy all the files to the errors dir
|
||
|
os.popen("copy " + _nBuild + "\\*.*" + " " + szErrDir + " /Y", "r").read()
|
||
|
# add the error log to the failure message
|
||
|
szMsg += " " + szErrDir + "\\" + g_szLocalLogFile + "\n"
|
||
|
|
||
|
# add the minidumps to the failure message
|
||
|
rgMinidumps = string.split( os.popen("dir " + _nBuild + "\\*.mdmp /b", "r").read(), "\n" )
|
||
|
if len(rgMinidumps) > 1:
|
||
|
szMsg += "\nCrash dump:\n"
|
||
|
for szMinidump in rgMinidumps:
|
||
|
if len(szMinidump) > 16:
|
||
|
szMsg += " " + szErrDir + "\\" + szMinidump + "\n"
|
||
|
szMsg += "To view the minidump, click the link above then click \"open\" on the next dialog.\nHit \"F5\" in the now open debugger. When it asks for the source code, change the start of the suggested path from \"c:\\\" to \"\\\\steam3builder\\\".\n"
|
||
|
|
||
|
# delete the minidumps, so they don't confuse us next time
|
||
|
os.popen("del " + _nBuild + "\\*.mdmp", "r").read()
|
||
|
|
||
|
|
||
|
# parse out the error from the logfile
|
||
|
szLog = os.popen( "type " + _nBuild + "\\" + szLocalLogFile, "r").read()
|
||
|
szLogLines = []
|
||
|
szLogLines = string.split( szLog, "\n" )
|
||
|
bFoundErr = 0
|
||
|
for szLine in szLogLines:
|
||
|
aszToken = string.split(szLine, ' ')
|
||
|
if len( aszToken ) > 3:
|
||
|
if aszToken[0] == "***" and aszToken[1] == "TEST" and aszToken[2] == "FAILED":
|
||
|
# probably an error line, add to the list
|
||
|
szMsg += szLine
|
||
|
szMsg += "\n"
|
||
|
bFoundErr = 1
|
||
|
|
||
|
# if we haven't found any error lines, use the last line of the file
|
||
|
if bFoundErr == 0 and len(szLogLines) > 0:
|
||
|
szMsg += szLogLines[len(szLogLines) - 1]
|
||
|
|
||
|
return szMsg
|
||
|
|
||
|
|
||
|
# performs a single test run of the specified exe with the specified test parameters
|
||
|
def RunTest( _szCommand ):
|
||
|
|
||
|
aszParms = string.split( _szCommand, " ", 1)
|
||
|
print "running " + _szCommand
|
||
|
print os.popen( _szCommand, "r" ).read()
|
||
|
|
||
|
# return success
|
||
|
return aszParms[0]
|
||
|
|
||
|
def RunCompare( _szCommand ):
|
||
|
szResult = os.popen( _szCommand, "r" ).read()
|
||
|
return szResult
|
||
|
|
||
|
def SearchFileForErrors( _szFile, _szError ):
|
||
|
print ("Searching " + _szFile + " for occurences of " + _szError + ".\n")
|
||
|
bIncludeNext = 0
|
||
|
szErrorResults = ""
|
||
|
aszFileLines = string.split( os.popen( "type " + _szFile, "r").read(), "\n" )
|
||
|
|
||
|
for szLine in aszFileLines:
|
||
|
if ( bIncludeNext == 1 ):
|
||
|
szErrorResults += szLine + "\n"
|
||
|
bIncludeNext = 0
|
||
|
aszParms = string.split(szLine, " ", 1)
|
||
|
if (aszParms[0] == _szError):
|
||
|
#there is a UnitTest error, warning, or assert
|
||
|
szErrorResults += "\n" + szLine + "\n"
|
||
|
bIncludeNext = 1;
|
||
|
return szErrorResults
|
||
|
|
||
|
# runs a set of tests as defined by the test script file
|
||
|
def RunTestScript( ):
|
||
|
print ("Enter Testing")
|
||
|
# make sure we're in the right dir
|
||
|
SystemHelpers.ChangeDir("..")
|
||
|
# load the script
|
||
|
szReturn = os.popen( "RunTestScripts.py" ).read()
|
||
|
return szReturn
|
||
|
|
||
|
# runs a single build, and runs the tests on the build if specified
|
||
|
def RunBuild( _szBuild ):
|
||
|
# launch devstudio to build the solution
|
||
|
szCmd = _szBuild
|
||
|
aszToken = string.split(szCmd, " ", 3)
|
||
|
|
||
|
if aszToken[0] == "devenv":
|
||
|
#we are building this. Find out what it is.
|
||
|
if aszToken[2] == "/project":
|
||
|
#building a project. Grab it.
|
||
|
aszToken = string.split(szCmd, " ", 5)
|
||
|
szCmd = g_szBuildExe + " " + aszToken[1] + " /project " + aszToken[3] + " " + g_szBuildType + " " + aszToken[5]
|
||
|
else:
|
||
|
#not build a specific project. Probably everything under lostcoast.
|
||
|
szCmd = g_szBuildExe + " " + aszToken[1] + " " + g_szBuildType + " " + aszToken[3] + " " + g_szBuildFlags
|
||
|
else:
|
||
|
#didn't see the devenv line; not building this but it isn't an error either.
|
||
|
return ""
|
||
|
|
||
|
print "building: " + szCmd
|
||
|
szOutput = os.popen(szCmd, "r").read()
|
||
|
# parse the output for any errors
|
||
|
aszOutputLines = string.split(szOutput, "\n")
|
||
|
bSuccess = 1
|
||
|
szBuildErr = "\n\n\nError building configuration " + _szBuild + ":\n"
|
||
|
|
||
|
for szLine in aszOutputLines:
|
||
|
if g_bDebug:
|
||
|
print szLine;
|
||
|
aszTokens = string.split(string.lstrip(szLine), ' ', 4)
|
||
|
if len(aszTokens) > 1:
|
||
|
if aszTokens[0] == "--------------------Configuration:":
|
||
|
bPrintedProject = 0
|
||
|
szProject = aszTokens[1]
|
||
|
if aszTokens[1] == ":" and aszTokens[2] == "error" and aszTokens[3] != "PRJ0019":
|
||
|
# probably an error line, add to the list
|
||
|
count = string.count( szBuildErr, aszTokens[4])
|
||
|
if ( count == 0 ):
|
||
|
if ( bPrintedProject == 0 ):
|
||
|
szBuildErr += "Project: " + szProject + "\n"
|
||
|
bPrintedProject = 1
|
||
|
szBuildErr += szLine + "\n"
|
||
|
#err2 += szLine + "\n"
|
||
|
bSuccess = 0
|
||
|
if aszTokens[1] == ":" and aszTokens[2] == "error" and aszTokens[3] == "PRJ0019":
|
||
|
# the delete error line, add to the list
|
||
|
szBuildErr += "IGNORE: "
|
||
|
szBuildErr += szLine + "\n"
|
||
|
#err2 += szLine + "\n"
|
||
|
aszTokens = string.split(string.lstrip(szLine), ' ')
|
||
|
if len(aszTokens) > 4:
|
||
|
# can't do this: the weird delete error will trigger this and we need to ignore that
|
||
|
# check that the "Rebuild All: x succeeded, y failed, z skipped line says no failures
|
||
|
#if szT[0] == "Rebuild" and szT[3] rrorMessages + "The " + szTestName + " test failed\nThe error is " + szCompareLine
|
||
|
#if szErrorMessages== "succeeded," and szT[5] == "failed," and not szT[4] == "0":
|
||
|
# failure
|
||
|
# bSuccess = 0
|
||
|
# check for linker errors
|
||
|
if aszTokens[0] == "LINK" and aszTokens[1] == ":" and aszTokens[2] == "fatal" and aszTokens[3] == "error":
|
||
|
if ( bPrintedProject == 0 ):
|
||
|
szBuildErr += "Project: " + szProject + "\n"
|
||
|
bPrintedProject = 1
|
||
|
# linker error line, add to the list
|
||
|
szBuildErr += szLine + "\n"
|
||
|
#err2 += szLine + "\n"
|
||
|
bSuccess = 0
|
||
|
# can't do this either: Delete file problem
|
||
|
# check the standard error dealie.
|
||
|
# if szT[1] == '-' and szT[3] == "error(s)," and szT[2] != '0':
|
||
|
#we have a build error here
|
||
|
# err += szLine
|
||
|
# err += "\n"
|
||
|
#check for fatal error
|
||
|
if aszTokens[2] == "fatal" and aszTokens[3] == "error":
|
||
|
if ( bPrintedProject == 0 ):
|
||
|
szBuildErr += "Project: " + szProject + "\n"
|
||
|
bPrintedProject = 1
|
||
|
#fatal error
|
||
|
szBuildErr += szLine + "\n"
|
||
|
#err2 += szLine + "\n"
|
||
|
bSuccess = 0
|
||
|
|
||
|
# return immediately if failed
|
||
|
if not bSuccess:
|
||
|
print szBuildErr
|
||
|
szBuildErr + "\n\n"
|
||
|
#ComplainToAdmin(err2)
|
||
|
return szBuildErr
|
||
|
|
||
|
return ""
|
||
|
|
||
|
def RunBuildBatch():
|
||
|
bSuccess = 1
|
||
|
#aszBatchBuildLines = string.split( os.popen( "type " + szBatchFile, "r").read(), "\n" )
|
||
|
#bIsDevLine = 0
|
||
|
szBuildErrs = ""
|
||
|
szBuildResult = RunBuild( "devenv everything.sln /build \"debug|win32\" " )
|
||
|
|
||
|
szBuildResult += RunBuild( "devenv everything.sln /build \"release|win32\" " )
|
||
|
szTestResult = RunTestScript()
|
||
|
if szBuildResult != "":
|
||
|
szBuildErrs += szBuildResult
|
||
|
bSuccess = 0
|
||
|
if szTestResult != "\n":
|
||
|
szBuildErrs += szTestResult
|
||
|
bSuccess = 0
|
||
|
if not bSuccess:
|
||
|
SendFailureEmail(szBuildErrs)
|
||
|
return bSuccess
|
||
|
|
||
|
|
||
|
# runs all the builds
|
||
|
def RunAllBuilds():
|
||
|
bSuccess = 1
|
||
|
szBuildErrs = ""
|
||
|
SystemHelpers.ChangeDir("\game")
|
||
|
if g_bBuild:
|
||
|
SystemHelpers.ChangeDir("\src")
|
||
|
|
||
|
# build the shadercompiler and all shaders
|
||
|
if g_bShaders:
|
||
|
print( "Compiling shadercompile" )
|
||
|
os.system( "devenv shadercompile.sln /rebuild release > silence" )
|
||
|
# should check here to make sure the shadercompile worked
|
||
|
SystemHelpers.ChangeDir("\\src\\materialsystem\\stdshaders")
|
||
|
print( "Building shaders" )
|
||
|
child_stdin, child_stdout, child_stderr = os.popen3( "buildallshaders.bat" )
|
||
|
print( child_stdout.read() )
|
||
|
szSomeShaderErr = child_stderr.read()
|
||
|
szShaderErrors = ""
|
||
|
aszShaderLines = string.split( szSomeShaderErr, "\n" )
|
||
|
for szLine in aszShaderLines:
|
||
|
dPrint( szLine )
|
||
|
nCount = string.count( szLine, 'U1073:' )
|
||
|
if nCount > 0:
|
||
|
aszToken = string.split( szLine, " " )
|
||
|
szShaderName = aszToken[9]
|
||
|
szShaderErrors = szShaderErrors + "The shader file " + szShaderName + " is missing and failed during buildallshaders.bat.\n"
|
||
|
if szShaderErrors:
|
||
|
SendFailureEmail( szShaderErrors )
|
||
|
|
||
|
SystemHelpers.ChangeDir("\\src")
|
||
|
bSuccess = bSuccess & RunBuildBatch();
|
||
|
|
||
|
#XBOX Section
|
||
|
if g_bXBOX:
|
||
|
szXBoxOutput = RunBuild( "devenv source_x360.sln /rebuild \"release|xbox 360\"" )
|
||
|
if "\n\n\nError building configuration " + "devenv source_x360.sln /rebuild release" + ":\n" != szXBoxOutput:
|
||
|
bSuccess = 0
|
||
|
SendFailureEmail( szXBoxOutput )
|
||
|
#delete tier0.dll
|
||
|
|
||
|
|
||
|
if g_bRunTests:
|
||
|
szTestErrors = RunTestScript()
|
||
|
if szTestErrors != "\n":
|
||
|
# success = 0
|
||
|
ComplainToAdmin( szTestErrors )
|
||
|
return bSuccess
|
||
|
|
||
|
# builds from a local branch and runs a subset of tests
|
||
|
def PerformSourceBuild():
|
||
|
|
||
|
# build and test in each configuration
|
||
|
if not RunAllBuilds():
|
||
|
print "Source build failed"
|
||
|
return 0
|
||
|
|
||
|
print "Source build: SUCCESS"
|
||
|
return 1
|
||
|
|
||
|
|
||
|
# syncs, builds, runs tests
|
||
|
def PerformDailyBuild():
|
||
|
print " changes detected, starting daily build"
|
||
|
# update the counter to be what we're verifying
|
||
|
change = P4.SubmittedChangelist( g_szP4SrcFilesToWatch )
|
||
|
g_nP4MostRecentCheckin = change
|
||
|
g_nP4LastVerifiedCheckin = P4.GetCounter(g_szP4VerifiedCounter)
|
||
|
if g_nP4MostRecentCheckin and g_nP4LastVerifiedCheckin:
|
||
|
print "Most recent checkin is " + g_nP4MostRecentCheckin + "\n"
|
||
|
print "Last verified checkin is " + g_nP4LastVerifiedCheckin + "\n"
|
||
|
# the p4 command can occasionally fail to deliver a valid changelist number, unclear why
|
||
|
# can't update the counter, it just means we'll run twice
|
||
|
if change:
|
||
|
P4.SetCounter(g_szP4ChangeCounter, change)
|
||
|
# sync to the new files
|
||
|
if ( g_bSync ):
|
||
|
SystemHelpers.ChangeDir("\\src")
|
||
|
print( "Cleaning\n" )
|
||
|
os.system("cleanalltargets.bat > silence")
|
||
|
SystemHelpers.ChangeDir("\\")
|
||
|
print "Synching force files."
|
||
|
P4.Sync( g_szP4ForceFilesToWatch, 1 )
|
||
|
print "Synching other files."
|
||
|
P4.Sync( g_szP4SyncFilesToWatch, 0 )
|
||
|
print( "Setting up VPC" )
|
||
|
os.system("setupVPC.bat")
|
||
|
|
||
|
#P4.UnlockMutex(g_szP4Mutex)
|
||
|
# build and test in each configuration
|
||
|
if not RunAllBuilds():
|
||
|
print "Daily build failed"
|
||
|
return
|
||
|
|
||
|
# send a success email, from past the last successful checkin to the current
|
||
|
if change:
|
||
|
szVerifiedOrig = P4.GetCounter(g_szP4VerifiedCounter)
|
||
|
if szVerifiedOrig:
|
||
|
szVerifiedPlusOne = str( int( szVerifiedOrig ) + 1 )
|
||
|
changes = P4.GetChangelistRange(szVerifiedPlusOne, change, g_szP4SrcFilesToWatch );
|
||
|
for ch in changes:
|
||
|
if len(ch) > 1:
|
||
|
szEmail = P4.GetEmailFromChangeLine(ch)
|
||
|
SendSuccessEmail(szEmail, ch)
|
||
|
#SendSuccessEmail("jason", ch)
|
||
|
# remember this change that we've verified
|
||
|
P4.SetCounter(g_szP4VerifiedCounter, change)
|
||
|
|
||
|
print "Daily build: AN UNEQUIVOCAL SUCCESS"
|
||
|
|
||
|
def PrintConfig():
|
||
|
print("Configuration:")
|
||
|
print("test = " + str(g_bTest))
|
||
|
print("run_tests = " + str(g_bRunTests))
|
||
|
print("lock_mutex = " + str(g_bLockMutex))
|
||
|
print("build = " + str(g_bBuild))
|
||
|
print("debug = " + str(g_bDebug))
|
||
|
print("dev = " + str(g_bDev))
|
||
|
print("shaders = " + str(g_bShaders))
|
||
|
print("sync = " + str(g_bSync))
|
||
|
print("email_alias = " + g_szEmailAlias)
|
||
|
print("admin_email = " + g_szAdministrator)
|
||
|
print("mail_host = " + g_szMailhost)
|
||
|
print("sender_email = " + g_szSenderEmail)
|
||
|
print("build_exe = " + g_szBuildExe)
|
||
|
print("build_type = " + g_szBuildType)
|
||
|
print("build_flags = " + g_szBuildFlags)
|
||
|
print("test_file = " + g_szTestingFile)
|
||
|
print("log_file = " + g_szLocalLogFile)
|
||
|
print("error_dir = " + g_szPublishedErrorsDir)
|
||
|
print("test_dir = " + g_szTestDirectory)
|
||
|
print("src_files = " + g_szP4SrcFilesToWatch)
|
||
|
print("force_files = " + g_szP4ForceFilesToWatch)
|
||
|
print("sync_files = " + g_szP4SyncFilesToWatch)
|
||
|
print("mutex = " + g_szP4Mutex)
|
||
|
print("change_counter = " + g_szP4ChangeCounter)
|
||
|
print("verify_counter = " + g_szP4VerifiedCounter)
|
||
|
print("build_name = " + g_szBuildName)
|
||
|
|
||
|
def ParseConfigFile(configFileName):
|
||
|
aszBatchBuildLines = string.split( os.popen( "type " + configFileName, "r").read(), "\n" )
|
||
|
global g_bTest
|
||
|
global g_bRunTests
|
||
|
global g_bLockMutex
|
||
|
global g_bBuild
|
||
|
global g_bDebug
|
||
|
global g_bDev
|
||
|
global g_bShaders
|
||
|
global g_bSync
|
||
|
global g_szEmailAlias
|
||
|
global g_szAdministrator
|
||
|
global g_szMailhost
|
||
|
global g_szSenderEmail
|
||
|
global g_szBuildExe
|
||
|
global g_szBuildType
|
||
|
global g_szBuildFlags
|
||
|
global g_szTestingFile
|
||
|
global g_szLocalLogFile
|
||
|
global g_szPublishedErrorsDir
|
||
|
global g_szTestDirectory
|
||
|
global g_szP4SrcFilesToWatch
|
||
|
global g_szP4ForceFilesToWatch
|
||
|
global g_szP4SyncFilesToWatch
|
||
|
global g_szP4Mutex
|
||
|
global g_szP4ChangeCounter
|
||
|
global g_szP4VerifiedCounter
|
||
|
global g_szBuildName
|
||
|
for szLine in aszBatchBuildLines:
|
||
|
aszTokens = string.split(string.lstrip(szLine), ' ', 2)
|
||
|
firstToken = aszTokens[0]
|
||
|
if firstToken == '#' or firstToken == '':
|
||
|
continue
|
||
|
secondToken = aszTokens[1]
|
||
|
if firstToken == "test":
|
||
|
g_bTest = int(secondToken)
|
||
|
elif firstToken == "run_tests":
|
||
|
g_bRunTests = int(secondToken)
|
||
|
elif firstToken == "lock_mutex":
|
||
|
g_bLockMutex = int(secondToken)
|
||
|
elif firstToken == "build":
|
||
|
g_bBuild = int(secondToken)
|
||
|
elif firstToken == "debug":
|
||
|
g_bDebug = int(secondToken)
|
||
|
elif firstToken == "dev":
|
||
|
g_bDev = int(secondToken)
|
||
|
elif firstToken == "shaders":
|
||
|
g_bShaders = int(secondToken)
|
||
|
elif firstToken == "sync":
|
||
|
g_bSync = int(secondToken)
|
||
|
elif firstToken == "email_alias":
|
||
|
g_szEmailAlias = secondToken
|
||
|
elif firstToken == "admin_email":
|
||
|
g_szAdministrator = secondToken
|
||
|
elif firstToken == "mail_host":
|
||
|
g_szMailhost = secondToken
|
||
|
elif firstToken == "sender_email":
|
||
|
g_szSenderEmail = secondToken
|
||
|
elif firstToken == "build_exe":
|
||
|
g_szBuildExe = secondToken
|
||
|
elif firstToken == "build_type":
|
||
|
g_szBuildType = secondToken
|
||
|
elif firstToken == "build_flags":
|
||
|
g_szBuildFlags = secondToken
|
||
|
elif firstToken == "test_file":
|
||
|
g_szTestingFile = secondToken
|
||
|
elif firstToken == "log_file":
|
||
|
g_szLocalLogFile = secondToken
|
||
|
elif firstToken == "error_dir":
|
||
|
g_szPublishedErrorsDir = secondToken
|
||
|
elif firstToken == "test_dir":
|
||
|
g_szTestDirectory = secondToken
|
||
|
elif firstToken == "src_files":
|
||
|
g_szP4SrcFilesToWatch += secondToken
|
||
|
elif firstToken == "force_files":
|
||
|
g_szP4ForceFilesToWatch += secondToken + ";"
|
||
|
elif firstToken == "sync_files":
|
||
|
g_szP4SyncFilesToWatch += secondToken + ";"
|
||
|
elif firstToken == "mutex":
|
||
|
g_szP4Mutex = secondToken
|
||
|
elif firstToken == "change_counter":
|
||
|
g_szP4ChangeCounter = secondToken
|
||
|
elif firstToken == "verify_counter":
|
||
|
g_szP4VerifiedCounter = secondToken
|
||
|
elif firstToken == "build_name":
|
||
|
g_szBuildName = secondToken
|
||
|
PrintConfig()
|
||
|
|
||
|
#-----------------------------------------------------------------------------
|
||
|
# Main
|
||
|
#-----------------------------------------------------------------------------
|
||
|
if __name__ == '__main__':
|
||
|
try:
|
||
|
print "----------------------------------------------------"
|
||
|
print g_szBuildName + " BUILD SCRIPT STARTED"
|
||
|
ParseConfigFile(sys.argv[1])
|
||
|
|
||
|
while 1:
|
||
|
if (g_bDev | P4.AnyNewCheckins( g_szP4ChangeCounter, g_szP4SrcFilesToWatch )):
|
||
|
print "Changes Detected.\n"
|
||
|
if ( (g_bTest & ~g_bLockMutex) | ~g_bLockMutex | P4.Query(g_szP4Mutex) ):
|
||
|
PerformDailyBuild()
|
||
|
g_bDev = 0
|
||
|
print ""
|
||
|
print "------------------------------------------"
|
||
|
print "waiting for changes to be detected..."
|
||
|
else:
|
||
|
time.sleep( g_nSleepTimeBetweenChecks - ( g_bTest * g_nSleepTimeBetweenChecks ))
|
||
|
else:
|
||
|
time.sleep( g_nSleepTimeBetweenChecks )
|
||
|
except RuntimeError, e:
|
||
|
ComplainToAdmin(e)
|
||
|
|