teapot 0.3.2 → 0.5.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.
- data/bin/teapot +110 -144
- data/lib/teapot/{platform.rb → build/component.rb} +36 -47
- data/lib/teapot/build/file_list.rb +67 -0
- data/lib/teapot/build/linker.rb +6 -1
- data/lib/teapot/build/target.rb +77 -0
- data/lib/teapot/build/targets/application.rb +55 -0
- data/lib/teapot/build/targets/compiler.rb +69 -0
- data/lib/teapot/build/targets/directory.rb +63 -0
- data/lib/teapot/build/targets/executable.rb +52 -0
- data/lib/teapot/build/targets/files.rb +82 -0
- data/lib/teapot/build/targets/library.rb +106 -0
- data/lib/teapot/build.rb +11 -214
- data/lib/teapot/commands.rb +63 -0
- data/lib/teapot/config.rb +32 -63
- data/lib/teapot/context.rb +47 -38
- data/lib/teapot/dependency.rb +182 -0
- data/lib/teapot/environment/constructor.rb +4 -0
- data/lib/teapot/target.rb +94 -0
- data/lib/teapot/version.rb +1 -1
- data/teapot.gemspec +1 -1
- data/test/test_config.rb +41 -0
- data/test/test_dependency.rb +114 -0
- data/test/test_environment.rb +3 -3
- metadata +22 -9
- data/lib/teapot/package.rb +0 -164
@@ -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
|
+
|
23
|
+
module Teapot
|
24
|
+
module Build
|
25
|
+
module Targets
|
26
|
+
module Compiler
|
27
|
+
def build_prefix!(environment)
|
28
|
+
build_prefix = Pathname.new(environment[:build_prefix]) + "compiled"
|
29
|
+
|
30
|
+
build_prefix.mkpath
|
31
|
+
|
32
|
+
return build_prefix
|
33
|
+
end
|
34
|
+
|
35
|
+
def link_prefix!(environment)
|
36
|
+
prefix = Pathname.new(environment[:build_prefix]) + "linked"
|
37
|
+
|
38
|
+
prefix.mkpath
|
39
|
+
|
40
|
+
return prefix
|
41
|
+
end
|
42
|
+
|
43
|
+
def compile(environment, root, source_file, commands)
|
44
|
+
object_file = (build_prefix!(environment) + source_file).sub_ext('.o')
|
45
|
+
|
46
|
+
# Ensure there is a directory for the output file:
|
47
|
+
object_file.dirname.mkpath
|
48
|
+
|
49
|
+
case source_file.extname
|
50
|
+
when ".cpp", ".mm"
|
51
|
+
commands.run(
|
52
|
+
environment[:cxx],
|
53
|
+
environment[:cxxflags],
|
54
|
+
"-c", root + source_file, "-o", object_file
|
55
|
+
)
|
56
|
+
when ".c", ".m"
|
57
|
+
commands.run(
|
58
|
+
environment[:cc],
|
59
|
+
environment[:cflags],
|
60
|
+
"-c", root + source_file, "-o", object_file
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
return Array object_file
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,63 @@
|
|
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 'teapot/build/target'
|
22
|
+
|
23
|
+
module Teapot
|
24
|
+
module Build
|
25
|
+
module Targets
|
26
|
+
class Directory < Build::Target
|
27
|
+
BUILD_FILE = "build.rb"
|
28
|
+
|
29
|
+
def initialize(parent, root = nil)
|
30
|
+
super parent
|
31
|
+
|
32
|
+
@root = root
|
33
|
+
@targets = []
|
34
|
+
end
|
35
|
+
|
36
|
+
def root
|
37
|
+
@root || @parent.root
|
38
|
+
end
|
39
|
+
|
40
|
+
attr :tasks
|
41
|
+
|
42
|
+
def << (target)
|
43
|
+
@targets << target
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_directory(path)
|
47
|
+
directory = Directory.target(self, @root + path)
|
48
|
+
|
49
|
+
build_path = (directory.root + BUILD_FILE).to_s
|
50
|
+
directory.instance_eval(File.read(build_path), build_path)
|
51
|
+
|
52
|
+
self << directory
|
53
|
+
end
|
54
|
+
|
55
|
+
def execute(command, *arguments)
|
56
|
+
@targets.each do |target|
|
57
|
+
target.execute(command, *arguments)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,52 @@
|
|
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 'teapot/build/targets/library'
|
22
|
+
|
23
|
+
module Teapot
|
24
|
+
module Build
|
25
|
+
module Targets
|
26
|
+
class Executable < Library
|
27
|
+
def subdirectory
|
28
|
+
options[:subdirectory] || "bin"
|
29
|
+
end
|
30
|
+
|
31
|
+
def link(environment, objects)
|
32
|
+
executable_file = link_prefix!(environment) + @name
|
33
|
+
|
34
|
+
Commands.run(
|
35
|
+
environment[:cxx],
|
36
|
+
environment[:cxxflags],
|
37
|
+
"-o", executable_file, objects,
|
38
|
+
environment[:ldflags]
|
39
|
+
)
|
40
|
+
|
41
|
+
return executable_file
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Directory
|
46
|
+
def compile_executable(*args, &block)
|
47
|
+
self << Executable.target(self, *args, &block)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,82 @@
|
|
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 'teapot/build/target'
|
22
|
+
require 'teapot/build/targets/directory'
|
23
|
+
require 'teapot/build/targets/compiler'
|
24
|
+
|
25
|
+
require 'fileutils'
|
26
|
+
|
27
|
+
module Teapot
|
28
|
+
module Build
|
29
|
+
module Targets
|
30
|
+
module Installation
|
31
|
+
def install_prefix!(environment)
|
32
|
+
install_prefix = Pathname.new(environment[:install_prefix])
|
33
|
+
|
34
|
+
install_prefix.mkpath
|
35
|
+
|
36
|
+
return install_prefix
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Files < Build::Target
|
41
|
+
include Installation
|
42
|
+
|
43
|
+
def initialize(parent, options = {})
|
44
|
+
super parent
|
45
|
+
@options = options
|
46
|
+
end
|
47
|
+
|
48
|
+
attr :options
|
49
|
+
|
50
|
+
def subdirectory
|
51
|
+
options[:subdirectory] || "./"
|
52
|
+
end
|
53
|
+
|
54
|
+
def install(environment)
|
55
|
+
prefix = install_prefix!(environment)
|
56
|
+
|
57
|
+
if self.respond_to? :source_files
|
58
|
+
file_list = self.source_files(environment)
|
59
|
+
|
60
|
+
file_list.copy(prefix + subdirectory)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Headers < Files
|
66
|
+
def subdirectory
|
67
|
+
super + "include/"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Directory
|
72
|
+
def copy_files(*args, &block)
|
73
|
+
self << Files.target(self, *args, &block)
|
74
|
+
end
|
75
|
+
|
76
|
+
def copy_headers(*args, &block)
|
77
|
+
self << Headers.target(self, *args, &block)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,106 @@
|
|
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 'teapot/build/target'
|
22
|
+
require 'teapot/build/targets/directory'
|
23
|
+
require 'teapot/build/targets/files'
|
24
|
+
require 'teapot/build/targets/compiler'
|
25
|
+
|
26
|
+
require 'fileutils'
|
27
|
+
|
28
|
+
module Teapot
|
29
|
+
module Build
|
30
|
+
module Targets
|
31
|
+
class Library < Build::Target
|
32
|
+
include Compiler
|
33
|
+
include Installation
|
34
|
+
|
35
|
+
def initialize(parent, name, options = {})
|
36
|
+
super parent
|
37
|
+
|
38
|
+
@name = name
|
39
|
+
@options = options
|
40
|
+
end
|
41
|
+
|
42
|
+
attr :options
|
43
|
+
|
44
|
+
def subdirectory
|
45
|
+
options[:subdirectory] || "lib"
|
46
|
+
end
|
47
|
+
|
48
|
+
def link(environment, objects)
|
49
|
+
library_file = link_prefix!(environment) + "lib#{@name}.a"
|
50
|
+
|
51
|
+
Linker.link_static(environment, library_file, objects)
|
52
|
+
|
53
|
+
return library_file
|
54
|
+
end
|
55
|
+
|
56
|
+
def build(environment)
|
57
|
+
file_list = self.source_files(environment)
|
58
|
+
|
59
|
+
pool = Commands::Pool.new
|
60
|
+
|
61
|
+
objects = file_list.collect do |source_file|
|
62
|
+
relative_path = source_file.relative_path_from(file_list.root)
|
63
|
+
|
64
|
+
compile(environment, file_list.root, relative_path, pool)
|
65
|
+
end
|
66
|
+
|
67
|
+
pool.wait
|
68
|
+
|
69
|
+
return Array link(environment, objects)
|
70
|
+
end
|
71
|
+
|
72
|
+
def install_file_list(file_list, prefix)
|
73
|
+
file_list.each do |path|
|
74
|
+
relative_path = path.relative_path_from(file_list.root)
|
75
|
+
destination_path = prefix + file_list.prefix + relative_path
|
76
|
+
|
77
|
+
destination_path.dirname.mkpath
|
78
|
+
FileUtils.cp path, destination_path
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def install(environment)
|
83
|
+
prefix = install_prefix!(environment)
|
84
|
+
|
85
|
+
build(environment).each do |path|
|
86
|
+
destination_path = prefix + subdirectory + path.basename
|
87
|
+
|
88
|
+
destination_path.dirname.mkpath
|
89
|
+
|
90
|
+
FileUtils.cp path, destination_path
|
91
|
+
end
|
92
|
+
|
93
|
+
if self.respond_to? :headers
|
94
|
+
install_file_list(self.headers(environment), prefix + "include")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class Directory
|
100
|
+
def compile_library(*args, &block)
|
101
|
+
self << Library.target(self, *args, &block)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/lib/teapot/build.rb
CHANGED
@@ -18,227 +18,24 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
-
require 'teapot/
|
22
|
-
require 'teapot/
|
23
|
-
|
24
|
-
require '
|
25
|
-
require '
|
26
|
-
require 'shellwords'
|
27
|
-
|
28
|
-
require 'teapot/build/linker'
|
21
|
+
require 'teapot/build/targets/directory'
|
22
|
+
require 'teapot/build/targets/files'
|
23
|
+
require 'teapot/build/targets/library'
|
24
|
+
require 'teapot/build/targets/executable'
|
25
|
+
require 'teapot/build/targets/application'
|
29
26
|
|
30
27
|
module Teapot
|
31
28
|
module Build
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
class Task
|
36
|
-
def initialize(inputs, outputs)
|
37
|
-
@inputs = inputs
|
38
|
-
@outputs = outputs
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
class Target
|
43
|
-
def initialize(parent)
|
44
|
-
@parent = parent
|
45
|
-
@tasks = []
|
46
|
-
|
47
|
-
@configure = nil
|
48
|
-
end
|
49
|
-
|
50
|
-
def root
|
51
|
-
@parent.root
|
52
|
-
end
|
53
|
-
|
54
|
-
def configure(&block)
|
55
|
-
@configure = Proc.new &block
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.target(*args, &block)
|
59
|
-
instance = self.new(*args)
|
60
|
-
|
61
|
-
if block_given?
|
62
|
-
instance.instance_eval(&block)
|
63
|
-
end
|
64
|
-
|
65
|
-
return instance
|
66
|
-
end
|
67
|
-
|
68
|
-
def execute(command, environment, *arguments)
|
69
|
-
if @configure
|
70
|
-
environment = environment.merge &@configure
|
71
|
-
end
|
72
|
-
|
73
|
-
# Flatten the environment to a hash:
|
74
|
-
values = environment.flatten
|
75
|
-
|
76
|
-
puts "Executing command #{command} for #{root}...".color(:cyan)
|
77
|
-
|
78
|
-
# Show the environment to the user:
|
79
|
-
Environment::System::dump(values)
|
80
|
-
|
81
|
-
self.send(command, values, *arguments)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
class CompilerTarget < Target
|
86
|
-
def initialize(parent, name, options = {})
|
87
|
-
super parent
|
88
|
-
|
89
|
-
@name = name
|
90
|
-
@options = options
|
91
|
-
end
|
92
|
-
|
93
|
-
def build_prefix!(environment)
|
94
|
-
build_prefix = Pathname.new(environment[:build_prefix]) + @name
|
95
|
-
|
96
|
-
build_prefix.mkpath
|
97
|
-
|
98
|
-
return build_prefix
|
99
|
-
end
|
100
|
-
|
101
|
-
def install_prefix!(environment)
|
102
|
-
install_prefix = Pathname.new(environment[:install_prefix])
|
103
|
-
|
104
|
-
install_prefix.mkpath
|
105
|
-
|
106
|
-
return install_prefix
|
107
|
-
end
|
108
|
-
|
109
|
-
def compile(environment, source_file)
|
110
|
-
object_file = (build_prefix!(environment) + source_file.basename).sub_ext('.o')
|
111
|
-
|
112
|
-
case source_file.extname
|
113
|
-
when ".cpp"
|
114
|
-
Commands.run(
|
115
|
-
environment[:cxx],
|
116
|
-
environment[:cxxflags],
|
117
|
-
"-c", source_file, "-o", object_file
|
118
|
-
)
|
119
|
-
when ".c"
|
120
|
-
Commands.run(
|
121
|
-
environment[:cc],
|
122
|
-
environment[:cflags],
|
123
|
-
"-c", source_file, "-o", object_file
|
124
|
-
)
|
125
|
-
end
|
126
|
-
|
127
|
-
return Array object_file
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
class Library < CompilerTarget
|
132
|
-
def subdirectory
|
133
|
-
"lib"
|
134
|
-
end
|
135
|
-
|
136
|
-
def link(environment, objects)
|
137
|
-
library_file = build_prefix!(environment) + "lib#{@name}.a"
|
138
|
-
|
139
|
-
Linker.link_static(environment, library_file, objects)
|
140
|
-
|
141
|
-
return library_file
|
142
|
-
end
|
143
|
-
|
144
|
-
def build(environment)
|
145
|
-
files = sources
|
146
|
-
|
147
|
-
objects = sources.collect do |file|
|
148
|
-
compile(environment, file)
|
149
|
-
end
|
150
|
-
|
151
|
-
return Array link(environment, objects)
|
152
|
-
end
|
153
|
-
|
154
|
-
def install(environment)
|
155
|
-
prefix = install_prefix!(environment)
|
156
|
-
|
157
|
-
build(environment).each do |path|
|
158
|
-
destination_path = prefix + subdirectory + path.basename
|
159
|
-
|
160
|
-
destination_path.dirname.mkpath
|
161
|
-
FileUtils.cp path, destination_path
|
162
|
-
end
|
163
|
-
|
164
|
-
if defined? headers
|
165
|
-
headers.each do |path|
|
166
|
-
relative_path = path.relative_path_from(root)
|
167
|
-
destination_path = prefix + "include" + relative_path
|
168
|
-
|
169
|
-
destination_path.dirname.mkpath
|
170
|
-
FileUtils.cp path, destination_path
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
if defined? files
|
175
|
-
files.each do |path|
|
176
|
-
relative_path = path.relative_path_from(root)
|
177
|
-
destination_path = prefix + relative_path
|
178
|
-
|
179
|
-
destination_path.dirname.mkpath
|
180
|
-
FileUtils.cp path, destination_path
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
class Executable < Library
|
187
|
-
def subdirectory
|
188
|
-
"bin"
|
189
|
-
end
|
190
|
-
|
191
|
-
def link(environment, objects)
|
192
|
-
executable_file = build_prefix!(environment) + "#{@name}"
|
193
|
-
|
194
|
-
Commands.run(
|
195
|
-
environment[:cxx],
|
196
|
-
environment[:cxxflags],
|
197
|
-
"-o", executable_file, objects,
|
198
|
-
environment[:ldflags]
|
199
|
-
)
|
200
|
-
|
201
|
-
return executable_file
|
202
|
-
end
|
29
|
+
def self.top(path)
|
30
|
+
Targets::Directory.target(nil, path)
|
203
31
|
end
|
204
|
-
|
205
|
-
class Directory < Target
|
206
|
-
def initialize(parent, root)
|
207
|
-
@root = root
|
208
|
-
@targets = []
|
209
|
-
end
|
210
32
|
|
211
|
-
|
212
|
-
|
33
|
+
def self.install_directory(root, directory, *args)
|
34
|
+
target = top(root)
|
213
35
|
|
214
|
-
|
215
|
-
@targets << Library.target(self, *args, &block)
|
216
|
-
end
|
36
|
+
target.add_directory(directory)
|
217
37
|
|
218
|
-
|
219
|
-
@targets << Executable.target(self, *args, &block)
|
220
|
-
end
|
221
|
-
|
222
|
-
def add_directory(path)
|
223
|
-
directory = Directory.target(self, @root + path)
|
224
|
-
|
225
|
-
$stderr.puts "Loading #{directory.root}..."
|
226
|
-
build_path = (directory.root + "build.rb").to_s
|
227
|
-
directory.instance_eval(File.read(build_path), build_path)
|
228
|
-
|
229
|
-
@targets << directory
|
230
|
-
end
|
231
|
-
|
232
|
-
def execute(command, *arguments)
|
233
|
-
$stderr.puts "Executing #{command} for #{@root}"
|
234
|
-
@targets.each do |target|
|
235
|
-
target.execute(command, *arguments)
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
def self.top(path)
|
241
|
-
Directory.target(nil, path)
|
38
|
+
target.execute(:install, *args)
|
242
39
|
end
|
243
40
|
end
|
244
41
|
end
|
data/lib/teapot/commands.rb
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
+
require 'set'
|
21
22
|
require 'rainbow'
|
22
23
|
require 'shellwords'
|
23
24
|
|
@@ -41,5 +42,67 @@ module Teapot
|
|
41
42
|
raise CommandError.new("Non-zero exit status")
|
42
43
|
end
|
43
44
|
end
|
45
|
+
|
46
|
+
def self.run!(*args)
|
47
|
+
run(*args)
|
48
|
+
rescue CommandError
|
49
|
+
false
|
50
|
+
end
|
51
|
+
|
52
|
+
def wait
|
53
|
+
# No parallel execution supported by default.
|
54
|
+
end
|
55
|
+
|
56
|
+
class Pool
|
57
|
+
def initialize(options = {})
|
58
|
+
@commands = []
|
59
|
+
@limit = options[:limit] || 16
|
60
|
+
|
61
|
+
@running = Set.new
|
62
|
+
end
|
63
|
+
|
64
|
+
def run(*args)
|
65
|
+
args = args.flatten.collect &:to_s
|
66
|
+
|
67
|
+
puts args.join(' ').color(:blue)
|
68
|
+
|
69
|
+
@commands << args
|
70
|
+
|
71
|
+
schedule!
|
72
|
+
end
|
73
|
+
|
74
|
+
def schedule!
|
75
|
+
while @running.size < @limit and @commands.size > 0
|
76
|
+
command = @commands.shift
|
77
|
+
|
78
|
+
pid = Process.fork do
|
79
|
+
exec(*command)
|
80
|
+
|
81
|
+
exit!(0)
|
82
|
+
end
|
83
|
+
|
84
|
+
@running << pid
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def wait
|
89
|
+
while @running.size > 0
|
90
|
+
pid = Process.wait(0)
|
91
|
+
@running.delete(pid)
|
92
|
+
|
93
|
+
schedule!
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.pipeline(parallel = false)
|
99
|
+
if parallel == false
|
100
|
+
# Non-parallel execution pipeline
|
101
|
+
Commands
|
102
|
+
else
|
103
|
+
# Pool based parallel execution pipeline
|
104
|
+
Pool.new(parallel == true ? {} : parallel)
|
105
|
+
end
|
106
|
+
end
|
44
107
|
end
|
45
108
|
end
|