1182 lines
38 KiB
Ruby
Executable File
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
|