mtbuild 0.0.9 → 0.1.0

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.
@@ -0,0 +1,21 @@
1
+ module MTBuild
2
+ require 'mtbuild/toolchains/arm_none_eabi_gcc'
3
+
4
+ Toolchain.register_toolchain(:arm_none_eabi_gpp, 'MTBuild::ToolchainArmNoneEabiGpp')
5
+
6
+ # This ToolchainGcc subclass can build using arm-non-eabi-g++
7
+ class ToolchainArmNoneEabiGpp < ToolchainArmNoneEabiGcc
8
+
9
+ private
10
+
11
+ def compiler
12
+ return 'arm-none-eabi-g++'
13
+ end
14
+
15
+ def linker
16
+ return 'arm-none-eabi-g++'
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -1,8 +1,8 @@
1
1
  module MTBuild
2
+ require 'mtbuild/cleaner'
2
3
  require 'mtbuild/loaders/makefile'
3
4
  require 'mtbuild/toolchain'
4
5
  require 'mtbuild/utils'
5
- require 'rake/clean'
6
6
 
7
7
  Toolchain.register_toolchain(:gcc, 'MTBuild::ToolchainGcc')
8
8
 
@@ -11,9 +11,11 @@ module MTBuild
11
11
 
12
12
  attr_accessor :cppflags, :cflags, :cxxflags, :asflags, :ldflags, :linker_script
13
13
 
14
- def initialize(configuration)
14
+ def initialize(parent_configuration, toolchain_configuration)
15
15
  super
16
16
 
17
+ @tracked_folders = []
18
+
17
19
  begin
