# Main entry point for all Origen commands, some global option handling # is done here (i.e. options that apply to all commands) before handing # over to the specific command handlers require 'optparse' ARGV << '--help' if ARGV.empty? ORIGEN_COMMAND_ALIASES = { 'g' => 'generate', 'p' => 'program', 't' => 'target', '-t' => 'target', # For legacy reasons 'e' => 'environment', '-e' => 'environment', 'l' => 'lsf', 'i' => 'interactive', 'c' => 'compile', 'pl' => 'plugin', '-v' => 'version', '--version' => 'version', '-version' => 'version', 'm' => 'mode' } @command = ARGV.shift @command = ORIGEN_COMMAND_ALIASES[@command] || @command @global_commands = [] # Moved here so boot.rb file can know the current command Origen.send :current_command=, @command # Don't log to file during the save command since we need to preserve the last log, # this is done as early in the process as possible so any deprecation warnings during # load don't trigger a new log Origen::Log.console_only = %w(save target environment version).include?(@command) if ARGV.delete('--coverage') || ((@command == 'specs' || @command == 'examples' || @command == 'test') && (ARGV.delete('-c') || ARGV.delete('--coverage'))) require 'simplecov' begin if ENV['CONTINUOUS_INTEGRATION'] require 'coveralls' SimpleCov.formatter = Coveralls::SimpleCov::Formatter end rescue LoadError # No problem end SimpleCov.start Origen.log.info 'Started code coverage' SimpleCov.configure do filters.clear # This will remove the :root_filter that comes via simplecov's defaults add_filter do |src| !(src.filename =~ /^#{Origen.root}\/lib/) end # Results from commands run in succession will be merged by default use_merging(!ARGV.delete('--no_merge')) # Try and make a guess about which directory contains the bulk of the application's code # and create groups to match the main folders d1 = "#{Origen.root}/lib/#{Origen.app.name.to_s.underscore}" d2 = "#{Origen.root}/lib/#{Origen.app.namespace.to_s.underscore}" d3 = "#{Origen.root}/lib" if File.exist?(d1) && File.directory?(d1) dir = d1 elsif File.exist?(d2) && File.directory?(d2) dir = d2 else dir = d3 end Dir.glob("#{dir}/*").each do |d| d = Pathname.new(d) if d.directory? add_group d.basename.to_s.camelcase, d.to_s end end command_name @command path_to_coverage_report = Pathname.new("#{Origen.root}/coverage/index.html").relative_path_from(Pathname.pwd) at_exit do SimpleCov.result.format! puts '' puts 'To view coverage report:' puts " firefox #{path_to_coverage_report} &" puts '' end end end require 'origen/global_methods' include Origen::GlobalMethods Origen.lsf.current_command = @command if ARGV.delete('-d') || ARGV.delete('--debug') begin if RUBY_VERSION >= '2.0.0' require 'byebug' else require 'rubygems' require 'ruby-debug' end rescue LoadError def debugger caller[0] =~ /.*\/(\w+\.rb):(\d+).*/ puts 'The debugger gem is not installed, add the following to your Gemfile:' puts puts "if RUBY_VERSION >= '2.0.0'" puts " gem 'byebug', '~>3.5'" puts 'else' puts " gem 'debugger', '~>1.6'" puts 'end' puts end end Origen.enable_debugger else def debugger caller[0] =~ /.*\/(\w+\.rb):(\d+).*/ puts "#{Regexp.last_match[1]}:#{Regexp.last_match[2]} - debugger statement ignored, run again with '-d' to enable it" end end if ARGV.include?('-verbose') || ARGV.include?('--verbose') options ||= {} Origen.log.level = :verbose ARGV.delete('-verbose') ARGV.delete('--verbose') end if ARGV.include?('-silent') || ARGV.include?('--silent') options ||= {} Origen.log.level = :silent ARGV.delete('-silent') ARGV.delete('--silent') end # If the current command is an LSF execution request (that is a request to # execute a non-Origen command remotely) if (@command == 'lsf' || @command == 'l') && (ARGV.include?('-e') || ARGV.include?('--execute')) # Don't apply these global options yet, pass them through to the underlying command else if ARGV.delete('--profile') # This means that as well as applying to the current thread, this option will also # be applied to any remote jobs triggered by this thread Origen.app.lsf_manager.add_command_option('--profile') Origen.enable_profiling end if ARGV.delete('--exec_remote') && @command != 'lsf' && @command != 'l' Origen.running_remotely = true end # Set the Origen operating mode if supplied ix = ARGV.index('-m') || ARGV.index('--mode') if ix ARGV.delete_at(ix) mode = ARGV[ix] ARGV.delete_at(ix) Origen.app.lsf_manager.add_command_option('--mode', mode) Origen.mode = mode # Make sure this sticks for the remainder of this thread Origen.mode.freeze end end # Give application commands the first shot at executing the given command, # the application file must exit upon servicing the command if it wants to # prevent Origen from then having a go. # This order is preferable to allowing Origen to go first since it allows # overloading of Origen commands by the application. @application_options = [] @plugin_commands = [] # Prevent plugins from being able to accidentally override app commands # @application_commands = [] app_id = @application_options.object_id plugin_id = @plugin_commands.object_id # Prevent plugins from being able to accidentally override app commands # app_cmd_id = @application_commands.object_id app_opt_err = false plugin_opt_err = false app_cmd_err = false if File.exist? "#{Origen.root}/config/commands.rb" require "#{Origen.root}/config/commands" if @application_options.object_id != app_id Origen.log.warning "Don't assign @application_options to a value in config/commands.rb!" Origen.log.warning 'Do something like this instead:' Origen.log.warning ' @application_options << ["-v", "--vector_comments", "Add the vector and cycle number to the vector comments"]' app_opt_err = true end if @plugin_commands.object_id != plugin_id Origen.log.warning "Don't assign @plugin_commands to a new value in config/commands.rb!" Origen.log.warning 'Do something like this instead:' Origen.log.warning ' @plugin_commands << " testers:build Build a test program from a collection of sub-programs"' plugin_opt_err = true end end # Only the app can set this, so cache it locally prevent any plugins overriding it application_commands = @application_commands || '' shared_commands = Origen.app.plugins.shared_commands if shared_commands && shared_commands.size != 0 shared_commands.each do |file| require file if @application_options.object_id != app_id && !app_opt_err Origen.log.warning "Don't assign @application_options to a new value in #{file}!" Origen.log.warning 'Do something like this instead:' Origen.log.warning ' @application_options << ["-v", "--vector_comments", "Add the vector and cycle number to the vector comments"]' app_opt_err = true end if @plugin_commands.object_id != plugin_id && !plugin_opt_err Origen.log.warning "Don't assign @plugin_commands to a new value in #{file}!" Origen.log.warning 'Do something like this instead:' Origen.log.warning ' @plugin_commands << " testers:build Build a test program from a collection of sub-programs"' plugin_opt_err = true end end end # Get a list of registered plugins and get the global launcher @global_launcher = Origen._applications_lookup[:name].dup.map do |plugin_name, plugin| shared = plugin.config.shared || {} if shared[:global_launcher] file = "#{plugin.root}/#{shared[:global_launcher]}" require file file end end.compact case @command when 'generate', 'program', 'compile', 'merge', 'interactive', 'target', 'environment', 'save', 'lsf', 'web', 'time', 'dispatch', 'rc', 'lint', 'plugin', 'fetch', 'mode', 'gem' # , 'add' require "origen/commands/#{@command}" exit 0 unless @command == 'interactive' when 'exec' load ARGV.first exit 0 when 'version' Origen.app # Load app require 'origen/commands/version' exit 0 when 'site' require 'origen/commands/site' exit 0 else if ['-h', '--help'].include?(@command) status = 0 else puts "Error: Command not recognized: #{@command}" status = 1 end puts <<-EOT Usage: origen COMMAND [ARGS] The core origen commands are: EOT cmds = <<-EOT environment Display or set the environment (short-cut alias: "e") target Display or set the target (short-cut alias: "t") mode Display or set the mode (short-cut alias: "m") plugin Display or set the plugin (short-cut alias: "pl") generate Generate a test pattern (short-cut alias: "g") program Generate a test program (short-cut alias: "p") interactive Start an interactive Origen console (short-cut alias: "i") compile Compile a template file or directory (short-cut alias: "c") exec Execute any Ruby file with access to your app environment rc Revision control commands, see -h for details save Save the new or changed files from the last run or a given log file lsf Monitor and manage LSF jobs (short-cut alias: "l") web Web page tools, see -h for details time Tools for test time analysis and forecasting lint Lint and style check (and correct) your application code site Monitor and manage the Origen site configuration EOT cmds.split(/\n/).each do |line| puts Origen.clean_help_line(line) end puts if @application_commands && !@application_commands.empty? puts 'In addition to these the application has added:' @application_commands.split(/\n/).each do |cmds| cmds.split(/\n/).each do |line| puts Origen.clean_help_line(line) end end puts end if @plugin_commands && !@plugin_commands.empty? puts 'The following commands are provided by plugins:' @plugin_commands.each do |cmds| cmds.split(/\n/).each do |line| puts Origen.clean_help_line(line) end end puts end if @global_launcher && !@global_launcher.empty? puts 'The following global commands are provided by plugins:' @global_commands.each do |cmds| cmds.split(/\n/).each do |line| puts Origen.clean_help_line(line) end end puts end puts <<-EOT All commands can be run with -d (or --debugger) to enable the debugger. All commands can be run with --coverage to enable code coverage. Many commands can be run with -h (or --help) for more information. EOT exit status end