mtbuild 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/LICENSE.md +27 -0
 - data/README.md +528 -0
 - data/bin/mtbuild +10 -0
 - data/lib/mtbuild.rb +13 -0
 - data/lib/mtbuild/application.rb +39 -0
 - data/lib/mtbuild/application_configuration.rb +38 -0
 - data/lib/mtbuild/application_project.rb +21 -0
 - data/lib/mtbuild/application_task.rb +23 -0
 - data/lib/mtbuild/compiled_configuration.rb +73 -0
 - data/lib/mtbuild/configuration.rb +46 -0
 - data/lib/mtbuild/dsl.rb +46 -0
 - data/lib/mtbuild/mtbuild.rb +10 -0
 - data/lib/mtbuild/project.rb +71 -0
 - data/lib/mtbuild/staticlibrary_configuration.rb +49 -0
 - data/lib/mtbuild/staticlibrary_project.rb +21 -0
 - data/lib/mtbuild/staticlibrary_task.rb +31 -0
 - data/lib/mtbuild/test_application_configuration.rb +33 -0
 - data/lib/mtbuild/test_application_project.rb +22 -0
 - data/lib/mtbuild/test_application_task.rb +23 -0
 - data/lib/mtbuild/toolchain.rb +109 -0
 - data/lib/mtbuild/toolchains/arm_none_eabi_gcc.rb +69 -0
 - data/lib/mtbuild/toolchains/gcc.rb +160 -0
 - data/lib/mtbuild/utils.rb +46 -0
 - data/lib/mtbuild/version.rb +4 -0
 - data/lib/mtbuild/versioner.rb +54 -0
 - data/lib/mtbuild/versioners/mt_std_version.rb +72 -0
 - data/lib/mtbuild/workspace.rb +112 -0
 - metadata +153 -0
 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module MTBuild
         
     | 
| 
      
 2 
     | 
    
         
            +
              require "mtbuild/staticlibrary_configuration"
         
     | 
| 
      
 3 
     | 
    
         
            +
              require 'mtbuild/project'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              # This class is used to build static libraries. A static library has
         
     | 
| 
      
 6 
     | 
    
         
            +
              # compilation and archival phases that produce a binary library package.
         
     | 
| 
      
 7 
     | 
    
         
            +
            	class StaticLibraryProject < Project
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                # Adds a named static library configuration to the project.
         
     | 
| 
      
 10 
     | 
    
         
            +
                def add_configuration(configuration_name, configuration)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  super
         
     | 
| 
      
 12 
     | 
    
         
            +
                  default_configuration = Workspace.configuration_defaults.fetch(configuration_name, {})
         
     | 
| 
      
 13 
     | 
    
         
            +
                  merged_configuration = Utils.merge_configurations(default_configuration, configuration)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  cfg = StaticLibraryConfiguration.new(@project_name, @project_folder, effective_output_folder, configuration_name, merged_configuration)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @configurations << cfg
         
     | 
| 
      
 16 
     | 
    
         
            +
                  return cfg
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            	end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,31 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rake
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              require 'rake'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              # This is a top-level Rake task for creating a static library
         
     | 
| 
      
 6 
     | 
    
         
            +
              class StaticLibraryTask < Task
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                # API header location for the static library
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_accessor :api_headers
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                # The static library output file(s)
         
     | 
| 
      
 12 
     | 
    
         
            +
                attr_accessor :library_files
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def initialize(task_name, app)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  super
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @api_headers = ''
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @library_files = ''
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              module DSL
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                # DSL method to create a static library task.
         
     | 
| 
      
 25 
     | 
    
         
            +
                def static_library_task(*args, &block)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  new_task = Rake::StaticLibraryTask.define_task(*args, &block)
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module MTBuild
         
     | 
| 
      
 2 
     | 
    
         
            +
              require 'mtbuild/compiled_configuration'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              # Use this class to create test application configurations. You won't typically
         
     | 
