700 lines
17 KiB
Ruby
Executable File
700 lines
17 KiB
Ruby
Executable File
require 'xml'
|
|
require 'pipeline/coding/projbuild/project'
|
|
require 'pipeline/coding/projbuild/config'
|
|
require 'pipeline/coding/projbuild/generators/vsutility'
|
|
require 'pipeline/coding/projbuild/generators/vsshared'
|
|
require 'pipeline/coding/xml2vsxml'
|
|
|
|
module Pipeline
|
|
|
|
module ProjBuild
|
|
|
|
class VS2005VSSlnExporter < VSProjShared
|
|
|
|
@@log = nil
|
|
|
|
def VS2005VSSlnExporter.log
|
|
|
|
@@log = Log.new( 'vs2005vsslnexporter' ) if @@log == nil
|
|
@@log
|
|
end
|
|
|
|
def initialize()
|
|
|
|
@log = VS2005VSSlnExporter.log
|
|
|
|
config = Pipeline::Config.instance
|
|
|
|
@p4 = SCM::Perforce.new()
|
|
@p4.port = config.sc_server
|
|
@p4.client = config.sc_workspace
|
|
@p4.user = config.sc_username
|
|
@p4.connect()
|
|
end
|
|
|
|
def export(path, project)
|
|
|
|
path = VS2005Generator.get_solution_filename(path)
|
|
|
|
#add_in_p4(path) as of yet adding is not supported - but I think it should be eventually.
|
|
|
|
sln_guid = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}"
|
|
proj_build = ProjBuildData::instance()
|
|
|
|
edit_in_p4(@p4, path ) # DW - mmm naughty - why different from other exporters?
|
|
|
|
File.open(path,"w+") { |file|
|
|
|
|
main_filename = VS2005Generator.get_project_filename(project.name)
|
|
|
|
#identifying character sequence for a 2005 sln
|
|
|
|
file.putc(0xef)
|
|
file.putc(0xbb)
|
|
file.putc(0xbf)
|
|
file.write("\n")
|
|
file.write("Microsoft Visual Studio Solution File, Format Version 9.00\n")
|
|
file.write("# Visual Studio 2005\n")
|
|
file.write("Project(\"#{sln_guid}\") = \"#{project.name}\", \"#{main_filename}\", \"#{project.guid}\"\n")
|
|
file.write("\tProjectSection(ProjectDependencies) = postProject\n")
|
|
|
|
dep_guids = ActiveSupport::OrderedHash.new()
|
|
|
|
project.dep_guids.each { |dep_guid|
|
|
|
|
dep_guids[dep_guid] = true
|
|
|
|
dep_project = proj_build.dependent_projects[dep_guid]
|
|
file.write("\t\t#{dep_project.guid} = #{dep_project.guid}\n")
|
|
}
|
|
|
|
file.write("\tEndProjectSection\n")
|
|
file.write("EndProject\n")
|
|
|
|
proj_build.dependent_projects.keys.each { |dep_guid|
|
|
|
|
next if dep_guid == project.guid
|
|
|
|
dep_project = proj_build.dependent_projects[dep_guid]
|
|
|
|
filename = OS::Path.combine(dep_project.path,dep_project.name)
|
|
filename = OS::Path.make_relative(filename,OS::Path.get_directory(main_filename))
|
|
filename = OS::Path.dos_format(VS2005Generator.get_project_filename(filename))
|
|
|
|
file.write("Project(\"#{sln_guid}\") = \"#{dep_project.name}\", \"#{filename}\", \"#{dep_project.guid}\"\n")
|
|
file.write("\tProjectSection(ProjectDependencies) = postProject\n")
|
|
file.write("\tEndProjectSection\n")
|
|
file.write("EndProject\n")
|
|
}
|
|
|
|
file.write("Global\n")
|
|
file.write("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n")
|
|
|
|
proj_build.sln_platforms.each { |sln_platform,targets|
|
|
|
|
targets.each { |sln_target,proj_cfg|
|
|
|
|
platform_out = VSProjShared.get_platform_string(sln_platform)
|
|
config = "#{sln_target}|#{platform_out}"
|
|
|
|
file.write("\t\t#{config} = #{config}\n")
|
|
}
|
|
}
|
|
|
|
file.write("\tEndGlobalSection\n")
|
|
|
|
file.write("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n")
|
|
|
|
proj_build.sln_platforms.each { |sln_platform,targets|
|
|
|
|
targets.each { |sln_target,proj_cfgs|
|
|
|
|
#First process the start up project.
|
|
proj_cfg = proj_cfgs[project.guid]
|
|
prj_cfg = VSUtility.create_config_name(proj_cfg.platform,proj_cfg.target)
|
|
sln_cfg = "#{sln_target}|#{VSProjShared.get_platform_string(sln_platform)}"
|
|
config_out = "#{project.guid}.#{sln_cfg}"
|
|
|
|
file.write("\t\t#{config_out}.ActiveCfg = #{prj_cfg}\n")
|
|
file.write("\t\t#{config_out}.Build.0 = #{prj_cfg}\n")
|
|
|
|
#Process its dependent projects.
|
|
proj_build.dependent_projects.keys.each { |guid|
|
|
|
|
next if proj_cfgs[guid] == nil
|
|
proj_cfg = proj_cfgs[guid]
|
|
|
|
prj_cfg = VSUtility.create_config_name(proj_cfg.platform,proj_cfg.target)
|
|
sln_cfg = "#{sln_target}|#{VSProjShared.get_platform_string(sln_platform)}"
|
|
config_out = "#{guid}.#{sln_cfg}"
|
|
|
|
file.write("\t\t#{config_out}.ActiveCfg = #{prj_cfg}\n")
|
|
|
|
if dep_guids[guid] or guid == project.guid then
|
|
|
|
file.write("\t\t#{config_out}.Build.0 = #{prj_cfg}\n")
|
|
end
|
|
}
|
|
}
|
|
}
|
|
|
|
file.write("\tEndGlobalSection\n")
|
|
|
|
file.write("\tGlobalSection(SolutionProperties) = preSolution\n")
|
|
file.write("\t\tHideSolutionNode = FALSE\n")
|
|
file.write("\tEndGlobalSection\n")
|
|
file.write("EndGlobal\n")
|
|
}
|
|
|
|
revert_unchanged(path)
|
|
|
|
true
|
|
end
|
|
end
|
|
|
|
class VS2005VSProjExporter < VSProjExporterShared
|
|
|
|
@@log = nil
|
|
|
|
def VS2005VSProjExporter.log
|
|
|
|
@@log = Log.new( 'vs2005vsprojexporter' ) if @@log == nil
|
|
@@log
|
|
end
|
|
|
|
def initialize()
|
|
|
|
@log = VS2005VSProjExporter.log
|
|
@version = "2005"
|
|
end
|
|
|
|
protected
|
|
|
|
def create_project_node( project )
|
|
|
|
xml_node = XML::Node.new("VisualStudioProject")
|
|
xml_node.attributes["ProjectType"] = "Visual C++"
|
|
xml_node.attributes["Version"] = "8.00"
|
|
xml_node.attributes["Name"] = project.name
|
|
xml_node.attributes["ProjectGUID"] = project.guid
|
|
xml_node.attributes["Keyword"] = "Win32Proj"
|
|
|
|
xml_node
|
|
end
|
|
end
|
|
|
|
class VS2005VSProjLoader < VSProjShared
|
|
|
|
@@log = nil
|
|
|
|
def VS2005VSProjLoader.log
|
|
|
|
@@log = Log.new( 'vs2005vsprojloader' ) if @@log == nil
|
|
@@log
|
|
end
|
|
|
|
def initialize()
|
|
|
|
@log = VS2005VSProjLoader.log
|
|
end
|
|
|
|
def import( path, project_path = nil )
|
|
|
|
if File.exists?(path) == false then
|
|
|
|
@log.debug("couldn't open #{path}")
|
|
return false
|
|
end
|
|
|
|
@log.debug("checking #{path} with vs2005 project loader")
|
|
|
|
data = nil
|
|
|
|
parser = XML::Parser.file(path)
|
|
doc = parser.parse
|
|
|
|
if doc.root.attributes["Version"] != "8.00" then
|
|
|
|
@log.debug("#{path} not in the correct format")
|
|
return false
|
|
end
|
|
|
|
strip_unused_info(doc)
|
|
|
|
@log.debug("parsing #{path} with vs2005 project loader")
|
|
|
|
@curr_project_path = project_path if project_path != nil
|
|
@curr_project_path = OS::Path.normalise(OS::Path.get_directory(path)) unless project_path != nil
|
|
|
|
@curr_project = Info::Project.new(OS::Path.get_basename(path))
|
|
@curr_project.name = doc.root["Name"]
|
|
@curr_project.path = @curr_project_path
|
|
@curr_project.config.xml_data = XML::Node.new("config")
|
|
|
|
#files
|
|
files_node = doc.find_first("Files")
|
|
import_proj_files(files_node,@curr_project)
|
|
|
|
#root config
|
|
configs_node = doc.find_first("Configurations")
|
|
import_root_configs(configs_node)
|
|
|
|
@curr_project.guid = doc.root.attributes["ProjectGUID"]
|
|
|
|
@log.debug("parsed #{path}")
|
|
return true, @curr_project
|
|
end
|
|
|
|
protected
|
|
|
|
def strip_unused_info( doc )
|
|
|
|
doc.find("/VisualStudioProject/Configurations/Configuration/Tool").each { |xml_node|
|
|
|
|
case xml_node.attributes["Name"]
|
|
|
|
when "VCWebDeploymentTool":
|
|
|
|
xml_node.remove!
|
|
end
|
|
}
|
|
end
|
|
|
|
def import_file_config_hierarchy( xml_in )
|
|
|
|
xml_out = nil
|
|
|
|
if xml_in.name == "FileConfiguration" then
|
|
|
|
xml_out = XML::Node.new("config")
|
|
clone_attributes(xml_in,xml_out)
|
|
elsif xml_in.name == "Tool" then
|
|
|
|
xml_out = XML::Node.new(xml_in.attributes["Name"])
|
|
clone_attributes(xml_in,xml_out)
|
|
elsif xml_in.name == "custombuild" then
|
|
|
|
xml_out = XML::Node.new(xml_in.attributes["Name"])
|
|
clone_attributes(xml_in,xml_out)
|
|
end
|
|
|
|
# if xml_out == nil then
|
|
#
|
|
# ProjBuilder.log.debug("Not loaded!")
|
|
# ProjBuilder.log.debug(xml_in)
|
|
# end
|
|
|
|
if xml_out != nil and xml_in.children? then
|
|
|
|
xml_in.children.each { |child|
|
|
|
|
xml_new = import_file_config_hierarchy(child)
|
|
xml_out << xml_new if xml_new != nil
|
|
}
|
|
end
|
|
|
|
xml_out
|
|
end
|
|
|
|
def import_proj_files( xml_node, filter_node )
|
|
|
|
xml_node.find("File").each do |xml_file_node|
|
|
|
|
file_path = xml_file_node.attributes["RelativePath"]
|
|
file_path = File.expand_path(file_path,@curr_project_path)
|
|
|
|
new_file = Info::File.new(file_path)
|
|
|
|
xml_file_node.find("FileConfiguration").each do |xml_file_config_node|
|
|
|
|
platform, target = VSProjShared.parse_config_name(xml_file_config_node.attributes["Name"])
|
|
next if (platform == nil or target == nil)
|
|
config = new_file.platforms[platform].get_target(target)
|
|
config.xml_data = import_file_config_hierarchy(xml_file_config_node)
|
|
|
|
end
|
|
|
|
filter_node.files << new_file
|
|
end
|
|
|
|
xml_node.find("Filter").each do |xml_filter_node|
|
|
|
|
new_filter_node = Info::Filter.new(xml_filter_node.attributes["Name"])
|
|
filter_node.filters << new_filter_node
|
|
|
|
import_proj_files(xml_filter_node,new_filter_node)
|
|
end
|
|
end
|
|
|
|
def import_config_hierarchy( xml_in, doc, platform, target )
|
|
|
|
xml_out = nil
|
|
|
|
if xml_in.name == "Configuration" then
|
|
|
|
doc.root = XML::Node.new("config")
|
|
xml_out = XML::Node.new("vc")
|
|
doc.root << xml_out
|
|
|
|
case xml_in["ConfigurationType"]
|
|
|
|
when "1": doc.root["type"] = :exe.to_s
|
|
when "2": doc.root["type"] = :dll.to_s
|
|
when "4": doc.root["type"] = :library.to_s
|
|
end
|
|
|
|
doc.root["output_path"] = xml_in["OutputDirectory"].downcase if xml_in["OutputDirectory"]
|
|
|
|
elsif xml_in.name == "Tool" or xml_in.name == "custombuild" then
|
|
|
|
found = false
|
|
if xml_in["Name"] == "VCCLCompilerTool" or xml_in["Name"] == "VCCLX360CompilerTool" then
|
|
|
|
if xml_in["AdditionalIncludeDirectories"] then
|
|
|
|
found = true
|
|
xml_incpaths = create_xml_path(doc.root,"includepaths")
|
|
dirs = xml_in["AdditionalIncludeDirectories"].split(";")
|
|
xml_in.attributes.get_attribute("AdditionalIncludeDirectories").remove!
|
|
|
|
dirs.each { |dir|
|
|
|
|
xml_incpath = XML::Node.new("includepath")
|
|
xml_incpath["path"] = dir
|
|
|
|
xml_incpaths << xml_incpath
|
|
}
|
|
end
|
|
|
|
if xml_in["PreprocessorDefinitions"] then
|
|
|
|
found = true
|
|
xml_defines = create_xml_path(doc.root,"defines")
|
|
defines = xml_in["PreprocessorDefinitions"].split(";")
|
|
xml_in.attributes.get_attribute("PreprocessorDefinitions").remove!
|
|
|
|
defines.each { |define|
|
|
|
|
next if define == ""
|
|
|
|
xml_define = XML::Node.new("define")
|
|
xml_define["value"] = define
|
|
|
|
xml_defines << xml_define
|
|
}
|
|
end
|
|
|
|
if xml_in["ForcedIncludeFiles"] then
|
|
|
|
found = true
|
|
xml_forceincludes = create_xml_path(doc.root,"forceincludes")
|
|
forceincludes = xml_in["ForcedIncludeFiles"].split(";")
|
|
xml_in.attributes.get_attribute("ForcedIncludeFiles").remove!
|
|
|
|
i = 0
|
|
|
|
forceincludes.each { |forceinclude|
|
|
|
|
xml_forceinclude = XML::Node.new("forceinclude")
|
|
xml_forceinclude["path"] = forceinclude
|
|
xml_forceinclude["order"] = i.to_s
|
|
|
|
i = i + 1
|
|
|
|
xml_forceincludes << xml_forceinclude
|
|
}
|
|
end
|
|
end
|
|
|
|
if (xml_in.attributes["Name"] != nil and xml_in.attributes.length > 1) then
|
|
|
|
xml_out = XML::Node.new(xml_in.attributes["Name"])
|
|
clone_attributes(xml_in,xml_out)
|
|
end
|
|
elsif xml_in.name == "DebuggerTool" then
|
|
|
|
xml_out = XML::Node.new("DebuggerTool")
|
|
clone_attributes(xml_in,xml_out)
|
|
end
|
|
|
|
# if xml_out == nil then
|
|
#
|
|
# ProjBuilder.log.debug("Not loaded!")
|
|
# ProjBuilder.log.debug(xml_in)
|
|
# end
|
|
|
|
if xml_out != nil and xml_in.children? then
|
|
|
|
xml_in.children.each { |child|
|
|
|
|
xml_new = import_config_hierarchy(child,doc,platform,target)
|
|
xml_out << xml_new if xml_new != nil
|
|
}
|
|
end
|
|
|
|
xml_out
|
|
end
|
|
|
|
def import_root_config( xml_node )
|
|
|
|
platform, target = VSProjShared.parse_config_name(xml_node.attributes["Name"])
|
|
|
|
return nil if (platform == nil or target == nil)
|
|
|
|
config = @curr_project.platforms[platform].get_target(target)
|
|
|
|
doc = XML::Document.new()
|
|
import_config_hierarchy(xml_node,doc,platform,target)
|
|
|
|
config.xml_data = doc.root
|
|
end
|
|
|
|
def import_root_configs( xml_node )
|
|
|
|
config_nodes = xml_node.find("Configuration")
|
|
|
|
config_nodes.each do |xml_config_node|
|
|
|
|
import_root_config(xml_config_node)
|
|
end
|
|
end
|
|
end
|
|
|
|
class VS2005SlnLoader
|
|
|
|
attr_reader :projects
|
|
|
|
@@log = nil
|
|
|
|
def VS2005SlnLoader.log
|
|
@@log = Log.new( 'vs2005slnloader' ) if @@log == nil
|
|
@@log
|
|
end
|
|
|
|
def initialize()
|
|
|
|
@log = VS2005SlnLoader.log
|
|
end
|
|
|
|
def import( path )
|
|
@log.debug("parsing #{path}")
|
|
|
|
#make sure the path is absolute...
|
|
|
|
#set the parent path
|
|
@sln_dir = OS::Path.normalise(OS::Path.get_directory(path))
|
|
|
|
sln_lines = File.readlines(path)
|
|
|
|
# puts(sln_lines[0]) #first line is just a file format comment
|
|
|
|
state = :none
|
|
|
|
line_buffer = Array.new()
|
|
|
|
sln_lines.each { |line|
|
|
|
|
case state
|
|
when :none
|
|
|
|
if line.index("Project") == 0 then
|
|
|
|
state = :project
|
|
line_buffer = Array.new()
|
|
line_buffer << line
|
|
end
|
|
|
|
if line.index("Global") == 0 then
|
|
|
|
state = :global
|
|
line_buffer = Array.new()
|
|
line_buffer << line
|
|
end
|
|
when :project
|
|
|
|
if line.index("EndProject") == 0 then
|
|
|
|
state = :none
|
|
line_buffer << line
|
|
load_sln_project_section(line_buffer)
|
|
else
|
|
line_buffer << line
|
|
end
|
|
|
|
when :global
|
|
|
|
if line.index("EndGlobal") == 0 then
|
|
state = :none
|
|
line_buffer << line
|
|
load_sln_global_section(line_buffer)
|
|
else
|
|
|
|
line_buffer << line
|
|
end
|
|
|
|
end
|
|
}
|
|
|
|
return true, nil
|
|
end
|
|
|
|
def load_sln_project_section( lines )
|
|
|
|
tokens = lines[0].split("=")
|
|
tokens = tokens[1].split(",")
|
|
|
|
name = tokens[0]
|
|
proj_file = tokens[1].strip
|
|
proj_file = OS::Path.normalise(proj_file[1...(proj_file.size - 1)])
|
|
proj_file = File.expand_path(proj_file,@sln_dir)
|
|
|
|
guid = tokens[2]
|
|
deps = Array.new()
|
|
|
|
|
|
state = :none
|
|
|
|
lines.each { |line|
|
|
|
|
case state
|
|
|
|
when :none
|
|
|
|
if line.strip.index("ProjectSection(ProjectDependencies) = postProject") == 0 then
|
|
|
|
state = :deps
|
|
|
|
end
|
|
when :deps
|
|
|
|
if line.strip.index("EndProjectSection") == 0 then
|
|
|
|
state = :none
|
|
else
|
|
|
|
deps << line.split("=")[0].strip
|
|
end
|
|
end
|
|
}
|
|
|
|
loader = VS2005VSProjLoader.new()
|
|
ret, project = loader.import(proj_file)
|
|
ProjBuildData::instance().projects[project.guid] = project if ret == true
|
|
end
|
|
|
|
def load_sln_global_section( lines )
|
|
|
|
state = :none
|
|
|
|
lines.each { |line|
|
|
|
|
case state
|
|
when :none
|
|
|
|
if line.strip.index("GlobalSection(ProjectConfigurationPlatforms) = postSolution") == 0 then
|
|
|
|
state = :configs
|
|
end
|
|
when :configs
|
|
|
|
if line.strip.index("EndGlobalSection") == 0 then
|
|
|
|
state = :none
|
|
else
|
|
|
|
tokens = line.strip.split("=")
|
|
prj_data = tokens[0]
|
|
sln_cfg = tokens[1].strip
|
|
tokens = prj_data.split(".")
|
|
guid = tokens[0].strip
|
|
prj_cfg = tokens[1].strip
|
|
command = tokens[2].strip
|
|
|
|
if command == "ActiveCfg" then
|
|
|
|
sln_tokens = sln_cfg.split("|")
|
|
sln_platform = sln_tokens[1]
|
|
sln_target = sln_tokens[0]
|
|
proj_platform, proj_target = VSProjShared.parse_config_name(prj_cfg)
|
|
ProjBuildData::instance().add_projectconfig(sln_platform,sln_target,guid,proj_platform,proj_target)
|
|
end
|
|
end
|
|
end
|
|
}
|
|
end
|
|
end
|
|
|
|
class VS2005Generator
|
|
|
|
@@log = nil
|
|
|
|
GENERATOR_ID = "2005"
|
|
|
|
@@unity_build_filenames = nil # if true filenames that are created have "_unity" in them.
|
|
def set_unity_build_filenames( set )
|
|
@@unity_build_filenames = set
|
|
end
|
|
|
|
def get_unity_build_filenames( )
|
|
@@unity_build_filenames
|
|
end
|
|
|
|
def self.get_project_filename( basename )
|
|
(@@unity_build_filenames and not basename.downcase.include?("shaders")) ? "#{basename}_#{GENERATOR_ID}_unity.vcproj" : "#{basename}_#{GENERATOR_ID}.vcproj"
|
|
end
|
|
|
|
def self.get_solution_filename( basename )
|
|
(@@unity_build_filenames and not basename.downcase.include?("shaders")) ? "#{basename}_#{GENERATOR_ID}_unity.sln" : "#{basename}_#{GENERATOR_ID}.sln"
|
|
end
|
|
|
|
def VS2005Generator.log
|
|
|
|
@@log = Log.new( 'VS2005Generator' ) if @@log == nil
|
|
@@log
|
|
end
|
|
|
|
def initialize()
|
|
|
|
@log = VS2005Generator.log
|
|
end
|
|
|
|
def export( path, project, options = nil )
|
|
|
|
VS2005Generator.log.debug("exporting #{path} through vs2005 path")
|
|
|
|
if options != nil and options[:type] == :solution then
|
|
|
|
return VS2005VSSlnExporter.new().export(path,project)
|
|
else
|
|
|
|
path = VS2005Generator.get_project_filename(path)
|
|
return VS2005VSProjExporter.new().export(path,project)
|
|
end
|
|
|
|
false
|
|
end
|
|
|
|
def import( path, options = nil )
|
|
|
|
case OS::Path::get_extension(path).downcase
|
|
|
|
when 'sln':
|
|
|
|
@log.debug("import solution #{path}")
|
|
loader = VS2005SlnLoader.new()
|
|
return loader.import(path)
|
|
|
|
when 'vcproj':
|
|
|
|
@log.debug("import project #{path}")
|
|
loader = VS2005VSProjLoader.new()
|
|
return loader.import(path)
|
|
end
|
|
|
|
false
|
|
end
|
|
end
|
|
|
|
end #module ProjBuild
|
|
|
|
end #module Pipeline |