require 'cxxproject/ext/rake' require 'cxxproject/utils/printer' require "cxxproject/toolchain/colorizing_formatter" require "option/parser" module Cxxproject class Options < Parser attr_reader :build_config, :main_dir, :project, :filename, :eclipse_version, :alias_filename # String attr_reader :roots, :include_filter, :exclude_filter # String List attr_reader :clean, :rebuild, :single, :verbose, :nocache, :color, :show_includes, :linkOnly, :check_uninc, :printLess, :no_autodir, :clobber # Boolean attr_reader :threads, :socket # Fixnum def initialize(argv) super(argv) @build_config = "" @main_dir = nil @project = nil @filename = nil @single = false @clean = false @clobber = false @rebuild = false @verbose = false @nocache = false @check_uninc = false @color = false @show_includes = false @linkOnly = false @printLess = false @no_autodir = false @threads = 8 @roots = [] @socket = 0 @include_filter = [] @exclude_filter = [] @def_root = nil @eclipse_version = "" @alias_filename = "" add_default(Proc.new{ |x| set_build_config_default(x) }) add_option(Option.new("-m",true) { |x| set_main_dir(x) }) add_option(Option.new("-b",true) { |x| set_build_config(x) }) add_option(Option.new("-p",true) { |x| set_project(x); set_single }) add_option(Option.new("-f",true) { |x| set_filename(x) }) add_option(Option.new("-c",false) { set_clean }) add_option(Option.new("-a",true) { |x| set_color(x) }) add_option(Option.new("-w",true) { |x| set_root(x) }) add_option(Option.new("-r",false) { set_error }) add_option(Option.new("--rebuild",false) { set_rebuild }) add_option(Option.new("--prepro",false) { set_prepro }) add_option(Option.new("--link_only",false) { set_linkOnly }) add_option(Option.new("--no_autodir",false) { set_no_autodir }) add_option(Option.new("-v0",false) { set_v(0) }) add_option(Option.new("-v1",false) { set_v(1) }) add_option(Option.new("-v2",false) { set_v(2) }) add_option(Option.new("--clobber",false) { set_clobber }) add_option(Option.new("--ignore_cache",false) { set_nocache }) add_option(Option.new("--threads",true) { |x| set_threads(x) }) add_option(Option.new("--socket",true) { |x| set_socket(x) }) add_option(Option.new("--toolchain_info",true) { |x| print_toolchain(x) }) add_option(Option.new("--toolchain_names",false) { print_toolchains }) add_option(Option.new("--include_filter",true) { |x| set_include_filter(x) }) add_option(Option.new("--exclude_filter",true) { |x| set_exclude_filter(x) }) add_option(Option.new("--show_abs_paths",false) { set_show_fullnames }) add_option(Option.new("--visualStudio",false) { set_visualStudio }) add_option(Option.new("-h",false) { usage; ExitHelper.exit(0) }) add_option(Option.new("--help",false) { usage; ExitHelper.exit(0) }) add_option(Option.new("--show_include_paths",false) { set_show_inc }) add_option(Option.new("--eclipse_version",true) { |x| set_eclipse_version(x) }) add_option(Option.new("--show_license",false) { show_license }) add_option(Option.new("--version",false) { ExitHelper.exit(0) }) add_option(Option.new("--check_uninc",false) { set_check_uninc }) add_option(Option.new("--alias",true) { |x| set_alias_filename(x) }) end def usage puts "\nUsage: bake [options]" puts " [-b] Config name of main project" puts " -m Directory of main project (default is current directory)." puts " -p Project to build/clean (default is main project)" puts " -f Build/Clean this file only." puts " -c Clean the file/project." puts " -a Use ansi color sequences (console must support it). Possible values are 'white' and 'black'." puts " -v Verbose level from 0 to 2, whereas -v0 is less, -v1 is normal (default) and -v2 is more verbose." puts " -r Stop on first error." puts " -w Add a workspace root (can be used multiple times)." puts " If no root is specified, the parent directory of the main project is added automatically." puts " --rebuild Clean before build." puts " --clobber Clean the file/project (same as option -c) AND the bake cache files." puts " --prepro Stop after preprocessor." puts " --link_only Only link executable - doesn't update objects and archives or start PreSteps and PostSteps" puts " --ignore_cache Rereads the original meta files - usefull if workspace structure has been changed." puts " --check_uninc Checks for unnecessary includes (only done for successful project builds)." puts " --threads Set NUMBER of parallel compiled files (default is 8)." puts " --socket Set SOCKET for sending errors, receiving commands, etc. - used by e.g. Eclipse." puts " --toolchain_info Prints default values of a toolchain." puts " --toolchain_names Prints available toolchains." puts " --include_filter Includes steps with this filter name (can be used multiple times)." puts " 'PRE' or 'POST' includes all PreSteps respectively PostSteps." puts " --exclude_filter Excludes steps with this filter name (can be used multiple times)." puts " 'PRE' or 'POST' excludes all PreSteps respectively PostSteps." puts " --show_abs_paths Compiler prints absolute filename paths instead of relative paths." puts " --no_autodir Disable auto completion of paths like in IncludeDir" puts "" puts " --version Print version." puts " -h, --help Print this help." puts " --show_license Print the license." end def parse_options() parse_internal(false) set_main_dir(Dir.pwd) if @main_dir.nil? set_project(File.basename(@main_dir)) if @project.nil? @roots << @def_root if @roots.length == 0 Rake::application.max_parallel_tasks = @threads if @linkOnly if @rebuild Printer.printError "Error: --link_only and --rebuild not allowed at the same time" ExitHelper.exit(1) end if @clean Printer.printError "Error: --link_only and -c not allowed at the same time" ExitHelper.exit(1) end end end def check_valid_dir(dir) if not File.exists?(dir) Printer.printError "Error: Directory #{dir} does not exist" ExitHelper.exit(1) end if not File.directory?(dir) Printer.printError "Error: #{dir} is not a directory" ExitHelper.exit(1) end end def set_include_filter(x) @include_filter << x end def set_exclude_filter(x) @exclude_filter << x end def set_build_config_default(config) index = config.index('-') return false if (index != nil and index == 0) set_build_config(config) return true end def set_build_config(config) if not @build_config.empty? Printer.printError "Error: Cannot set build config '#{config}', because build config is already set to '#{@build_config}'" ExitHelper.exit(1) end @build_config = config end def set_main_dir(dir) check_valid_dir(dir) @main_dir = File.expand_path(dir.gsub(/[\\]/,'/')) @def_root = File.dirname(@main_dir) end def set_project(name) @project = name end def set_filename(filename) @filename = filename.gsub(/[\\]/,'/') end def set_single() @single = true end def set_clean() @clean = true end def set_clobber() @clobber = true set_clean end def set_rebuild() @clean = true @rebuild = true end def set_nocache() @nocache = true end def set_check_uninc() @check_uninc = true end def set_prepro() Rake::application.preproFlags = true end def set_linkOnly() @linkOnly = true set_single() end def set_no_autodir() @no_autodir = true end def set_v(num) if num == 0 @printLess = true @verbose = false Rake::application.options.silent = true elsif num == 1 Rake::application.options.silent = false @printLess = false @verbose = false elsif num == 2 Rake::application.options.silent = false @printLess = false @verbose = true end end def set_color(x) if (x != "black" and x != "white") Printer.printError "Error: color scheme must be 'black' or 'white'" ExitHelper.exit(1) end begin ColorizingFormatter::setColorScheme(x.to_sym) @color = true ColorizingFormatter.enabled = true rescue Exception => e Printer.printError "Error: colored gem not installed (#{e.message})" puts e.backtrace if @verbose ExitHelper.exit(1) end end def set_error() Rake::Task.bail_on_first_error = true end def set_show_inc @show_includes = true end def set_show_fullnames Rake::application.consoleOutput_fullnames = true end def set_visualStudio Rake::application.consoleOutput_visualStudio = true end def set_root(dir) check_valid_dir(dir) r = File.expand_path(dir.gsub(/[\\]/,'/')) @roots << r if not @roots.include?r end def set_threads(num) @threads = String === num ? num.to_i : num if @threads <= 0 Printer.printError "Error: number of threads must be > 0" ExitHelper.exit(1) end end def set_socket(num) @socket = String === num ? num.to_i : num end def printHash(x, level) x.each do |k,v| if Hash === v if level > 0 level.times {print " "} else print "\n" end puts k printHash(v,level+1) elsif Array === v or String === v level.times {print " "} puts "#{k} = #{v}" end end end def print_toolchain(x) tcs = Cxxproject::Toolchain::Provider[x] if tcs.nil? puts "Toolchain not available" else printHash(tcs, 0) end ExitHelper.exit(0) end def print_toolchains() puts "Available toolchains:" Cxxproject::Toolchain::Provider.list.keys.each { |c| puts "* #{c}" } ExitHelper.exit(0) end def show_license() licenseFile = File.join(File.dirname(File.dirname(File.dirname(__FILE__))), "license.txt") file = File.new(licenseFile, "r") while (line = file.gets) puts "#{line}" end file.close ExitHelper.exit(0) end def set_eclipse_version(x) @eclipse_version = x end def set_alias_filename(x) @alias_filename = x end end end