| 
      
 5 
     | 
    
         
            +
              # instantiate this directly. Instead, the TestApplicationProject.add_configuration
         
     | 
| 
      
 6 
     | 
    
         
            +
              # method will create this for you.
         
     | 
| 
      
 7 
     | 
    
         
            +
            	class TestApplicationConfiguration < CompiledConfiguration
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                # Create the actual Rake tasks that will perform the configuration's work
         
     | 
| 
      
 10 
     | 
    
         
            +
                def configure_tasks
         
     | 
| 
      
 11 
     | 
    
         
            +
                  super
         
     | 
| 
      
 12 
     | 
    
         
            +
                  all_object_files = []
         
     | 
| 
      
 13 
     | 
    
         
            +
                  all_object_folders = []
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @toolchains.each do |toolchain, sources|
         
     | 
| 
      
 15 
     | 
    
         
            +
                    object_files, object_folders = toolchain.create_compile_tasks(sources)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    all_object_files |= object_files
         
     | 
| 
      
 17 
     | 
    
         
            +
                    all_object_folders |= object_folders
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  application_binaries, application_files, application_folders = @default_toolchain.create_application_tasks(all_object_files, @project_name)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  dependencies = @dependencies+all_object_folders+application_folders+application_files+application_binaries
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  desc "Build and run test application '#{@project_name}' with configuration '#{@configuration_name}'"
         
     | 
| 
      
 24 
     | 
    
         
            +
                  new_task = test_application_task @configuration_name => dependencies do |t|
         
     | 
| 
      
 25 
     | 
    
         
            +
                    puts "built test application #{t.name}."
         
     | 
| 
      
 26 
     | 
    
         
            +
                    sh application_binaries.first
         
     | 
| 
      
 27 
     | 
    
         
            +
                    puts "ran test application #{t.name}."
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            	end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module MTBuild
         
     | 
| 
      
 2 
     | 
    
         
            +
              require "mtbuild/test_application_configuration"
         
     | 
| 
      
 3 
     | 
    
         
            +
              require 'mtbuild/project'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              # This class is used to build test applications. A test application has
         
     | 
| 
      
 6 
     | 
    
         
            +
              # compilation and link phases that produce a binary test executable. The test
         
     | 
| 
      
 7 
     | 
    
         
            +
              # executable is invoked after building successfully.
         
     | 
| 
      
 8 
     | 
    
         
            +
            	class TestApplicationProject < Project
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                # Adds a named test application configuration to the project.
         
     | 
| 
      
 11 
     | 
    
         
            +
                def add_configuration(configuration_name, configuration)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  super
         
     | 
| 
      
 13 
     | 
    
         
            +
                  default_configuration = Workspace.configuration_defaults.fetch(configuration_name, {})
         
     | 
| 
      
 14 
     | 
    
         
            +
                  merged_configuration = Utils.merge_configurations(default_configuration, configuration)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  cfg = TestApplicationConfiguration.new(@project_name, @project_folder, effective_output_folder, configuration_name, merged_configuration)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @configurations << cfg
         
     | 
| 
      
 17 
     | 
    
         
            +
                  return cfg
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            	end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rake
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              require 'rake'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              # This is a top-level Rake task for creating a test application
         
     | 
| 
      
 6 
     | 
    
         
            +
              class TestApplicationTask < Task
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                def initialize(task_name, app)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  super
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              module DSL
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                # DSL method to create a test application task.
         
     | 
| 
      
 17 
     | 
    
         
            +
                def test_application_task(*args, &block)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  new_task = Rake::TestApplicationTask.define_task(*args, &block)
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,109 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module MTBuild
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              # This is the base class for all toolchain types.
         
     | 
| 
      
 4 
     | 
    
         
            +
            	class Toolchain
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                # The toolchain's output folder
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_accessor :output_folder
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                # The project's folder. Relative path references are interpreted as
         
     | 
| 
      
 10 
     | 
    
         
            +
                # relative to this folder.
         
     | 
