123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- # Copyright 2016 The Chromium Authors. All rights reserved.
- # Use of this source code is governed by a BSD-style license that can be
- # found in the LICENSE file.
- import os
- import glob
- import re
- import sys
- from shutil import copyfile
- # Helpers
- def ensureExists(path):
- try:
- os.makedirs(path)
- except OSError:
- pass
- def writeLinesToFile(lines, fileName):
- ensureExists(os.path.dirname(fileName))
- with open(fileName, "w") as f:
- f.writelines(lines)
- def extractIdg(projFileName):
- result = []
- with open(projFileName) as projFile:
- lines = iter(projFile)
- for pLine in lines:
- if "<ItemDefinitionGroup" in pLine:
- while not "</ItemDefinitionGroup" in pLine:
- result.append(pLine)
- pLine = lines.next()
- result.append(pLine)
- return result
- # [ (name, hasSln), ... ]
- configs = []
- # Find all directories that can be used as configs (and record if they have VS
- # files present)
- for root, dirs, files in os.walk("out"):
- for outDir in dirs:
- gnFile = os.path.join("out", outDir, "build.ninja.d")
- if os.path.exists(gnFile):
- slnFile = os.path.join("out", outDir, "all.sln")
- configs.append((outDir, os.path.exists(slnFile)))
- break
- # Every project has a GUID that encodes the type. We only care about C++.
- cppTypeGuid = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"
- # name -> [ (config, pathToProject, GUID), ... ]
- allProjects = {}
- projectPattern = (r'Project\("\{' + cppTypeGuid +
- r'\}"\) = "([^"]*)", "([^"]*)", "\{([^\}]*)\}"')
- projectNamePattern = (r'obj/(.*)\.vcxproj')
- for config in configs:
- if config[1]:
- slnLines = iter(open("out/" + config[0] + "/all.sln"))
- for slnLine in slnLines:
- matchObj = re.match(projectPattern, slnLine)
- if matchObj:
- projPath = matchObj.group(2)
- nameObj = re.match(projectNamePattern, projPath)
- if nameObj:
- projName = nameObj.group(1).replace('/', '.')
- if not allProjects.has_key(projName):
- allProjects[projName] = []
- allProjects[projName].append((config[0], projPath,
- matchObj.group(3)))
- # We need something to work with. Typically, this will fail if no GN folders
- # have IDE files
- if len(allProjects) == 0:
- print "ERROR: At least one GN directory must have been built with --ide=vs"
- sys.exit()
- # Create a new solution. We arbitrarily use the first config as the GUID source
- # (but we need to match that behavior later, when we copy/generate the project
- # files).
- newSlnLines = []
- newSlnLines.append(
- 'Microsoft Visual Studio Solution File, Format Version 12.00\n')
- newSlnLines.append('# Visual Studio 2015\n')
- for projName, projConfigs in allProjects.items():
- newSlnLines.append('Project("{' + cppTypeGuid + '}") = "' + projName +
- '", "' + projConfigs[0][1] + '", "{' + projConfigs[0][2]
- + '}"\n')
- newSlnLines.append('EndProject\n')
- newSlnLines.append('Global\n')
- newSlnLines.append(
- '\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n')
- for config in configs:
- newSlnLines.append('\t\t' + config[0] + '|x64 = ' + config[0] + '|x64\n')
- newSlnLines.append('\tEndGlobalSection\n')
- newSlnLines.append(
- '\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n')
- for projName, projConfigs in allProjects.items():
- projGuid = projConfigs[0][2]
- for config in configs:
- newSlnLines.append('\t\t{' + projGuid + '}.' + config[0] +
- '|x64.ActiveCfg = ' + config[0] + '|x64\n')
- newSlnLines.append('\t\t{' + projGuid + '}.' + config[0] +
- '|x64.Build.0 = ' + config[0] + '|x64\n')
- newSlnLines.append('\tEndGlobalSection\n')
- newSlnLines.append('\tGlobalSection(SolutionProperties) = preSolution\n')
- newSlnLines.append('\t\tHideSolutionNode = FALSE\n')
- newSlnLines.append('\tEndGlobalSection\n')
- newSlnLines.append('\tGlobalSection(NestedProjects) = preSolution\n')
- newSlnLines.append('\tEndGlobalSection\n')
- newSlnLines.append('EndGlobal\n')
- # Write solution file
- writeLinesToFile(newSlnLines, "out/sln/skia.sln")
- idgHdr = "<ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='"
- # Now, bring over the project files
- for projName, projConfigs in allProjects.items():
- # Paths to project and filter file in src and dst locations
- srcProjPath = os.path.join("out", projConfigs[0][0], projConfigs[0][1])
- dstProjPath = os.path.join("out", "sln", projConfigs[0][1])
- srcFilterPath = srcProjPath + ".filters"
- dstFilterPath = dstProjPath + ".filters"
- # Copy the filter file unmodified
- ensureExists(os.path.dirname(dstProjPath))
- copyfile(srcFilterPath, dstFilterPath)
- # Bring over the project file, modified with extra configs
- with open(srcProjPath) as srcProjFile:
- projLines = iter(srcProjFile)
- newProjLines = []
- for line in projLines:
- if "<ItemDefinitionGroup" in line:
- # This is a large group that contains many settings. We need to
- # replicate it, with conditions so it varies per configuration.
- idgLines = []
- while not "</ItemDefinitionGroup" in line:
- idgLines.append(line)
- line = projLines.next()
- idgLines.append(line)
- for projConfig in projConfigs:
- configIdgLines = extractIdg(os.path.join("out",
- projConfig[0],
- projConfig[1]))
- newProjLines.append(idgHdr + projConfig[0] + "|x64'\">\n")
- for idgLine in configIdgLines[1:]:
- newProjLines.append(idgLine)
- elif "ProjectConfigurations" in line:
- newProjLines.append(line)
- projConfigLines = [
- projLines.next(),
- projLines.next(),
- projLines.next(),
- projLines.next() ]
- for config in configs:
- for projConfigLine in projConfigLines:
- newProjLines.append(projConfigLine.replace("GN",
- config[0]))
- elif "<OutDir" in line:
- newProjLines.append(line.replace(projConfigs[0][0],
- "$(Configuration)"))
- else:
- newProjLines.append(line)
- with open(dstProjPath, "w") as newProj:
- newProj.writelines(newProjLines)
|