teapot 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.2"
4
+ - "1.9.3"
5
+ - rbx-19mode
data/Gemfile CHANGED
@@ -2,3 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in teapot.gemspec
4
4
  gemspec
5
+
6
+ group :test do
7
+ gem "rake"
8
+ end
data/README.md CHANGED
@@ -4,6 +4,8 @@ Teapot is a tool for managing complex cross-platform builds. It provides
4
4
  advanced dependency management via the Teapot file and is supported by
5
5
  the infusions ecosystem of packages and platform tooling.
6
6
 
7
+ [![Build Status](https://secure.travis-ci.org/ioquatix/teapot.png)](http://travis-ci.org/ioquatix/teapot)
8
+
7
9
  ## Installation
8
10
 
9
11
  Add this line to your application's Gemfile:
@@ -20,7 +22,50 @@ Or install it yourself as:
20
22
 
21
23
  ## Usage
22
24
 
23
- TODO: Write usage instructions here
25
+ Create a Teapot file in the root directory of your project:
26
+
27
+ source "https://github.com/infusions"
28
+
29
+ host /linux/ do
30
+ platform "linux"
31
+ end
32
+
33
+ host /darwin/ do
34
+ platform "darwin-osx"
35
+ end
36
+
37
+ package "png"
38
+ package "freetype"
39
+ package "vorbis"
40
+ package "ogg"
41
+ package "jpeg"
42
+
43
+ Then run
44
+
45
+ $ teapot install
46
+
47
+ This will download and compile all the selected packages into the `build` directory.
48
+
49
+ ### CMake ###
50
+
51
+ To use these packages in a CMake project, update your `CMakeLists.txt`:
52
+
53
+ list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/build/${TEAPOT_PLATFORM}/")
54
+
55
+ Then configure like so:
56
+
57
+ cmake path/to/src -DTEAPOT_PLATFORM=linux
58
+
59
+ ### Xcode ###
60
+
61
+ To use these packages in an Xcode project, creating a custom `teapot.xcconfig` is recommended:
62
+
63
+ TEAPOT_PLATFORM=darwin-osx
64
+ TEAPOT_PREFIX_PATH=$(SRCROOT)/build/$(TEAPOT_PLATFORM)
65
+
66
+ // Search paths:
67
+ HEADER_SEARCH_PATHS=$(inherited) "$(TEAPOT_PREFIX_PATH)/include"
68
+ LIBRARY_SEARCH_PATHS=$(inherited) "$(TEAPOT_PREFIX_PATH)/lib"
24
69
 
25
70
  ## Contributing
26
71
 
data/Rakefile CHANGED
@@ -1 +1,9 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ end
7
+
8
+ desc "Run tests"
9
+ task :default => :test
data/bin/teapot CHANGED
@@ -30,7 +30,7 @@ $app = Rake.application = Rake::Application.new
30
30
  $app.init('teapot')
31
31
 
32
32
  task :fetch do
33
- config = Teapot::Config.load
33
+ config = Teapot::Config.load_default
34
34
  context = Teapot::Context.new(config)
35
35
 
36
36
  base_uri = URI(config.options[:source].to_s + '/')
@@ -38,10 +38,10 @@ task :fetch do
38
38
  config.records.each do |record|
39
39
  destination_path = record.destination_path
40
40
 
41
- $stderr.puts "Fetching #{record}...".color(:blue)
41
+ puts "Fetching #{record}...".color(:blue)
42
42
 
43
43
  unless File.exist? destination_path
44
- $stderr.puts "Cloning package at path #{destination_path} ...".color(:green)
44
+ puts "Cloning package at path #{destination_path} ...".color(:green)
45
45
 
46
46
  source_uri = URI(record.uri)
47
47
 
@@ -53,59 +53,127 @@ task :fetch do
53
53
  source_uri = source_uri.path
54
54
  end
55
55
 
56
- sh("git", "clone", source_uri.to_s, destination_path.to_s)
56
+ Teapot::Commands.run("git", "clone", "--recursive", source_uri.to_s, destination_path.to_s)
57
57
  else
58
- $stderr.puts "Updating package at path #{destination_path} ...".color(:green)
58
+ puts "Updating package at path #{destination_path} ...".color(:green)
59
59
 
60
60
  Dir.chdir(destination_path) do
61
- sh("git", "pull")
61
+ Teapot::Commands.run("git", "pull")
62
+ Teapot::Commands.run("git", "submodule", "update", "--init")
62
63
  end
63
64
  end
64
65
  end
65
66
  end
66
67
 
67
- task :install => :fetch do
68
- config = Teapot::Config.load
68
+ task :build do
69
+ config = Teapot::Config.load_default
69
70
  context = Teapot::Context.new(config)
70
71
 
71
72
  config.records.each do |record|
72
- $stderr.puts "Installing #{record.name}...".color(:blue)
73
-
74
- record.load(context).each do |bundle|
75
- if bundle.respond_to? :fetch_location
76
- location = bundle.fetch_location
77
-
78
- if !location
79
- puts "Could not determine fetch location for #{name}!".color(:red)
80
- elsif File.exist? bundle.source_path
81
- puts "Source path #{bundle.source_path} already exists!".color(:red)
82
- else
83
- url = location[:url]
84
- local_path = bundle.path + (location[:filename] || File.basename(url))
73
+ destination_path = record.destination_path
74
+
75
+ bundles = record.load(context)
76
+
77
+ bundles.each do |bundle|
85
78
 
86
- puts "Local path: #{local_path}"
79
+ end
80
+ end
81
+ end
82
+
83
+ task :build do |task, arguments|
84
+ config = Teapot::Config.load_default
85
+ context = Teapot::Context.new(config)
86
+
87
+ config.records.each do |record|
88
+ destination_path = record.destination_path
89
+
90
+ record.load(context)
91
+ end
92
+
93
+ build_package = ENV['PACKAGE']
94
+ build_platform = ENV['PLATFORM']
95
+
96
+ if build_package
97
+ package = context.packages[build_package]
98
+
99
+ unless package
100
+ puts "Could not find package #{build_package}".color(:red)
87
101
 
88
- unless bundle.source_path.exist?
89
- unless local_path.exist?
90
- puts "Downloading #{bundle.name} to #{local_path}..."
91
- sh("curl", "-L", url, "-o", local_path.to_s)
92
- end
102
+ next
103
+ end
104
+
105
+ packages = [package]
106
+ else
107
+ packages = context.packages.values
108
+ end
109
+
110
+ if build_platform
111
+ platform = context.platforms[build_platform.to_sym]
112
+
113
+ unless platform
114
+ puts "Could not find platform #{build_platform}".color(:red)
93
115
 
94
- puts "Extracting #{bundle.name}..."
95
- sh("mkdir", bundle.source_path.to_s)
96
- sh("tar", "-C", bundle.source_path.to_s, "--strip-components", "1", "-xvf", local_path.to_s)
97
- end
98
- end
99
- end
116
+ next
100
117
  end
118
+
119
+ platforms = [platform]
120
+ end
121
+
122
+ unless ENV['ONLY']
123
+ ordered = Teapot::Package.build_order(context.packages, packages)
124
+ else
125
+ ordered = packages
126
+ end
127
+
128
+ puts "Building #{ordered.join(', ')} for variant #{config.variant}".color(:blue)
129
+
130
+ context.platforms.each do |name, platform|
131
+ next unless platform.available?
132
+
133
+ puts "Building for #{platform}...".color(:blue)
134
+
135
+ platform.prepare!
136
+
137
+ ordered.each do |package|
138
+ package.build!(platform, :variant => config.variant)
139
+ end
140
+ end
141
+
142
+ puts "Completed build successfully.".color(:green)
143
+ end
144
+
145
+ task :list do
146
+ config = Teapot::Config.load_default
147
+ context = Teapot::Context.new(config)
148
+
149
+ config.records.each do |record|
150
+ destination_path = record.destination_path
151
+
152
+ record.load(context)
153
+ end
154
+
155
+ ordered = Teapot::Package::build_order(context.packages, context.packages.values)
156
+
157
+ ordered.each do |package|
158
+ puts "Package: #{package.name}"
159
+
160
+ if package.depends.size > 0
161
+ puts " (depends on #{package.depends.join(', ')})"
162
+ end
163
+ end
164
+
165
+ context.platforms.each do |platform|
166
+ puts "Platform: #{platform.name}"
101
167
  end
102
168
  end
103
169
 
104
170
  task :help do
105
- $stderr.puts "To create a new teapot, use the setup task:"
106
- $stderr.puts "$ #{File.basename($0)} setup project-path"
171
+ puts "To create a new teapot, use the setup task:"
172
+ puts "$ #{File.basename($0)} setup project-path"
107
173
  end
108
174
 
175
+ task :install => [:fetch, :build]
176
+
109
177
  task :default => :help
110
178
 
111
179
  $app.top_level
@@ -0,0 +1,32 @@
1
+ # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'rainbow'
22
+
23
+ module Teapot
24
+ module Commands
25
+ def self.run(*args)
26
+ args.collect!(&:to_s)
27
+
28
+ puts args.join(' ').color(:blue)
29
+ system(*args)
30
+ end
31
+ end
32
+ end
data/lib/teapot/config.rb CHANGED
@@ -21,6 +21,8 @@
21
21
  require 'pathname'
22
22
 
23
23
  require 'teapot/context'
24
+ require 'teapot/environment'
25
+ require 'teapot/commands'
24
26
 
25
27
  module Teapot
26
28
  class Config
@@ -42,12 +44,14 @@ module Teapot
42
44
  end
43
45
 
44
46
  @options = options
47
+ @global = Environment.new
45
48
  end
46
49
 
47
50
  attr :klass
48
51
  attr :name
49
52
  attr :uri
50
53
  attr :options
54
+ attr :global
51
55
 
52
56
  def load(context)
53
57
  context.load(self)
@@ -84,6 +88,8 @@ module Teapot
84
88
 
85
89
  @packages = []
86
90
  @platforms = []
91
+
92
+ @environment = Environment.new
87
93
  end
88
94
 
89
95
  def packages_path
@@ -98,9 +104,34 @@ module Teapot
98
104
  @root + (@options[:build_path] || "build")
99
105
  end
100
106
 
107
+ def variant(*args, &block)
108
+ name = @options[:variant] || 'debug'
109
+
110
+ if block_given?
111
+ if args.find{|arg| arg === name}
112
+ yield
113
+ end
114
+ else
115
+ name
116
+ end
117
+ end
118
+
119
+ def host(*args, &block)
120
+ name = @options[:host_platform] || RUBY_PLATFORM
121
+
122
+ if block_given?
123
+ if args.find{|arg| arg === name}
124
+ yield
125
+ end
126
+ else
127
+ name
128
+ end
129
+ end
130
+
101
131
  attr :options
102
132
  attr :packages
103
133
  attr :platforms
134
+ attr :environment
104
135
 
105
136
  def source(path)
106
137
  @options[:source] = path
@@ -115,10 +146,11 @@ module Teapot
115
146
  end
116
147
 
117
148
  def platform(name, options = {})
149
+ options = {:environment => @environment}.merge(options)
118
150
  @platforms << Record.new(self, Platform, name, options)
119
151
  end
120
152
 
121
- def self.load(root = Dir.getwd, options = {})
153
+ def self.load(root, options = {})
122
154
  config = new(root, options)
123
155
 
124
156
  teapot_path = File.join(root, "Teapot")
@@ -129,5 +161,11 @@ module Teapot
129
161
 
130
162
  return config
131
163
  end
164
+
165
+ def self.load_default(root = Dir.getwd, options = {})
166
+ options.merge!(:variant => ENV['TEAPOT_VARIANT'])
167
+
168
+ load(root, options)
169
+ end
132
170
  end
133
171
  end
@@ -19,13 +19,12 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  require 'pathname'
22
+ require 'rainbow'
22
23
 
23
24
  require 'teapot/package'
24
25
  require 'teapot/platform'
25
26
 
26
27
  module Teapot
27
- PACKAGE_FILE = "package.rb"
28
-
29
28
  class Context
30
29
  def initialize(config)
31
30
  @config = config
@@ -41,6 +40,7 @@ module Teapot
41
40
  attr :platforms
42
41
 
43
42
  def load(record)
43
+ @record = record
44
44
  @defined = []
45
45
 
46
46
  path = (record.destination_path + record.loader_path).to_s
@@ -49,8 +49,8 @@ module Teapot
49
49
  @defined
50
50
  end
51
51
 
52
- def define_package(name, &block)
53
- package = Package.new(self, name)
52
+ def define_package(*args, &block)
53
+ package = Package.new(self, @record, *args)
54
54
 
55
55
  yield(package)
56
56
 
@@ -59,8 +59,8 @@ module Teapot
59
59
  @defined << package
60
60
  end
61
61
 
62
- def define_platform(name, &block)
63
- platform = Platform.new(self, name)
62
+ def define_platform(*args, &block)
63
+ platform = Platform.new(self, @record, *args)
64
64
 
65
65
  yield(platform)
66
66
 
@@ -70,5 +70,9 @@ module Teapot
70
70
 
71
71
  @defined << platform
72
72
  end
73
+
74
+ def global name
75
+ @config.environment[name]
76
+ end
73
77
  end
74
78
  end
@@ -0,0 +1,232 @@
1
+ # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'pathname'
22
+ require 'rainbow'
23
+
24
+ require 'rexec'
25
+ require 'yaml'
26
+
27
+ require 'teapot/package'
28
+ require 'teapot/platform'
29
+ require 'teapot/commands'
30
+
31
+ module Teapot
32
+ class Environment
33
+ Default = Struct.new(:value)
34
+
35
+ class Constructor
36
+ def initialize(environment)
37
+ @environment = environment
38
+ end
39
+
40
+ def method_missing(name, value = nil, &block)
41
+ if block_given?
42
+ @environment[name] = block
43
+ else
44
+ @environment[name] = value
45
+ end
46
+
47
+ name
48
+ end
49
+
50
+ def [] key
51
+ @environment[key]
52
+ end
53
+
54
+ def default(name)
55
+ @environment[name] = Default.new(@environment[name])
56
+ end
57
+ end
58
+
59
+ class Evaluator
60
+ def initialize(environment)
61
+ @environment = environment
62
+ end
63
+
64
+ def method_missing(name)
65
+ object_value(@environment[name])
66
+ end
67
+
68
+ private
69
+
70
+ # Compute the literal object value for a given key:
71
+ def object_value(value)
72
+ case value
73
+ when Array
74
+ value.collect{|item| object_value(item)}
75
+ when Symbol
76
+ object_value(@values[value])
77
+ when Proc
78
+ object_value(instance_eval(&value))
79
+ when Default
80
+ object_value(value.value)
81
+ else
82
+ value
83
+ end
84
+ end
85
+ end
86
+
87
+ def self.combine(*environments)
88
+ # Flatten the list of environments:
89
+ environments = environments.collect do |environment|
90
+ if Environment === environment
91
+ environment.to_a
92
+ else
93
+ environment
94
+ end
95
+ end.flatten
96
+
97
+ # Resequence based on order:
98
+ first = Environment.new(nil, environments.shift)
99
+ top = first
100
+
101
+ environments.each do |tail|
102
+ top = Environment.new(top, tail)
103
+ end
104
+
105
+ return top
106
+ end
107
+
108
+ def initialize(parent = nil, values = nil, &block)
109
+ @values = (values || {}).to_hash
110
+ @parent = parent
111
+
112
+ @evaluator = Evaluator.new(self)
113
+
114
+ if block_given?
115
+ construct(&block)
116
+ end
117
+ end
118
+
119
+ def construct(&block)
120
+ Constructor.new(self).instance_eval(&block)
121
+ end
122
+
123
+ def dup
124
+ self.class.new(@values)
125
+ end
126
+
127
+ attr :values
128
+ attr :parent
129
+
130
+ def [] (key)
131
+ environment = lookup(key)
132
+
133
+ environment ? environment.values[key] : nil
134
+ end
135
+
136
+ def []= (key, value)
137
+ @values[key] = value
138
+ end
139
+
140
+ def to_hash
141
+ @values
142
+ end
143
+
144
+ def flatten
145
+ hash = {}
146
+
147
+ flatten_to_hash(hash)
148
+
149
+ Environment.new(nil, hash)
150
+ end
151
+
152
+ def to_string_hash
153
+ Hash[@values.map{|key, value| [key.to_s.upcase, string_value(value)]}]
154
+ end
155
+
156
+ def use(options = {}, &block)
157
+ system_environment = flatten.to_string_hash
158
+
159
+ puts YAML::dump(system_environment).color(:magenta)
160
+
161
+ Dir.chdir(options[:in] || ".") do
162
+ RExec.env(system_environment) do
163
+ @evaluator.instance_eval(&block)
164
+ end
165
+ end
166
+ end
167
+
168
+ def to_s
169
+ "<#{self.class} #{self.values}>"
170
+ end
171
+
172
+ def to_a
173
+ flat = []
174
+
175
+ flatten_to_array(flat)
176
+
177
+ return flat
178
+ end
179
+
180
+ protected
181
+
182
+ def flatten_to_array(array)
183
+ if @parent
184
+ @parent.flatten_to_array(array)
185
+ end
186
+
187
+ array << self
188
+ end
189
+
190
+ def flatten_to_hash(hash)
191
+ if @parent
192
+ @parent.flatten_to_hash(hash)
193
+ end
194
+
195
+ @values.each do |key, value|
196
+ previous = hash[key]
197
+
198
+ if Array === previous
199
+ hash[key] = previous + Array(value)
200
+ elsif Default == previous
201
+ hash[key] ||= previous
202
+ else
203
+ hash[key] = value
204
+ end
205
+ end
206
+ end
207
+
208
+ # Compute the literal string value for a given key:
209
+ def string_value(value)
210
+ case value
211
+ when Array
212
+ value.collect{|item| string_value(item)}.join(' ')
213
+ when Symbol
214
+ string_value(@values[value])
215
+ when Proc
216
+ string_value(@evaluator.instance_eval(&value))
217
+ when Default
218
+ string_value(value.value)
219
+ else
220
+ value.to_s
221
+ end
222
+ end
223
+
224
+ def lookup(name)
225
+ if @values.include? name
226
+ self
227
+ elsif @parent
228
+ @parent.lookup(name)
229
+ end
230
+ end
231
+ end
232
+ end
@@ -1,82 +1,71 @@
1
+ # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
1
20
 
2
21
  require 'pathname'
3
22
 
4
23
  module Teapot
5
- class Package
6
- class BuildError < StandardError
24
+ class BuildError < StandardError
25
+ end
26
+
27
+ class Task
28
+ def initialize
29
+ @callbacks = {}
7
30
  end
8
-
9
- class Task
10
- def initialize
11
- @callbacks = {}
12
- end
13
31
 
14
- def define(name, &callback)
15
- @callbacks[name] = callback
16
- end
17
-
18
- def [](name)
19
- @callbacks[name] || @callbacks[:all]
20
- end
32
+ def define(name, &callback)
33
+ @callbacks[name] = callback
21
34
  end
22
-
23
- def self.build_order(available, packages)
24
- ordered = []
25
-
26
- expand = lambda do |name|
27
- package = available[name]
28
-
29
- unless package
30
- puts "Couldn't resolve #{name}"
31
- else
32
- package.depends.each do |dependency|
33
- expand.call(dependency)
34
- end
35
-
36
- unless ordered.include? package
37
- ordered << package
38
- end
39
- end
40
- end
41
-
42
- packages.each do |package|
43
- expand.call(package.name)
44
- end
45
-
46
- return ordered
35
+
36
+ def [](name)
37
+ @callbacks[name] || @callbacks[:all]
47
38
  end
48
-
49
- def initialize(context, name, path = nil)
39
+ end
40
+
41
+ class Package
42
+ def initialize(context, record, name)
50
43
  @context = context
51
-
44
+ @record = record
45
+
52
46
  parts = name.split('-')
53
47
  @name = parts[0..-2].join('-')
54
48
  @version = parts[-1]
55
49
 
56
- @path = path || (context.config.packages_path + @name)
57
-
58
50
  @build = Task.new
59
51
 
60
52
  @depends = []
61
53
 
54
+ @path = @record.destination_path
62
55
  @source_path = @path + name
63
- @fetch_location = nil
64
56
  end
65
57
 
58
+ attr :context
59
+ attr :record
60
+
66
61
  attr :name
67
62
  attr :version
63
+
68
64
  attr :path
69
- attr :variants
70
- attr :fetch_location
71
65
 
72
66
  attr :depends, true
73
67
  attr :source_path, true
74
68
 
75
- def install!
76
- if @fetch_location
77
- end
78
- end
79
-
80
69
  def build(platform, &block)
81
70
  @build.define(platform, &block)
82
71
  end
@@ -84,23 +73,49 @@ module Teapot
84
73
  def build!(platform = :all, config = {})
85
74
  task = @build[platform.name]
86
75
 
87
- puts "Building #{@name} for #{platform.name}"
88
76
  if task
77
+ environment = Environment.combine(
78
+ @record.options[:environment],
79
+ platform.environment,
80
+ config,
81
+ )
82
+
89
83
  Dir.chdir(@path) do
90
- puts "Entering #{@path}..."
91
- task.call(platform, platform.config.merge(config))
84
+ task.call(platform, environment)
92
85
  end
93
86
  else
94
- raise BuildError.new("Could not find task #{task_name} for #{platform.name}!")
87
+ raise BuildError.new("Could not find build task for #{platform.name}!")
95
88
  end
96
89
  end
97
90
 
98
- def fetch_from(location)
99
- @fetch_location = location
100
- end
101
-
102
91
  def to_s
103
92
  "<Package: #{@name}>"
104
93
  end
94
+
95
+ def self.build_order(available, packages)
96
+ ordered = []
97
+
98
+ expand = lambda do |name|
99
+ package = available[name]
100
+
101
+ unless package
102
+ puts "Couldn't resolve #{name}"
103
+ else
104
+ package.depends.each do |dependency|
105
+ expand.call(dependency)
106
+ end
107
+
108
+ unless ordered.include? package
109
+ ordered << package
110
+ end
111
+ end
112
+ end
113
+
114
+ packages.each do |package|
115
+ expand.call(package.name)
116
+ end
117
+
118
+ return ordered
119
+ end
105
120
  end
106
121
  end
@@ -1,32 +1,43 @@
1
+ # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
1
20
 
2
21
  require 'fileutils'
22
+ require 'rexec/environment'
3
23
 
4
24
  module Teapot
25
+ class UnavailableError < StandardError
26
+ end
27
+
5
28
  class Platform
6
- class Config
7
- def initialize(values = {})
8
- @values = values
9
- end
29
+ def initialize(context, record, name)
30
+ @context = context
31
+ @record = record
32
+
33
+ @name = name
34
+ @configure = nil
35
+
36
+ @available = false
37
+ end
10
38
 
11
- attr :values
39
+ attr :name
12
40
 
13
- def method_missing(name, *args)
14
- if name.to_s.match(/^(.*?)(\=)?$/)
15
- if $2
16
- return @values[$1.to_sym] = args[0]
17
- else
18
- return @values[$1.to_sym]
19
- end
20
- else
21
- super(name, *args)
22
- end
23
- end
24
-
25
- def merge(config)
26
- Config.new(@values.merge(config))
27
- end
28
- end
29
-
30
41
  def prefix
31
42
  @context.config.build_path + @name.to_s
32
43
  end
@@ -34,30 +45,19 @@ module Teapot
34
45
  def cmake_modules_path
35
46
  prefix + "share/cmake/modules"
36
47
  end
37
-
38
- def initialize(context, name)
39
- @context = context
40
-
41
- @name = name
42
- @config = nil
43
- @available = false
44
- end
45
-
46
- attr :name
47
48
 
48
49
  def configure(&block)
49
- @configuration = Proc.new &block
50
+ @configure = Proc.new &block
50
51
  end
51
52
 
52
- def config
53
- if available?
54
- config = Config.new
55
-
56
- @configuration.call(config)
57
-
58
- return config
53
+ def environment
54
+ if @available
55
+ return Environment.combine(
56
+ @record.options[:environment],
57
+ Environment.new(&@configure),
58
+ )
59
59
  else
60
- return nil
60
+ raise UnavailableError.new("Platform is not available for configuration!")
61
61
  end
62
62
  end
63
63
 
@@ -70,7 +70,7 @@ module Teapot
70
70
  end
71
71
 
72
72
  def to_s
73
- "<Platform #{@name}: #{@availble ? 'available' : 'inactive'}>"
73
+ "<Platform #{@name}: #{@available ? 'available' : 'inactive'}>"
74
74
  end
75
75
 
76
76
  def prepare!
@@ -1,3 +1,23 @@
1
+ # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
1
21
  module Teapot
2
- VERSION = "0.0.1"
22
+ VERSION = "0.0.3"
3
23
  end
data/lib/teapot.rb CHANGED
@@ -1,5 +1,24 @@
1
+ # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
1
21
  require "teapot/version"
2
22
 
3
23
  module Teapot
4
- # Your code goes here...
5
24
  end
data/teapot.gemspec CHANGED
@@ -23,4 +23,5 @@ Gem::Specification.new do |gem|
23
23
 
24
24
  gem.add_dependency "rake"
25
25
  gem.add_dependency "rainbow"
26
+ gem.add_dependency "rexec"
26
27
  end
@@ -0,0 +1,69 @@
1
+ # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'pathname'
22
+ require 'test/unit'
23
+ require 'stringio'
24
+
25
+ require 'teapot/environment'
26
+
27
+ class TestEnvironment < Test::Unit::TestCase
28
+ def test_environment_chaining
29
+ a = Teapot::Environment.new
30
+ a[:cflags] = ["-std=c++11"]
31
+
32
+ b = Teapot::Environment.new(a)
33
+ b[:cflags] = ["-stdlib=libc++"]
34
+
35
+ expected = {:cflags => ["-std=c++11", "-stdlib=libc++"]}
36
+
37
+ assert_equal expected, b.flatten.to_hash
38
+ end
39
+
40
+ def test_environment_lambda
41
+ a = Teapot::Environment.new do
42
+ sdk "bob-2.6"
43
+ cflags {"-sdk=#{sdk}"}
44
+ end
45
+
46
+ b = Teapot::Environment.new(a) do
47
+ sdk "bob-2.8"
48
+ end
49
+
50
+ expected = {'SDK' => "bob-2.8", 'CFLAGS' => "-sdk=bob-2.8"}
51
+
52
+ assert_equal [:cflags, :sdk], b.flatten.to_hash.keys.sort
53
+ assert_equal expected, b.flatten.to_string_hash
54
+ end
55
+
56
+ def test_combine
57
+ a = Teapot::Environment.new(nil, {:name => 'a'})
58
+ b = Teapot::Environment.new(a, {:name => 'b'})
59
+ c = Teapot::Environment.new(nil, {:name => 'c'})
60
+ d = Teapot::Environment.new(c, {:name => 'd'})
61
+
62
+ top = Teapot::Environment.combine(b, d)
63
+
64
+ assert_equal d.values, top.values
65
+ assert_equal c.values, top.parent.values
66
+ assert_equal b.values, top.parent.parent.values
67
+ assert_equal a.values, top.parent.parent.parent.values
68
+ end
69
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: teapot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-07 00:00:00.000000000 Z
12
+ date: 2012-11-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rexec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
46
62
  description: ! "\tTeapot is a tool for managing complex cross-platform builds. It
47
63
  provides\n\tadvanced dependency management via the Teapot file and is supported
48
64
  by\n\tthe infusions ecosystem of packages and platform tooling.\n"
@@ -54,17 +70,21 @@ extensions: []
54
70
  extra_rdoc_files: []
55
71
  files:
56
72
  - .gitignore
73
+ - .travis.yml
57
74
  - Gemfile
58
75
  - README.md
59
76
  - Rakefile
60
77
  - bin/teapot
61
78
  - lib/teapot.rb
79
+ - lib/teapot/commands.rb
62
80
  - lib/teapot/config.rb
63
81
  - lib/teapot/context.rb
82
+ - lib/teapot/environment.rb
64
83
  - lib/teapot/package.rb
65
84
  - lib/teapot/platform.rb
66
85
  - lib/teapot/version.rb
67
86
  - teapot.gemspec
87
+ - test/test_environment.rb
68
88
  homepage: ''
69
89
  licenses: []
70
90
  post_install_message:
@@ -79,7 +99,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
99
  version: '0'
80
100
  segments:
81
101
  - 0
82
- hash: -3245373006178987296
102
+ hash: -2599303512074911541
83
103
  required_rubygems_version: !ruby/object:Gem::Requirement
84
104
  none: false
85
105
  requirements:
@@ -88,11 +108,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
108
  version: '0'
89
109
  segments:
90
110
  - 0
91
- hash: -3245373006178987296
111
+ hash: -2599303512074911541
92
112
  requirements: []
93
113
  rubyforge_project:
94
114
  rubygems_version: 1.8.24
95
115
  signing_key:
96
116
  specification_version: 3
97
117
  summary: Teapot is a tool for managing complex cross-platform builds.
98
- test_files: []
118
+ test_files:
119
+ - test/test_environment.rb