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

304 lines
9.0 KiB
Ruby
Executable File

#
# File:: %RS_TOOLSLIB%/util/findMakefiles.rb
# Description:: ironruby script that recursively scans for projgen.config files and all recognised makefiles
# it then produces a series of local *.makefiles files.
# - each file contains the correct build directive to build the makefiles with the appropriate settings
#
# Author:: Derek Ward <derek.ward@rockstarnorth.com>
# Date:: 04th October 2012
#
#-----------------------------------------------------------------------------
# Uses
#-----------------------------------------------------------------------------
require 'RSG.Base.dll'
require 'mscorlib'
require 'System.Core'
require 'pathname'
require 'RSG.Pipeline.Core.dll'
require 'RSG.Base.Configuration.dll'
require 'RSG.Base.Windows.dll'
require 'RSG.SourceControl.Perforce.dll'
include System::IO
include RSG::Base::Logging
include RSG::Base::Logging::Universal
include RSG::Base::OS
include RSG::Base::Configuration
include RSG::Base::Windows
include RSG::Pipeline::Core
include RSG::SourceControl::Perforce
require 'pipeline/os/options'
include Pipeline
using_clr_extensions RSG::Base::Extensions
using_clr_extensions System::Linq
module FindMakeFiles
#-----------------------------------------------------------------------------
# Constants
#-----------------------------------------------------------------------------
# Order matters, slndefs should be converted after makefiles.
MAKEFILE_SEARCHES = [ "*.makefile", "makefile.txt", "*.slndef" ]
BUILDFILE_SEARCHES = [ "projgen.config" ]
AUTHOR = 'RSGEDI Tools'
EMAIL = 'RSGEDI Tools <*tools@rockstarnorth.com>'
OPTIONS = [
LongOption::new( 'nonrecursive', LongOption::ArgType.None, '1', 'Do not recurse.' ),
LongOption::new( 'exclude', LongOption::ArgType.Required, 'x', 'Exclusion Regex' )
]
class Utility
#------------------------------------------------------------------
# search routine
def Utility::search_files( searches, list, searchOptions, exclusionRegex, log )
searches.each do |search|
files = Directory::GetFiles(Dir.pwd, search, searchOptions )
files = files.collect { |f| File.expand_path(f) }
excluded = 0
if exclusionRegex # delete_if doesnt work!!!!
newfiles = []
files.each do |f|
if (f=~exclusionRegex)
excluded += 1
log.Message " excluding #{f}"
else
newfiles << f
end
end
files = newfiles
end
list.concat files
log.Message "- Discovered #{files.length} x #{search} : #{excluded} excluded" if (files.length>0)
end
end
end
#-----------------------------------------------------------------------------
# Implementation
#-----------------------------------------------------------------------------
if ( __FILE__ == $0 ) then
# Initialise log and console output.
puts "a"
LogFactory.Initialize()
puts "b"
g_Log = LogFactory.method(:CreateUniversalLog).call( 'findMakefiles' )
puts "c"
LogFactory.CreateApplicationConsoleLogTarget( )
puts "d"
g_Options = OS::Options::new( OPTIONS )
puts "e"
begin
if ( g_Options.is_enabled?( 'help' ) )
g_Log.Message "#{__FILE__}"
g_Log.Message "Usage:"
g_Log.Message g_Options.usage()
exit( 1 )
end
g_Recurse = g_Options.get( 'nonrecursive' ) ? false : true
searchOptions = g_Recurse ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly
g_ExclusionRegex = nil
if g_Options.has_option?( 'exclude' )
regex = g_Options.get( 'exclude' )
g_ExclusionRegex = Regexp.new( regex, 'i')
g_Log.Message " "
g_Log.Message "Excluding #{regex}"
g_Log.Message " "
end
makefiles = []
buildfiles = []
#
# Search recursively for specific files.
#
g_Log.Message " "
g_Log.Message "--------------------- Recursive Directory Search --------------------" if g_Recurse
g_Log.Message "------------------- Non Recursive Directory Search ------------------" unless g_Recurse
g_Log.Message " Searching within #{Dir.pwd}..."
Utility::search_files(MAKEFILE_SEARCHES, makefiles, searchOptions, g_ExclusionRegex, g_Log)
Utility::search_files(BUILDFILE_SEARCHES, buildfiles,searchOptions, g_ExclusionRegex, g_Log)
g_Log.Message " "
g_Log.Message " Searching (walking up) #{Dir.pwd}..."
# these buildfiles can be in a folder above!
BUILDFILE_SEARCHES.each do |search|
path_name = Pathname.new(Dir.pwd)
begin
path_name = path_name.parent
if (path_name!=nil)
files = Directory::GetFiles(path_name.to_s, search, SearchOption.TopDirectoryOnly)
files = files.collect { |f| File.expand_path(f) }
excluded = 0
if g_ExclusionRegex
newfiles = []
files.each do |f|
if (f=~g_ExclusionRegex)
excluded += 1
#g_Log.Message " excluding #{f}"
else
newfiles << f
end
end
files = newfiles
end
g_Log.Message "- Discovered #{files.length} x #{search} : #{excluded} excluded" if (files.length>0)
buildfiles.concat files
end
end while (path_name!=nil && !path_name.root?)
end
g_Log.Message "---------------------------------------------------------------------"
#
# Get all the build files.
#
# - DW: TODO will conversion order become a concern?
# Actually I don't think I can practically guarantee any order by virtue of the batching I do.... bah
buildfiles = buildfiles.sort{|x, y| File.dirname(y).length <=> File.dirname(x).length}
buildfile_hash = {}
buildfiles.each do |build_file|
f = File.open(build_file)
lines = f.readlines
fileScope = nil
tmpFile = nil
squiggle_depth = 0
lines.each do |line|
#g_Log.Message ">>>#{line}"
if (/\s*#(.*)/.match(line)) # ignore comments
# deliberately left empty
elsif fileScope != nil
squiggle_depth += 1 if line.trim.ends_with("{")
squiggle_depth -= 1 if line.trim.ends_with("}")
if squiggle_depth<=0
fileScope = nil
tmpFile = nil
else
g_Log.Message "Writing #{fileScope} : #{line}"
tmpFile.write(line)
end
elsif (/(.*)\s*\{/.match(line))
filename = $1
g_Log.Message "Matched filename #{filename}"
fileScope = Environment.ExpandEnvironmentVariables(filename)
g_Log.Message "Creating #{fileScope}"
tmpFile = File.open(fileScope)
squiggle_depth += 1
elsif (/\s*(.+)\s*/.match(line)) # this is what we are looking for.
setup_file = $1
# TODO : figure out why this aint workin
#setup_file = System::Object::Environment::ExpandEnvironmentVariables(setup_file)
#setup_file = File.expand_path(setup_file)
#g_Log.Message setup_file
buildfile_hash[setup_file] = build_file
end
end
end
#
# Order hash - we have to match with the deepest project.config
#
all_makefiles = {}
buildfile_hash.each_key do |key|
all_makefiles[key] = []
end
# I know hashes are unordered - this is ruby magic.
buildfile_sorted = buildfile_hash.sort_by { |key, val| File.dirname(val).length }.reverse
g_Log.Message " "
g_Log.Message "-------------------------- ProjGen.Configs --------------------------"
buildfile_sorted.each do |h|
g_Log.Message "#{h[1]}:"
g_Log.Message "\t( #{h[0]} )"
end
g_Log.Message "---------------------------------------------------------------------"
g_Log.Message " "
#
# Construct a hash keyed by setup file and the makefiles beneath to process,
#
makefiles.each do |makefile|
found = false
# this deepest buildfile needs to match first
buildfile_sorted.each do |a|
setup_file = a[0]
buildfile = a[1]
#g_Log.Message "matching #{buildfile} for #{makefile}"
dir = File.dirname(buildfile)
if (makefile.include?(dir))
#g_Log.Message "#{f} chooses build setup file #{setup_file}"
all_makefiles[setup_file] << makefile
found = true
break
end
end
if (!found)
g_Log.Error( "Makefile can't find a projgen.config in its source tree and above #{makefile}" )
end
end
#
# each key is serialised to a ,makefiles file so that it can be converted externally
# DW: - if I had designed the project generator to be a dll ( but I didn't ) I could have run it directly in here
#
i = 0
all_makefiles.each_pair do |build_file, makefiles|
if (makefiles.length>0)
File.open("#{i}.makefiles", 'w') do |f|
f.puts("build #{build_file}\n")
makefiles.each do |makefile|
f.puts("#{makefile}\n")
end
end
i+=1
end
end
rescue SystemExit => ex
exit( ex.status )
rescue Exception => ex
ConsoleLog::new( )
Log::Log__Error( "Unhandled error in findMakefiles.rb" )
Log::Log__Error( ex.backtrace.join("\n" ) + "\n" + ex.Message )
end
end
end # module findMakeFiles