blob: f5ad0b10ab53db6b841bb7ec0ac6b3492847123f [file] [log] [blame]
#TODO: Propgroups below UserMacros, ClCompile, Link, & Lib stuff, pre and postbuild events, custom compiler directives
# parsed from makefiles
import os
import string
import random
import sys
outputDir = 'converted-module-projects'
libProj = 'libProj.vcxproj'
sourceExtensions = ['c', 'cpp', 'cxx','l','y','ll','yy', 'crc']
headerExtensions = ['h', 'hxx', 'hrc']
libExtensions = ['lib']
includeDebug = False
postBuildName = 'postbuild.bat'
def main(moduleDir, mainDir):
os.chdir(moduleDir)
print (moduleDir)
name = moduleDir.rsplit('\\',1)
outputFile =(mainDir+'\\' + outputDir + '\\'+name[len(name)-1] + ".vcxproj","w+")
#printAndOutput("Name:",outputFile)
#printAndOutput(name[1],outputFile)
#printAndOutput('',outputFile)
try:
file = open('prj/d.lst')
except IOError:
print ('prj.lst not found, skipping folder')
outputFile.close()
return
constructProjFile(outputFile, file, name[1], moduleDir, mainDir)
def constructProjFile(projFile, buildFile, name, moduleDir, mainDir):
indentationLevel = 0;
xmlVersionTag(projFile, indentationLevel)
projectTag(projFile, buildFile, name, mainDir, moduleDir, indentationLevel)
def xmlVersionTag(projFile, indentationLevel):
printAndOutput(projFile, '<?xml version="1.0" encoding="utf-8"?>', indentationLevel)
def projectTag(projFile, buildFile, name, mainDir, moduleDir, indentationLevel):
printAndOutput(projFile, '<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">', indentationLevel)
projectConfiguration(projFile, indentationLevel + 1)
globalsProperty(projFile, name, indentationLevel + 1)
if (includeDebug):
conditionProperty(projFile, indentationLevel + 1)
conditionProperty(projFile, indentationLevel + 1)
importProject(projFile, 'props', indentationLevel + 1) # imports 'props' project
extensionSettings(projFile, indentationLevel + 1)
if (includeDebug):
propertySheets(projFile, indentationLevel + 1) # Include if debug version is included
propertySheets(projFile, indentationLevel + 1)
userMacros(projFile, indentationLevel + 1)
if (includeDebug):
libPropertyGroup(projFile, mainDir, name, indentationLevel + 1) # include if debug version is included
libPropertyGroup(projFile, mainDir, name, indentationLevel + 1)
if (includeDebug):
itemDefinitionGroup(projFile, mainDir, moduleDir, indentationLevel + 1)
itemDefinitionGroup(projFile, mainDir, moduleDir, indentationLevel + 1)
headerFiles(projFile, moduleDir, indentationLevel + 1)
sourceFiles(projFile, moduleDir, indentationLevel + 1)
importProject(projFile, 'targets', indentationLevel + 1) # imports 'targets' project
extensionSettings(projFile, indentationLevel + 1)
printAndOutput(projFile, '</Project>', indentationLevel)
# Whether or not a debug version is included is defined here
def projectConfiguration(projFile, indentationLevel):
printAndOutput(projFile, '<ItemGroup Label="ProjectConfigurations">', indentationLevel)
printAndOutput(projFile, '<ProjectConfiguration Include="Debug|Win32">', indentationLevel + 1)
printAndOutput(projFile, '<Configuration>Debug</Configuration>', indentationLevel + 2)
printAndOutput(projFile, '<Platform>Win32</Platform>', indentationLevel + 2)
printAndOutput(projFile, '</ProjectConfiguration>', indentationLevel + 1)
printAndOutput(projFile, '<ProjectConfiguration Include="Release|Win32">', indentationLevel + 1)
printAndOutput(projFile, '<Configuration>Release</Configuration>', indentationLevel + 2)
printAndOutput(projFile, '<Platform>Win32</Platform>', indentationLevel + 2)
printAndOutput(projFile, '</ProjectConfiguration>', indentationLevel + 1)
printAndOutput(projFile, '</ItemGroup>', indentationLevel)
# Requires a GUID of form: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12 chars & ints)
def globalsProperty(projFile, name, indentationLevel):
printAndOutput(projFile, '<PropertyGroup Label="Globals">', indentationLevel)
printAndOutput(projFile, '<ProjectGuid>{' + ProjectGUID() + '}</ProjectGuid>', indentationLevel + 1)
printAndOutput(projFile, '<Keyword>Win32Proj</Keyword>', indentationLevel + 1)
printAndOutput(projFile, '<RootNamespace>' + name + '</RootNamespace>', indentationLevel + 1)
printAndOutput(projFile, '</PropertyGroup>', indentationLevel)
# I'm not sure how this is generated, but it looks like each VS Project has a unique identifier. This function should try to generate one.
# Could just use rand on each char in the sequence from 0-F
# Format is 8-4-4-4-12 hexadecimal characters (0-9A-F)
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
# May need to look in build.lst to see what type to buiild to - dll, app, etc.
def conditionProperty(projFile, indentationLevel):
if (includeDebug):
printAndOutput(projFile, '<PropertyGroup Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'" Label="Configuration">', indentationLevel)
else:
printAndOutput(projFile, '<PropertyGroup Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'" Label="Configuration">', indentationLevel)
printAndOutput(projFile, '<ConfigurationType>Application</ConfigurationType>', indentationLevel + 1)
printAndOutput(projFile, '<UseDebugLibraries>false</UseDebugLibraries>', indentationLevel + 1)
printAndOutput(projFile, '<PlatformToolset>v110</PlatformToolset>', indentationLevel + 1) # Looks like this is where we can change the VS version - v110 is VS2012
#printAndOutput(projFile, '<WholeProgramOptimization>true</WholeProgramOptimization>', indentationLevel + 1)
printAndOutput(projFile, '<CharacterSet>NotSet</CharacterSet>', indentationLevel + 1)
printAndOutput(projFile, '</PropertyGroup>', indentationLevel)
def importProject(projFile, proj, indentationLevel):
printAndOutput(projFile, '<Import Project="$(VCTargetsPath)\Microsoft.Cpp.' + proj + '" />', indentationLevel)
def extensionSettings(projFile, indentationLevel):
printAndOutput(projFile, '<ImportGroup Label="ExtensionSettings">', indentationLevel)
printAndOutput(projFile, '</ImportGroup>', indentationLevel)
def propertySheets(projFile, indentationLevel):
if (includeDebug):
printAndOutput(projFile, '<ImportGroup Label="PropertySheets" Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">', indentationLevel)
else:
printAndOutput(projFile, '<ImportGroup Label="PropertySheets" Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">', indentationLevel)
printAndOutput(projFile, '<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists(\'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props\')"', indentationLevel + 1)
printAndOutput(projFile, 'Label="LocalAppDataPlatform" />', indentationLevel + 1)
printAndOutput(projFile, '</ImportGroup>', indentationLevel)
def userMacros(projFile, indentationLevel):
printAndOutput(projFile, '<PropertyGroup Label="UserMacros" />', indentationLevel)
def libPropertyGroup(projFile, mainPath, projName, indentationLevel):
if (includeDebug):
printAndOutput(projFile, '<PropertyGroup Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">', indentationLevel)
printAndOutput(projFile, '<LinkIncremental>true</LinkIncremental>', indentationLevel + 1)
printAndOutput(projFile, '<LibraryPath>' + mainPath + '\\solver\\410\\wntmsci12.pro\\lib;$(LibraryPath)</LibraryPath>', indentationLevel + 1) # Make sure this is actual path!
else:
printAndOutput(projFile, '<PropertyGroup Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">', indentationLevel)
printAndOutput(projFile, '<LinkIncremental>false</LinkIncremental>', indentationLevel + 1)
printAndOutput(projFile, '<OutDir>' + mainPath + '\\solver\\410\\wntmsci12.pro\\bin\\</OutDir>', indentationLevel + 1)
printAndOutput(projFile, '<TargetName>' + projName + '</TargetName>', indentationLevel + 1)
printAndOutput(projFile, '</PropertyGroup>', indentationLevel)
def itemDefinitionGroup(projFile, mainPath, modulePath, indentationLevel):
if (includeDebug):
printAndOutput(projFile, '<ItemDefinitionGroup Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">', indentationLevel)
else:
printAndOutput(projFile, '<ItemDefinitionGroup Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">', indentationLevel)
clCompile(projFile, mainPath, modulePath, indentationLevel + 1)
link(projFile, mainPath, indentationLevel + 1)
printAndOutput(projFile, '</ItemDefinitionGroup>', indentationLevel)
def clCompile(projFile, mainPath, modulePath, indentationLevel):
printAndOutput(projFile, '<ClCompile>', indentationLevel)
if (includeDebug):
printAndOutput(projFile, '<WarningLevel>Level3</WarningLevel>', indentationLevel + 1)
printAndOutput(projFile, '<Optimization>Disabled</Optimization>', indentationLevel + 1)
else:
printAndOutput(projFile, '<WarningLevel>Level3</WarningLevel>', indentationLevel + 1)
printAndOutput(projFile, '<Optimization>MaxSpeed</Optimization>', indentationLevel + 1)
printAndOutput(projFile, '<FunctionLevelLinking>true</FunctionLevelLinking>', indentationLevel + 1)
printAndOutput(projFile, '<IntrinsicFunctions>true</IntrinsicFunctions>', indentationLevel + 1)
printAndOutput(projFile, '<PrecompiledHeader>', indentationLevel + 1)
printAndOutput(projFile, '</PrecompiledHeader>', indentationLevel + 1)
additionalIncludeDirectories(projFile, modulePath, indentationLevel + 1) # Debug & non are equivalent
printAndOutput(projFile, '<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WNT;CPPU_ENV;%(PreprocessorDefinitions)', indentationLevel + 1) # Needs to be found through makefile
printAndOutput(projFile, '</PreprocessorDefinitions>', indentationLevel + 1) # Important, may need editing
printAndOutput(projFile, '<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>', indentationLevel + 1) # Necessary?
printAndOutput(projFile, '</ClCompile>', indentationLevel)
def link(projFile, mainPath, indentationLevel):
printAndOutput(projFile, '<Link>', indentationLevel)
if (includeDebug):
printAndOutput(projFile, '<GenerateDebugInformation>true</GenerateDebugInformation>', indentationLevel + 1)
else:
printAndOutput(projFile, '<GenerateDebugInformation>false</GenerateDebugInformation>', indentationLevel + 1)
printAndOutput(projFile, '<EnableCOMDATFolding>true</EnableCOMDATFolding>', indentationLevel + 1)
printAndOutput(projFile, '<OptimizeReferences>true</OptimizeReferences>', indentationLevel + 1)
printAndOutput(projFile, '<SubSystem>Windows</SubSystem>', indentationLevel + 1)
additionalDependencies(projFile, mainPath, indentationLevel + 1)
printAndOutput(projFile, '<AdditionalLibraryDirectories>' + mainPath + '<\\solver\\410\\wntmscipro12.pro\\lib;', indentationLevel + 1)
printAndOutput(projFile, '%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>', indentationLevel + 1)
printAndOutput(projFile, '<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>', indentationLevel + 1)
printAndOutput(projFile, '<IgnoreSpecificDefaultLibraries>LIBCMT</IgnoreSpecificDefaultLibraries>', indentationLevel + 1)
postBuildEvent(projFile, indentationLevel + 1)
printAndOutput(projFile, '</Link>', indentationLevel)
if (includeDebug):
printAndOutput(projFile, '<Lib>', indentationLevel) # Doubt this is needed
printAndOutput(projFile, '<AdditionalDependencies>sfx.lib;%(AdditionalDependencies)</AdditionalDependencies>', indentationLevel + 1)
printAndOutput(projFile, '</Lib', indentationLevel)
def postBuildEvent(projFile, indentationLevel):
printAndOutput(projFile, '<PostBuildEvent>', indentationLevel)
printAndOutput(projFile, '<Command>batch\\' + postBuildName + '</Command>', indentationLevel + 1)
printAndOutput(projFile, '</PostBuildEvent>', indentationLevel)
# Not sure which directories this will need to include
def additionalIncludeDirectories(projFile, modulePath, indentationLevel):
printAndOutput(projFile, '<AdditionalIncludeDirectories>', indentationLevel)
printAndOutput(projFile, modulePath + '\\inc\\pch;', indentationLevel + 1)
printAndOutput(projFile, modulePath + '\\source', indentationLevel + 1)
# hwpfilter\win32\hwpfilter\hwpfilter - shouldn't be needed
cwd = modulePath.rpartition('\\')[0] # Goes back a directory from module directory
printAndOutput(projFile, cwd + '\\solver\\410\\wntmsci12.pro\\inc', indentationLevel + 1)
printAndOutput(projFile, cwd + '\\solver\\410\\wntmsci12.pro\inc\\external', indentationLevel + 1)
printAndOutput(projFile, cwd + '\\solver\\410\\wntmsci12.pro\\inc\\offuh', indentationLevel + 1)
printAndOutput(projFile, '%(AdditionalIncludeDirectories)', indentationLevel + 1)
printAndOutput(projFile, '</AdditionalIncludeDirectories>', indentationLevel)
def additionalDependencies(projFile, mainPath, indentationLevel):
printAndOutput(projFile, '<AdditionalDependencies>', indentationLevel)
loadLibFiles(projFile, mainPath, indentationLevel + 1)
#loadFileTypes(libExtensions, mainPath, '', projFile, 2) # Loads lib files
printAndOutput(projFile, '%(AdditionalDependencies)', indentationLevel + 1)
printAndOutput(projFile, '</AdditionalDependencies>', indentationLevel)
def headerFiles(projFile, curDir, indentationLevel):
printAndOutput(projFile, '<ItemGroup>', indentationLevel)
loadFileTypes(headerExtensions, curDir, '', projFile, 0, indentationLevel + 1)
printAndOutput(projFile, '</ItemGroup>', indentationLevel)
def sourceFiles(projFile, curDir, indentationLevel):
printAndOutput(projFile, '<ItemGroup>', indentationLevel)
loadFileTypes(sourceExtensions, curDir, '', projFile, 1, indentationLevel + 1)
printAndOutput(projFile, '</ItemGroup>', indentationLevel)
def printAndOutput(outputFile, out, indentationLevel):
for i in range(indentationLevel):
outputFile.write('\t')
print ('\t')
print (out)
outputFile.write(out + '\r\n')
def loadLibFiles(projFile, mainPath, indentationLevel):
path = mainPath + '\\solver\\410\\wntmsci12.pro\\lib\\' # This should always be the lib path
for file in os.listdir(path):
fileExt = file.split('.') # index 0 is name, 1 is ext
if (len(fileExt) > 1 and fileExt[1] in libExtensions):
printAndOutput(projFile, file + ';', indentationLevel)
def parseOutputFile(fileName):
#try:
file = open(fileName,"r")
outputString = file.read()
it = 0
while (1):
libArgs = ""
linkOut = ""
objOut = ""
#Limit our processing to be between the first 'Making' output
#and the next: this should correspond to one Makefile/project
it = outputString.find("Making: ",it)
#Find the first line containing the Making command: the rest
#of it should be the call to cl.exe or lib; we want the
#arguments to cl.exe to put under additional dependencies
makeStr = outputString[it:outputString.find("\n",it)]
end_it = outputString.find(makeStr,it+len("Making: "))
fileNames = []
compIt = it
#Process any files that were compiled and add their paths
#to an array: this ensures that only files that should
#actually be processed are used
while (1):
compIt = outputString.find("Compiling: ",compIt,end_it)
if compIt == -1:
break
compIt += len("Compiling: ")
endCompIt = outputString.find("\n",compIt,end_it)
filePath = outputString[compIt:endCompIt]
filePath = filePath.replace(" ","")
filePath = filePath.split("/",1)
fileNames.append(filePath[1])
#print fileNames
#If we failed to find a 'Making' word then we are out of things
#to process
if (it == -1):
break
#Figure out which command we are dealing with
old_it = outputString.find("cl.exe",it)
lib_it = outputString.find("\nlib ",it,end_it)
if (lib_it != -1):
out_it = outputString.find("/OUT:")+len("/OUT:")
outDir = outputString[out_it:outputString.find(" ",out_it)]
tmp_it = lib_it
lib_it = outputString.find("Making: ",lib_it)
tmpString = outputString[tmp_it+len("\nlib "):lib_it]
#Remove any argument beginning with an @
at_it = tmpString.find("@")
if (at_it != -1):
tmpString = tmpString.replace(tmpString[at_it:tmpString.find("\n",at_it)],"")+"\n"
cmds = tmpString.split("\n")
for cmd in cmds:
cmd = fixPaths(cmd)
if (cmd[0:len("Microsoft")] == "Microsoft" or cmd[0:len("Copyright")] == "Copyright"):
continue
libArgs+= cmd
#print outbuf
it = old_it
#Offset the index of 'cl.exe' to beyond it so we
#don't find it again
old_it += len("cl.exe")
if (it == -1):
break
#Get the index of the end of the string
it = outputString.find("\n",it)
if (it == -1):
break
cmd = outputString[old_it:it]
#These strings generally need to be changed
#due to differences in the working directory
cmd = fixPaths(cmd)
cmd = str.split(cmd)
#Get rid of the last element since it specifies the filename
cmd.pop()
newArg = []
for arg in cmd:
#Replace full paths
if arg.find(":") != -1:
#Don't want absolute paths
arg = arg.replace("C:/steve/TestARea/main","..")
#We need to split off the filename in the output
#parameter as we are running multiple files
#and therefor just need the directory name
if arg.find("-Fo") != -1:
temp = arg.rsplit("/",1)
arg = temp[0] + "/"
objOut = arg[3:]
objOut = objOut.strip(" \t\n\r")
continue
#We tend to not need these paths
if arg.find("~") == -1:
newArg.append(arg)
#Take off the last two slashes to get the deepest directory name
#(plus the first filename) and set the project name to that
prjName = fileNames[0].rsplit("/",2)
prjName = prjName[1]
patchVCProjLib(prjName,fileNames,newArg,libArgs,linkOut,objOut)
it = end_it
def fixPaths(cmd):
cmd = cmd.replace("../../","")
cmd = cmd.replace("../","source")
return cmd
def patchVCProjLib(prjName,files,arguments,libArgs,linkOut,objOut):
rootFile = "libProj.vcxproj"
print objOut
#print "##########################################"
#print prjName
#print files
#print arguments
#print outDir
compileStr = "^BEGIN_CLCOMPILE^"
endCompileStr = "^END_CLCOMPILE^"
clFileName = "^CLFILENAME^"
guidStr = "^GUID^"
addStr = "^ADDITIONAL_OPTIONS^"
nameStr = "^PROJ_NAME^"
outStr = "^OUTPUT^"
libStr = "^LIB_OPTIONS^"
linkOut = "^LINK_OUT^"
objStr = "^OBJ_FILE_NAME^"
f = open(rootFile,"r")
origFile = f.read()
it = origFile.find(compileStr)+len(compileStr)
end_it = origFile.find(endCompileStr,it)
compileLine = origFile[it:end_it]
fileOut = ""
for fName in files:
fileOut += compileLine.replace(clFileName,fName) + "\n\t"
origFile = origFile.replace(origFile[it-len(compileStr):end_it+len(endCompileStr)],fileOut)
origFile = origFile.replace(guidStr,ProjectGUID())
origFile = origFile.replace(addStr, ' '.join(map(str, arguments)))
origFile = origFile.replace(nameStr,prjName)
origFile = origFile.replace(libStr,libArgs)
origFile = origFile.replace(objStr,objOut)
outFile = open(prjName + ".vcxproj","w")
outFile.write(origFile)
def loadFileTypes(extensions, path, matchName, projFile, extType, indentationLevel):
for root, dirs, files in os.walk(path):
for name in files:
tempName = name.rsplit('\\',1)
p = os.path.join(root,name)
if checkFilename(tempName[len(tempName)-1], matchName, extensions):
if (extType == 0): # 0 is headers
printAndOutput(projFile, '<ClInclude Include="..\\..\\..\\' + p.replace(path+"\\","") + '" />', indentationLevel)
elif (extType == 1): # 1 is sources
printAndOutput(projFile, '<ClCompile Include="..\\..\\..\\' + p.replace(path+"\\","") + '" />', indentationLevel)
else: # 2/otherwise is libs
printAndOutput(projFile, name + ';', indentationLevel) # Is lib file
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) == 1:
# runEveryFolder(os.getcwd())
for arg in sys.argv:
if arg == sys.argv[0]:
continue
main(arg, os.getcwd())
parseOutputFile("rdbmaker.txt")
print("\n##############################################\n")
#parseOutputFile("idl.txt")