279 lines
8.9 KiB
Ruby
Executable File
279 lines
8.9 KiB
Ruby
Executable File
#
|
|
# File:: projbuild.rb
|
|
#
|
|
# Pipeline::Cross platform generic project file builder system that supports
|
|
# output to multiple target compilers.
|
|
#
|
|
# Author:: Greg Smith <greg@rockstarnorth.com>
|
|
# Date:: 15 January 2010
|
|
#
|
|
#
|
|
|
|
#-----------------------------------------------------------------------------
|
|
# Uses
|
|
#-----------------------------------------------------------------------------
|
|
require "pipeline/coding/projbuild/generators/csharp"
|
|
require "pipeline/coding/projbuild/generators/ragegen"
|
|
require "pipeline/coding/projbuild/generators/rageprojbuilder"
|
|
require "pipeline/coding/projbuild/generators/vs2005"
|
|
require "pipeline/coding/projbuild/generators/vs2008"
|
|
require "pipeline/coding/projbuild/generators/vs2010"
|
|
require "pipeline/coding/projbuild/generators/shadermakefile"
|
|
require "pipeline/coding/projbuild/generators/qaitems"
|
|
require "pipeline/coding/projbuild/generators/internal"
|
|
require "pipeline/coding/projbuild/unity_build"
|
|
require "pipeline/os/path"
|
|
require "pipeline/gui/exception_dialog"
|
|
require "pipeline/log/log"
|
|
|
|
#-----------------------------------------------------------------------------
|
|
# Implementation
|
|
#-----------------------------------------------------------------------------
|
|
module Pipeline
|
|
|
|
module ProjBuild
|
|
|
|
class ProjBuilder
|
|
|
|
attr_accessor :unity_build
|
|
attr_accessor :vs2010
|
|
|
|
@@log = nil
|
|
|
|
def ProjBuilder.log
|
|
|
|
@@log = Log.new( 'projbuild' ) if @@log == nil
|
|
@@log
|
|
end
|
|
|
|
def initialize( vs2010 = false )
|
|
|
|
@vs2010 = vs2010 # sadly this code needs to specialise for VS2010, IIRC for PSCCustom jobs, under VS2010 the interal macros differ.
|
|
|
|
OS::Path.set_downcase_on_normalise(false)
|
|
|
|
@generators = Hash.new()
|
|
@generators[:csharp] = CSharpGenerator.new()
|
|
@generators[:vs2005] = VS2005Generator.new()
|
|
@generators[:vs2008] = VS2008Generator.new()
|
|
@generators[:vs2010] = VS2010Generator.new()
|
|
@generators[:internal] = ProjBuildGenerator.new()
|
|
@generators[:ragegen] = RageGenGenerator.new()
|
|
|
|
@generators[:rageprojbuilder] = RageProjBuilder.new(@vs2010)
|
|
|
|
@generators[:shadermakefile] = ShaderMakefileGenerator.new()
|
|
@generators[:qaitems] = QAItemsGenerator.new()
|
|
|
|
@config = Pipeline::Config.instance
|
|
@config.project.load_config
|
|
|
|
@p4 = SCM::Perforce.new()
|
|
@p4.port = @config.sc_server
|
|
@p4.client = @config.sc_workspace
|
|
@p4.user = @config.sc_username
|
|
@p4.connect()
|
|
|
|
@projects = Array.new
|
|
end
|
|
|
|
#possible extra options:
|
|
#single file, or recursively
|
|
#look for related files (pass _2008, ask it to look for _2008 variants etc)
|
|
def import( path, forcetype = nil, options = nil )
|
|
|
|
begin
|
|
|
|
initialize(@vs2010) # DW - what on earth is this all about?
|
|
|
|
# DW : sigh it needs set here due to design flaws with the project builder - since at import we need to know if a unity build is enabled due to 2010 vcxproj project references.
|
|
if (options[:unity_build_enabled])
|
|
@generators.values.each { |g| g.set_unity_build_filenames( true ) }
|
|
else
|
|
@generators.values.each { |g| g.set_unity_build_filenames( false ) }
|
|
end
|
|
|
|
|
|
#ProjBuildData::instance().reset()
|
|
|
|
GC.enable()
|
|
GC.start()
|
|
GC.disable()
|
|
|
|
path = OS::Path.normalise(path)
|
|
|
|
#ProjBuilder::log.info("Importing #{path}...")
|
|
#ProjBuilder::log.info("Forcetype: #{forcetype.to_s}") if forcetype != nil
|
|
|
|
#Does the file exist?
|
|
#raise Exception.new("#{path} doesn't exist!") if File.exists?(path) == false
|
|
|
|
if forcetype == nil then
|
|
|
|
#pass it to each generator
|
|
@generators.values.each { |g|
|
|
ret, @projects = g.import(path, options)
|
|
ProjBuilder::log.info("..generator import returned false") if ret == false
|
|
return false if ret == false
|
|
|
|
if @projects != nil then
|
|
|
|
@projects.each do |project|
|
|
|
|
ProjBuildData::instance().projects[project.guid] = project
|
|
end
|
|
end
|
|
|
|
return true
|
|
}
|
|
else
|
|
|
|
#ProjBuilder::log.info("..generator import path #{path} options #{options}")
|
|
ret, @projects = @generators[forcetype].import(path, options)
|
|
|
|
ProjBuilder::log.info("@projects.length is #{@projects.length}") if @projects and @projects.length <= 0
|
|
|
|
return false if ret == false
|
|
ProjBuilder::log.info("..generator import returned false") if ret == false
|
|
|
|
if @projects != nil then
|
|
|
|
@projects.each do |project|
|
|
ProjBuildData::instance().projects[project.guid] = project
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
return false
|
|
|
|
rescue Exception => ex
|
|
|
|
puts "Unhandled exception: #{ex.message}"
|
|
puts ex.backtrace.join( "\n" )
|
|
|
|
#log.error( ex, 'Unhandled exception in projbuild' )
|
|
GUI::ExceptionDialog::show_dialog( ex, 'Unhandled exception in projbuild' )
|
|
ensure
|
|
#LogSystem::instance( ).shutdown( )
|
|
end
|
|
end
|
|
|
|
def export( path, forcetype = nil, options = nil )
|
|
|
|
begin
|
|
retval = false
|
|
|
|
GC.enable()
|
|
|
|
path = OS::Path.normalise(path)
|
|
|
|
#ProjBuilder::log.info("exporting(projbuild.rb export) #{path}")
|
|
ProjBuilder::log.debug("forcetype #{forcetype.to_s}") if forcetype != nil
|
|
|
|
proj_build = ProjBuildData::instance()
|
|
|
|
#ProjBuilder::log.info("No projects to export - did the import succeed?") if @projects == nil
|
|
|
|
return true if @projects == nil
|
|
|
|
if @projects.size < 1
|
|
ProjBuilder::log.info("Generator did not create any projects to export ( projbuild.rb)!\n")
|
|
return false
|
|
end
|
|
|
|
ProjBuilder::log.info("About to export #{@projects.size} projects") if @projects.size > 1
|
|
|
|
@projects.each do |project|
|
|
|
|
if project == nil
|
|
#HACK: In some generators, such as the RageGen solution generator, we can not rely on the export
|
|
#call of the generator to do our work. For now, gracefully handle the instances were project
|
|
#is nil so we do not crash.
|
|
ProjBuildData::instance().reset()
|
|
return true
|
|
end
|
|
|
|
#The output path will be the directory of the 'path' object, plus the name of the project.
|
|
path = OS::Path.combine(File.dirname(path), project.name)
|
|
#TODO: Determine if we can use the project.path variable...
|
|
|
|
unity_setup = "%RS_TOOLSROOT%/etc/project.xml/project/branches/branch/codeconfigs/codeconfig/unity_build/@enabled"
|
|
if (not options[:unity_build_enabled].nil?) and options[:unity_build_enabled]
|
|
#path = "#{path}_unity"
|
|
ProjBuilder::log.info("Unity build enabled via #{unity_setup} for #{path}")
|
|
unity_config_file = "#{project.name}.unity"
|
|
ret = unity_process( unity_config_file, project )
|
|
if ret == false or ret.nil?
|
|
ProjBuilder::log.warn("\n\nWARNING : *** Unity build is enabled but a unity build failed to run ok - possibly no unity file - this project will not be built ***\n\n")
|
|
return false
|
|
end
|
|
else
|
|
ProjBuilder::log.info("Unity build disabled via #{unity_setup}.")
|
|
end
|
|
|
|
# filenames will be built with _unity in them if unity build is enabled via options,
|
|
# but it may not have built a unity configured project file as it can still be disabled
|
|
# via a missing .unity file, or disabled in the .unity file, hence the name 'unity_build_filenames'
|
|
if (options[:unity_build_enabled])
|
|
#ProjBuilder::log.info("Setting all generators (#{@generators.length}) to have unity filenames enabled.")
|
|
@generators.values.each { |g| g.set_unity_build_filenames( true ) }
|
|
else
|
|
#ProjBuilder::log.info("Setting all generators (#{@generators.length}) to have unity filenames DISABLED.")
|
|
@generators.values.each { |g| g.set_unity_build_filenames( false ) }
|
|
end
|
|
|
|
do_checkout = false
|
|
|
|
# Do not test for the file's attributes as writable.
|
|
# All .sln and .vcproj files are marked writable on client.
|
|
|
|
if forcetype == nil then
|
|
ProjBuilder::log.info("Forcetype is not set - whatever that achieves?")
|
|
#pass it to each generator
|
|
@generators.values.each { |g|
|
|
if g.export(path, project, options) then
|
|
|
|
retval = true
|
|
break
|
|
end
|
|
}
|
|
else
|
|
#ProjBuilder::log.info("Forcetype is set #{forcetype} - whatever that achieves?")
|
|
#ProjBuilder::log.info("class #{@generators[forcetype].class}")
|
|
retval = @generators[forcetype].export(path, project, options)
|
|
end
|
|
|
|
if do_checkout then
|
|
|
|
@p4.run_revert("-a",path)
|
|
end
|
|
|
|
if retval == false then
|
|
|
|
ProjBuilder::log.debug("Did not export #{path}!")
|
|
break;
|
|
end
|
|
end
|
|
|
|
ProjBuildData::instance().reset()
|
|
return retval
|
|
|
|
rescue Exception => ex
|
|
|
|
puts "Unhandled exception: #{ex.message}"
|
|
puts ex.backtrace.join( "\n" )
|
|
|
|
ProjBuilder::log.error( ex, 'Unhandled exception in projbuild' )
|
|
GUI::ExceptionDialog::show_dialog( ex, 'Unhandled exception in projbuild' )
|
|
ensure
|
|
LogSystem::instance( ).shutdown( )
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
end
|