blob: f674af0b2da19a58842ccc7d1e049e00bc443990 [file] [log] [blame]
#TODO:
import os
import string
import random
import sys
import fnmatch
import copy
import glob
libProj = 'libProj.vcxproj'
sourceExtensions = ['c', 'cpp', 'cxx','l','y','ll','yy', 'crc']
headerExtensions = ['h', 'hxx', 'hrc']
libExtensions = ['lib']
deliverFileName = "d.lst"
# The path to the main OO directory
# If this isn't working on a new machine, this
# is probably why
mainPaths = ["C:/steve/TestARea/main","C:/steve/TestArea/main"]
# Use this to figure out which step we are in
# Most modules will end with the same string
# that they began with
findModuleStr = "Making:"
# These commands are in the output but should not be part
# of the resulting input
skipCommands = ["Microsoft", "Copyright", "-------", "using:"]
badMapStr = "-map:"
outStr = "/OUT:"
moduleName = ""
buildFolder = "wntmsci12.pro"
curDir = ""
it = 0
# Keep track of everywhere we have seen a source file at
# and automatically add it as an include directory
# This fixes some issues with include directories
# not being detected properly when we have changed into that
# directory via cd
extraIncludeDirs = []
outputString = ""
deliverBatName = "WinDeliver.bat"
FILESIZE_LIMIT = 1024*500
inFileGroup = []
outFileGroup = []
# prjTuple = prjName, prjId, outputFile, dependencies, fileName
allProjects = []
# Visual studio doesn't like projects sharing the same name
# so keep track of ones that we've seen and append a 1 to the end of them
usedPrjNames = []
includeDebug = False
postBuildName = 'postbuild.bat'
## NEW
def getDirPath(filePath):
dirPath = filePath.rsplit("/",1)
return dirPath[0]
beginDepComment = "#Begin Dependencies\n"
endDepComment = "#End Dependencies\n"
# Description:
# Generates a random 32-character project id. Each character represents
# a hexadecimal character (0-9, A-F). Visual Studio uses the following format
# for project ids: 8-4-4-4-12 hexadecimal characters. For example, the string
# "0462A45F-E456-A56B-0289-CF4630B744E2" is a valid project id. Dashes ("-")
# are inserted between characters as specified by the format, resulting in a
# string with a length of 32+4.
# Note:
# return: 36-character string.
def ProjectGUID():
output = ""
for x in range(0,36):
if x == 8 or x == 12+1 or x == 16+2 or x == 20+3:
output += '-'
else:
output += random.choice('0123456789ABCDEF')
return output
def findNext(str,it):
findStr = "Entering /"
ret_it = len(str)+1
fStr = "null"
tmp_it = str.find(findStr,it)
if (tmp_it < ret_it and tmp_it != -1):
ret_it = tmp_it
fStr = findStr
fStr = fStr.strip()
return ret_it, fStr
def parseNext(str,moduleName):
it = 0
while (1):
it, type = findNext(str,it)
end_it = -1
tmp_it = -1
tmp = []
#Obj Tuple = Name, inFiles, outFiles, args
if (type != "null"):
it = str.find(" ",it)+1
it = str.find("\n",it)
start_it = str.rfind("/",0,it)+1
prjName = str[start_it:it]
prjName = prjName.strip()
it = it+2
end_it = str.find("\n",it)
args = str[it:end_it]
args = args.strip()
args = fixPaths(args)
#Don't want to do anything with this
if (prjName == "inc"):
continue
patchVCProjJava(prjName,moduleName)
else:
break
return it
def newParse(fileName,moduleName):
output = open(fileName)
origFile = output.read()
output.close()
parseNext(origFile,moduleName)
# while(more cmds):
# if(can find buildFolder+"/" in curCmd):
# repCmd = text between "." and buildFolder+"/"
# break
# while(more cmds):
# tmpCmd = curCmd.remove(repCmd)
# if(can find "../"):
# error if repCmd = ''
#
def fixPaths(cmd):
cmd = cmd.replace("C:/steve/TestARea/main","..")
cmd = cmd.replace("C:/steve/TestArea/main","..")
return cmd
def parseDLst(path):
repStrs = [("%_DEST%","..\solver\\410\\" + buildFolder),("%_EXT%",""),("%__SRC%",buildFolder)]
copyStr = "xcopy \"^SRC^\" \"^DEST^\\\" /D /Y /c"
try:
d = open(path)
except:
print ("Warning: Failed to load prj.lst; WinDeliver.bat will not be made")
return
data = d.read()
d.close()
data = data.split("\n")
outputBuf = ""
for line in data:
#We need to be one directory up from where we started
tmpLines = line.split()
line = ""
for tmpLine in tmpLines:
tmpLine = tmpLine.replace("..\\","",1)
line += tmpLine + " "
for repStr in repStrs:
line = line.replace(repStr[0],repStr[1])
if (tmpLines != []):
lines = line.split(":",1)
#print lines
cmd = ""
#print lines
if (len(lines) == 1):
isDir = True
#Don't need the second filenames with XCopy
#print tmpLines
#tmpLines[1] = (tmpLines[1].rsplit("\\"))[0]
copyCmd = copyStr
files = line.split(" ")
newFiles = []
for f in files:
if f == "":
continue
if f.find("*") != -1:
tmp = tryToFindFile(f,"","")
if len(tmp) == 0:
isDir = isDir
#print "Warning: no match for file " + f + " found"
elif len(tmp) > 1:
print "Warning: Multiple matches for file: " + f + " found"
print "Defaulting to use the first match"
f = tmp[0]
else:
print len(tmp)
print tmp[0]
f = tmp[0]
f = f.replace("/","\\")
if f.strip() != "" and f.strip() != []:
newFiles.append(f)
files = newFiles
dot_it = newFiles[0].rfind(".")
if dot_it > newFiles[0].rfind("\\"):
isDir = False
#print files
if (len(files) != 2):
print "Warning: unable to parse d.lst copy command"
#print files
continue
files[1] = (files[1].rsplit("\\",1))[0]
copyCmd = copyCmd.replace("^SRC^",files[0])
copyCmd = copyCmd.replace("^DEST^",files[1])
#Add these commands to copy over folders (including empty)
#and specify that the destination is a folder as well
if isDir:
copyCmd += " /i /E"
outputBuf += copyCmd + "\r\n"
else:
if (lines[0].strip() == "mkdir"):
outputBuf += lines[0].strip() + " " + lines[1] + "\n"
else:
print "Unknown command " + lines[0].strip() + "; ignoring"
out = open(os.path.join(moduleName,deliverBatName),"w")
out.write(outputBuf)
out.close()
#Open the last file used and add the batch file to its post build events
#patchLastVcProj()
def patchSolution(projects,fileName):
masterFileName = "solutionMaster.sln"
prjHeader = "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 2012\n"
startDependStr = "\tProjectSection(ProjectDependencies) = postProject\n"
endDependStr = "\tEndProjectSection\n"
dependStr = "\t\t{^DEPENDENCY_GUID^} = {^DEPENDENCY_GUID^}"
dependStrId = "^DEPENDENCY_GUID^"
startPrjStr = "Project(\"{^SOLUTION_GUID^}\") = \"^PRJ_NAME^\", \"^FILENAME^\", \"{^THIS_PRJ_ID^}\""
endPrjStr = "EndProject\n"
prjNameStr = "^PRJ_NAME^"
fileNameStr = "^FILENAME^"
thisPrjStr = "^THIS_PRJ_ID^"
slnIdStr = "^SOLUTION_GUID^"
globalStartStr = "Global\n"
globalEndStr = "EndGlobal\n"
globalPreStr = "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tRelease|Win32 = Release|Win32\n\tEndGlobalSection\n"
globalPreSolution = "\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n"
startGlobalPostStr = "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n"
endGlobalPostStr = "EndGlobalSection\n"
nestStart = "GlobalSection(NestedProjects) = preSolution\n"
nestMiddle = "{^PRJ_ID^} = {^FOLDER_ID^}\n"
nestEnd = "EndGlobalSection\n"
globalSettingsStr = "\t\t{^PRJ_ID^}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{^PRJ_ID^}.Release|Win32.Build.0 = Release|Win32\n"
#Not 100% certain if the first GUID is supposed to be the solution's
#but I can't find that GUID in any of the generated files so...
slnIdStr = "^SOLUTION_GUID^"
outFile = open(fileName,"w")
outputBuf = prjHeader
slnId = ProjectGUID()
allPrjIds = []
if len(projects) > 0:
#ToDo: Add all projects from dependency
#solution files if they exist, or add placeholder
#Makefile projects
for prj in projects:
prjStr = startPrjStr
prjStr = prjStr.replace(prjNameStr,prj[0])
tempPrj = prj[0]
tempPrj = tempPrj.replace(moduleName + "\\","",1)
tempPrj += ".vcxproj"
prjStr = prjStr.replace(fileNameStr,tempPrj)
prjStr = prjStr.replace(slnIdStr,slnId)
prjStr = prjStr.replace(thisPrjStr,prj[1])
outputBuf += prjStr + "\n"
outputBuf += endPrjStr
outputBuf += beginDepComment
outputBuf += globalStartStr
#Include projects from the global dependencies here
outputBuf += globalEndStr
outFile.write(outputBuf)
else:
print "No projects were found for this solution, so the solution file will not be written"
outFile.close()
def findFiles(moduleName,prjName):
retFiles = []
pathStr = os.path.join(moduleName,"source",prjName,"*.java")
files = glob.glob(pathStr)
#Change this to not use glob as it does not work recursively
for f in files:
f = f[len(moduleName)+1:]
if f != "":
retFiles.append(f)
return retFiles
def patchVCProjJava(prjName,moduleName):
rootFile = "java.template"
prjNameStr = "^PRJ_NAME^"
guidStr = "^GUID^"
solutionStr = "^SOLUTION_NAME^"
fileNameStr = "^FILES^"
includeStr = "<ClCompile Include=\"^FILE^\"/>"
files = findFiles(moduleName,prjName)
fileStr = ""
for f in files:
f = fixPaths(f)
f = includeStr.replace("^FILE^",f)
fileStr.append(f+"\n")
javaFile = open(os.path.join(moduleName,"java.template"))
origFile = javaFile.read()
javaFile.close()
guid = ProjectGUID()
origFile = origFile.replace(prjNameStr,prjName)
origFile = origFile.replace(guidStr,guid)
origFile = origFile.replace(fileNameStr,fileStr)
origFile = origFile.replace(solutionStr,moduleName)
outFile = open(os.path.join(moduleName,prjName+".vcxproj"),"w")
outFile.write(origFile)
outFile.close()
allProjects.append((prjName,guid))
def patchVCProjMake(prjName,isPostBuild,buildCmd,rebuildCmd,cleanCmd):
rootFile = "make_proj_master.vcxproj"
f = open(rootFile,"r")
guidStr = "^GUID^"
prjNameStr = "^PRJ_NAME^"
buildTypeStr = "^BUILD_TYPE^"
buildCmdStr = "^BUILD_CMD^"
rebuildCmdStr = "^REBUILD_CMD^"
cleanCmdStr = "^CLEAN_CMD^"
origFile = f.read()
moduleFileName = ""
if isPostBuild:
buildType = "deliver"
else:
buildType = "prebuild"
f.close()
if (isPostBuild):
moduleFileName = prjName+"/"+prjName+"_deliver.vcxproj"
f = open(moduleFileName,"w")
prjId = ProjectGUID()
origFile = origFile.replace(guidStr,sanitizeArg(prjId))
origFile = origFile.replace(prjNameStr,sanitizeArg(prjName))
origFile = origFile.replace(buildTypeStr,sanitizeArg(buildType))
origFile = origFile.replace(buildCmdStr,buildCmd)
origFile = origFile.replace(rebuildCmdStr,rebuildCmd)
origFile = origFile.replace(cleanCmdStr,cleanCmd)
f.write(origFile)
f.close()
dependencies = []
for prj in allProjects:
dependencies.append(prj[1])
prjTuple = prjName.strip(), prjId, "", dependencies, moduleFileName[moduleFileName.rfind("/")+1:], []
allProjects.append(prjTuple)
def checkFilename(inputName, names, extensions):
temp = inputName.split(".")
if temp[0] in names:
return True
elif (len(temp) > 1 and temp[1] in extensions):
return True
else:
return False
def directories(path):
for file in os.listdir(path):
if os.path.isdir(os.path.join(path, file)):
yield file
def runEveryFolder(startDir):
try:
os.mkdir(startDir + '\\' + outputDir)
except:
pass
for d in directories(startDir):
print ('######################')
main(os.path.join(startDir + '\\' + d),startDir)
print ('######################')
# Run the script from the AOO main directory - alternatively, pass in the path to the main directory below
if (len(sys.argv) != 2):
print "Usage: python vcGen.py moduleName\nRun from main AOO directory and have output file in the name <modulename>/<modulename>.txt"
exit
#moduleName = sys.argv[1]
moduleName = "xmerge"
print ###############################################
try:
os.mkdir(os.getcwd() + "\\" + moduleName)
except:
pass
newParse(moduleName + "/" + moduleName + ".txt",moduleName)
patchSolution(allProjects,os.path.join(moduleName, moduleName + ".sln"))
parseDLst(os.path.join(moduleName,"prj",deliverFileName))
print allProjects