514 lines
12 KiB
Ruby
Executable File
514 lines
12 KiB
Ruby
Executable File
#generic xml config data...
|
|
#bye bye vs project
|
|
|
|
require 'xml'
|
|
require 'active_support/ordered_hash'
|
|
require 'singleton'
|
|
|
|
module Pipeline
|
|
|
|
module ProjBuild
|
|
|
|
module Info
|
|
|
|
class PlatformInfo
|
|
|
|
include Singleton
|
|
|
|
attr_reader :platforms
|
|
|
|
def initialize()
|
|
|
|
@platforms = ActiveSupport::OrderedHash.new()
|
|
@platforms[:ps3] = "PS3"
|
|
@platforms[:psp2] = "PSP2"
|
|
@platforms[:win32] = "Win32"
|
|
@platforms[:win64] = "Win64"
|
|
@platforms[:xbox360] = "Xbox360"
|
|
end
|
|
|
|
def is_valid( platform_sym )
|
|
|
|
return true if @platforms[platform_sym] != nil
|
|
false
|
|
end
|
|
|
|
def get_platform_symbol( platform_str )
|
|
|
|
@platforms.keys.each { |symbol|
|
|
string = @platforms[symbol]
|
|
|
|
if string.eql?(platform_str) == true
|
|
return symbol
|
|
end
|
|
}
|
|
|
|
nil
|
|
end
|
|
|
|
def create_output_path( platform, target)
|
|
|
|
output_path = case platform
|
|
when :win32
|
|
"win32_#{target}"
|
|
when :win64
|
|
"win64_#{target}"
|
|
when :xbox360
|
|
"xenon_#{target}"
|
|
when :ps3
|
|
"psn_#{target}"
|
|
when :psp2
|
|
"psp2_#{target}"
|
|
end
|
|
|
|
output_path.downcase
|
|
end
|
|
end
|
|
|
|
class CustomBuild
|
|
|
|
attr_reader :command, :output, :dependencies
|
|
attr_writer :command, :output, :dependencies
|
|
|
|
def initialize()
|
|
|
|
@command = nil
|
|
@output = nil
|
|
@dependencies = nil
|
|
@description = nil
|
|
end
|
|
|
|
def initialize(command, output, dependencies, description)
|
|
|
|
@command = command
|
|
@output = output
|
|
@dependencies = dependencies
|
|
@description = description
|
|
end
|
|
|
|
def create_node()
|
|
|
|
xml_node = XML::Node.new("custombuild")
|
|
|
|
xml_node["Name"] = "custombuild"
|
|
xml_node["CommandLine"] = @command
|
|
xml_node["Outputs"] = @output if @output != nil
|
|
xml_node["AdditionalDependencies"] = @dependencies if @dependencies != nil
|
|
xml_node["Description"] = @description if @description != nil
|
|
|
|
xml_node
|
|
end
|
|
|
|
def find_dependencies( path, rel_path )
|
|
|
|
#todo: this works as well as the one in rageprojbuilder but doesn't
|
|
#find any files if there are based on other include paths that just relative
|
|
#to the custom build file
|
|
|
|
path = ::File.expand_path(path)
|
|
|
|
@deps = ActiveSupport::OrderedHash.new()
|
|
@scanned = ActiveSupport::OrderedHash.new()
|
|
|
|
find_dependencies_inner(path,nil)
|
|
|
|
dependencies = Array.new()
|
|
|
|
@deps.keys.each { |dep|
|
|
|
|
dependencies << dep.gsub(OS::Path.get_directory(path),rel_path)
|
|
}
|
|
|
|
@dependencies = dependencies.join(";")
|
|
|
|
#Don't print out the dependencies element of the custom build step if we don't have to.
|
|
@dependencies = nil if @dependencies.size == 0
|
|
end
|
|
|
|
protected
|
|
|
|
def find_dependencies_inner( path, parent_path )
|
|
|
|
return nil if @scanned[path]
|
|
return nil if ::File.exists?(path) == false
|
|
|
|
@scanned[path] = true
|
|
|
|
if parent_path != nil then
|
|
|
|
@deps[path] = true
|
|
end
|
|
|
|
parent_path = OS::Path.get_directory(path)
|
|
|
|
::File::open( path ) do |fp|
|
|
lines = fp.readlines( )
|
|
|
|
lines.each do |line|
|
|
if line.index("#include") != nil or line.index(".include") != nil then
|
|
|
|
re = /[\.|#]include "([a-zA-Z0-9_\.\/\\]+)"/
|
|
md = re.match(line)
|
|
|
|
next if md == nil
|
|
|
|
include_path = OS::Path.combine(parent_path,md[1])
|
|
|
|
find_dependencies_inner(include_path,parent_path)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
class JobCustomBuild < CustomBuild
|
|
|
|
def initialize( path, file_info )
|
|
|
|
rel_path = ::File.dirname(file_info.path);
|
|
|
|
@command = "call $(RS_TOOLSROOT)\\script\\coding\\custom_steps\\make_spurs_job_pb $(InputDir) $(IntDir) $(InputName) "$(ConfigurationName)""
|
|
@output = "$(IntDir)/$(InputName).job.obj"
|
|
|
|
find_dependencies(path, rel_path)
|
|
end
|
|
|
|
end
|
|
|
|
class FragCustomBuild < CustomBuild
|
|
|
|
def initialize( path )
|
|
|
|
@command = "call $(RS_TOOLSROOT)\\script\\coding\\custom_steps\\make_spu_frag_pb $(InputDir) $(IntDir) $(InputName) "$(ConfigurationName)""
|
|
@output = "$(IntDir)/$(InputName).frag.obj"
|
|
|
|
#need to scan through the file to see if there are any other dependencies...
|
|
end
|
|
end
|
|
|
|
class TaskCustomBuild < CustomBuild
|
|
|
|
def initialize( path )
|
|
|
|
@command = "call $(RS_TOOLSROOT)\\script\\coding\\custom_steps\\make_spurs_task_pb $(InputDir) $(IntDir) $(InputName) "$(ConfigurationName)""
|
|
@output = "$(IntDir)/$(InputName).task.obj"
|
|
|
|
#need to scan through the file to see if there are any other dependencies...
|
|
end
|
|
end
|
|
|
|
class FxCustomBuild < CustomBuild
|
|
|
|
def initialize( path, file_path, platform_sym )
|
|
|
|
rel_path = ::File.dirname(file_path);
|
|
|
|
platform_out = ActiveSupport::OrderedHash.new()
|
|
platform_out[:ps3] = "psn"
|
|
platform_out[:win32] = "win32_30"
|
|
platform_out[:win64] = "win32_30"
|
|
platform_out[:xbox360] = "fxl_final"
|
|
platform_out[:psp2] = "psp2"
|
|
|
|
#This custom step prior had:
|
|
#rem IncrediBuild_DontAllowRemote

|
|
#at the front to tell IncrediBuild that the custom build step would be executed only locally.
|
|
#The IncrediBuild database no longer supports this indicator and has deferred to a default
|
|
#of all custom build steps being executed locally unless specifying otherwise with:
|
|
# REM IncrediBuild_AllowRemote
|
|
#
|
|
@description = "Building embedded shader $(InputName) . . ."
|
|
@command = "cmd /c "chdir $(InputDir) && call $(RS_TOOLSROOT)\\script\\coding\\shaders\\makeembeddedshader.bat -platform #{platform_out[platform_sym]} $(InputName).fx""
|
|
@output = "$(InputDir)\\embedded_$(InputName)_#{platform_out[platform_sym]}.h"
|
|
|
|
find_dependencies(path, rel_path)
|
|
|
|
#need to scan through the file to see if there are any other dependencies...
|
|
end
|
|
end
|
|
|
|
|
|
class PscCustomBuild < CustomBuild
|
|
|
|
def initialize( path, file_path, vs2010 = false )
|
|
|
|
@vs2010 = vs2010
|
|
|
|
rel_path = ::File.dirname(file_path);
|
|
@dependencies_array = Array.new()
|
|
find_psc_dependencies(path, rel_path)
|
|
|
|
@description = "Generating parser code..."
|
|
|
|
if @vs2010
|
|
@command = "pushd $(InputDir) && $(RS_TOOLSROOT)\\bin\\coding\\python\\parCodeGen.exe %(filename)%(extension) "
|
|
else
|
|
@command = "pushd $(InputDir) && $(RS_TOOLSROOT)\\bin\\coding\\python\\parCodeGen.exe $(InputFileName) "
|
|
end
|
|
@dependencies_array.each { |x|
|
|
@command << "--depends #{x} "
|
|
}
|
|
@command << "&& popd"
|
|
|
|
@output = "$(InputDir)\\$(InputName)_parser.h" # do we need to list these too? $(InputName).h %(InputName).cpp"
|
|
|
|
@dependencies_array.push("$(RS_TOOLSROOT)\\bin\\coding\\python\\parCodeGen.zip") # add this so we rebuild the .pscs if the code generator changes
|
|
@dependencies = @dependencies_array.join(";")
|
|
|
|
#Don't print out the dependencies element of the custom build step if we don't have to.
|
|
@dependencies = nil if @dependencies.size == 0
|
|
end
|
|
|
|
|
|
@@import_token = "<import"
|
|
@@href_token = "href=\""
|
|
def find_psc_dependencies( path, relative_path )
|
|
|
|
@deps = ActiveSupport::OrderedHash.new()
|
|
@scanned = ActiveSupport::OrderedHash.new()
|
|
|
|
path = ::File.expand_path(path)
|
|
|
|
f = ::File.new(path)
|
|
lines = f.readlines
|
|
f.close
|
|
|
|
lines.each { |line|
|
|
|
|
line.strip!
|
|
|
|
if line.index(@@import_token) != nil
|
|
|
|
href_index = line.index(@@href_token) + @@href_token.length
|
|
end_quote_index = line.index("\"", href_index+1)
|
|
|
|
if end_quote_index != nil
|
|
|
|
href_attribute = line[href_index,end_quote_index-href_index]
|
|
new_dependency = process_import(href_attribute, relative_path)
|
|
|
|
@dependencies_array << new_dependency
|
|
find_psc_dependencies_inner(new_dependency,nil)
|
|
end
|
|
|
|
end
|
|
}
|
|
end
|
|
|
|
def find_psc_dependencies_inner( path, parent_path )
|
|
|
|
return nil if @scanned[path]
|
|
return nil if ::File.exists?(path) == false
|
|
|
|
@scanned[path] = true
|
|
|
|
if parent_path != nil then
|
|
|
|
@deps[path] = true
|
|
end
|
|
|
|
parent_path = OS::Path.get_directory(path)
|
|
f = ::File.new(path)
|
|
lines = f.readlines
|
|
f.close
|
|
|
|
lines.each { |line|
|
|
|
|
line.strip!
|
|
|
|
if line.index(@@import_token) != nil
|
|
|
|
href_index = line.index(@@href_token) + @@href_token.length
|
|
end_quote_index = line.index("\"", href_index+1)
|
|
|
|
if end_quote_index != nil
|
|
|
|
href_attribute = line[href_index,end_quote_index-href_index]
|
|
new_dependency = process_import(href_attribute, parent_path)
|
|
|
|
@dependencies_array << new_dependency
|
|
find_dependencies_inner(new_dependency,parent_path)
|
|
end
|
|
end
|
|
}
|
|
end
|
|
|
|
def process_import(href_attribute, parent_path)
|
|
|
|
#Once a new dependency is acquired, convert any environment variables
|
|
#it may contain. Since the psc files are based in Python, the syntax will be
|
|
#like: ${RS_BUILDBRANCH} or ${RS_TOOLSROOT}. Use $(RS_BUILDBRANCH) or $(RS_TOOLSROOT).
|
|
new_dependency = href_attribute.gsub("", "") #HACK: Without calling gsub and creating a copy, Ruby will use the same pointer in the below loop. Doing so will cause an obscure "string modified" exception.
|
|
has_matches = false
|
|
|
|
reg_expr = /([\$\{\[a-zA-Z0-9_\.]+\}\]*)/
|
|
href_attribute.gsub(reg_expr) { |match|
|
|
|
|
env_var_expr = /([a-zA-Z0-9_\.])+/
|
|
env_var_match = env_var_expr.match(match.to_s)
|
|
|
|
env_var_match.to_a.each { |env_var|
|
|
has_matches = true
|
|
new_dependency.gsub!(match, "$(#{env_var})")
|
|
}
|
|
}
|
|
|
|
if has_matches == false
|
|
new_dependency = OS::Path.combine(parent_path, href_attribute)
|
|
end
|
|
|
|
return new_dependency
|
|
end
|
|
|
|
end
|
|
|
|
class VSICustomBuild < CustomBuild
|
|
|
|
def initialize( path )
|
|
|
|
@command = "echo > NUL"
|
|
@output = "\"$(IntDir)\\vsi.out\""
|
|
|
|
#need to scan through the file to see if there are any other dependencies...
|
|
end
|
|
end
|
|
|
|
class PreBuild
|
|
|
|
def initialize( buildsteps )
|
|
|
|
@buildsteps = buildsteps
|
|
end
|
|
|
|
def create_node()
|
|
|
|
xml_node = XML::Node.new("prebuild")
|
|
xml_node["count"] = @buildsteps.size.to_s
|
|
|
|
index = 0
|
|
|
|
@buildsteps.each { |buildstep|
|
|
|
|
xml_new = XML::Node.new("buildstep")
|
|
xml_new["cmd"] = buildstep
|
|
xml_new["index"] = index.to_s
|
|
|
|
index = index + 1
|
|
xml_node << xml_new
|
|
}
|
|
|
|
xml_node
|
|
end
|
|
end
|
|
|
|
class LibraryDirectory
|
|
|
|
attr_reader :path, :platform
|
|
|
|
def initialize( path, platform = nil)
|
|
|
|
@path = path
|
|
@platform = platform
|
|
end
|
|
|
|
def create_node()
|
|
|
|
xml_new = XML::Node.new("librarydirectory")
|
|
xml_new["path"] = @path
|
|
|
|
xml_new
|
|
end
|
|
end
|
|
|
|
class LibraryDirectories
|
|
|
|
def initialize( paths )
|
|
|
|
@paths = paths
|
|
end
|
|
|
|
def create_node()
|
|
|
|
xml_node = XML::Node.new("librarydirectories")
|
|
|
|
@paths.each { |path|
|
|
|
|
xml_new = path.create_node()
|
|
|
|
xml_node << xml_new
|
|
}
|
|
|
|
xml_node
|
|
end
|
|
end
|
|
|
|
class IncludePath
|
|
|
|
attr_reader :path, :platform
|
|
|
|
def initialize( path, platform = nil)
|
|
|
|
@path = path
|
|
@platform = platform
|
|
end
|
|
|
|
def create_node()
|
|
|
|
xml_new = XML::Node.new("includepath")
|
|
xml_new["path"] = @path
|
|
|
|
xml_new
|
|
end
|
|
end
|
|
|
|
class IncludePaths
|
|
|
|
def initialize( paths )
|
|
|
|
@paths = paths
|
|
end
|
|
|
|
def create_node()
|
|
|
|
xml_node = XML::Node.new("includepaths")
|
|
|
|
@paths.each { |path|
|
|
|
|
xml_new = path.create_node()
|
|
|
|
xml_node << xml_new
|
|
}
|
|
|
|
xml_node
|
|
end
|
|
end
|
|
|
|
class ForceIncludes
|
|
|
|
def initialize( header_files )
|
|
|
|
@header_files = header_files
|
|
end
|
|
|
|
def create_node()
|
|
|
|
xml_node = XML::Node.new("forceincludes")
|
|
|
|
@header_files.each { |path|
|
|
|
|
xml_new = XML::Node.new("forceinclude")
|
|
xml_new["path"] = path
|
|
|
|
xml_node << xml_new
|
|
}
|
|
|
|
xml_node
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|