#!/usr/bin/env ruby require 'como' include Como require 'rubu' include Rubu require 'fileutils' Spec.command( 'rubu_example', 'Tero Isannainen', '2018', [ [ :opt_multi, 'conf', '-c', "Configuration option." ], [ :switch, 'verbose', '-v', "Verbose." ], [ :switch, 'serial', '-s', "Serial execution." ], [ :default, nil, nil, "Flow(s) to execute." ], ] ) # ------------------------------------------------------------ # Build specific definitions: # Set flow related options. Var[ :bin_dir ] = 'bin' Var[ :source_dir ] = 'src' Var[ :build_dir ] = 'build' Var[ :exe_name ] = 'build/hello' # Default for :fast option. Var[ :fast ] = false # Change Rubu to verbose mode. if Opt['verbose'].given Order[ :verbose ] = true end # Read setup files and apply Como command line arguments to Var space. Flow.setup( :como => 'conf' ) # ------------------------------------------------------------ # Build Commands: # Code generator with generated file dependency. class GenWorld < MarkBuild def build shrun "bin/gen_world" end end # Typical C compilation with GCC, from source to object. class GccCompileFile < DateBuild def setup @cmd = "gcc -Wall -I #{Var[:source_dir]} -c #{source.rpath} -o #{target.rpath}" # Compile with "-O2" if :fast is set. if Var[ :fast ] @cmd += " -O2" else @cmd += " -g" end end def build shrun @cmd end end # GCC linking. class GccLinkExe < DateBuild def setup @cmd = "gcc #{sources.rpath} -o #{target.rpath}" end def build shrun @cmd end end # Cleaning. class CleanObjects < Build def build # Multiple jobs are grouped with walk (serial execution). walk do shdef "rm -f #{Info[ :gen_files ].rpath}" shdef "rm -f #{Var[ :build_dir ]}/*.o" # Use Ruby for deleting the exe as an example. rbdef "rm -f #{Var[ :exe_name ]}" do FileUtils.rm_f Var[ :exe_name ] end end end end # ------------------------------------------------------------ # Collect sources and create targets: # Generator file and the target. gen_file = Mark.path( "#{Var[:bin_dir]}/gen_world" ) gen_cee_file = Mark.path( "#{Var[:build_dir]}/world.c" ) # Collect "normal" C files. cee_files = Mark.glob( "#{Var[:source_dir]}/*.c" ) # Create list of all C files. all_cee_files = [ gen_cee_file ] + cee_files # Convert C files to corresponding Object files. obj_files = all_cee_files.peer( Var[ :build_dir ], '.o' ) # Specify executable file. exe_file = Mark.path( Var[ :exe_name ] ) # Generate execution time information to Info. Used by CleanObjects. Info[ :gen_files ] = [ gen_cee_file ] # ------------------------------------------------------------ # Define flows: # Serial flow for code generation. Walk.form 'gen-cee' do # Create GenWorld build and register it to 'gen-cee'. GenWorld.use( gen_file, gen_cee_file ) end # Parallel compilation of all C files. Fork.form 'compile-cee' do # Create set of GCC builds by joining 'all_cee_files' and # 'obj_files' in pairs. GccCompileFile.usezip( all_cee_files, obj_files ) end # Default flow, i.e. generate, compile, link to executable. Walk.form 'default' do # Reference 'gen-cee' flow. pick 'gen-cee' # Reference 'compile-cee' flow. pick 'compile-cee' # Create GCC link build and register it. GccLinkExe.use( obj_files, exe_file ) end # Cleaner flow. Walk.form 'clean' do CleanObjects.use end # ------------------------------------------------------------ # Run selected flows: flows = nil if Opt[ nil ].given flows = Opt[ nil ].value else flows = [ 'default' ] end if Opt[ 'serial' ].given Order[ :serial ] = true end Flow.run( flows )