18
20
  toolchain_test_output=%x{#{compiler} --version 2>&1}
19
21
  toolchain_test_passed=$?.success?
@@ -23,12 +25,12 @@ module MTBuild
23
25
  fail "Toolchain component #{compiler} not found." unless toolchain_test_passed
24
26
 
25
27
  @compiler_is_LLVM_gcc = toolchain_test_output.include?'LLVM'
26
- @cppflags = Utils.ensure_array(configuration.fetch(:cppflags, '')).to_a.flatten.join(' ')
27
- @cflags = Utils.ensure_array(configuration.fetch(:cflags, '')).to_a.flatten.join(' ')
28
- @cxxflags = Utils.ensure_array(configuration.fetch(:cxxflags, '')).to_a.flatten.join(' ')
29
- @asflags = Utils.ensure_array(configuration.fetch(:asflags, '')).to_a.flatten.join(' ')
30
- @ldflags = Utils.ensure_array(configuration.fetch(:ldflags, '')).to_a.flatten.join(' ')
31
- @linker_script = configuration.fetch(:linker_script, '')
28
+ @cppflags = Utils.ensure_array(toolchain_configuration.fetch(:cppflags, '')).to_a.flatten.join(' ')
29
+ @cflags = Utils.ensure_array(toolchain_configuration.fetch(:cflags, '')).to_a.flatten.join(' ')
30
+ @cxxflags = Utils.ensure_array(toolchain_configuration.fetch(:cxxflags, '')).to_a.flatten.join(' ')
31
+ @asflags = Utils.ensure_array(toolchain_configuration.fetch(:asflags, '')).to_a.flatten.join(' ')
32
+ @ldflags = Utils.ensure_array(toolchain_configuration.fetch(:ldflags, '')).to_a.flatten.join(' ')
33
+ @linker_script = toolchain_configuration.fetch(:linker_script, '')
32
34
  end
33
35
 
34
36
  # Create Rake tasks for compilation
@@ -44,15 +46,17 @@ module MTBuild
44
46
 
45
47
  object_folders << output_folder unless object_folders.include?output_folder
46
48
 
47
- directory output_folder
48
- CLOBBER.include(output_folder)
49
+ unless @tracked_folders.include?output_folder
50
+ @tracked_folders << output_folder
51
+ directory output_folder
52
+ @parent_configuration.parent_project.add_files_to_clean(output_folder)
53
+ end
49
54
 
50
55
  object_file = File.join(output_folder, source_file.pathmap('%n.o'))
51
56
  dependency_file = File.join(output_folder, source_file.pathmap('%n.d'))
52
57
 
53
58
  object_files << object_file
54
- CLEAN.include(object_file)
55
- CLEAN.include(dependency_file)
59
+ @parent_configuration.parent_project.add_files_to_clean(object_file, dependency_file)
56
60
 
57
61
  file_type = get_file_type(source_file)
58
62
 
@@ -72,9 +76,14 @@ module MTBuild
72
76
  def create_static_library_tasks(objects, library_name)
73
77
  library_file = File.join(@output_folder, "lib#{library_name}#{@output_decorator}.a")
74
78
  library_folder = @output_folder
75
- directory library_folder
76
- CLOBBER.include(library_folder)
77
- CLOBBER.include(library_file)
79
+
80
+ unless @tracked_folders.include?library_folder
81
+ @tracked_folders << library_folder
82
+ directory library_folder
83
+ @parent_configuration.parent_project.add_files_to_clean(library_folder)
84
+ end
85
+
86
+ @parent_configuration.parent_project.add_files_to_clean(library_file)
78
87
 
79
88
  file library_file => objects do |t|
80
89
  command_line = construct_archive_command(objects, t.name)
@@ -88,9 +97,14 @@ module MTBuild
88
97
  elf_file = File.join(@output_folder, "#{executable_name}#{@output_decorator}")
89
98
  map_file = File.join(@output_folder, "#{executable_name}#{@output_decorator}.map")
90
99
  executable_folder = @output_folder
91
- directory executable_folder
92
- CLOBBER.include(executable_folder)
93
- CLOBBER.include(elf_file)
100
+
101
+ unless @tracked_folders.include?executable_folder
102
+ @tracked_folders << executable_folder
103
+ directory executable_folder
104
+ @parent_configuration.parent_project.add_files_to_clean(executable_folder)
105
+ end
106
+
107
+ @parent_configuration.parent_project.add_files_to_clean(map_file, elf_file)
94
108
 
95
109
  all_objects = objects+get_include_objects
96
110
 
@@ -0,0 +1,21 @@
1
+ module MTBuild
2
+ require 'mtbuild/toolchains/gcc'
3
+
4
+ Toolchain.register_toolchain(:gpp, 'MTBuild::ToolchainGpp')
5
+
6
+ # This ToolchainGcc subclass can build using g++
7
+ class ToolchainGpp < ToolchainGcc
8
+
9
+ private
10
+
11
+ def compiler
12
+ return 'g++'
13
+ end
14
+
15
+ def linker
16
+ return 'g++'
17
+ end
18
+
19
+ end
20
+
21
+ end
data/lib/mtbuild/utils.rb CHANGED
@@ -2,7 +2,6 @@ module MTBuild
2
2
 
3
3
  module Utils
4
4
 
5
- require 'rake'
6
5
  require 'pathname'
7
6
 
8
7
  def self.path_difference(root, subdir)
@@ -3,7 +3,8 @@ module MTBuild
3
3
  # Use this class to create a workspace
4
4
  class Workspace
5
5
  require 'mtbuild/utils'
6
- require 'rake/clean'
6
+ require 'mtbuild/build_registry'
7
+ require 'mtbuild/cleaner'
7
8
 
8
9
  # The workspace's name
9
10
  attr_reader :workspace_name
@@ -15,40 +16,93 @@ module MTBuild
15
16
  # The workspace's output folder
16
17
  attr_reader :output_folder
17
18
 
19
+ # The workspace's parent workspace
20
+ attr_reader :parent_workspace
21
+
22
+ # Workspace configuration defaults
23
+ attr_reader :configuration_defaults
24
+
25
+ # List of configuration defaults that child workspaces should take from
26
+ # this workspace
27
+ attr_reader :push_configuration_defaults
28
+
29
+ # List of default tasks to build with this workspace
30
+ attr_reader :default_tasks
31
+
18
32
  def initialize(workspace_name, workspace_folder, &configuration_block)
19
- @workspace_name = workspace_name
20
33
  @workspace_folder = File.expand_path(workspace_folder)
21
34
  @output_folder = File.expand_path(File.join(@workspace_folder, MTBuild.default_output_folder))
22
35
  @projects = []
36
+ @workspaces = []
23
37
  @default_tasks = []
38
+ @configuration_defaults = {}
39
+ @child_workspaces = {}
40
+ @push_configuration_defaults = []
41
+ @workspace_name, @parent_workspace = MTBuild::BuildRegistry.enter_workspace(workspace_name, self)
24
42
 
25
- # Only process the first workspace found.
26
- # Subsequent workspaces will be ignored
27
- if MTBuild::Workspace.workspace.nil?
28
- MTBuild::Workspace.set_workspace(self)
43
+ unless @parent_workspace.nil?
44
+ pull_configuration_defaults(@parent_workspace, @parent_workspace.push_configuration_defaults)
45
+ end
29
46
 
30
- configuration_block.call(self) if configuration_block
47
+ configuration_block.call(self) if configuration_block
31
48
 
32
- @projects.each do |project|
33
- require project
49
+ # If there's a parent workspace, use its output folder.
50
+ # Don't use the current workspace's output folder.
51
+ @output_folder = @parent_workspace.output_folder unless @parent_workspace.nil?
52
+
53
+ @workspaces.each do |workspace|
54
+ MTBuild::BuildRegistry.expect_workspace
55
+ @push_configuration_defaults = workspace[:push_cfg]
56
+ require workspace[:build_file]
57
+ last_workspace = MTBuild::BuildRegistry.reenter_workspace(self)
58
+ unless last_workspace.nil?
59
+ pull_configuration_defaults(last_workspace, workspace[:pull_cfg])
60
+ @default_tasks+=last_workspace.default_tasks if workspace[:pull_tasks]
34
61
  end
62
+ end
35
63
 
36
- CLOBBER.include(@output_folder)
64
+ @projects.each do |project|
65
+ MTBuild::BuildRegistry.expect_project
66
+ require project
67
+ end
37
68
 
38
- task :workspace do
39
- puts "built workspace #{@workspace_name}"
40
- end
69
+ Cleaner.global_clean_list.include(@output_folder)
41
70
 
42
- task :default => @default_tasks+[:workspace]
71
+ # Only register default tasks and generate global clean if we're the top-level workspace.
72
+ if @parent_workspace.nil?
73
+ task :default => @default_tasks
74
+ Cleaner.generate_global_clean_task
43
75
  end
76
+
77
+ MTBuild::BuildRegistry.exit_workspace
78
+ end
79
+
80
+ # Adds a workspace subfolder
81
+ def add_workspace(workspace_location, pull_default_tasks: false, pull_configurations: [], push_configurations: [])
82
+ new_workspaces = []
83
+ Utils.expand_folder_list(workspace_location, @workspace_folder).each do |workspace_path|
84
+ if File.directory? workspace_path
85
+ workspace_rakefile = MTBuild::Workspace.find_build_file(workspace_path)
86
+ unless workspace_rakefile.nil?
87
+ new_workspaces << {
88
+ :build_file=>workspace_rakefile,
89
+ :pull_tasks=>pull_default_tasks,
90
+ :pull_cfg=>pull_configurations,
91
+ :push_cfg=>push_configurations
92
+ }
93
+ end
94
+ end
95
+ end
96
+ $stderr.puts "Could not find a valid workspace at '#{workspace_location}'. Ignored." if new_workspaces.empty?
97
+ @workspaces += new_workspaces
44
98
  end
45
99
 
46
100
  # Adds a project subfolder
47
101
  def add_project(project_location)
48
102
  new_projects = []
49
- Utils.expand_folder_list(project_location, Rake.original_dir).each do |project_path|
103
+ Utils.expand_folder_list(project_location, @workspace_folder).each do |project_path|
50
104
  if File.directory? project_path
51
- project_rakefile = MTBuild::Workspace.find_mtbuildfile(project_path)
105
+ project_rakefile = MTBuild::Workspace.find_build_file(project_path)
52
106
  new_projects << project_rakefile unless project_rakefile.nil?
53
107
  end
54
108
  end
@@ -56,14 +110,22 @@ module MTBuild
56
110
  @projects += new_projects
57
111
  end
58
112
 
59
- # Adds tasks to be run by default when MTBuild is invoked with no arguments.
113
+ # Adds tasks to be run by default when MTBuild is invoked with no arguments. This method
114
+ # expects only MTBuild tasks and will namespace them according to the current workspace
115
+ # hierarchy.
60
116
  def add_default_tasks(default_tasks)
117
+ @default_tasks |= Utils.ensure_array(default_tasks).flatten.collect {|default_task| "#{@workspace_name}:#{default_task}"}
118
+ end
119
+
120
+ # Adds Rake tasks to be run by default when MTBuild is invoked with no arguments. This method
121
+ # will not namespace the tasks, so it can be used to specify plain Rake task names.
122
+ def add_default_rake_tasks(default_tasks)
61
123
  @default_tasks |= Utils.ensure_array(default_tasks).flatten
62
124
  end
63
125
 
64
126
  # Sets defaults for all configurations with the specified name
65
127
  def set_configuration_defaults(configuration_name, defaults_hash)
66
- Workspace.set_configuration_defaults(configuration_name, defaults_hash)
128
+ @configuration_defaults[configuration_name] = defaults_hash
67
129
  end
68
130
 
69
131
  # Sets the build output folder location
@@ -71,45 +133,16 @@ module MTBuild
71
133
  @output_folder = File.expand_path(File.join(@workspace_folder,output_folder))
72
134
  end
73
135
 
74
- @workspace = nil
75
-
76
- # The singleton workspace instance
77
- def self.workspace
78
- return @workspace
79
- end
80
-
81
- # Sets the singleton workspace instance
82
- def self.set_workspace(workspace)
83
- @workspace = workspace
84
- end
85
-
86
- # Queries whether a workspace exists
87
- def self.have_workspace?
88
- return !@workspace.nil?
89
- end
90
-
91
- # Add default tasks to the singleton workspace instance
136
+ # Add default tasks to the last active workspace
92
137
  def self.add_default_tasks(default_tasks)
93
- @workspace.add_default_tasks(default_tasks) unless @workspace.nil?
138
+ MTBuild::BuildRegistry.active_workspace.add_default_rake_tasks(default_tasks) unless MTBuild::BuildRegistry.active_workspace.nil?
94
139
  end
95
140
 
96
- @configuration_defaults = {}
97
-
98
- # Gets the singleton configuration defaults
99
- def self.configuration_defaults
100
- return @configuration_defaults
101
- end
102
-
103
- # Adds or updates defaults to the singleton configuration defaults
104
- def self.set_configuration_defaults(configuration_name, defaults_hash)
105
- @configuration_defaults[configuration_name] = defaults_hash
106
- end
107
-
108
- def self.find_mtbuildfile(project_path)
141
+ def self.find_build_file(project_path)
109
142
  Rake.application.rakefiles.each do |fn|
110
- mtbuildfile = File.join(project_path, fn)
111
- if File.file? mtbuildfile
112
- return mtbuildfile
143
+ build_file = File.join(project_path, fn)
144
+ if File.file? build_file
145
+ return build_file
113
146
  end
114
147
  end
115
148
  return nil
@@ -117,6 +150,21 @@ module MTBuild
117
150
 
118
151
  include Rake::DSL
119
152
 
153
+ private
154
+
155
+ # pulls specific configuration defaults from a workspace
156
+ def pull_configuration_defaults(workspace, configurations_to_pull)
157
+ configurations_to_pull.each do |configuration_name|
158
+ if workspace.configuration_defaults.has_key?(configuration_name)
159
+ child_config = workspace.configuration_defaults[configuration_name]
160
+ my_config = @configuration_defaults.fetch(configuration_name, {})
161
+ @configuration_defaults[configuration_name] = MTBuild::Utils.merge_configurations(my_config, child_config)
162
+ else
163
+ $stderr.puts "Warning: workspace '#{workspace.workspace_name}' does not have a configuration named #{configuration_name} to retrieve. Ignored."
164
+ end
165
+ end
166
+ end
167
+
120
168
  end
121
169
 
122
170
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mtbuild
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jerry Ryle
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-17 00:00:00.000000000 Z
11
+ date: 2015-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -104,6 +104,8 @@ files:
104
104
  - lib/mtbuild/application_configuration.rb
105
105
  - lib/mtbuild/application_project.rb
106
106
  - lib/mtbuild/application_task.rb
107
+ - lib/mtbuild/build_registry.rb
108
+ - lib/mtbuild/cleaner.rb
107
109
  - lib/mtbuild/compiled_configuration.rb
108
110
  - lib/mtbuild/configuration.rb
109
111
  - lib/mtbuild/dsl.rb
@@ -123,7 +125,9 @@ files:
123
125
  - lib/mtbuild/test_application_task.rb
124
126
  - lib/mtbuild/toolchain.rb
125
127
  - lib/mtbuild/toolchains/arm_none_eabi_gcc.rb
128
+ - lib/mtbuild/toolchains/arm_none_eabi_gpp.rb
126
129
  - lib/mtbuild/toolchains/gcc.rb
130
+ - lib/mtbuild/toolchains/gpp.rb
127
131
  - lib/mtbuild/utils.rb
128
132
  - lib/mtbuild/version.rb
129
133
  - lib/mtbuild/versioner.rb
@@ -145,7 +149,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
145
149
  requirements:
146
150
  - - ">="
147
151
  - !ruby/object:Gem::Version
148
- version: 1.9.1
152
+ version: 2.0.0
149
153
  required_rubygems_version: !ruby/object:Gem::Requirement
150
154
  requirements:
151
155
  - - ">="