mode :all do config :all, :build_prefix => 'tmp/build', :staging_prefix => 'tmp/staging', :tmp_root => 'tmp', # where our libs are kept - i.e. what should be a valid build item :lib_directories => ['lib'], # which sub directory do our javascripts go into :javascripts_prefix => 'javascripts', # which sub dir do our built stylesheets go into :stylesheets_prefix => 'stylesheets', # final name for our js built file (:project_name for name of project, # other wise to_s is called on it) :javascript_name => :project_name, # same as above :stylehseet_name => :project_name, # default bin file to run.. if none given, then it defaults to :project_name # which is replaced by the actual project name. This will then mean either # a bin file of the given name, or lib/project_name will be loaded :bin_file => :project_name, # by default do NOT build stylesheets.. only cherrykit/spec wants this, so # for browsers etc, do not do this. :build_stylesheets => false, # should we copy the html files (if found?) :copy_html => false end mode :debug do config :all, :build_prefix => '', :staging_prefix => 'tmp/debug/staging' end mode :spec do config :all, :build_prefix => 'tmp/built_specs', :staging_prefix => 'tmp/spec/staging' end # This is the root opalfile. It is used as the basis for every target. These can # all be overridden by each opalfile, and so provide "defaults". # Building targets - each opal (app, framework, theme etc) are a single target namespace :target do desc "Preparing the target" task :prepare do # set the build root @target.build_root = File.join(@project.build_root, @config.staging_prefix, 'opals', @target.target_name) # set the staging root @target.staging_root = File.join(@project.build_root, @config.staging_prefix, @target.target_name) end desc "Building the target" task :build => [:catalog, :hide_non_build_files, :'prepare_build_tasks:all'] desc "catalog" task :catalog do target_root = @target.target_root Dir[File.join(target_root, '**', '*')].each do |source| next if !File.exist?(source) || File.directory?(source) # should check if its another target relative_path = source.sub(/^#{Regexp.escape target_root}\//, "") relative_path = relative_path.split(::File::SEPARATOR).join('/') @target.add_build_item relative_path end end desc "Hide opalfiles etc" task :hide_non_build_files => [:catalog] do # puts "checking for extra files" @target.build_items.each do |item| can_skip = false # skip if item is in our lib directory(s) can_skip = @config.lib_directories.each do |dir| break true if item.filename =~ /^#{dir}.+(rb|js)$/ end # puts "trying #{item.filename}" if @config.copy_html && item.filename =~ /\.html$/ # allow html files if we have said so next end next if can_skip == true # skip all resources if @config.build_stylesheets # puts "can build styleheets for #{item.filename}" next if item.filename =~ /^resources.+$/ end # if we have a bin item, and our config says we should include the bin # file... next if item.filename =~ /^bin.+$/ and @config.include_bin # puts "hiding #{item.filename}" # hide any other file item.hide! end # puts "running hide_opalfiles with #{@target.build_items}" # remove all non build files.. for example, if target is not main target, # then remove any bin files.. only want lib files, also remove spec folders # really... the only ruby, for example, we want is in the lib folder end end namespace :prepare_build_tasks do desc "This should invoke all needed tasks" task :all => [:css, :ruby, :javascript, :combine] desc "setup" task :setup => [:'target:prepare'] desc "Ruby sources" task :ruby => [:setup] do # puts "running ruby tasks for #{@target}" # make sure we only grab the ruby files build_items = @target.build_items.select { |item| item.ext == 'rb' } build_items.each do |item| # p "item.filename is #{item.filename}" item = @target.add_transform item, :filename => item.filename, :build_task => 'build:ruby', :resource => :ruby, # give our ruby a name.rb.js extension to make it clearer what it is :build_path => File.join(@target.build_root, item.filename) + '.js', :staging_path => File.join(@target.staging_root, item.filename) + '.js' end end desc "Any javascript sources - not likely to be many" task :javascript => [:setup] do # puts @target.build_items.map { |a| a.filename } build_items = @target.build_items.select { |item| item.ext == 'js' } # puts "found some javascript items: #{build_items}" build_items.each do |item| item = @target.add_transform item, :filename => item.filename, :build_task => 'build:javascript', :resource => :javascript, :build_path => File.join(@target.build_root, item.filename), :staging_path => File.join(@target.staging_root, item.filename) end end desc "Collect all css resources" task :css => [:setup] do if @config.build_stylesheets build_items = @target.build_items.select { |item| item.ext == "css" } build_items.each do |item| item = @target.add_transform item, :filename => item.filename, :build_task => 'build:css', :resource => :css, :build_path => File.join(@target.build_root, item.filename), :staging_path => File.join(@target.staging_root, item.filename) end end end desc "combined ruby etc" task :combine => [:css, :ruby, :javascript] do # puts "combining for #{@target.target_name}" code_items = [] css_items = [] @target.build_items.each do |item| # all resouurce (ruby, css etc) types will have a .resource property next if item.resource.nil? # lookup specific ruby, css etc case item.resource when :ruby, :javascript code_items << item when :css css_items << item else # puts "found NON ruby #{item.inspect}" end end # code target: the opal - javascript and ruby sources code_target_name = @target.target_name + '.js' @target.add_composite code_target_name, :build_task => 'build:opal', :source_items => code_items if @config.build_stylesheets # css target is all the css resources (less, css, sass) css_target_name = @target.target_name + '.css' @target.add_composite css_target_name, :build_task => 'build:opal_css', :source_items => css_items end end end namespace :build_item do task :prepare do filename = @build_item.filename raise "All build items must have a filename." unless filename # default build task for a build item @build_item.build_task ||= 'build:copy' # make sure we have an extension set @build_item.ext = File.extname(filename)[1..-1] # make sure our full source path is ready @build_item.source_path ||= File.join(@target.target_root, filename) end end namespace :build do task :clean do # clean.. remove only tmps etc, leave final build as it is staging = File.join @project.build_root, @config.tmp_root FileUtils.rm_rf staging end task :copy do # puts "building simple copy task for #{@build_item.source_path}" from = @build_item.source_path to = File.join(@project.build_root, @config.build_prefix, @build_item.filename) # puts from # puts to FileUtils.mkdir_p File.dirname(to) FileUtils.copy_file from, to end task :ruby do Vienna::Builders::Ruby.build @build_item, @dst_path end task :javascript do Vienna::Builders::Javascript.build @build_item, @dst_path end task :css do Vienna::Builders::CSS.build @build_item, @dst_path end desc "Build the opal itself (as javascript)" task :opal do Vienna::Builders::Opal.build @build_item, @dst_path end task :opal_css do source_items = @build_item.source_items build_path = @build_item.build_path FileUtils.mkdir_p File.dirname(build_path) File.open(build_path, 'w') do |out| source_items.each do |item| out.write File.read(item.stage!.staging_path) end end end desc "Final package to combine all opals" task :package do # puts "running package task!" # only run package task if we are the main target if @target.main_target? js_build_path = File.join @project.build_root, @config.build_prefix, @config.javascripts_prefix FileUtils.mkdir_p js_build_path js_name = @config.javascript_name if js_name == :project_name js_name = "#{@project.project_name}.js" end # if @config.build_stylesheets css_build_path = File.join @project.build_root, @config.build_prefix, @config.stylesheets_prefix # FileUtils.mkdir_p css_build_path css_name = @config.stylesheet_name if css_name == :project_name css_name = "#{@project.project_name}.css" end # end # javascripts_prefix opals = @project.targets.each_value.to_a.dup # puts "opals are:" # p opals # order is more-a-less irrelevant, but we MUST have opal first opals.unshift(opals.find { |o| o.target_name.to_sym == :runtime }).uniq! # puts "opals are now:" # p opals # build the final javascript.js package File.open(File.join(js_build_path, js_name), 'w') do |out| opals.each do |opal| item = opal.build_item_for("#{opal.target_name}.js") out.puts File.read(item.build_path) end # Also, we must include the bin file we want to use, and set the working # directory (which is in the base folder of the main_target) bin_file = @config.bin_file bin_file = @project.project_name if bin_file == :project_name working_dir = @target.target_name.to_s out.puts "opal.run('#{bin_file}','#{working_dir}');" end # if @config.build_stylesheets # puts "in a" # puts css_build_path # puts css_name all_css_targets = [] opals.each do |opal| item = opal.build_item_for("#{opal.target_name}.css") # puts item (all_css_targets << item) if item end if all_css_targets.length > 0 FileUtils.mkdir_p css_build_path File.open(File.join(css_build_path, css_name), 'w') do |out| all_css_targets.each do |item| out.puts File.read(item.build_path) end end end # FileUtils.mkdir_p css_build_path # build the final stylesheet.css package # File.open(File.join(css_build_path, css_name), 'w') do |out| # opals.each do |opal| # puts opal.target_name # item = /opal.build_item_for("#{opal.target_name}.css") # puts item # out.puts(File.read(item.build_path)) if item # end # end # end end end end