erebrus 0.1.0 → 0.1.2
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 +4 -4
- data/README.md +1 -1
- data/bin/erebrus +174 -83
- data/examples/.gitignore +5 -0
- data/examples/Buildfile +156 -26
- data/examples/include/hello.hpp +4 -0
- data/examples/src/hello.cpp +5 -0
- data/examples/src/main.cpp +7 -0
- data/examples/templates/app_config.tpl +8 -0
- data/examples/tests/test_main.cpp +10 -0
- data/lib/erebrus/build_engine.rb +197 -12
- data/lib/erebrus/target.rb +0 -11
- data/lib/erebrus/version.rb +2 -2
- data/sig/erebrus/build_engine.rbs +78 -0
- data/sig/erebrus/dsl.rbs +37 -0
- data/sig/erebrus/target.rbs +37 -0
- data/sig/erebrus.rbs +20 -1
- metadata +11 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c0a0cf035d47b272eefe1385dd63919f5b6c58c75765248dc165f3ba942057b6
|
|
4
|
+
data.tar.gz: 637e125435680c16aefe62e318bc78990b2b0e1910d3c669071757996442279c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 935badb603ccfa49c812c702fd884f143a130fa051fda3f66fab25080a704549c11df48fc4fb3d731dd3789a1225488d2bd3229a700a5ef0dcab42cb6136bd9f
|
|
7
|
+
data.tar.gz: '008219953c4f5ca5f9e245240bc824c7db35cba780830dee4e2fa58680fe3a8259a87350e4146f42bb91ab838381a51c0b8b899a960338e6eb4bdcd69496861d'
|
data/README.md
CHANGED
data/bin/erebrus
CHANGED
|
@@ -5,147 +5,186 @@ require "erebrus"
|
|
|
5
5
|
class ErebrusCommand < Thor
|
|
6
6
|
class_option :verbose, aliases: "-v", type: :boolean, desc: "Verbose output"
|
|
7
7
|
class_option :file, aliases: "-f", desc: "Buildfile to use", default: "Buildfile"
|
|
8
|
+
class_option :color, type: :boolean, default: true, desc: "Enable colored output (--no-color to disable)"
|
|
9
|
+
class_option :dir, aliases: "-d", type: :string, desc: "Directory to run the build in"
|
|
8
10
|
|
|
9
11
|
desc "build [TARGET]", "Builds the project with optional target"
|
|
10
12
|
option :namespace, aliases: "-n", desc: "Target namespace"
|
|
11
13
|
option :var, aliases: "-D", type: :hash, desc: "Set variables (e.g., -D CC=gcc -D CFLAGS=-O2)"
|
|
12
14
|
option :parallel, aliases: "-j", type: :numeric, desc: "Number of parallel jobs"
|
|
13
15
|
def build(target = nil)
|
|
14
|
-
|
|
16
|
+
in_working_dir do
|
|
17
|
+
load_buildfile_with_error_handling
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
target_name = resolve_target_name(target)
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
context = prepare_context
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
begin
|
|
24
|
+
Erebrus.build(target_name, context)
|
|
25
|
+
rescue Erebrus::Error => e
|
|
26
|
+
say_error "Build failed: #{e.message}"
|
|
27
|
+
exit 1
|
|
28
|
+
rescue StandardError => e
|
|
29
|
+
say_error "Unexpected error: #{e.message}"
|
|
30
|
+
puts e.backtrace if options[:verbose]
|
|
31
|
+
exit 1
|
|
32
|
+
end
|
|
30
33
|
end
|
|
31
34
|
end
|
|
32
35
|
|
|
33
36
|
desc "list [NAMESPACE]", "Lists all available targets, optionally filtered by namespace"
|
|
34
37
|
def list(namespace = nil)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
in_working_dir do
|
|
39
|
+
load_buildfile_with_error_handling
|
|
40
|
+
|
|
41
|
+
begin
|
|
42
|
+
puts "" # spacing for readability
|
|
43
|
+
if namespace
|
|
44
|
+
say_title("Targets in namespace '#{namespace}'")
|
|
45
|
+
else
|
|
46
|
+
say_title("Available targets")
|
|
47
|
+
end
|
|
48
|
+
if namespace
|
|
49
|
+
Erebrus.list_targets(namespace: namespace)
|
|
50
|
+
else
|
|
51
|
+
Erebrus.list_targets
|
|
52
|
+
end
|
|
53
|
+
rescue StandardError => e
|
|
54
|
+
say_error "Error listing targets: #{e.message}"
|
|
55
|
+
exit 1
|
|
42
56
|
end
|
|
43
|
-
rescue StandardError => e
|
|
44
|
-
puts "Error listing targets: #{e.message}"
|
|
45
|
-
exit 1
|
|
46
57
|
end
|
|
47
58
|
end
|
|
48
59
|
|
|
49
60
|
desc "namespaces", "Lists all available namespaces"
|
|
50
61
|
def namespaces
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
62
|
+
in_working_dir do
|
|
63
|
+
load_buildfile_with_error_handling
|
|
64
|
+
|
|
65
|
+
begin
|
|
66
|
+
say_title "Available namespaces"
|
|
67
|
+
Erebrus.list_namespaces
|
|
68
|
+
rescue StandardError => e
|
|
69
|
+
say_error "Error listing namespaces: #{e.message}"
|
|
70
|
+
exit 1
|
|
71
|
+
end
|
|
58
72
|
end
|
|
59
73
|
end
|
|
60
74
|
|
|
61
75
|
desc "init [TYPE]", "Initializes the project with a sample Buildfile"
|
|
62
76
|
def init(type = "basic")
|
|
63
|
-
|
|
77
|
+
in_working_dir do
|
|
78
|
+
buildfile = options[:file]
|
|
64
79
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
if File.exist?(buildfile)
|
|
81
|
+
puts "Buildfile '#{buildfile}' already exists!"
|
|
82
|
+
return
|
|
83
|
+
end
|
|
69
84
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
sample_content = case type.downcase
|
|
86
|
+
when "cpp", "c++"
|
|
87
|
+
generate_cpp_buildfile
|
|
88
|
+
when "c"
|
|
89
|
+
generate_c_buildfile
|
|
90
|
+
when "advanced"
|
|
91
|
+
generate_advanced_buildfile
|
|
92
|
+
else
|
|
93
|
+
generate_basic_buildfile
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
File.write(buildfile, sample_content)
|
|
97
|
+
say_success "Created #{buildfile} (#{type} template)"
|
|
98
|
+
say_info "Edit the file to define your build targets and run 'erebrus build' to build your project"
|
|
99
|
+
end
|
|
84
100
|
end
|
|
85
101
|
|
|
86
102
|
desc "validate", "Validates the Buildfile syntax"
|
|
87
103
|
def validate
|
|
88
|
-
|
|
104
|
+
in_working_dir do
|
|
105
|
+
buildfile = options[:file]
|
|
89
106
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
107
|
+
unless File.exist?(buildfile)
|
|
108
|
+
puts "Error: Buildfile '#{buildfile}' not found"
|
|
109
|
+
exit 1
|
|
110
|
+
end
|
|
94
111
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
112
|
+
begin
|
|
113
|
+
Erebrus.reset!
|
|
114
|
+
Erebrus.load_buildfile(buildfile)
|
|
115
|
+
say_success "Buildfile is valid \u2713"
|
|
116
|
+
rescue StandardError => e
|
|
117
|
+
say_error "Buildfile validation failed: #{e.message}"
|
|
118
|
+
exit 1
|
|
119
|
+
end
|
|
102
120
|
end
|
|
103
121
|
end
|
|
104
122
|
|
|
105
123
|
desc "graph [TARGET]", "Shows dependency graph for target"
|
|
106
124
|
def graph(target = nil)
|
|
107
|
-
|
|
125
|
+
in_working_dir do
|
|
126
|
+
load_buildfile_with_error_handling
|
|
108
127
|
|
|
109
|
-
|
|
128
|
+
target_name = resolve_target_name(target)
|
|
110
129
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
130
|
+
begin
|
|
131
|
+
say_title "Dependency graph for '#{target_name}'"
|
|
132
|
+
say_info "(Graph visualization not yet implemented)"
|
|
133
|
+
rescue StandardError => e
|
|
134
|
+
say_error "Error generating graph: #{e.message}"
|
|
135
|
+
exit 1
|
|
136
|
+
end
|
|
117
137
|
end
|
|
118
138
|
end
|
|
119
139
|
|
|
120
140
|
desc "clean", "Runs the clean target if available"
|
|
121
141
|
def clean
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
142
|
+
in_working_dir do
|
|
143
|
+
load_buildfile_with_error_handling
|
|
144
|
+
|
|
145
|
+
begin
|
|
146
|
+
Erebrus.build("clean")
|
|
147
|
+
rescue Erebrus::Error => e
|
|
148
|
+
if e.message.include?("not found")
|
|
149
|
+
say_warn "No clean target defined"
|
|
150
|
+
else
|
|
151
|
+
say_error "Clean failed: #{e.message}"
|
|
152
|
+
exit 1
|
|
153
|
+
end
|
|
132
154
|
end
|
|
133
155
|
end
|
|
134
156
|
end
|
|
135
157
|
|
|
136
158
|
desc "version", "Show version"
|
|
137
159
|
def version
|
|
138
|
-
|
|
160
|
+
say_info "Erebrus #{Erebrus::VERSION}"
|
|
139
161
|
end
|
|
140
162
|
|
|
141
163
|
private
|
|
142
164
|
|
|
165
|
+
def in_working_dir
|
|
166
|
+
dir = options[:dir]
|
|
167
|
+
return yield unless dir
|
|
168
|
+
|
|
169
|
+
unless Dir.exist?(dir)
|
|
170
|
+
say_error "Error: directory '#{dir}' not found"
|
|
171
|
+
exit 1
|
|
172
|
+
end
|
|
173
|
+
old = Dir.pwd
|
|
174
|
+
Dir.chdir(dir)
|
|
175
|
+
begin
|
|
176
|
+
yield
|
|
177
|
+
ensure
|
|
178
|
+
Dir.chdir(old)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
143
182
|
def load_buildfile_with_error_handling
|
|
144
183
|
buildfile = options[:file]
|
|
145
184
|
|
|
146
185
|
unless File.exist?(buildfile)
|
|
147
|
-
|
|
148
|
-
|
|
186
|
+
say_error "Error: Buildfile '#{buildfile}' not found"
|
|
187
|
+
say_info "Run 'erebrus init' to create a sample Buildfile"
|
|
149
188
|
exit 1
|
|
150
189
|
end
|
|
151
190
|
|
|
@@ -153,7 +192,7 @@ class ErebrusCommand < Thor
|
|
|
153
192
|
Erebrus.reset!
|
|
154
193
|
Erebrus.load_buildfile(buildfile)
|
|
155
194
|
rescue StandardError => e
|
|
156
|
-
|
|
195
|
+
say_error "Error loading buildfile: #{e.message}"
|
|
157
196
|
puts e.backtrace if options[:verbose]
|
|
158
197
|
exit 1
|
|
159
198
|
end
|
|
@@ -170,6 +209,7 @@ class ErebrusCommand < Thor
|
|
|
170
209
|
|
|
171
210
|
context.merge!(options[:var]) if options[:var]
|
|
172
211
|
|
|
212
|
+
# Legacy variables for backward compatibility
|
|
173
213
|
context["PLATFORM"] = RUBY_PLATFORM
|
|
174
214
|
context["RUBY_VERSION"] = RUBY_VERSION
|
|
175
215
|
context["PWD"] = Dir.pwd
|
|
@@ -177,6 +217,57 @@ class ErebrusCommand < Thor
|
|
|
177
217
|
context
|
|
178
218
|
end
|
|
179
219
|
|
|
220
|
+
# --- Styling helpers -----------------------------------------------------
|
|
221
|
+
def color_enabled?
|
|
222
|
+
options[:color] && $stdout.respond_to?(:isatty) && $stdout.isatty && ENV["NO_COLOR"].nil?
|
|
223
|
+
rescue StandardError
|
|
224
|
+
options[:color]
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def color_code(color)
|
|
228
|
+
case color
|
|
229
|
+
when :black then 30
|
|
230
|
+
when :red then 31
|
|
231
|
+
when :green then 32
|
|
232
|
+
when :yellow then 33
|
|
233
|
+
when :blue then 34
|
|
234
|
+
when :magenta then 35
|
|
235
|
+
when :cyan then 36
|
|
236
|
+
when :white then 37
|
|
237
|
+
else nil
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def c(text, color = nil, bold: false)
|
|
242
|
+
return text unless color_enabled? && (bold || color)
|
|
243
|
+
|
|
244
|
+
codes = []
|
|
245
|
+
codes << 1 if bold
|
|
246
|
+
cc = color_code(color)
|
|
247
|
+
codes << cc if cc
|
|
248
|
+
"\e[#{codes.join(";")}m#{text}\e[0m"
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def say_title(msg)
|
|
252
|
+
puts c("==> #{msg}", :blue, bold: true)
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def say_success(msg)
|
|
256
|
+
puts c(msg, :green, bold: true)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def say_error(msg)
|
|
260
|
+
puts c(msg, :red, bold: true)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def say_warn(msg)
|
|
264
|
+
puts c(msg, :yellow)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def say_info(msg)
|
|
268
|
+
puts c(msg, :cyan)
|
|
269
|
+
end
|
|
270
|
+
|
|
180
271
|
def generate_basic_buildfile
|
|
181
272
|
<<~BUILDFILE
|
|
182
273
|
target :clean, description: "Clean build artifacts" do
|
data/examples/.gitignore
ADDED
data/examples/Buildfile
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# Erebrus Buildfile Example
|
|
2
2
|
# This demonstrates the Ruby build DSL for C/C++ projects
|
|
3
3
|
|
|
4
|
+
# Global variables used in the example and templates
|
|
5
|
+
set_variable "APP_NAME", "myapp"
|
|
6
|
+
set_variable "VERSION", "1.0.0"
|
|
7
|
+
|
|
4
8
|
target :clean, description: "Clean all build artifacts" do
|
|
5
9
|
remove "build"
|
|
6
10
|
remove "dist"
|
|
@@ -15,44 +19,53 @@ end
|
|
|
15
19
|
|
|
16
20
|
target :configure, description: "Configure build environment" do
|
|
17
21
|
depends_on :setup
|
|
18
|
-
|
|
22
|
+
|
|
19
23
|
action do |context|
|
|
20
|
-
puts "Configuring build for #{context[:platform] ||
|
|
24
|
+
puts "Configuring build for #{context[:platform] || "default"} platform"
|
|
21
25
|
end
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
target :compile_sources, description: "Compile source files" do
|
|
25
29
|
depends_on :configure
|
|
26
|
-
|
|
27
|
-
# Compile all C++ files in src/
|
|
30
|
+
|
|
28
31
|
run "g++ -std=c++17 -Wall -Wextra -O2 -c src/*.cpp -Iinclude"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
|
|
33
|
+
action do
|
|
34
|
+
require "fileutils"
|
|
35
|
+
Dir.glob("*.o").each do |obj|
|
|
36
|
+
FileUtils.mv(obj, File.join("obj", File.basename(obj)))
|
|
37
|
+
end
|
|
38
|
+
end
|
|
32
39
|
end
|
|
33
40
|
|
|
34
41
|
target :compile_tests, description: "Compile test files" do
|
|
35
42
|
depends_on :compile_sources
|
|
36
|
-
|
|
43
|
+
|
|
37
44
|
run "g++ -std=c++17 -Wall -Wextra -O2 -c tests/*.cpp -Iinclude -Isrc"
|
|
38
|
-
|
|
45
|
+
|
|
46
|
+
action do
|
|
47
|
+
require "fileutils"
|
|
48
|
+
Dir.glob("*.o").each do |obj|
|
|
49
|
+
FileUtils.mv(obj, File.join("obj", File.basename(obj)))
|
|
50
|
+
end
|
|
51
|
+
end
|
|
39
52
|
end
|
|
40
53
|
|
|
41
54
|
target :link_main, description: "Link main executable" do
|
|
42
55
|
depends_on :compile_sources
|
|
43
|
-
|
|
44
|
-
run "g++ obj
|
|
56
|
+
|
|
57
|
+
run "g++ obj/main.o obj/hello.o -o dist/myapp"
|
|
45
58
|
end
|
|
46
59
|
|
|
47
60
|
target :link_tests, description: "Link test executable" do
|
|
48
61
|
depends_on :compile_tests
|
|
49
|
-
|
|
50
|
-
run "g++ obj
|
|
62
|
+
|
|
63
|
+
run "g++ obj/test_main.o obj/hello.o -o dist/test_runner"
|
|
51
64
|
end
|
|
52
65
|
|
|
53
66
|
target :build, description: "Build the main application" do
|
|
54
67
|
depends_on :link_main
|
|
55
|
-
|
|
68
|
+
|
|
56
69
|
action do
|
|
57
70
|
puts "Build completed successfully!"
|
|
58
71
|
puts "Executable: dist/myapp"
|
|
@@ -61,29 +74,65 @@ end
|
|
|
61
74
|
|
|
62
75
|
target :test, description: "Run all tests" do
|
|
63
76
|
depends_on :link_tests
|
|
64
|
-
|
|
77
|
+
|
|
65
78
|
run "dist/test_runner"
|
|
66
79
|
end
|
|
67
80
|
|
|
68
81
|
target :install, description: "Install the application" do
|
|
69
82
|
depends_on :build
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
83
|
+
|
|
84
|
+
platform :linux do
|
|
85
|
+
directory_exists "/usr/local/bin" do
|
|
86
|
+
copy "dist/myapp", "/usr/local/bin/myapp"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
platform :windows do
|
|
90
|
+
directory_exists "C:/Users/Public" do
|
|
91
|
+
copy "dist/myapp", "C:/Users/Public/myapp.exe"
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
platform :darwin do
|
|
95
|
+
directory_exists "/usr/local/bin" do
|
|
96
|
+
copy "dist/myapp", "/usr/local/bin/myapp"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
73
100
|
action do
|
|
74
|
-
puts "Application installed
|
|
101
|
+
puts "Application installed for ${HOST_OS}"
|
|
75
102
|
end
|
|
76
103
|
end
|
|
77
104
|
|
|
78
105
|
target :package, description: "Create distribution package" do
|
|
79
106
|
depends_on :build
|
|
80
|
-
|
|
107
|
+
|
|
108
|
+
# Ensure stale file or directory doesn't block packaging
|
|
109
|
+
remove "package"
|
|
81
110
|
mkdir "package"
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
111
|
+
# Copy executable (handle Windows .exe)
|
|
112
|
+
file_exists "dist/myapp" do
|
|
113
|
+
copy "dist/myapp", "package"
|
|
114
|
+
end
|
|
115
|
+
file_exists "dist/myapp.exe" do
|
|
116
|
+
copy "dist/myapp.exe", "package"
|
|
117
|
+
end
|
|
118
|
+
# Include docs
|
|
119
|
+
file_exists "README.md" do
|
|
120
|
+
copy "README.md", "package"
|
|
121
|
+
end
|
|
122
|
+
file_exists "LICENSE" do
|
|
123
|
+
copy "LICENSE", "package"
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
platform :linux do
|
|
127
|
+
run "tar -czf dist/myapp-1.0.tar.gz -C package ."
|
|
128
|
+
end
|
|
129
|
+
platform :darwin do
|
|
130
|
+
run "tar -czf dist/myapp-1.0.tar.gz -C package ."
|
|
131
|
+
end
|
|
132
|
+
platform :windows do
|
|
133
|
+
echo "Creating zip archive on Windows"
|
|
134
|
+
run "powershell -NoProfile -Command \"Compress-Archive -Path package/* -DestinationPath dist/myapp-1.0.zip -Force\""
|
|
135
|
+
end
|
|
87
136
|
remove "package"
|
|
88
137
|
end
|
|
89
138
|
|
|
@@ -92,5 +141,86 @@ target :all, description: "Build, test, and package" do
|
|
|
92
141
|
depends_on :package
|
|
93
142
|
end
|
|
94
143
|
|
|
144
|
+
target :show_info, description: "Show host and environment info" do
|
|
145
|
+
echo "Host OS: ${HOST_OS}"
|
|
146
|
+
echo "Host Architecture: ${HOST_ARCH}"
|
|
147
|
+
echo "CPU Count: ${CPU_COUNT}"
|
|
148
|
+
echo "User: ${USER}"
|
|
149
|
+
echo "Home Directory: ${HOME}"
|
|
150
|
+
echo "Temp Directory: ${TEMP_DIR}"
|
|
151
|
+
echo "Build Time: ${BUILD_TIME}"
|
|
152
|
+
echo "Build Timestamp: ${BUILD_TIMESTAMP}"
|
|
153
|
+
echo "Ruby: ${RUBY_VERSION}"
|
|
154
|
+
echo "PWD: ${PWD}"
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
target :gen_config, description: "Generate config from template" do
|
|
158
|
+
depends_on :setup
|
|
159
|
+
template "templates/app_config.tpl", "dist/config.txt"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Demonstrate write/append utilities
|
|
163
|
+
target :write_demo, description: "Write and append notes" do
|
|
164
|
+
depends_on :setup
|
|
165
|
+
write "dist/notes.txt", "Build Notes\n"
|
|
166
|
+
append "dist/notes.txt", "Host: ${HOST_OS} ${HOST_ARCH}\n"
|
|
167
|
+
append "dist/notes.txt", "User: ${USER}\n"
|
|
168
|
+
append "dist/notes.txt", "Built at: ${BUILD_TIME}\n"
|
|
169
|
+
append "dist/notes.txt", "CPU Count: ${CPU_COUNT}\n"
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Demonstrate environment handling
|
|
173
|
+
target :env_demo, description: "Run with temporary environment" do
|
|
174
|
+
with_env("MY_FLAG" => "42") do |ctx|
|
|
175
|
+
run "ruby -e \"puts ENV['MY_FLAG']\""
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Demonstrate optional symlink on Unix-like systems
|
|
180
|
+
target :symlink_demo, description: "Create a symlink to myapp (Unix only)" do
|
|
181
|
+
depends_on :build
|
|
182
|
+
platform :linux do
|
|
183
|
+
symlink "dist/myapp", "dist/myapp_link"
|
|
184
|
+
end
|
|
185
|
+
platform :darwin do
|
|
186
|
+
symlink "dist/myapp", "dist/myapp_link"
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Parallel demonstration: compile sources and tests concurrently
|
|
191
|
+
target :parallel_compile, description: "Compile sources and tests in parallel" do
|
|
192
|
+
parallel :compile_sources, :compile_tests
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Demonstrate conditional logic with system variables
|
|
196
|
+
target :system_specific, description: "Show system-specific behavior" do
|
|
197
|
+
echo "Detected system: ${HOST_OS} on ${HOST_ARCH}"
|
|
198
|
+
|
|
199
|
+
conditional(get_variable("HOST_OS") == "windows") do
|
|
200
|
+
echo "Running Windows-specific commands"
|
|
201
|
+
echo "User profile: ${HOME}"
|
|
202
|
+
echo "Temp directory: ${TEMP_DIR}"
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
conditional(get_variable("HOST_ARCH") == "x64") do
|
|
206
|
+
echo "64-bit architecture detected"
|
|
207
|
+
echo "Using optimized 64-bit settings"
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Show CPU-based logic
|
|
211
|
+
echo "System has ${CPU_COUNT} CPU cores available"
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Aggregate demo target
|
|
215
|
+
target :demo, description: "Run all demonstration features" do
|
|
216
|
+
depends_on :show_info
|
|
217
|
+
depends_on :gen_config
|
|
218
|
+
depends_on :write_demo
|
|
219
|
+
depends_on :env_demo
|
|
220
|
+
depends_on :system_specific
|
|
221
|
+
depends_on :build
|
|
222
|
+
depends_on :symlink_demo
|
|
223
|
+
end
|
|
224
|
+
|
|
95
225
|
# Set the default target
|
|
96
|
-
default :build
|
|
226
|
+
default :build
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#include <iostream>
|
|
2
|
+
#include <cassert>
|
|
3
|
+
#include "../include/hello.hpp"
|
|
4
|
+
|
|
5
|
+
int main() {
|
|
6
|
+
std::string msg = hello();
|
|
7
|
+
assert(msg == "Hello from Erebrus example");
|
|
8
|
+
std::cout << "Test passed: hello() returns expected message" << std::endl;
|
|
9
|
+
return 0;
|
|
10
|
+
}
|
data/lib/erebrus/build_engine.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require "pathname"
|
|
2
|
+
require "rbconfig"
|
|
2
3
|
|
|
3
4
|
module Erebrus
|
|
4
5
|
class BuildEngine
|
|
@@ -14,6 +15,19 @@ module Erebrus
|
|
|
14
15
|
@included_files = Set.new
|
|
15
16
|
@file_watchers = {}
|
|
16
17
|
@conditional_stack = []
|
|
18
|
+
@progress_total = 0
|
|
19
|
+
@progress_count = 0
|
|
20
|
+
@progress_enabled = false
|
|
21
|
+
@progress_line_open = false
|
|
22
|
+
# Predefine useful system and build variables
|
|
23
|
+
@variables["HOST_OS"] = detect_host_os
|
|
24
|
+
@variables["HOST_ARCH"] = detect_host_arch
|
|
25
|
+
@variables["CPU_COUNT"] = detect_cpu_count
|
|
26
|
+
@variables["USER"] = detect_user
|
|
27
|
+
@variables["HOME"] = detect_home_dir
|
|
28
|
+
@variables["TEMP_DIR"] = detect_temp_dir
|
|
29
|
+
@variables["BUILD_TIME"] = Time.now.strftime("%Y-%m-%d %H:%M:%S")
|
|
30
|
+
@variables["BUILD_TIMESTAMP"] = Time.now.to_i.to_s
|
|
17
31
|
end
|
|
18
32
|
|
|
19
33
|
def target(name, description: nil, namespace: nil, &block)
|
|
@@ -126,8 +140,16 @@ module Erebrus
|
|
|
126
140
|
|
|
127
141
|
merged_context = @variables.merge(context)
|
|
128
142
|
|
|
143
|
+
# Setup build-level progress bar across targets to execute
|
|
144
|
+
target_obj = @targets[target_name]
|
|
145
|
+
to_run = collect_targets_to_run(target_obj)
|
|
146
|
+
@progress_total = to_run.size
|
|
147
|
+
@progress_count = 0
|
|
148
|
+
@progress_enabled = $stdout.respond_to?(:isatty) && $stdout.isatty
|
|
149
|
+
|
|
129
150
|
reset_all_targets!
|
|
130
151
|
execute_target(target_obj, merged_context)
|
|
152
|
+
finish_progress_bar if @progress_enabled
|
|
131
153
|
end
|
|
132
154
|
|
|
133
155
|
def list_targets(namespace: nil)
|
|
@@ -218,8 +240,8 @@ module Erebrus
|
|
|
218
240
|
return if target.executed
|
|
219
241
|
|
|
220
242
|
unless target.conditions.all? { |condition| condition.call(context) }
|
|
221
|
-
puts "Skipping target '#{target_name}' (conditions not met)"
|
|
222
243
|
target.executed = true
|
|
244
|
+
increment_progress!
|
|
223
245
|
return
|
|
224
246
|
end
|
|
225
247
|
|
|
@@ -233,7 +255,10 @@ module Erebrus
|
|
|
233
255
|
execute_target(dep_target, context, visited.dup)
|
|
234
256
|
end
|
|
235
257
|
|
|
258
|
+
# Ensure progress bar line is terminated before any action output
|
|
259
|
+
finish_progress_bar if @progress_enabled
|
|
236
260
|
target.execute(context)
|
|
261
|
+
increment_progress!
|
|
237
262
|
|
|
238
263
|
visited.delete(target_name)
|
|
239
264
|
end
|
|
@@ -241,6 +266,103 @@ module Erebrus
|
|
|
241
266
|
def reset_all_targets!
|
|
242
267
|
@targets.each_value(&:reset!)
|
|
243
268
|
end
|
|
269
|
+
|
|
270
|
+
# Progress helpers -------------------------------------------------------
|
|
271
|
+
def collect_targets_to_run(root)
|
|
272
|
+
seen = Set.new
|
|
273
|
+
stack = [root]
|
|
274
|
+
until stack.empty?
|
|
275
|
+
t = stack.pop
|
|
276
|
+
next if seen.include?(t.name)
|
|
277
|
+
|
|
278
|
+
seen.add(t.name)
|
|
279
|
+
t.dependencies.each do |dep|
|
|
280
|
+
dep_name = resolve_target_name(dep)
|
|
281
|
+
dt = @targets[dep_name]
|
|
282
|
+
stack << dt if dt
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
seen
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def increment_progress!
|
|
289
|
+
return unless @progress_enabled
|
|
290
|
+
|
|
291
|
+
@progress_count += 1
|
|
292
|
+
print_progress_bar(@progress_count, @progress_total)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def print_progress_bar(current, total)
|
|
296
|
+
current = [current, total].min
|
|
297
|
+
percent = total.zero? ? 100 : ((current.to_f / total) * 100).round
|
|
298
|
+
bar_length = 30
|
|
299
|
+
filled = (percent * bar_length / 100.0).round
|
|
300
|
+
bar = "[" + "#" * filled + " " * (bar_length - filled) + "]"
|
|
301
|
+
$stdout.print "\rProgress #{bar} #{percent}% (#{current}/#{total})"
|
|
302
|
+
$stdout.flush
|
|
303
|
+
@progress_line_open = true
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def finish_progress_bar
|
|
307
|
+
return unless @progress_enabled
|
|
308
|
+
return unless @progress_line_open
|
|
309
|
+
|
|
310
|
+
$stdout.puts
|
|
311
|
+
@progress_line_open = false
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
private
|
|
315
|
+
|
|
316
|
+
def detect_host_os
|
|
317
|
+
host = RbConfig::CONFIG["host_os"].downcase
|
|
318
|
+
case host
|
|
319
|
+
when /mswin|mingw|cygwin/
|
|
320
|
+
"windows"
|
|
321
|
+
when /darwin|mac os/
|
|
322
|
+
"macos"
|
|
323
|
+
when /linux/
|
|
324
|
+
"linux"
|
|
325
|
+
when /freebsd|openbsd|netbsd/
|
|
326
|
+
"bsd"
|
|
327
|
+
else
|
|
328
|
+
"unknown"
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def detect_host_arch
|
|
333
|
+
arch = RbConfig::CONFIG["host_cpu"].downcase
|
|
334
|
+
case arch
|
|
335
|
+
when /x86_64|amd64/
|
|
336
|
+
"x64"
|
|
337
|
+
when /i[3-6]86/
|
|
338
|
+
"x86"
|
|
339
|
+
when /arm64|aarch64/
|
|
340
|
+
"arm64"
|
|
341
|
+
when /arm/
|
|
342
|
+
"arm"
|
|
343
|
+
else
|
|
344
|
+
arch
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def detect_cpu_count
|
|
349
|
+
require "etc"
|
|
350
|
+
Etc.nprocessors.to_s
|
|
351
|
+
rescue StandardError
|
|
352
|
+
"1"
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def detect_user
|
|
356
|
+
ENV["USER"] || ENV["USERNAME"] || "unknown"
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def detect_home_dir
|
|
360
|
+
ENV["HOME"] || ENV["USERPROFILE"] || Dir.pwd
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def detect_temp_dir
|
|
364
|
+
ENV["TMPDIR"] || ENV["TMP"] || ENV["TEMP"] || "/tmp"
|
|
365
|
+
end
|
|
244
366
|
end
|
|
245
367
|
|
|
246
368
|
class TargetContext
|
|
@@ -277,10 +399,83 @@ module Erebrus
|
|
|
277
399
|
@target.action(&block)
|
|
278
400
|
end
|
|
279
401
|
|
|
402
|
+
def echo(message)
|
|
403
|
+
@target.action do |context|
|
|
404
|
+
puts expand_variables(message, context)
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def sleep(seconds)
|
|
409
|
+
@target.action do |context|
|
|
410
|
+
s = expand_variables(seconds, context)
|
|
411
|
+
Kernel.sleep(s.to_f)
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
def move(source, destination)
|
|
416
|
+
@target.action do |context|
|
|
417
|
+
expanded_source = expand_variables(source, context)
|
|
418
|
+
expanded_dest = expand_variables(destination, context)
|
|
419
|
+
require "fileutils"
|
|
420
|
+
FileUtils.mv(expanded_source, expanded_dest)
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
def symlink(target, link_name)
|
|
425
|
+
@target.action do |context|
|
|
426
|
+
expanded_target = expand_variables(target, context)
|
|
427
|
+
expanded_link = expand_variables(link_name, context)
|
|
428
|
+
require "fileutils"
|
|
429
|
+
FileUtils.ln_s(expanded_target, expanded_link, force: true)
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
def write(file, content)
|
|
434
|
+
@target.action do |context|
|
|
435
|
+
expanded_file = expand_variables(file, context)
|
|
436
|
+
expanded_content = expand_variables(content, context)
|
|
437
|
+
File.write(expanded_file, expanded_content)
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
def append(file, content)
|
|
442
|
+
@target.action do |context|
|
|
443
|
+
expanded_file = expand_variables(file, context)
|
|
444
|
+
expanded_content = expand_variables(content, context)
|
|
445
|
+
File.open(expanded_file, "a") { |f| f.write(expanded_content) }
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
def with_env(vars = {})
|
|
450
|
+
@target.action do |context|
|
|
451
|
+
merged = vars.transform_keys(&:to_s).transform_values { |v| expand_variables(v, context).to_s }
|
|
452
|
+
backup = {}
|
|
453
|
+
merged.each do |k, v|
|
|
454
|
+
backup[k] = ENV[k]
|
|
455
|
+
ENV[k] = v
|
|
456
|
+
end
|
|
457
|
+
begin
|
|
458
|
+
yield(context) if block_given?
|
|
459
|
+
ensure
|
|
460
|
+
merged.each_key { |k| ENV[k] = backup[k] }
|
|
461
|
+
end
|
|
462
|
+
end
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def run_set(name, command)
|
|
466
|
+
@target.action do |context|
|
|
467
|
+
expanded_command = expand_variables(command, context)
|
|
468
|
+
puts "Running (capture): #{expanded_command}"
|
|
469
|
+
result = `#{expanded_command}`
|
|
470
|
+
raise Error, "Command failed: #{expanded_command}" unless $?.success?
|
|
471
|
+
|
|
472
|
+
@engine&.set_variable(name, result.chomp)
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
|
|
280
476
|
def run(command, options = {})
|
|
281
477
|
@target.action do |context|
|
|
282
478
|
expanded_command = expand_variables(command, context)
|
|
283
|
-
puts "Running: #{expanded_command}"
|
|
284
479
|
|
|
285
480
|
if options[:capture]
|
|
286
481
|
result = `#{expanded_command}`
|
|
@@ -297,8 +492,6 @@ module Erebrus
|
|
|
297
492
|
@target.action do |context|
|
|
298
493
|
expanded_source = expand_variables(source, context)
|
|
299
494
|
expanded_dest = expand_variables(destination, context)
|
|
300
|
-
|
|
301
|
-
puts "Copying #{expanded_source} to #{expanded_dest}"
|
|
302
495
|
require "fileutils"
|
|
303
496
|
|
|
304
497
|
if options[:preserve]
|
|
@@ -312,7 +505,6 @@ module Erebrus
|
|
|
312
505
|
def mkdir(path)
|
|
313
506
|
@target.action do |context|
|
|
314
507
|
expanded_path = expand_variables(path, context)
|
|
315
|
-
puts "Creating directory: #{expanded_path}"
|
|
316
508
|
require "fileutils"
|
|
317
509
|
FileUtils.mkdir_p(expanded_path)
|
|
318
510
|
end
|
|
@@ -321,7 +513,6 @@ module Erebrus
|
|
|
321
513
|
def remove(path)
|
|
322
514
|
@target.action do |context|
|
|
323
515
|
expanded_path = expand_variables(path, context)
|
|
324
|
-
puts "Removing: #{expanded_path}"
|
|
325
516
|
require "fileutils"
|
|
326
517
|
FileUtils.rm_rf(expanded_path)
|
|
327
518
|
end
|
|
@@ -330,7 +521,6 @@ module Erebrus
|
|
|
330
521
|
def touch(path)
|
|
331
522
|
@target.action do |context|
|
|
332
523
|
expanded_path = expand_variables(path, context)
|
|
333
|
-
puts "Touching: #{expanded_path}"
|
|
334
524
|
require "fileutils"
|
|
335
525
|
FileUtils.touch(expanded_path)
|
|
336
526
|
end
|
|
@@ -339,7 +529,6 @@ module Erebrus
|
|
|
339
529
|
def chmod(mode, path)
|
|
340
530
|
@target.action do |context|
|
|
341
531
|
expanded_path = expand_variables(path, context)
|
|
342
|
-
puts "Changing permissions of #{expanded_path} to #{mode}"
|
|
343
532
|
require "fileutils"
|
|
344
533
|
FileUtils.chmod(mode, expanded_path)
|
|
345
534
|
end
|
|
@@ -349,8 +538,6 @@ module Erebrus
|
|
|
349
538
|
@target.action do |context|
|
|
350
539
|
expanded_url = expand_variables(url, context)
|
|
351
540
|
expanded_dest = expand_variables(destination, context)
|
|
352
|
-
|
|
353
|
-
puts "Downloading #{expanded_url} to #{expanded_dest}"
|
|
354
541
|
require "net/http"
|
|
355
542
|
require "uri"
|
|
356
543
|
|
|
@@ -371,8 +558,6 @@ module Erebrus
|
|
|
371
558
|
expanded_template = expand_variables(template_file, context)
|
|
372
559
|
expanded_output = expand_variables(output_file, context)
|
|
373
560
|
|
|
374
|
-
puts "Processing template #{expanded_template} -> #{expanded_output}"
|
|
375
|
-
|
|
376
561
|
template_content = File.read(expanded_template)
|
|
377
562
|
merged_vars = context.merge(variables)
|
|
378
563
|
|
data/lib/erebrus/target.rb
CHANGED
|
@@ -75,15 +75,8 @@ module Erebrus
|
|
|
75
75
|
|
|
76
76
|
start_time = Time.now
|
|
77
77
|
|
|
78
|
-
puts "Executing target: #{@name}"
|
|
79
|
-
puts " #{@description}" if @description
|
|
80
|
-
puts " Namespace: #{@namespace}" if @namespace
|
|
81
|
-
puts " Tags: #{@tags.join(", ")}" unless @tags.empty?
|
|
82
|
-
|
|
83
78
|
begin
|
|
84
79
|
@actions.each_with_index do |action, index|
|
|
85
|
-
puts " Action #{index + 1}/#{@actions.size}" if @actions.size > 1
|
|
86
|
-
|
|
87
80
|
if action.arity == 0
|
|
88
81
|
action.call
|
|
89
82
|
else
|
|
@@ -93,11 +86,7 @@ module Erebrus
|
|
|
93
86
|
|
|
94
87
|
@executed = true
|
|
95
88
|
@last_run = Time.now
|
|
96
|
-
|
|
97
|
-
execution_time = Time.now - start_time
|
|
98
|
-
puts " Completed in #{execution_time.round(2)}s"
|
|
99
89
|
rescue StandardError => e
|
|
100
|
-
puts " Failed: #{e.message}"
|
|
101
90
|
raise Error, "Target '#{@name}' failed: #{e.message}"
|
|
102
91
|
end
|
|
103
92
|
end
|
data/lib/erebrus/version.rb
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
module Erebrus
|
|
2
|
-
VERSION = "0.1.
|
|
3
|
-
end
|
|
2
|
+
VERSION = "0.1.2"
|
|
3
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
module Erebrus
|
|
2
|
+
class BuildEngine
|
|
3
|
+
attr_reader targets: Hash[String, Erebrus::Target]
|
|
4
|
+
attr_reader namespaces: Hash[String, Array[String]]
|
|
5
|
+
attr_reader variables: Hash[String, untyped]
|
|
6
|
+
attr_reader included_files: ::Set[String]
|
|
7
|
+
|
|
8
|
+
attr_accessor current_namespace: String?
|
|
9
|
+
|
|
10
|
+
def initialize: () -> void
|
|
11
|
+
|
|
12
|
+
def target: ((String | Symbol) name, description?: String?, namespace?: String?, ?{ () -> void }) -> Erebrus::Target
|
|
13
|
+
def namespace: ((String | Symbol) name) { () -> void } -> void
|
|
14
|
+
def include_buildfile: (String file_path, namespace?: String?) -> void
|
|
15
|
+
|
|
16
|
+
def set_variable: ((String | Symbol) name, untyped value) -> void
|
|
17
|
+
def get_variable: ((String | Symbol) name, untyped? default) -> untyped
|
|
18
|
+
|
|
19
|
+
def conditional: (untyped condition) { () -> void } -> void
|
|
20
|
+
|
|
21
|
+
def platform?: ((String | Symbol) name) -> bool
|
|
22
|
+
def file_exists?: (String path) -> bool
|
|
23
|
+
def directory_exists?: (String path) -> bool
|
|
24
|
+
|
|
25
|
+
def default: ((String | Symbol) target_name) -> void
|
|
26
|
+
def build: (? (String | Symbol) target_name, ?Hash[Symbol | String, untyped] context) -> void
|
|
27
|
+
|
|
28
|
+
def list_targets: (namespace?: String) -> void
|
|
29
|
+
def list_namespaces: () -> void
|
|
30
|
+
|
|
31
|
+
def watch_file: (String pattern) { (String) -> untyped } -> void
|
|
32
|
+
def check_file_changes: () -> void
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class TargetContext
|
|
36
|
+
def initialize: (Erebrus::Target target, ?Erebrus::BuildEngine engine) -> void
|
|
37
|
+
|
|
38
|
+
def depends_on: (* (String | Symbol) deps) -> Erebrus::Target
|
|
39
|
+
def depends_on_files: (* String files) -> Erebrus::Target
|
|
40
|
+
def produces: (* String files) -> Erebrus::Target
|
|
41
|
+
|
|
42
|
+
def condition: () ?{ (Hash[Symbol | String, untyped]) -> bool } -> Erebrus::Target
|
|
43
|
+
def only_if: ((::Proc | Symbol | String | bool) condition) -> Erebrus::Target
|
|
44
|
+
|
|
45
|
+
def tag: (* (String | Symbol) tags) -> Erebrus::Target
|
|
46
|
+
|
|
47
|
+
def action: () { () -> untyped } -> Erebrus::Target
|
|
48
|
+
| () { (Hash[Symbol | String, untyped]) -> untyped } -> Erebrus::Target
|
|
49
|
+
| () -> Erebrus::Target
|
|
50
|
+
|
|
51
|
+
def run: (String command, Hash[Symbol, untyped]? options) -> Erebrus::Target
|
|
52
|
+
def copy: (String source, String destination, Hash[Symbol, untyped]? options) -> Erebrus::Target
|
|
53
|
+
def mkdir: (String path) -> Erebrus::Target
|
|
54
|
+
def remove: (String path) -> Erebrus::Target
|
|
55
|
+
def touch: (String path) -> Erebrus::Target
|
|
56
|
+
def chmod: (Integer mode, String path) -> Erebrus::Target
|
|
57
|
+
def download: (String url, String destination) -> Erebrus::Target
|
|
58
|
+
def template: (String template_file, String output_file, Hash[Symbol | String, untyped]? variables) -> Erebrus::Target
|
|
59
|
+
def parallel: (* (String | Symbol) targets) -> Erebrus::Target
|
|
60
|
+
|
|
61
|
+
def conditional: (untyped condition) { (Hash[Symbol | String, untyped]) -> untyped } -> Erebrus::Target
|
|
62
|
+
def platform: ((String | Symbol) name) { (Hash[Symbol | String, untyped]) -> untyped } -> Erebrus::Target
|
|
63
|
+
def file_exists: (String path) { (Hash[Symbol | String, untyped]) -> untyped } -> Erebrus::Target
|
|
64
|
+
def directory_exists: (String path) { (Hash[Symbol | String, untyped]) -> untyped } -> Erebrus::Target
|
|
65
|
+
|
|
66
|
+
def set_variable: ((String | Symbol) name, untyped value) -> Erebrus::Target
|
|
67
|
+
def get_variable: ((String | Symbol) name, untyped? default) -> untyped
|
|
68
|
+
|
|
69
|
+
def echo: (String message) -> Erebrus::Target
|
|
70
|
+
def sleep: ((Integer | Float | String) seconds) -> Erebrus::Target
|
|
71
|
+
def move: (String source, String destination) -> Erebrus::Target
|
|
72
|
+
def symlink: (String target, String link_name) -> Erebrus::Target
|
|
73
|
+
def write: (String file, String content) -> Erebrus::Target
|
|
74
|
+
def append: (String file, String content) -> Erebrus::Target
|
|
75
|
+
def with_env: (Hash[Symbol | String, untyped] vars) { (Hash[Symbol | String, untyped]) -> untyped } -> Erebrus::Target
|
|
76
|
+
def run_set: ((String | Symbol) name, String command) -> Erebrus::Target
|
|
77
|
+
end
|
|
78
|
+
end
|
data/sig/erebrus/dsl.rbs
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Erebrus
|
|
2
|
+
module DSL
|
|
3
|
+
def self.included: (untyped base) -> void
|
|
4
|
+
|
|
5
|
+
module ClassMethods
|
|
6
|
+
def build_engine: () -> Erebrus::BuildEngine
|
|
7
|
+
|
|
8
|
+
def target: ((String | Symbol) name, description?: String?, namespace?: String?, ?{ () -> void }) -> Erebrus::Target
|
|
9
|
+
def namespace: ((String | Symbol) name) { () -> void } -> void
|
|
10
|
+
def include_buildfile: (String file_path, namespace?: String?) -> void
|
|
11
|
+
|
|
12
|
+
def set_variable: ((String | Symbol) name, untyped value) -> void
|
|
13
|
+
def get_variable: ((String | Symbol) name, untyped? default) -> untyped
|
|
14
|
+
|
|
15
|
+
def conditional: (untyped condition) { () -> void } -> void
|
|
16
|
+
def platform?: ((String | Symbol) name) -> bool
|
|
17
|
+
def default: ((String | Symbol) target_name) -> void
|
|
18
|
+
def build: (? (String | Symbol) target_name, ?Hash[Symbol | String, untyped] context) -> void
|
|
19
|
+
def list_targets: (namespace?: String) -> void
|
|
20
|
+
def list_namespaces: () -> void
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def target: ((String | Symbol) name, description?: String?, namespace?: String?, ?{ () -> void }) -> Erebrus::Target
|
|
24
|
+
def namespace: ((String | Symbol) name) { () -> void } -> void
|
|
25
|
+
def include_buildfile: (String file_path, namespace?: String?) -> void
|
|
26
|
+
|
|
27
|
+
def set_variable: ((String | Symbol) name, untyped value) -> void
|
|
28
|
+
def get_variable: ((String | Symbol) name, untyped? default) -> untyped
|
|
29
|
+
|
|
30
|
+
def conditional: (untyped condition) { () -> void } -> void
|
|
31
|
+
def platform?: ((String | Symbol) name) -> bool
|
|
32
|
+
def default: ((String | Symbol) target_name) -> void
|
|
33
|
+
def build: (? (String | Symbol) target_name, ?Hash[Symbol | String, untyped] context) -> void
|
|
34
|
+
def list_targets: (namespace?: String) -> void
|
|
35
|
+
def list_namespaces: () -> void
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Erebrus
|
|
2
|
+
class Target
|
|
3
|
+
attr_reader name: String
|
|
4
|
+
attr_reader dependencies: Array[String]
|
|
5
|
+
attr_reader description: String?
|
|
6
|
+
attr_reader conditions: Array[::Proc]
|
|
7
|
+
attr_reader file_dependencies: Array[String]
|
|
8
|
+
attr_reader outputs: Array[String]
|
|
9
|
+
|
|
10
|
+
attr_accessor executed: bool
|
|
11
|
+
attr_accessor namespace: String?
|
|
12
|
+
attr_accessor tags: Array[String]
|
|
13
|
+
attr_accessor priority: Integer
|
|
14
|
+
|
|
15
|
+
def initialize: ((String | Symbol) name, ?description: String?) -> void
|
|
16
|
+
|
|
17
|
+
def depends_on: (* (String | Symbol) deps) -> Erebrus::Target
|
|
18
|
+
def depends_on_files: (* String files) -> Erebrus::Target
|
|
19
|
+
def produces: (* String files) -> Erebrus::Target
|
|
20
|
+
|
|
21
|
+
def condition: () ?{ (Hash[Symbol | String, untyped]) -> bool } -> Erebrus::Target
|
|
22
|
+
def only_if: ((::Proc | Symbol | String | bool) condition) -> Erebrus::Target
|
|
23
|
+
|
|
24
|
+
def tag: (* (String | Symbol) tags) -> Erebrus::Target
|
|
25
|
+
|
|
26
|
+
def action: () { () -> untyped } -> Erebrus::Target
|
|
27
|
+
| () { (Hash[Symbol | String, untyped]) -> untyped } -> Erebrus::Target
|
|
28
|
+
| () -> Erebrus::Target
|
|
29
|
+
|
|
30
|
+
def needs_execution?: (?Hash[Symbol | String, untyped]) -> bool
|
|
31
|
+
def execute: (?Hash[Symbol | String, untyped]) -> void
|
|
32
|
+
def reset!: () -> void
|
|
33
|
+
def file_dependencies_changed?: () -> bool
|
|
34
|
+
def to_s: () -> String
|
|
35
|
+
def inspect: () -> String
|
|
36
|
+
end
|
|
37
|
+
end
|
data/sig/erebrus.rbs
CHANGED
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
module Erebrus
|
|
2
2
|
VERSION: String
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
class Error < ::StandardError
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def self.target: ((String | Symbol) name, description?: String?, namespace?: String?, ?{ () -> void }) -> Erebrus::Target
|
|
8
|
+
def self.namespace: ((String | Symbol) name) { () -> void } -> void
|
|
9
|
+
def self.include_buildfile: (String file_path, namespace?: String?) -> void
|
|
10
|
+
|
|
11
|
+
def self.set_variable: ((String | Symbol) name, untyped value) -> void
|
|
12
|
+
def self.get_variable: ((String | Symbol) name, untyped? default) -> untyped
|
|
13
|
+
|
|
14
|
+
def self.conditional: (untyped condition) { () -> void } -> void
|
|
15
|
+
def self.platform?: ((String | Symbol) name) -> bool
|
|
16
|
+
def self.default: ((String | Symbol) target_name) -> void
|
|
17
|
+
def self.build: (? (String | Symbol) target_name, ?Hash[Symbol | String, untyped] context) -> void
|
|
18
|
+
def self.list_targets: (namespace?: String) -> void
|
|
19
|
+
def self.list_namespaces: () -> void
|
|
20
|
+
|
|
21
|
+
def self.load_buildfile: (String file_path) -> void
|
|
22
|
+
def self.reset!: () -> void
|
|
4
23
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: erebrus
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- jel9
|
|
@@ -34,13 +34,22 @@ files:
|
|
|
34
34
|
- README.md
|
|
35
35
|
- Rakefile
|
|
36
36
|
- bin/erebrus
|
|
37
|
+
- examples/.gitignore
|
|
37
38
|
- examples/Buildfile
|
|
39
|
+
- examples/include/hello.hpp
|
|
40
|
+
- examples/src/hello.cpp
|
|
41
|
+
- examples/src/main.cpp
|
|
42
|
+
- examples/templates/app_config.tpl
|
|
43
|
+
- examples/tests/test_main.cpp
|
|
38
44
|
- lib/erebrus.rb
|
|
39
45
|
- lib/erebrus/build_engine.rb
|
|
40
46
|
- lib/erebrus/dsl.rb
|
|
41
47
|
- lib/erebrus/target.rb
|
|
42
48
|
- lib/erebrus/version.rb
|
|
43
49
|
- sig/erebrus.rbs
|
|
50
|
+
- sig/erebrus/build_engine.rbs
|
|
51
|
+
- sig/erebrus/dsl.rbs
|
|
52
|
+
- sig/erebrus/target.rbs
|
|
44
53
|
homepage: https://github.com/daedalus-os/erebrus
|
|
45
54
|
licenses: []
|
|
46
55
|
metadata:
|
|
@@ -62,5 +71,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
62
71
|
requirements: []
|
|
63
72
|
rubygems_version: 3.6.9
|
|
64
73
|
specification_version: 4
|
|
65
|
-
summary: Modern
|
|
74
|
+
summary: Modern Ruby based build system like make.
|
|
66
75
|
test_files: []
|