-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathmake.rb
427 lines (369 loc) · 14.4 KB
/
make.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
#!/usr/bin/env ruby
#******************************************************************************
#
# make.rb - launch build with default options
#
#******************************************************************************
#******************************************************************************
#
# Display and validate options
#
# This secion is responsible to control which options are available, parse them,
# and verify their coherence.
#
#******************************************************************************
require 'fileutils'
require 'stringio'
require 'tmpdir'
require 'open3'
require 'optparse'
# Force stdout to flush its content immediately
STDOUT.sync = true
# Initialize global variables
$script_dir = File.expand_path(File.dirname(__FILE__))
$build_dir = File.join($script_dir, "build")
$lib_dir = ENV["SR_LIB_DIR"] || File.join($build_dir, "libs")
$lib_dir = $lib_dir.gsub("\\", "/")
# Parse command-line arguments into options
$options = {}
if $system_windows
$processes = ["stingray_editor_backend.exe", "stingray_editor.exe", "stingray_win32_dev.exe", "stingray_win32_debug.exe",
"stingray_win32_release.exe", "stingray_win64_dev.exe", "stingray_win64_debug.exe", "stingray_win64_release.exe", "console.exe"]
else
$processes = []
end
require_relative 'tools/common.rb'
# Parse command-line arguments into options
def parse_options(argv, options)
options[:extra_plugins] = []
opt_parser = OptionParser.new do |opts|
opts.banner = "Usage: make.rb [options]"
opts.separator ""
opts.separator "Common Options:"
opts.on("-p", "--platform PLATFORM", "Platform to target (#{$platforms.join(", ")}, #{$platform_aliases.keys.join(", ")})") { |v| options[:platform] = v }
opts.on("-c", "--config CONFIGURATION", "Build configuration to use (#{$configs.join(", ")})") { |v| options[:config] = v }
opts.on("-e", "--devenv ENVIRONMENT", "Development environment to use (#{$devenvs.join(", ")})") { |v| options[:devenv] = v }
opts.on("-t", "--target TARGET", "Target project to build (default is all)") { |v| options[:target] = v }
opts.on("-o", "--output DIRECTORY", "Binaries output directory (override SR_BIN_DIR)") { |v| options[:output] = v }
opts.on("-g", "--[no-]generate", "Generate project files (default)") { |v| options[:generate] = v }
opts.on("-b", "--[no-]build", "Launch a build of generated project files (default)") { |v| options[:build] = v }
opts.on("-z", "--[no-]debug-info", "Enable debug information in all configurations (default)") { |v| options[:debug_info] = v }
opts.on("-r", "--rebuild", "Clean all output targets before build") { |v| options[:rebuild] = v }
opts.on("-x", "--clean", "Clean all output targets only") { |v| options[:clean] = v }
opts.on("--[no-]engine", "Enable Engine target") { |v| options[:engine] = v }
opts.on("--[no-]editor", "Enable Editor target") { |v| options[:editor] = v }
opts.separator ""
opts.separator "Other Options:"
opts.on("-k", "--kill", "Kill running processes") { |v| options[:kill] = v }
opts.on("-u", "--[no-]update", "Update library directory with latest versions (default)") { |v| options[:update] = v }
opts.on("-v", "--[no-]verbose", "Print detailed build informations") { |v| options[:verbose] = v }
opts.on("--distrib", "Bundle your plugin for distribution") { |v| options[:distrib] = v }
opts.on("--pause", "Pause system on completion or error") { |v| options[:pause] = v }
opts.on("-h", "--help", "Prints this help") do
puts opts
exit 1
end
end
# Parse options
begin
opt_parser.parse(argv)
rescue OptionParser::ParseError => e
puts e
puts
puts opt_parser
exit 1
end
return opt_parser
end
# Validate options
def validate_options(options, opt_parser)
if options[:verbose] == nil
options[:verbose] = true
end
# Test or set default platform
if options[:platform] == nil
options[:platform] = $default_platform
else
#Check if platform is an alias
if $platform_aliases.has_key?(options[:platform])
# Enable options for this alias
$platform_alias_options[options[:platform]].each do |plugin|
options[plugin] = true
end
# Switch the platform to what it's an alias for
options[:platform_alias] = options[:platform]
options[:platform] = $platform_aliases[options[:platform]]
end
if !$platforms.include?(options[:platform])
puts "\nError: Invalid platform '#{options[:platform]}' specified.".bold.red
puts
puts "Valid choices are one of: #{$platforms.join(", ")}, #{$platform_aliases.keys.join(", ")}"
exit 1
end
end
# Make sure the host system can build this platform
if !$platforms_whitelist[$system_name].include?(options[:platform])
puts "\nError: Platform '#{options[:platform]}' is not supported on #{$system_name} host system.".bold.red
exit 1
end
# Test or set default configuration
if options[:config] == nil
options[:config] = $default_config
else
if !$configs.include?(options[:config])
puts "\nError: Invalid configuration '#{options[:config]}' specified.".bold.red
puts
puts "Valid choices are one of: #{$configs.join(", ")}"
exit 1
end
if options[:distrib]
puts "\nOption --config has no effect in distrib builds.".bold.yellow
end
end
# Test or set default development environment
if options[:devenv] == nil
options[:devenv] = $default_devenv[options[:platform]]
else
if !$devenvs.include?(options[:devenv])
puts "\nError: Invalid development environment '#{options[:devenv]}' specified.".bold.red
puts
puts "Valid choices are one of: #{$devenvs.join(", ")}"
exit 1
end
if !$devenvs_whitelist[options[:platform]].include?(options[:devenv])
puts "\nError: Platform '#{options[:platform]}' using development environment '#{options[:devenv]}' is not supported.".bold.red
exit 1
end
end
# Test or set default target
if options[:target] == nil
if $system_windows and options[:devenv].include?("msvc")
options[:target] = "build"
else
options[:target] = "install"
end
end
# Enable debug info in all configurations by default
if options[:debug_info] == nil
options[:debug_info] = true
end
# Rebuild or Clean implies Build and Kill
if options[:rebuild] or options[:clean]
options[:build] = true
options[:kill] = true
end
# Set default build products if none specified
if options[:engine] == nil and options[:editor] == nil
options[:engine] = true
options[:editor] = options[:devenv] == "msvc14"
end
# Disable some products not supported by platform
if options[:platform] != "win64"
options[:editor] = false
end
# Set default output dir
if options[:output] == nil
options[:output] = File.join($script_dir, "plugin/binaries")
end
options[:output] = options[:output].gsub("\\", "/")
# Make sure output dir is not equal to build dir
if options[:output] == $build_dir
puts "\nError: Output directory cannot be the same as build directory!".bold.red
puts "Output directory: #{options[:output]}"
exit 1
end
end
def is_verbose?
return $options[:verbose]
end
# Check if the user has a custom file that indicates what to build.
if File.exist?('make_args.txt') || File.exist?('.makeargs')
make_arg_file_name = File.exist?('make_args.txt') ? 'make_args.txt' : '.makeargs'
make_file_args = File.open(make_arg_file_name).read.strip.gsub(/#[^{].*[\r\n]?/, "").gsub(/\s+/, " ")
validate_options($options, parse_options(make_file_args.split(" ").concat(ARGV), $options))
else
validate_options($options, parse_options(ARGV, $options))
end
# Update libraries by default
if $options[:update] == nil
$options[:update] = true
end
# Generate projects by default
if $options[:generate] == nil
$options[:generate] = true
end
# Launch build by default
if $options[:build] == nil and $options[:rebuild] == nil and $options[:clean] == nil
$options[:build] = true
end
# Enable debug info in all configurations by default
if $options[:debug_info] == nil
$options[:debug_info] = true
end
#******************************************************************************
#
# Generate and build targets
#
# This secion is responsible for generating and building targets.
#
#******************************************************************************
start_time = Time.now
# Update libraries
report_block($options[:update], "packages", "Downloading") do
command = ["ruby", "./tools/spm.rb", "install-group", "--lib-dir", "\"#{$lib_dir}\"", "common"]
command << "engine" if $options[:engine]
command << "editor" if $options[:editor]
command << "distrib" if $options[:distrib]
command << "--platforms"
command << $options[:platform]
command << "--devenvs"
if $options[:devenv].include?("msvc")
if $options[:devenv] == "msvc12"
command << "vc12"
elsif $options[:devenv] == "msvc11"
command << "vc11"
elsif $options[:devenv] == "msvc14"
command << "vc14"
else
puts "\nERROR: Unknown development environment for spm.rb script!".bold.red
exit 1
end
else
command << $options[:devenv]
end
# Go and run spm
run_or_die(command.join(" "), false, true, true)
end
# Setup build system
report_block("plugin", "Configuring", true) do
# Test cmake binaries exist
$cmake_bin = File.join(find_package_root($options[:platform], $options[:devenv], "cmake"), $system_windows ? "win/cmake.exe" : $system_mac ? "mac/cmake" : "linux/cmake")
if $cmake_bin == nil or !File.exist?($cmake_bin)
puts "\nERROR: CMake binaries not found in library path!".bold.red
exit 1
end
# Make sure the cmake binary has executable bit set on Unix based systems
if !$system_windows
if !File.stat($cmake_bin).executable?
File.chmod(0755, $cmake_bin)
end
end
# Setup NMake JOM build environment on Windows if using makefile
if $system_windows and $options[:devenv] == "makefile"
# Locate NMake JOM in library directory
$jom_dir = find_package_root($options[:platform], $options[:devenv], "jom")
$jom_bin = File.join($jom_dir, "jom.exe")
if $jom_bin == nil or !File.exist?($jom_bin)
puts "\nERROR: JOM binary not found in library path!".bold.red
exit 1
end
# Make sure JOM binary is in PATH for CMake to find it
jom_path = which("jom.exe")
if jom_path == nil
ENV["PATH"] = "#{$jom_dir};#{ENV["PATH"]}"
else
if !jom_path.include?($lib_dir)
puts "\nWARNING: JOM binary location found in PATH, but expected to find it here:".bold.yellow
puts $jom_bin
end
end
end
# Setup Emscripten build environment if targeting platform Web
if $options[:platform] == "web"
if ENV["EMSDK"] == nil
# Locate Emscripten in library directory
$emsdk_dir = find_package_root($options[:platform], $options[:devenv], "emsdk")
if $emsdk_dir == nil or !Dir.exists?($emsdk_dir)
puts "\nERROR: Emscripten not found in library path!".bold.red
exit 1
end
# Find Emscripten directories
$emsdk_emscripten_dir = File.dirname(Dir.glob("#{$emsdk_dir}/**/emcc.bat").first)
$emsdk_llvm_dir = File.dirname(Dir.glob("#{$emsdk_dir}/**/clang.exe").first)
$emsdk_binaryen_dir = File.expand_path(File.join(File.dirname(Dir.glob("#{$emsdk_dir}/**/asm2wasm.exe").first), "../"))
$emsdk_nodejs = Dir.glob("#{$emsdk_dir}/**/node.exe").first
$emsdk_python = Dir.glob("#{$emsdk_dir}/**/python.exe").first
$emsdk_java = Dir.glob("#{$emsdk_dir}/**/java.exe").first
$emsdk_optimizer = Dir.glob("#{$emsdk_dir}/**/optimizer.exe").first
$emsdk_config = File.join($emsdk_dir, ".emscripten")
$emsdk_config_sanity = $emsdk_config + "_sanity"
$emsdk_cache_dir = File.join($emsdk_dir, ".emscripten_cache")
$emsdk_tmp_dir = (ENV["SR_TMP_DIR"] || Dir.tmpdir).gsub("\\", "/")
# Find Emscripten and LLVM version
$emsdk_emscripten_version = File.read(File.join($emsdk_emscripten_dir, "emscripten-version.txt")).lines[0].gsub(/[\n\r"]/, '')
Open3.popen3("#{File.join($emsdk_llvm_dir, "clang.exe")} -v") do |stdin, stdout, stderr, wait_thr|
$emsdk_llvm_version = stderr.read.lines[0][/[\d].[\d]/]
end
# Temporarily override Emscripten environment
ENV["EMSDK"] = $emsdk_dir
ENV["EM_CONFIG"] = $emsdk_config
ENV["EM_CACHE"] = $emsdk_cache_dir
ENV["BINARYEN_ROOT"] = $emsdk_binaryen_dir
ENV["JAVA_HOME"] = File.dirname($emsdk_java)
ENV["EMSCRIPTEN"] = $emsdk_emscripten_dir
# Temporarily add paths to PATH environment
ENV["PATH"] = "#{$emsdk_dir};#{ENV["PATH"]}"
ENV["PATH"] = "#{$emsdk_llvm_dir};#{ENV["PATH"]}"
ENV["PATH"] = "#{File.dirname($emsdk_nodejs)};#{ENV["PATH"]}"
ENV["PATH"] = "#{File.dirname($emsdk_python)};#{ENV["PATH"]}"
ENV["PATH"] = "#{File.dirname($emsdk_java)};#{ENV["PATH"]}"
ENV["PATH"] = "#{$emsdk_emscripten_dir};#{ENV["PATH"]}"
# Make sure directories exist
FileUtils.mkdir_p($emsdk_cache_dir) unless Dir.exists?($emsdk_cache_dir)
FileUtils.mkdir_p($emsdk_tmp_dir) unless Dir.exists?($emsdk_tmp_dir)
else
$emsdk_emscripten_dir = ENV["EMSCRIPTEN"].gsub("\\", "/")
end
end
# Kill running processes
if $options[:kill]
if ["win32", "win64", "osx"].include?($options[:platform])
$processes.each { |process| kill_process(process) }
end
end
# Run clean operations
if $options[:clean] or $options[:rebuild]
dirs = []
if $options[:editor]
dirs << "editor" << "tools"
end
if $options[:engine]
dirs << "engine"
end
dirs.each{|entry| FileUtils.rm_rf(File.join($options[:output], entry))}
elsif !!which("npm")
Dir.chdir(File.join($script_dir)) {
run_process("npm install", is_verbose?, $options[:pause])
}
end
end
# Build engine components
report_block(File.exist?(File.join($script_dir, "engine")) && $options[:engine], "", "", true) do
if $options[:distrib]
build_configs = ["dev", "release"]
else
build_configs = [$options[:config]]
end
cmake_report("engine plugin", build_configs)
cmake_build(File.join($script_dir, "engine"), File.join($build_dir, "engine/#{$options[:platform]}"), build_configs)
end
# Build editor components
report_block(File.exist?(File.join($script_dir, "editor")) && $options[:editor], "", "", true) do
build_configs = $options[:distrib] ? ["release"] : ["dev"]
cmake_report("editor plugin", build_configs)
cmake_build(File.join($script_dir, "editor"), File.join($build_dir, "editor/#{$options[:platform]}"), build_configs)
end
#******************************************************************************
#******************************************************************************
#******************************************************************************
# Print total time elapsed
puts "\nSUCCESSFULLY COMPLETED!".bold.green
puts "Total Time Elapsed: %.2f seconds." % (Time.now - start_time)
# Pause if requested
if $options[:pause]
if $system_windows
system "pause"
else
system "read -p \"Press any key to continue...\""
end
end