| 
      
 11 
     | 
    
         
            +
                attr_accessor :project_folder
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                # Text to append to the name of output files
         
     | 
| 
      
 14 
     | 
    
         
            +
                attr_accessor :output_decorator
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            		def initialize(configuration)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @output_folder = ''
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @project_folder = ''
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @output_decorator = ''
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @include_objects = []
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @include_paths = []
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @library_paths = []
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  add_include_paths(expand_project_relative_paths(configuration.fetch(:include_paths, [])))
         
     | 
| 
      
 25 
     | 
    
         
            +
                  add_include_objects(expand_project_relative_paths(configuration.fetch(:include_objects, [])))
         
     | 
| 
      
 26 
     | 
    
         
            +
                  add_library_paths(expand_project_relative_paths(configuration.fetch(:library_paths, [])))
         
     | 
| 
      
 27 
     | 
    
         
            +
            		end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                # Retrieve a list of additional objects to link with
         
     | 
| 
      
 30 
     | 
    
         
            +
                def get_include_objects
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @include_objects.collect {|i| File.expand_path(i.gsub('$(PROJECT_DIR)', @project_folder))}
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                # Retrieve a list of include paths to compile with
         
     | 
| 
      
 35 
     | 
    
         
            +
                def get_include_paths
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @include_paths.collect {|i| File.expand_path(i.gsub('$(PROJECT_DIR)', @project_folder))}
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                # Retrieve a list of library paths to link with
         
     | 
| 
      
 40 
     | 
    
         
            +
                def get_library_paths
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @library_paths.collect {|i| File.expand_path(i.gsub('$(PROJECT_DIR)', @project_folder))}
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                # Add an additional object to the list of additional objects to link with
         
     | 
| 
      
 45 
     | 
    
         
            +
                def add_include_objects(include_objects)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  include_objects = Utils.ensure_array(include_objects).to_a.flatten
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @include_objects |= include_objects
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                # Add an include path to the list of include paths to compile with
         
     | 
| 
      
 51 
     | 
    
         
            +
                def add_include_paths(include_paths)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  include_paths = Utils.ensure_array(include_paths).to_a.flatten
         
     | 
| 
      
 53 
     | 
    
         
            +
                  @include_paths |= include_paths
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                # Add a library path to the list of library paths to link with
         
     | 
| 
      
 57 
     | 
    
         
            +
                def add_library_paths(library_paths)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  library_paths = Utils.ensure_array(library_paths).to_a.flatten
         
     | 
| 
      
 59 
     | 
    
         
            +
                  @library_paths |= library_paths
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                # Create Rake tasks for compilation
         
     | 
| 
      
 63 
     | 
    
         
            +
                def create_compile_tasks(source_files)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  fail "Toolchain didn't provide create_compile_tasks"
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                # Create Rake tasks for archival
         
     | 
| 
      
 68 
     | 
    
         
            +
                def create_static_library_tasks(objects, library_name)
         
     | 
| 
      
 69 
     | 
    
         
            +
                  fail "Toolchain didn't provide create_static_library_tasks"
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                # Create Rake tasks for linking
         
     | 
| 
      
 73 
     | 
    
         
            +
                def create_application_tasks(objects, executable_name)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  fail "Toolchain didn't provide create_executable_tasks"
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                private
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                def expand_project_relative_paths(paths)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  return Utils.ensure_array(paths).to_a.flatten.collect{ |p| (File.join('$(PROJECT_DIR)', p))}
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                @registered_toolchains = {}
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                def self.register_toolchain(toolchain_name, toolchain_class)
         
     | 
| 
      
 86 
     | 
    
         
            +
                  @registered_toolchains[toolchain_name] = toolchain_class;
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                def self.create_toolchain(toolchain_configuration)
         
     | 
| 
      
 90 
     | 
    
         
            +
                  toolchain_name = toolchain_configuration.fetch(:name, nil)
         
     | 
