#!/usr/bin/env ruby #these are always used require 'rubygems' require 'fileutils' unless (File.exists?("project.yml")) #===================================== We Do Not Have A Project ================================================ puts "Welcome to Ceedling!" require 'thor' def here File.dirname(__FILE__) + "/.." end class CeedlingTasks < Thor include Thor::Actions desc "new PROJECT_NAME", "create a new ceedling project" method_option :nodocs, :type => :boolean, :default => false, :desc => "No docs in vendor directory" method_option :as_gem, :type => :boolean, :default => false, :desc => "Create the scaffold using Ceedling as a gem instead of filling in the vendor directory. Implies --no-docs." def new(name, silent = false) ceedling_path = File.join(name, 'vendor', 'ceedling') source_path = File.join(name, 'src') test_path = File.join(name, 'test') test_support_path = File.join(name, 'test/support') build_path = File.join(name, 'build') [source_path, test_path, test_support_path, build_path].each do |d| FileUtils.mkdir_p d end unless options[:as_gem] FileUtils.mkdir_p ceedling_path unless options[:nodocs] doc_path = File.join(ceedling_path, 'docs') FileUtils.mkdir_p doc_path in_doc_path = lambda {|f| File.join(doc_path, f)} doc_files = [ 'docs/CeedlingPacket.pdf', 'vendor/c_exception/docs/CExceptionSummary.pdf', 'vendor/cmock/docs/CMock Summary.pdf', 'vendor/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf', 'vendor/unity/docs/UnityAssertionsReference.pdf', 'vendor/unity/docs/UnityConfigurationGuide.pdf', 'vendor/unity/docs/UnityGettingStartedGuide.pdf', 'vendor/unity/docs/UnityHelperScriptsGuide.pdf', ] doc_files.each do |f| copy_file f, in_doc_path.call(File.basename(f)) end end folders = %w{plugins lib} folders.map do |f| {:src => f, :dst => File.join(ceedling_path, f)} end.each do |f| directory f[:src], f[:dst] end sub_components = [ {:src => 'vendor/c_exception/lib/', :dst => 'vendor/c_exception/lib'}, {:src => 'vendor/c_exception/release/', :dst => 'vendor/c_exception/release'}, {:src => 'vendor/cmock/config/', :dst => 'vendor/cmock/config'}, {:src => 'vendor/cmock/lib/', :dst => 'vendor/cmock/lib'}, {:src => 'vendor/cmock/release/', :dst => 'vendor/cmock/release'}, {:src => 'vendor/cmock/src/', :dst => 'vendor/cmock/src'}, {:src => 'vendor/constructor/lib/', :dst => 'vendor/constructor/lib'}, {:src => 'vendor/deep_merge/lib/', :dst => 'vendor/deep_merge/lib'}, {:src => 'vendor/diy/lib', :dst => 'vendor/diy/lib'}, {:src => 'vendor/unity/auto/', :dst => 'vendor/unity/auto'}, {:src => 'vendor/unity/release/', :dst => 'vendor/unity/release'}, {:src => 'vendor/unity/src/', :dst => 'vendor/unity/src'}, ] sub_components.each do |c| directory c[:src], File.join(ceedling_path, c[:dst]) end end if options[:as_gem] copy_file File.join('assets', 'project_as_gem.yml'), File.join(name, 'project.yml') copy_file File.join('assets', 'rakefile_as_gem.rb'), File.join(name, 'rakefile.rb') else copy_file File.join('assets', 'project_with_guts.yml'), File.join(name, 'project.yml') copy_file File.join('assets', 'rakefile_with_guts.rb'), File.join(name, 'rakefile.rb') end unless silent puts "\n" puts "Project '#{name}' created!" puts " - Tool documentation is located in vendor/ceedling/docs" if (not options[:nodocs]) and (not options[:as_gem]) puts " - Execute 'rake -T' to view available test & build tasks" puts '' end end desc "examples", "list available example projects" def examples() puts "Available sample projects:" FileUtils.cd(File.join(here, "examples")) do Dir["*"].each {|proj| puts " #{proj}"} end end desc "example PROJ_NAME [DEST]", "new specified example project (in DEST, if specified)" def example(proj_name, dest=nil) if dest.nil? then dest = proj_name end invoke :new, [dest, true] dest_src = File.join(dest,'src') dest_test = File.join(dest,'test') dest_rakefile = File.join(dest,'rakefile.rb') dest_project = File.join(dest,'project.yml') directory "examples/#{proj_name}/src", dest_src directory "examples/#{proj_name}/test", dest_test remove_file dest_rakefile remove_file dest_project copy_file "examples/#{proj_name}/rakefile.rb", dest_rakefile copy_file "examples/#{proj_name}/project.yml", dest_project puts "\n" puts "Example project '#{proj_name}' created!" puts " - Tool documentation is located in vendor/ceedling/docs" puts " - Execute 'rake -T' to view available test & build tasks" puts '' end desc "version", "return the version of the tools installed" def version() require 'ceedling/version.rb' puts " Ceedling:: #{Ceedling::Version::CEEDLING}" puts " CMock:: #{Ceedling::Version::CMOCK}" puts " Unity:: #{Ceedling::Version::UNITY}" puts " CException:: #{Ceedling::Version::CEXCEPTION}" end end if (ARGV[0] =~ /^\-T$/) puts "\n(No Project Detected, Therefore Showing Options to Create Projects)" CeedlingTasks.tasks.each_pair do |k,v| puts v.usage.ljust(25,' ') + v.description end puts "\n" else CeedlingTasks.source_root here CeedlingTasks.start end #===================================== We Have A Project Already ================================================ else begin require 'pty' #if available, we use PTY because it will live-stream our data instead of buffering it all up def spawn_command(cmd, &block) begin PTY.spawn(cmd) do |stdout, stdin, pid| begin block.call(stdout) rescue Errno::EIO end end rescue Exception => e STDERR.puts e.inspect unless (e == PTY::ChildExited) end end rescue LoadError begin require 'popen4' #if pty wasn't available, we'll use POPEN instead def spawn_command(cmd, &block) POpen4.popen4(cmd) do |stdout, stderr, stdin| begin block.call(stdout) rescue Errno::EIO end end end rescue LoadError #if neither of these libraries were available, we can just shell out to the command and collect results def spawn_command(cmd, &block) results = `#{cmd}` if ($?.exitstatus != 0) block.call( StringIO.new("ERROR: Aborted with Exit Code #{$?.exitstatus.to_s}") ) else block.call( StringIO.new(results) ) end end end end require 'yaml' require 'rbconfig' #determine the width of the screen cols = 80 begin require 'curses' Curses.init_screen() cols = Curses.cols rescue LoadError end #determine platform platform = begin case(RbConfig::CONFIG['host_os']) when /mswin|mingw|cygwin/i :mswin when /darwin/ :osx else :linux end rescue :linux end #create our default meta-runner option set options = { :pretend_we_are_gtest => false, :args => "", :pretest => nil, :outfile => nil, :add_path => [], :path_connector => (platform == :mswin) ? ";" : ":", } #guess that we need a special script file first if it exists if (platform == :mswin) options[:pretest] = File.exists?("#{ platform.to_s }_setup.bat") ? "#{ platform.to_s }_setup.bat" : nil else options[:pretest] = File.exists?("#{ platform.to_s }_setup.sh") ? "source #{ platform.to_s }_setup.sh" : nil end #merge in project settings if they can be found here yaml_options = YAML.load_file('project.yml') options[:pretend_we_are_gtest] = (yaml_options[:plugins][:enabled].include? :stdout_gtestlike_tests_report) if (yaml_options[:plugins] && yaml_options[:plugins][:enabled]) if (yaml_options[:paths]) options[:add_path] = yaml_options[:paths][:tools] || [] else options[:add_path] = [] end #sort through command line options options[:args] ARGV.each do |v| case(v) when /^(?:new|examples?|templates?)$/ puts "\nOops. You called ceedling with argument '#{v}'.\n" + " This is an operation that will create a new project... \n" + " but it looks like you're already in a project. If you really \n" + " want to do this, try moving to an empty folder.\n\n" abort when /^--gtest/ options[:pretend_we_are_gtest] = true when /^--debug/ options[:outfile] = "debug.txt" when /^help$/ options[:args] += "-T " else options[:args] += v + " " end end #add to the path if (options[:add_path] && !options[:add_path].empty?) path = ENV["PATH"] options[:add_path].each do |p| f = File.expand_path(File.dirname(__FILE__),p) path = (f + options[:path_connector] + path) unless path.include? f end ENV["PATH"] = path end if (options[:outfile]) f = File.open(options[:outfile],'w') f << ARGV.inspect << "\n\n" f << options.inspect << "\n\n" end #run rake and capture all the output options[:cmd] = if (options[:pretest].nil? || options[:pretest].empty?) "rake #{options[:args]}" else "#{options[:pretest]} && rake #{options[:args]}" end spawn_command(options[:cmd]) do |stdout| stdout.each do |line| if (!options[:pretend_we_are_gtest] || (line.match(/^\[.*\]/)) || (line.match(/\d+ FAILED TESTS/))) f.puts(line) if (options[:outfile]) if (options[:args].strip == "-T") line.gsub!(/(? cols) endings = line.match(/[\r\n]+/)[0] line.gsub!(endings,'') line = line.slice(0, cols-3) + '...' + endings end end puts(line) end end end f.close if options[:outfile] true #=================================================================================================================== end