Files
2025-09-29 00:52:08 +02:00

1182 lines
38 KiB
Ruby
Executable File

require 'xml'
require 'active_support/ordered_hash'
require 'pipeline/coding/projbuild/project'
require 'pipeline/coding/xml2vsxml'
require 'pipeline/coding/projbuild/scriptutility'
require 'pipeline/coding/projbuild/generators/vsshared'
require 'pipeline/coding/projbuild/custom/custom_build_step'
require 'pipeline/os/file'
require 'pipeline/os/path'
module Pipeline
module ProjBuild
# these projects are for conditional inclusion in VS2010 ps3 unity only.
PS3_UNITY_PROJECTS = ["vs_project_frags","vs_project_game_jobs","vs_project_binkspu","vs_project_jobs","vs_project_tasks"]
#HACK: Global search paths to be shared across all RageGenSolutionLoaders created.
$search_guid_paths = Hash.new()
class RageGenSolutionLoader
@@log = nil
def RageGenSolutionLoader.log
@@log = Log.new( 'ragegensolutionloader' ) if @@log == nil
@@log
end
def initialize()
if $search_guid_paths == nil
$search_guid_paths = Hash.new()
end
end
def import( path, output_format, options )
RageGenSolutionLoader.log.debug("Trying to import #{path} with ragegen project loader.")
selected_template = ScriptUtility.determine_solution_template(path)
if selected_template == nil
RageGenSolutionLoader.log.debug("Template doesn't exist: #{selected_template}!")
return false
end
config_filename = "#{selected_template}.configs"
if output_format == :vs2010
config_filename = "#{selected_template}_2010.configs"
RageGenSolutionLoader.log.info("Reading 2010 configs file : #{config_filename}")
end
if File.exists?(config_filename) == false then
print "Config file does not exist: #{config_filename}\n"
RageGenSolutionLoader.log.debug("template doesn't exist: #{config_filename}")
return false
end
solution_generation = ScriptUtility.acquire_variable(path, 'NO_SOLUTION_GENERATION')
if solution_generation != nil and solution_generation != ""
#Due to our reliance on the RageGen generation method to generate multiple projects
#in one folder, the ability to circumvent solution generation is inserted here.
print "No solution generation is switched on within #{path}. No solutions will be generated.\n"
return true
end
testers_var = ScriptUtility.acquire_variable(path, 'TESTERS')
testers_var = "" if testers_var.nil?
archive = ScriptUtility.acquire_variable(path, 'ARCHIVE')
testers_var += " " + archive if archive.nil? == false
@tester_array = testers_var.split(" ")
@working_directory = File.dirname(path)
build_data = ProjBuildData::instance()
build_data.reset
success = true
projects = Array.new()
@tester_array.each do |tester|
basename = OS::Path.get_basename(tester)
solution_file = OS::Path::combine(@working_directory, basename)
print "Generating #{solution_file}...\n"
#Read the .config file for all configurations to add to the solution.
platforms = ActiveSupport::OrderedHash.new()
targets = ActiveSupport::OrderedHash.new()
File.readlines(config_filename).each { |line|
tokens = line.split("=")
sln = tokens[0]
proj = tokens[1]
sln_tokens = sln.split("|")
if sln_tokens.size == 1
line.strip!
print "Unable to parse line \"#{line}\" in #{config_filename}!\n"
next
end
sln_target = sln.split("|")[0].strip
sln_platform = VSProjShared.get_platform(sln.split("|")[1].strip)
if proj == nil then
proj = sln
end
if platforms[sln_platform] == nil then
platforms[sln_platform] = Hash.new()
end
platforms[sln_platform][sln_target] = proj
}
#load in the root project...
guid_filename = OS::Path::combine(@working_directory, basename) + ".guid"
guid = VSProjShared.create_guid(guid_filename, @p4)
project = Info::Project.new(basename)
project.guid = guid
project.path = Dir.getwd
platforms.keys.each { |sln_platform|
targets = platforms[sln_platform]
targets.keys.each { |sln_target|
proj_cfg = targets[sln_target]
proj_platform, proj_target = VSProjShared.parse_config_name(proj_cfg)
build_data.add_projectconfig(sln_platform,sln_target,project.guid,proj_platform,proj_target)
}
}
build_data.projects[project.guid] = project
build_data.root_guid = guid
#load in each of the dependent projects...
search_paths = Array.new()
xproj = ScriptUtility.acquire_variable(path, 'XPROJ')
if xproj != nil
xproj.split(' ').each { |xpath|
search_paths << xpath
}
end
self_search_path = File.dirname(path) + "/"
self_search_path = OS::Path.normalise(self_search_path)
search_paths << self_search_path
search_paths << "%RAGE_DIR%\\stlport\\STLport-5.0RC5\\"
search_paths << "%RAGE_DIR%\\base\\src\\"
search_paths << "%RAGE_DIR%\\suite\\src\\"
search_paths << "%RAGE_DIR%\\base\\samples\\"
search_paths << "%RAGE_DIR%\\suite\\samples\\"
search_paths << "%RAGE_DIR%\\base\\tools\\"
search_paths << "%RAGE_DIR%\\suite\\tools\\"
libs = ScriptUtility.acquire_expanded_libs(path, basename)
Dir.chdir(OS::Path.get_directory(path)) {
if libs != nil
libs.each { |lib|
lib_name = OS::Path.get_basename(lib)
lib = OS::Path.normalise(lib)
guid = nil
guid_filename = nil
if (lib.index(":") == nil) and (lib.index("/") == nil) then
found = false
ambiguous = false
base_guid_name = "#{lib_name}.guid"
search_paths.each { |search_path|
search_path = ScriptUtility.convert_paths_in_line(search_path)
if $search_guid_paths[base_guid_name] != nil
found = true
guid_filename = $search_guid_paths[base_guid_name]
break
else
search_path = File.join(search_path, "**", base_guid_name)
search_path.gsub!("\\", "/")
found_files = Dir.glob( search_path )
if found_files.size == 1
found = true
guid_filename = found_files[0]
$search_guid_paths[base_guid_name] = guid_filename
break
elsif found_files.size > 1
ambiguous = true
break
end
end
}
if found == false
if ambiguous == true
RageGenSolutionLoader.log.debug("Ambiguous project! Multiple objects found; unable to resolve without a more precise path for project: #{lib}!")
print "Multiple GUID files have been found with the same name #{lib}.guid. Unable to proceed!\n"
else
RageGenSolutionLoader.log.debug("Unable to find any file for the library: #{lib}!")
print "Unable to find the library GUID: #{lib}\n"
return
end
next
end
else
lib = OS::Path.remove_extension(lib)
lib = File.expand_path(lib)
guid_filename = "#{lib}.guid"
end
guid_filename = OS::Path::make_relative( guid_filename, @working_directory )
guid = VSProjShared.create_guid(guid_filename, @p4)
if guid == nil
RageGenSolutionLoader.log.debug("Unable to acquire guid #{guid_filename}!")
print "Unable to acquire guid #{guid_filename}!\n"
return
end
guid = guid.strip.upcase
child_project = Info::Project.new(lib_name)
child_project.guid = guid
child_project.path = OS::Path.get_directory(guid_filename)
search_guid = child_project.guid[1..-2]
ignore_guids = ENV['IGNORE_GUIDS']
ignore_guids = ScriptUtility.acquire_variable(path, 'IGNORE_GUIDS') if ignore_guids == nil
#Assume that the startup project is dependent on all child projects.
if ignore_guids == nil or ignore_guids.index(search_guid) == nil then
project.dep_guids << child_project.guid
end
platforms.keys.each { |sln_platform|
targets = platforms[sln_platform]
targets.each_pair { |sln_target,proj_cfg|
proj_platform, proj_target = VSProjShared.parse_config_name(proj_cfg)
build_data.add_projectconfig(sln_platform,sln_target,child_project.guid,proj_platform,proj_target)
}
}
build_data.dependent_projects[child_project.guid] = child_project
}
end
}
projects << project
end
return true, projects
end
end
class RageGenProjectLoader < VSProjShared
@@log = nil
def RageGenProjectLoader.log
@@log = Log.new( 'ragegenprojectloader' ) if @@log == nil
@@log
end
def initialize(unity)
@unity = unity
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 find_files(path, extension, array)
#Handle any regular expressions
found_files = []
found_files = OS::FindEx::find_files_recurse( path + extension )
found_files.each do |found_file|
array.insert(array.size, found_file)
end
end
def process_qa_items(input_path)
input_dir = File.dirname(input_path)
found_files = OS::FindEx::find_files( OS::Path::combine(input_dir, "*.cpp") )
if found_files.size > 0
qaitems_header_path = OS::Path::combine(input_dir, "qaitems.h")
qaitems_source_path = OS::Path::combine(input_dir, "qaitems.cpp")
edit_in_p4(@p4, qaitems_header_path)
edit_in_p4(@p4, qaitems_source_path)
source_file_path = OS::Path::combine( input_dir, "*.cpp")
grep_exe = get_egrep_exe_path()
result = system(grep_exe + ' -h "^QA_ITEM" ' + source_file_path + ' > ' + qaitems_header_path)
if result == false
if File.exists?(qaitems_header_path)
File.delete(qaitems_header_path)
end
revert_from_p4(@p4, qaitems_header_path)
return
end
edit_in_p4(@p4, qaitems_header_path)
#QA Items have been found, so add qaitems as a tester to regenerate and add to source control.
@testers = @testers + " qaitems"
result = system( grep_exe + ' -s -h "^QA_ITEM_DRAW" ' + qaitems_header_path )
if result == false
if ENV["RAGE_DIR"] != nil
system('copy' + ENV["RAGE_DIR"] + '\qa\src\unittest\qaitemsdraw.cpp ' + qaitems_source_path)
end
edit_in_p4(@p4, qaitems_source_path)
return
end
@xdefine_var = @xdefine_var + " QA_ITEMS_DEPEND_ON_SAMPLE_GRCORE"
end
end
def create_project_definition_file( directory, project_name, guid, specified_files )
project_definition_file_name = OS::Path::combine(directory, "#{project_name}.rsp")
project_file = OS::Path::combine(directory, project_name)
if File.exist?(project_file + ".cpp")
project_file_source = project_file + ".cpp"
duplicate_file = false
specified_files.each do |file|
if project_file_source == file
duplicate_file = true
break
end
end
if duplicate_file == false
specified_files.insert(specified_files.size, project_file_source)
end
elsif File.exist?(project_file + ".c")
project_file_source = project_file + ".c"
duplicate_file = false
specified_files.each do |file|
if project_file_source == file
duplicate_file = true
break
end
end
if duplicate_file == false
specified_files.insert(specified_files.size, project_file_source)
end
end
#Add all extra files to the list.
# TODO: Re-evaluate if this is ever necessary.
if specified_files.size == 0
specified_files = []
specified_files = OS::FindEx::find_files( Pipeline::OS::Path::combine(directory, "*.h") ) #/.*[.]h|.*[.]cpp|(.*)[.]c/
specified_files += OS::FindEx::find_files( Pipeline::OS::Path::combine(directory, "*.cpp") )
specified_files += OS::FindEx::find_files( Pipeline::OS::Path::combine(directory, "*.c") )
end
file = File.new(project_definition_file_name, 'w')
#First line is always the project name
file.write(project_name + "\n")
#Second line is always the guid.
file.write(guid + "\n")
specified_files.each do |found_file|
file.write(found_file + "\n")
end
file.close
return project_definition_file_name
end
def import( path, output_format, options )
RageGenProjectLoader.log.info("RageGenProjectLoader import #{path} path output_format #{output_format}")
@working_directory = File.dirname(path)
#Makefile Variables
@testers = ScriptUtility.acquire_variable( path, 'TESTERS' )
@testers = "" if @testers.nil?
@xdefine_var = ScriptUtility.acquire_variable(path, 'XDEFINE')
@xdefine_var = "" if @xdefine_var.nil?
@custom_var = ScriptUtility.acquire_variable(path, 'CUSTOM')
@custom_var = "" if @custom_var.nil?
@archive = ScriptUtility.acquire_variable(path, 'ARCHIVE')
#Add the VSI.nul object to the CUSTOM variable if on TESTER_BASE has been determined.
tester_base = ScriptUtility.acquire_variable(path, 'TESTER_BASE')
if @archive == nil
#Deal with the QA Items
process_qa_items(path)
end
ENV["TESTERS"] = @testers
@tester_array = @testers.split(" ")
@process_array = @tester_array
@process_array << @archive if @archive != nil
success = true
projects = Array.new()
#RageGenProjectLoader.log.info("@process_array is a #{@process_array.class}")
@process_array.each do |process_project|
process_project += VSProjShared.get_project_suffix(output_format)
vcproj = OS::Path::combine(@working_directory, process_project)
result, project = import_project(path, vcproj, output_format, options)
if result == true
projects << project
end
end
return success, projects
end
def import_project(path, output, output_format, options)
return false if File.exists?(path) == false
version_suffix = VSProjShared.get_project_suffix(output_format)
output_name = File.basename(output, version_suffix) #Remove the version suffix.
output_path = OS::Path.get_directory(output)
selected_template = nil
if options[:template].nil? == false and File.exist?(options[:template]) == true
projbuild_root = Globals::instance().toolsconfig + "/projbuild"
selected_template = OS::Path::combine(projbuild_root, selected_template)
#RageGenProjectLoader.log.info("Selected_template found BY RAGEGEN IS #{selected_template}")
else
selected_template = ScriptUtility.determine_project_template(path, output_name)
#RageGenProjectLoader.log.info("Selected_template found BY RAGEGEN IS #{selected_template} ( ScriptUtility.determine_project_template)")
end
if selected_template.nil?
#Defer this to possibly another generator. This is not an error.
RageGenProjectLoader.log.debug("Unable to determine a template to use for project #{output_name}! This may be generated via another means.")
return true
end
RageGenProjectLoader.log.debug("Trying to import #{path} with ragegen project loader.")
if File.exists?(selected_template) == false
template_filename = selected_template + VSProjShared.get_project_suffix(output_format)
#RageGenProjectLoader.log.info("TEMPLATE FILENAME USED BY RAGEGEN IS #{template_filename}")
if template_filename.nil?
print "Bad Template File\n"
RageGenProjectLoader.log.error("Unable to properly acquire a template file!")
return false
elsif File.exists?(template_filename) == false
print "Unable to find template file: #{template_filename}.\n"
RageGenProjectLoader.log.error("Unable to find template file #{template_filename}!")
return false
end
end
expanded_files = [] # A list of all files with their extensions to add to the project
combined_files_value = ScriptUtility.acquire_variable( path, "FILES" )
if combined_files_value != nil
value_files = combined_files_value.split(" ")
value_files.each do |value_file|
filename = OS::Path::combine(@working_directory, value_file)
filename = File.expand_path(filename)
find_files(filename, ".h", expanded_files)
find_files(filename, ".c", expanded_files)
find_files(filename, ".cpp", expanded_files)
if File.exist?(filename)
expanded_files << value_file
end
end
end
#Find a list of all header files included in this combined file.
combined_files_value = ScriptUtility.acquire_variable( path, "HEADONLY" )
if combined_files_value != nil
header_files = combined_files_value.split(" ")
header_files.each do |header_file|
header_file = header_file + ".h"
expanded_files << header_file
end
end
combined_files_value = ScriptUtility.acquire_variable( path, "CCODEONLY" )
if combined_files_value != nil
c_files = combined_files_value.split(" ")
c_files.each do |c_file|
c_file = c_file + ".c"
expanded_files << c_file
end
end
combined_files_value = ScriptUtility.acquire_variable( path, "CODEONLY" )
if combined_files_value != nil
cpp_files = combined_files_value.split(" ")
cpp_files.each do |cpp_file|
#Ensure we're testing for existence from the correct root.
full_path_file = OS::Path::combine(output_path, cpp_file)
full_path_file = File.expand_path(full_path_file)
if File.exist?(full_path_file + ".cpp")
expanded_files << cpp_file + ".cpp"
elsif File.exist?(full_path_file + ".c")
expanded_files << cpp_file + ".c"
else File.exist?(full_path_file)
expanded_files << cpp_file
end
end
end
#Any additional custom files.
combined_files_value = @custom_var
if combined_files_value != nil
expanded_files += combined_files_value.split(" ")
end
#Additional Resource objects.
combined_files_value = ScriptUtility.acquire_variable( path, "RESOURCES" )
if combined_files_value != nil
expanded_files += combined_files_value.split(" ")
end
#Additional Embedded Shaders.
embedded_shaders = nil
combined_files_value = ScriptUtility.acquire_variable( path, "EMBEDDEDSHADERS" )
if combined_files_value != nil
embedded_shaders = combined_files_value.split(" ")
expanded_files += embedded_shaders
end
RageGenProjectLoader.log.info("RAGEGEN IS USING THE TEMPLATE : #{template_filename}.")
parser = XML::Parser.file(template_filename)
doc = parser.parse
correct_version = VSProjShared.get_version(output_format)
if doc.root.attributes["Version"] != correct_version then
#print "Bad version number!\n"
#RageGenProjectLoader.log.info("Template is not the correct Visual Studio version: #{doc.root.attributes['Version']} not #{correct_version}.")
#return false
end
RageGenProjectLoader.log.debug("Parsing #{path} with ragegen project loader.")
guid_filename = OS::Path::combine(@working_directory, output_name) + ".guid"
guid = VSProjShared.create_guid(guid_filename, @p4)
project_definition_file_name = create_project_definition_file(@working_directory, output_name, guid, expanded_files)
if File.exists?(project_definition_file_name) == false
RageGenProjectLoader.log.debug("Project definition file at: #{project_definition_file_name} could not be generated.")
return false;
end
#Assume this is a project definition file.
files = File.readlines(project_definition_file_name)
project_name = files.delete_at(0).strip
guid = files.delete_at(0).strip
files.collect { |x|
x.strip!
}
guid_filename = OS::Path.remove_extension(path) + ".guid"
if File.exists?(guid_filename) then
guid = File.readlines(guid_filename)[0].upcase
RageGenProjectLoader.log.debug("guid filename #{guid_filename}, guid changed to: #{guid}")
end
temporary_filename = OS::Path.combine(Globals::instance().toolstemp,"temp.vcproj")
#RageGenProjectLoader.log.info("Filling temporary vcproj #{temporary_filename}.")
doc.root.attributes["Name"] = project_name
doc.root.attributes["ProjectGUID"] = "{#{guid}}"
#Acquire a list of all the pertinent environment variables here.
@xproj_var = ScriptUtility.acquire_variable(path, 'XPROJ')
@xproj_var = "" if @xproj_var.nil?
@xinclude_var = ScriptUtility.acquire_variable(path, 'XINCLUDE')
@xinclude_var = "" if @xinclude_var.nil?
@temp_additional_includes = []
@temp_additional_includes = @xproj_var.split(" ")
@temp_additional_includes.concat(@xinclude_var.split(" "))
@additional_includes = []
@temp_additional_includes.each do |include|
include = ScriptUtility.find_include_definition( include )
found_duplicate = false
@additional_includes.each do |added_include|
if include.eql?(added_include) == true
found_duplicate = true
break
end
end
if found_duplicate == false
@additional_includes.insert(@additional_includes.size, include)
end
end
@force_include = ScriptUtility.acquire_variable(path, 'FORCE_INCLUDE')
@force_include = "" if @force_include.nil?
@xbox_title_id = ScriptUtility.acquire_variable(path, 'XBOX_TITLE_ID')
@xbox_spa_path = ScriptUtility.acquire_variable(path, 'XBOX_SPA_PATH')
@warning_level = ScriptUtility.acquire_variable(path, 'WARNINGS')
@parser_files = ScriptUtility.acquire_variable(path, 'PARSE')
@output_name_pattern_var = ScriptUtility.acquire_variable(path, 'OUTPUT_NAME_PATTERN')
@template_name = File.basename(selected_template)
doc.find("/VisualStudioProject/Configurations/Configuration").each { |config_node|
platform_config = config_node.attributes["OutputDirectory"]
platform,config = VSProjShared.parse_config_name(config_node.attributes["Name"])
output_pattern = nil
output_pattern_pdb = nil
@embedded_lib_var = nil
case platform
when :xbox360:
@embedded_lib_var_name = 'EMBEDDEDLIB_XENON'
when :ps3:
@embedded_lib_var_name = 'EMBEDDEDLIB_PSN'
when :win32
@embedded_lib_var_name = 'EMBEDDEDLIB_WIN32'
when :win64
@embedded_lib_var_name = 'EMBEDDEDLIB_WIN64'
end
@embedded_lib_var = ScriptUtility.acquire_variable(path, @embedded_lib_var_name) if @embedded_lib_var_name.nil?
@embedded_lib_var = "" if @embedded_lib_var.nil?
if @output_name_pattern_var != nil
output_pattern_noext = @output_name_pattern_var
output_pattern_noext = output_pattern_noext.gsub(/PLATFORM_CONFIG/,platform_config) if platform_config != nil
output_pattern = ""
output_pattern_pdb = ""
case platform
when :xbox360:
output_pattern = output_pattern_noext.gsub(/EXT/,"xex")
when :ps3:
output_pattern = output_pattern_noext.gsub(/EXT/,"self")
when :psp2:
output_pattern = output_pattern_noext.gsub(/EXT/,"self")
else
output_pattern = output_pattern_noext.gsub(/EXT/,"exe")
end
output_pattern_pdb = output_pattern_noext.gsub(/EXT/,"pdb")
end
config_node.find("Tool").each { |node|
case node.attributes["Name"]
when "VCPreBuildEventTool":
if @parser_files != nil then
#Add pre-build event attributes
#Preserve any additional pre-build steps.
if node.attributes["CommandLine"] != nil
node.attributes["Description"] = "Executing pre-build steps..."
node.attributes["CommandLine"] = node.attributes["CommandLine"] + "\n"
else
node.attributes["Description"] = "Generating parser code..."
node.attributes["CommandLine"] = ""
end
node.attributes["CommandLine"] = node.attributes["CommandLine"] + '$(RS_TOOLSROOT)\\bin\\coding\\python\\parCodeGen.exe ' + @parser_files
end
when "VCCLCompilerTool", "VCCLX360CompilerTool":
if node.attributes["AdditionalIncludeDirectories"] != nil then
if @xproj_var != nil
node.attributes["AdditionalIncludeDirectories"] = node.attributes["AdditionalIncludeDirectories"] + ";" + @additional_includes.join(";")
end
end
if node.attributes["ForcedIncludeFiles"] != nil and @force_include != nil then
node.attributes["ForcedIncludeFiles"] = node.attributes["ForcedIncludeFiles"].gsub(/FORCE_INCLUDE/,@force_include)
end
if node.attributes["PreprocessorDefinitions"] != nil and @xdefine_var != nil then
node.attributes["PreprocessorDefinitions"] = node.attributes["PreprocessorDefinitions"].gsub(/XDEFINE/,@xdefine_var)
end
if node.attributes["ProgramDataBaseFileName"] != nil then
if output_pattern_pdb.nil?
if node.attributes["ProgramDataBaseFileName"] != nil
node.attributes["ProgramDataBaseFileName"] = node.attributes["ProgramDataBaseFileName"].gsub(/OUTPUT_FILE_NAME/, output_name)
node.attributes["ProgramDataBaseFileName"] = node.attributes["ProgramDataBaseFileName"].gsub(/#{@template_name}/, output_name)
end
else
node.attributes["ProgramDataBaseFileName"] = output_pattern_pdb
end
end
if node.attributes["WarningLevel"] != nil then
if @warning_level.nil? == false
node.attributes["WarningLevel"] = @warning_level
end
end
when "VCLibrarianTool":
if output_pattern.nil?
if node.attributes["OutputFile"] != nil
node.attributes["OutputFile"] = node.attributes["OutputFile"].gsub(/OUTPUT_FILE_NAME/, output_name)
node.attributes["OutputFile"] = node.attributes["OutputFile"].gsub(/#{@template_name}/, output_name)
end
else
node.attributes["OutputFile"] = output_pattern
end
if node.attributes["AdditionalDependencies"] != nil and @embedded_lib_var != nil then
node.attributes["AdditionalDependencies"] = node.attributes["AdditionalDependencies"].gsub(@embedded_lib_var_name, @embedded_lib_var.split(" ").join(";"))
end
when "VCX360ImageTool":
if output_pattern.nil?
if node.attributes["OutputFileName"] != nil
node.attributes["OutputFileName"] = node.attributes["OutputFileName"].gsub(/OUTPUT_FILE_NAME/, output_name)
else
node.attributes["OutputFileName"] = ""
end
else
node.attributes["OutputFileName"] = output_pattern
end
if node.attributes["AdditionalSections"] != nil and @xbox_title_id != nil and @xbox_spa_path != nil then
node.attributes["AdditionalSections"] = node.attributes["AdditionalSections"].gsub(/XboxSpaLinkOpt/,"#{@xbox_title_id}=#{@xbox_spa_path}")
else
node.attributes["AdditionalSections"] = ""
end
if node.attributes["TitleID"] != nil and @xbox_title_id != nil then
#Backwards Compatibility - if the title id does not have 0x prefix in front of it.
if @xbox_title_id.index("0x") != 0
node.attributes["TitleID"] = node.attributes["TitleID"].gsub(/XboxTitleId/, "0x" + @xbox_title_id)
else
node.attributes["TitleID"] = node.attributes["TitleID"].gsub(/XboxTitleId/, @xbox_title_id)
end
else
node.attributes["TitleID"] = ""
end
if node.attributes["ProjectDefaults"] != nil then
node.attributes["ProjectDefaults"] = node.attributes["ProjectDefaults"].gsub(/XboxImageXexConfig/,"")
end
when "VCX360DeploymentTool":
if node.attributes["DeploymentFiles"] != nil then
replaceval = ENV['XBOX_DEPLOYMENT_FILES']
replaceval = "" if replaceval == nil
node.attributes["DeploymentFiles"] = node.attributes["DeploymentFiles"].gsub(/XBOX_DEPLOYMENT_FILES/,replaceval)
end
when "VCLinkerTool","VCX360LinkerTool":
if output_pattern.nil?
if node.attributes["OutputFile"] != nil
node.attributes["OutputFile"] = node.attributes["OutputFile"].gsub(/OUTPUT_FILE_NAME/, output_name)
node.attributes["OutputFile"] = node.attributes["OutputFile"].gsub(/#{@template_name}/, output_name)
end
else
if (node.attributes["Name"]=="VCX360LinkerTool" and output_format.to_s.include?("2010"))
node.attributes["OutputFile"] = "$(TargetPath)"
else
node.attributes["OutputFile"] = output_pattern
end
end
# override all 2010 output paths - due to weird VS2010 msbuild warnings
if (output_format.to_s.include?("2010"))
node.attributes["OutputFile"] = "$(TargetPath)"
end
if node.attributes["ProgramDatabaseFile"] != nil then
if output_pattern_pdb.nil?
if node.attributes["ProgramDatabaseFile"]
node.attributes["ProgramDatabaseFile"] = node.attributes["ProgramDatabaseFile"].gsub(/OUTPUT_FILE_NAME/, output_name)
node.attributes["ProgramDatabaseFile"] = node.attributes["ProgramDatabaseFile"].gsub(/#{@template_name}/, output_name)
end
else
node.attributes["ProgramDatabaseFile"] = output_pattern_pdb
end
end
end
}
}
file_node = doc.find_first("/VisualStudioProject/Files")
RageGenProjectLoader.log.error("Cant find /VisualStudioProject/Files #{doc}") unless file_node
files.each { |filename|
out_path = OS::Path.combine(output_path,filename)
out_path = File.expand_path(out_path)
out_path = OS::Path.make_relative(out_path,output_path)
out_path = OS::Path.dos_format(out_path)
new_node = XML::Node.new("File")
new_node["RelativePath"] = out_path
#Add any custom file configurations for this file.
if embedded_shaders != nil
base_filename = File.basename(out_path)
embedded_shaders.each do |embedded_shader|
if base_filename.eql?(embedded_shader) == true
embedded_shader = OS::Path::combine(@working_directory, embedded_shader)
#For every configuration add a new FileConfiguration
doc.find("/VisualStudioProject/Configurations/Configuration").each do |config_node|
config_name = config_node.attributes["Name"]
platform,target = VSProjShared.parse_config_name(config_name)
custom_step = Info::FxCustomBuild.new(embedded_shader, out_path, platform)
custom_step_node = custom_step.create_node()
file_configuration_node = XML::Node.new("FileConfiguration")
file_configuration_node["Name"] = config_name
file_configuration_node << custom_step_node
new_node << file_configuration_node
end
end
end
else
#For all non-standard files, look for a custom object in the projbuild root to use as a template.
extension = File.extname(filename)
extension = extension[1...extension.size]
if extension.eql?("cpp") == false and extension.eql?("c") == false and extension.eql?("h") == false and extension.eql?("nul") == false
custom_root = ScriptUtility.get_custom_root()
custom_path = OS::Path::combine(custom_root, "#{extension}.custom")
full_path = OS::Path::combine(@working_directory, filename)
if File.exist?(custom_path) == true
#For every configuration add a new FileConfiguration
doc.find("/VisualStudioProject/Configurations/Configuration").each do |config_node|
config_name = config_node.attributes["Name"]
file_configuration = CustomBuildStep::get_file_configuration(custom_path, full_path, config_name)
next if file_configuration.nil?
file_configuration_node = XML::Node.new("FileConfiguration")
tool_node = XML::Node.new(file_configuration)
file_configuration_node["Name"] = config_name
file_configuration_node << tool_node
new_node << file_configuration_node
end
end
end
end
file_node << new_node
}
#RageGenProjectLoader.log.info("Saving temporary file to #{temporary_filename}.")
doc.save(temporary_filename)
#RageGenProjectLoader.log.info("Passing #{temporary_filename} to Visual Studio loader.")
if output_format == :vs2005
result, curr_project = VS2005VSProjLoader.new().import(temporary_filename, output_path)
elsif output_format == :vs2008 or output_format == :vs2010
result, curr_project = VS2008VSProjLoader.new().import(temporary_filename, output_path)
end
if (output_format == :vs2010)
# ====================================== DW - THIS NEEDS SORTED OUT ====================================================
# under VS2010 you need to add references for everything so that they are linked in
#RageGenProjectLoader.log.info("DW attempting to add to the doc the library dependencies")
testers_var = ScriptUtility.acquire_variable(path, 'TESTERS')
testers_var = "" if testers_var.nil?
#RageGenSolutionLoader.log.info("DW attempting to add to the doc the library dependencies testers_var #{testers_var}")
archive = ScriptUtility.acquire_variable(path, 'ARCHIVE')
testers_var += " " + archive if archive.nil? == false
@tester_array = testers_var.split(" ")
@working_directory = File.dirname(path)
build_data = ProjBuildData::instance()
build_data.reset
success = true
projects = Array.new()
@tester_array.each do |tester|
#RageGenSolutionLoader.log.info("DW attempting to add to the doc the library dependencies : running tester #{tester}")
basename = OS::Path.get_basename(tester)
libs = ScriptUtility.acquire_expanded_libs(path, basename)
#RageGenSolutionLoader.log.info("libs #{libs.length} #{libs}")
Dir.chdir(OS::Path.get_directory(path)) {
if libs != nil
libs.each { |lib|
lib_name = OS::Path.get_basename(lib)
next if lib_name.downcase.include?("shaders")
#RageGenSolutionLoader.log.info("libs #{libs.length} #{libs}")
ps3_unity_only = false
PS3_UNITY_PROJECTS.each do |proj|
if (lib.downcase.include?proj)
ps3_unity_only = true
end
end
if (ps3_unity_only)
next unless @unity==true
end
lib = OS::Path.normalise(lib)
guid = nil
guid_filename = nil
lib = OS::Path.remove_extension(lib)
lib = File.expand_path(lib)
guid_filename = "#{lib}.guid"
guid_filename = OS::Path::make_relative( guid_filename, @working_directory )
guid = VSProjShared.create_guid(guid_filename, @p4)
if guid == nil
RageGenSolutionLoader.log.debug("Unable to acquire guid #{guid_filename}!")
print "Unable to acquire guid #{guid_filename}!\n"
return
end
guid = guid.strip.upcase
child_project = Info::Project.new(lib_name)
child_project.guid = guid
child_project.path = OS::Path.get_directory(guid_filename)
search_guid = child_project.guid[1..-2]
ignore_guids = ENV['IGNORE_GUIDS']
ignore_guids = ScriptUtility.acquire_variable(path, 'IGNORE_GUIDS') if ignore_guids == nil
#Assume that the startup project is dependent on all child projects.
if ignore_guids == nil or ignore_guids.index(search_guid) == nil then
curr_project.dep_guids << child_project.guid
end
#RageGenSolutionLoader.log.info("#Adding dependent project #{child_project.guid} #{child_project}")
build_data.dependent_projects[child_project.guid] = child_project
#RageGenSolutionLoader.log.info("curr_project.config.xml_data #{curr_project.config.xml_data}")
project_refs_node = XML::Node.new("ProjectReferences")
project_ref_node = XML::Node.new("ProjectReference")
project_node = XML::Node.new("Project")
unity = ""
unity = "_unity" if @unity==true and not lib_name.downcase.include?"shaders" and ps3_unity_only==false
#RageGenSolutionLoader.log.info("Unity is #{unity} #{@unity} for #{lib_name} ps3_unity_only = #{ps3_unity_only}")
project_node.content = "#{child_project.guid}"
project_ref_node["Include"] = "#{child_project.path}/#{lib_name}_2010#{unity}.vcxproj"
if ps3_unity_only==true
# this does not work - msbuild doesn;t support conditional project references!
# Condition="'$(Configuration)|$(Platform)'=='Debug|Xbox 360'"
# RageGenSolutionLoader.log.info("This project is conditional in MSBuild")
project_ref_node["Condition"] = "'$(Platform)'=='PS3'"
end
project_ref_node << project_node
project_refs_node << project_ref_node
curr_project.config.xml_data << project_refs_node
#RageGenSolutionLoader.log.info("================curr_project.config.xml_data===================\n #{curr_project.config.xml_data}")
#curr_project.config.xml_data.find("ProjectReferences/ProjectReference")
} # end libs.each
end # if libs != nil
} # end Dir.chdir
end #end @tester_array.each
end # end if (output_format == :vs2010)
File.delete(project_definition_file_name)
return result, curr_project
end
end
class RageGenGenerator
@@unity_build_filenames = nil # if true filenames that are created have "_unity" in them.
def set_unity_build_filenames( set )
#RageGenProjectLoader.log.info(".............Set unity build filenames #{set}")
@@unity_build_filenames = set
end
def get_unity_build_filenames( )
@@unity_build_filenames
end
def export( path, project, options = nil )
true
end
def import( path, options = nil )
RageGenProjectLoader.log.info("RageGenGenerator import path #{path} options #{options} unity #{get_unity_build_filenames()}")
return false if options == nil
case options[:type]
when :solution:
loader = RageGenSolutionLoader.new()
return loader.import(path, options[:out_format], options)
when :project:
loader = RageGenProjectLoader.new(get_unity_build_filenames())
return loader.import(path, options[:out_format], options)
end
false
end
end
end #module ProjBuild
end #module Pipeline