| 
      
 91 
     | 
    
         
            +
                  fail "error: toolchain name not specified." if toolchain_name.nil?
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                  toolchain_class = @registered_toolchains.fetch(toolchain_name, nil)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  if !toolchain_class
         
     | 
| 
      
 95 
     | 
    
         
            +
                    toolchain_file = File.join('mtbuild', 'toolchains', toolchain_name.to_s)
         
     | 
| 
      
 96 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 97 
     | 
    
         
            +
                      require toolchain_file
         
     | 
| 
      
 98 
     | 
    
         
            +
                    rescue LoadError
         
     | 
| 
      
 99 
     | 
    
         
            +
                    end
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
                  toolchain_class = @registered_toolchains.fetch(toolchain_name, nil)
         
     | 
| 
      
 102 
     | 
    
         
            +
                  fail "error: toolchain #{toolchain_name} could not be found." if toolchain_class.nil?
         
     | 
| 
      
 103 
     | 
    
         
            +
                  return Object::const_get(toolchain_class).new(toolchain_configuration)
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                include Rake::DSL
         
     | 
| 
      
 107 
     | 
    
         
            +
            	end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module MTBuild
         
     | 
| 
      
 2 
     | 
    
         
            +
              require 'mtbuild/toolchains/gcc'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              Toolchain.register_toolchain(:arm_none_eabi_gcc, 'MTBuild::ToolchainArmNoneEabiGcc')
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              # This ToolchainGcc subclass can build using arm-non-eabi-gcc
         
     | 
| 
      
 7 
     | 
    
         
            +
            	class ToolchainArmNoneEabiGcc < ToolchainGcc
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            		def initialize(configuration)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  super
         
     | 
| 
      
 11 
     | 
    
         
            +
            		end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                # Create Rake tasks for linking
         
     | 
| 
      
 14 
     | 
    
         
            +
                def create_application_tasks(objects, executable_name)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  elf_file = File.join(@output_folder, "#{executable_name}#{@output_decorator}.elf")
         
     | 
| 
      
 16 
     | 
    
         
            +
                  bin_file = File.join(@output_folder, "#{executable_name}#{@output_decorator}.bin")
         
     | 
| 
      
 17 
     | 
    
         
            +
                  hex_file = File.join(@output_folder, "#{executable_name}#{@output_decorator}.hex")
         
     | 
| 
      
 18 
     | 
    
         
            +
                  map_file = File.join(@output_folder, "#{executable_name}#{@output_decorator}.map")
         
     | 
| 
      
 19 
     | 
    
         
            +
                  executable_folder = @output_folder
         
     | 
| 
      
 20 
     | 
    
         
            +
                  directory executable_folder
         
     | 
| 
      
 21 
     | 
    
         
            +
                  CLOBBER.include(executable_folder)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  CLOBBER.include(elf_file)
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  all_objects = objects+get_include_objects
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  file elf_file => all_objects do |t|
         
     | 
| 
      
 27 
     | 
    
         
            +
                    command_line = construct_link_command(all_objects, t.name, get_include_paths, get_library_paths, map_file)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    sh command_line
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  file map_file => elf_file
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  file bin_file => elf_file do |t|
         
     | 
| 
      
 34 
     | 
    
         
            +
                    command_line = construct_objcopy_command(elf_file, t.name, ' -Obinary')
         
     | 
| 
      
 35 
     | 
    
         
            +
                    sh command_line
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                  file hex_file => elf_file do |t|
         
     | 
| 
      
 38 
     | 
    
         
            +
                    command_line = construct_objcopy_command(elf_file, t.name, ' -Oihex')
         
     | 
| 
      
 39 
     | 
    
         
            +
                    sh command_line
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  return [elf_file, bin_file, hex_file], [map_file], [executable_folder]
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                private
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                def construct_objcopy_command(input_name, output_name, objcopyflags)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  return "#{objcopy}#{objcopyflags} #{input_name} #{output_name}"
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                def compiler
         
     | 
| 
      
 52 
     | 
    
         
            +
                  return 'arm-none-eabi-gcc'
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                def archiver
         
     | 
| 
      
 56 
     | 
    
         
            +
                  return 'arm-none-eabi-ar'
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                def linker
         
     | 
| 
      
 60 
     | 
    
         
            +
                  return 'arm-none-eabi-gcc'
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                def objcopy
         
     | 
| 
      
 64 
     | 
    
         
            +
                  return 'arm-none-eabi-objcopy'
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            	end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,160 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module MTBuild
         
     | 
| 
      
 2 
     | 
    
         
            +
              require 'mtbuild/toolchain'
         
     | 
| 
      
 3 
     | 
    
         
            +
              require 'mtbuild/utils'
         
     | 
| 
      
 4 
     | 
    
         
            +
              require 'rake/clean'
         
     | 
| 
      
 5 
     | 
    
         
            +
              require 'rake/loaders/makefile'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              Toolchain.register_toolchain(:gcc, 'MTBuild::ToolchainGcc')
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              # This Toolchain subclass can build using GCC
         
     | 
| 
      
 10 
     | 
    
         
            +
            	class ToolchainGcc < Toolchain
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                attr_accessor :cppflags, :cflags, :cxxflags, :asflags, :ldflags, :linker_script
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            		def initialize(configuration)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  super
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 18 
     | 
    
         
            +
                    toolchain_test_output=%x{#{compiler} --version 2>&1}
         
     | 
| 
      
 19 
     | 
    
         
            +
                    toolchain_test_passed=$?.success?
         
     | 
| 
      
 20 
     | 
    
         
            +
                  rescue
         
     | 
| 
      
 21 
     | 
    
         
            +
                    toolchain_test_passed = false
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  fail "Toolchain component #{compiler} not found." unless toolchain_test_passed
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  @compiler_is_LLVM_gcc = toolchain_test_output.include?'LLVM'
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @cppflags = configuration.fetch(:cppflags, '')
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @cflags = configuration.fetch(:cflags, '')
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @cxxflags = configuration.fetch(:cxxflags, '')
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @asflags = configuration.fetch(:asflags, '')
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @ldflags = configuration.fetch(:ldflags, '')
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @linker_script = configuration.fetch(:linker_script, '')
         
     | 
| 
      
 32 
     | 
    
         
            +
            		end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                # Create Rake tasks for compilation
         
     | 
| 
      
 35 
     | 
    
         
            +
                def create_compile_tasks(source_files)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  object_files = []
         
     | 
| 
      
 37 
     | 
    
         
            +
                  object_folders = []
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  source_files.each do |source_file|
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    relative_source_location = Utils::path_difference(@project_folder, File.dirname(source_file))
         
     | 
| 
      
 42 
     | 
    
         
            +
                    fail "Source file #{source_file} must be within #{@project_folder}." if relative_source_location.nil?
         
     | 
| 
      
 43 
     | 
    
         
            +
                    output_folder = File.join(@output_folder, relative_source_location)
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    object_folders << output_folder unless object_folders.include?output_folder
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    directory output_folder
         
     | 
| 
      
 48 
     | 
    
         
            +
                    CLOBBER.include(output_folder)
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    object_file = File.join(output_folder, source_file.pathmap('%n.o'))
         
     | 
| 
      
 51 
     | 
    
         
            +
                    dependency_file = File.join(output_folder, source_file.pathmap('%n.d'))
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                    object_files << object_file
         
     | 
| 
      
 54 
     | 
    
         
            +
                    CLEAN.include(object_file)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    CLEAN.include(dependency_file)
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                    file_type = get_file_type(source_file)
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                    file object_file => [source_file] do |t|
         
     | 
| 
      
 60 
     | 
    
         
            +
                      command_line = construct_compile_command(file_type, [source_file], get_include_paths, t.name)
         
     | 
| 
      
 61 
     | 
    
         
            +
                      sh command_line
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
      
 63 
     | 
    
         
            +
                    Rake::MakefileLoader.new.load(dependency_file) if File.file?(dependency_file)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
                  return object_files, object_folders
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                # Create Rake tasks for archival
         
     | 
| 
      
 69 
     | 
    
         
            +
                def create_static_library_tasks(objects, library_name)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  library_file = File.join(@output_folder, "lib#{library_name}#{@output_decorator}.a")
         
     | 
| 
      
 71 
     | 
    
         
            +
                  library_folder = @output_folder
         
     | 
| 
      
 72 
     | 
    
         
            +
                  directory library_folder
         
     | 
| 
      
 73 
     | 
    
         
            +
                  CLOBBER.include(library_folder)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  CLOBBER.include(library_file)
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  file library_file => objects do |t|
         
     | 
| 
      
 77 
     | 
    
         
            +
                    command_line = construct_archive_command(objects, t.name)
         
     | 
| 
      
 78 
     | 
    
         
            +
                    sh command_line
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
                  return [library_file], [library_folder]
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                # Create Rake tasks for linking
         
     | 
| 
      
 84 
     | 
    
         
            +
                def create_application_tasks(objects, executable_name)
         
     | 
| 
      
 85 
     | 
    
         
            +
                  elf_file = File.join(@output_folder, "#{executable_name}#{@output_decorator}")
         
     | 
| 
      
 86 
     | 
    
         
            +
                  map_file = File.join(@output_folder, "#{executable_name}#{@output_decorator}.map")
         
     | 
| 
      
 87 
     | 
    
         
            +
                  executable_folder = @output_folder
         
     | 
| 
      
 88 
     | 
    
         
            +
                  directory executable_folder
         
     | 
| 
      
 89 
     | 
    
         
            +
                  CLOBBER.include(executable_folder)
         
     | 
| 
      
 90 
     | 
    
         
            +
                  CLOBBER.include(elf_file)
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                  all_objects = objects+get_include_objects
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                  file elf_file => all_objects do |t|
         
     | 
| 
      
 95 
     | 
    
         
            +
                    command_line = construct_link_command(all_objects, t.name, get_include_paths, get_library_paths, map_file)
         
     | 
| 
      
 96 
     | 
    
         
            +
                    sh command_line
         
     | 
| 
      
 97 
     | 
    
         
            +
                  end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  file map_file => elf_file
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                  return [elf_file], [map_file], [executable_folder]
         
     | 
| 
      
 102 
     | 
    
         
            +
                end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                private
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                def get_file_type(source_file)
         
     | 
| 
      
 107 
     | 
    
         
            +
                  file_extension = File.extname(source_file)
         
     | 
| 
      
 108 
     | 
    
         
            +
                  return :cplusplus if ['.cc', '.cp', '.cxx', '.cpp', '.CPP', '.c++', '.C'].include? file_extension
         
     | 
| 
      
 109 
     | 
    
         
            +
                  return :asm if ['.s', '.S', '.sx'].include? file_extension
         
     | 
| 
      
 110 
     | 
    
         
            +
                  return :c
         
     | 
| 
      
 111 
     | 
    
         
            +
                end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                def construct_compile_command(file_type, prerequisites, include_paths, output_name)
         
     | 
| 
      
 114 
     | 
    
         
            +
                  prerequisites_s = prerequisites.empty? ? '' : " #{prerequisites.join(' ')}"
         
     | 
| 
      
 115 
     | 
    
         
            +
                  include_paths_s = include_paths.empty? ? '' : " -I#{include_paths.join(' -I')}"
         
     | 
| 
      
 116 
     | 
    
         
            +
                  cppflags_s = @cppflags.empty? ? '' : " #{@cppflags}"
         
     | 
| 
      
 117 
     | 
    
         
            +
                  cflags_s = @cflags.empty? ? '' : " #{@cflags}"
         
     | 
| 
      
 118 
     | 
    
         
            +
                  cxxflags_s = @cxxflags.empty? ? '' : " #{@cxxflags}"
         
     | 
| 
      
 119 
     | 
    
         
            +
                  asflags_s = @asflags.empty? ? '' : " #{@asflags}"
         
     | 
| 
      
 120 
     | 
    
         
            +
                  return "#{compiler}#{cppflags_s}#{cflags_s}#{prerequisites_s}#{include_paths_s} -MMD -c -o #{output_name}" if file_type == :c
         
     | 
| 
      
 121 
     | 
    
         
            +
                  return "#{compiler}#{cppflags_s}#{cxxflags_s}#{prerequisites_s}#{include_paths_s} -MMD -c -o #{output_name}" if file_type == :cplusplus
         
     | 
| 
      
 122 
     | 
    
         
            +
                  return "#{compiler}#{cppflags_s}#{asflags_s}#{prerequisites_s}#{include_paths_s} -MMD -c -o #{output_name}" if file_type == :asm
         
     | 
| 
      
 123 
     | 
    
         
            +
                end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                def construct_archive_command(prerequisites, output_name)
         
     | 
| 
      
 126 
     | 
    
         
            +
                  prerequisites_s = prerequisites.empty? ? '' : " #{prerequisites.join(' ')}"
         
     | 
| 
      
 127 
     | 
    
         
            +
                  return "#{archiver} rcs #{output_name} #{prerequisites_s}"
         
     | 
| 
      
 128 
     | 
    
         
            +
                end
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                def construct_link_command(prerequisites, output_name, include_paths, library_paths, map_name)
         
     | 
| 
      
 131 
     | 
    
         
            +
                  prerequisites_s = prerequisites.empty? ? '' : " #{prerequisites.join(' ')}"
         
     | 
| 
      
 132 
     | 
    
         
            +
                  include_paths_s = include_paths.empty? ? '' : " -I#{include_paths.join(' -I')}"
         
     | 
| 
      
 133 
     | 
    
         
            +
                  library_paths_s = library_paths.empty? ? '' : " -L#{library_paths.join(' -L')}"
         
     | 
| 
      
 134 
     | 
    
         
            +
                  cppflags_s = @cppflags.empty? ? '' : " #{@cppflags}"
         
     | 
| 
      
 135 
     | 
    
         
            +
                  cflags_s = @cflags.empty? ? '' : " #{@cflags}"
         
     | 
| 
      
 136 
     | 
    
         
            +
                  ldflags_s = @ldflags.empty? ? '' : " #{@ldflags}"
         
     | 
| 
      
 137 
     | 
    
         
            +
                  linker_script_s = @linker_script.empty? ? '' : " -Wl,-T#{File.join(@project_folder,@linker_script)}"
         
     | 
| 
      
 138 
     | 
    
         
            +
                  return "#{compiler}#{cppflags_s}#{cflags_s}#{ldflags_s}#{linker_script_s}#{prerequisites_s}#{include_paths_s} #{map_flag(map_name)} -o #{output_name}"
         
     | 
| 
      
 139 
     | 
    
         
            +
                end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                def map_flag(map_file)
         
     | 
| 
      
 142 
     | 
    
         
            +
                  return "-Wl,-map,#{map_file}" if @compiler_is_LLVM_gcc
         
     | 
| 
      
 143 
     | 
    
         
            +
                  return "-Wl,-Map=#{map_file},--cref"
         
     | 
| 
      
 144 
     | 
    
         
            +
                end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                def compiler
         
     | 
| 
      
 147 
     | 
    
         
            +
                  return 'gcc'
         
     | 
| 
      
 148 
     | 
    
         
            +
                end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                def archiver
         
     | 
| 
      
 151 
     | 
    
         
            +
                  return 'ar'
         
     | 
| 
      
 152 
     | 
    
         
            +
                end
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
                def linker
         
     | 
| 
      
 155 
     | 
    
         
            +
                  return 'gcc'
         
     | 
| 
      
 156 
     | 
    
         
            +
                end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
            	end
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
            end
         
     |