mwc 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+
5
+ require 'mwc/utils/command_registry'
6
+ require 'mwc/config'
7
+ require 'mwc/commands/init'
8
+ require 'mwc/commands/compile'
9
+ require 'mwc/commands/server'
10
+
11
+ module Mwc
12
+ # :nodoc:
13
+ class Command < Thor
14
+ include Utils::CommandRegistry
15
+
16
+ desc 'version', 'show version'
17
+ def version
18
+ puts Mwc::VERSION
19
+ end
20
+
21
+ add_command Commands::Init
22
+ add_command Commands::Compile
23
+ add_command Commands::Server
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor/rake_compat'
4
+
5
+ require 'mwc/utils/command'
6
+ require 'mwc/tasks'
7
+ require 'mwc'
8
+
9
+ module Mwc
10
+ module Commands
11
+ # Compile mruby to wasm
12
+ class Compile < Thor::Group
13
+ include Utils::Command
14
+
15
+ name 'compile'
16
+ description 'compile source code to wasm'
17
+ display_on { Mwc.config.exist? }
18
+ add_option :format, default: 'html', enum: %w[html js wasm]
19
+
20
+ def compile
21
+ Tasks.new
22
+ Rake::Task[parent_options['format']].invoke
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mwc/utils/command'
4
+ require 'mwc'
5
+
6
+ module Mwc
7
+ module Commands
8
+ # Create a new project
9
+ class Init < Thor::Group
10
+ include Thor::Actions
11
+ include Utils::Command
12
+
13
+ name 'init'
14
+ usage 'init NAME'
15
+ description 'create a new project'
16
+ display_on { !Mwc.config.exist? }
17
+ argument :name, type: :string, desc: 'project name'
18
+
19
+ def create_project
20
+ empty_directory(name)
21
+ self.destination_root = name
22
+ Mwc.root = destination_root
23
+ end
24
+
25
+ # :nodoc:
26
+ def create_mwcrc
27
+ template('mwcrc.erb', '.mwcrc')
28
+ end
29
+
30
+ # :nodoc:
31
+ def setup_project
32
+ empty_directory('vendor')
33
+ empty_directory('dist')
34
+ empty_directory('src/js')
35
+ copy_file('config/build.rb')
36
+ copy_file('.gitignore')
37
+ end
38
+
39
+ # :nodoc:
40
+ def download_mruby
41
+ Mwc.config.reload!
42
+ # TODO: Allow choose download mode
43
+ inside(mruby_directory.dirname) do
44
+ run("curl -OL #{archive_url}")
45
+ run("tar -zxf #{filename}")
46
+ remove_file(filename)
47
+ run("mv mruby-#{version} #{mruby_directory}")
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def version
54
+ Mwc.config.mruby.version
55
+ end
56
+
57
+ # :nodoc:
58
+ def archive_url
59
+ "https://github.com/mruby/mruby/archive/#{filename}"
60
+ end
61
+
62
+ # :nodoc:
63
+ def filename
64
+ "#{version}.tar.gz"
65
+ end
66
+
67
+ def mruby_directory
68
+ Mwc.config.mruby.path
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rack'
4
+
5
+ require 'mwc/utils/command'
6
+ require 'mwc/server'
7
+ require 'mwc'
8
+
9
+ module Mwc
10
+ module Commands
11
+ # :nodoc:
12
+ class Server < Thor::Group
13
+ include Utils::Command
14
+
15
+ name 'server'
16
+ description 'serve compiled wasm'
17
+ add_option :port, type: :numeric, default: 8080
18
+
19
+ def boot
20
+ Rack::Handler
21
+ .default
22
+ .run(Mwc::Server.new, Port: parent_options['port'])
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mwc'
4
+
5
+ module Mwc
6
+ # The compile options
7
+ class CompileOptions
8
+ # :nodoc:
9
+ EXTRA_JS_TYPE = {
10
+ library_js: '--js-library',
11
+ pre_js: '--pre-js',
12
+ post_js: '--post-js'
13
+ }.freeze
14
+
15
+ OPTIONS = %i[shell source_map extra].freeze
16
+
17
+ # :nodoc:
18
+ def initialize(options = {})
19
+ @options = []
20
+
21
+ options.each do |name, value|
22
+ handler = "add_#{name}"
23
+ send(handler, value) if respond_to?(handler)
24
+ end
25
+
26
+ OPTIONS.each { |name| send("setup_#{name}") }
27
+ output(options[:format])
28
+ end
29
+
30
+ # Setup shell file
31
+ #
32
+ # @since 0.2.0
33
+ # @api private
34
+ def setup_shell
35
+ return if Mwc.config.project.shell.nil?
36
+
37
+ path = Mwc.root.join(Mwc.config.project.shell)
38
+ @options.push "--shell-file #{path}"
39
+ end
40
+
41
+ # Setup source map
42
+ #
43
+ # @since 0.2.0
44
+ # @api private
45
+ def setup_source_map
46
+ return unless Mwc.config.project.source_map
47
+
48
+ @options.push '-g4 --source-map-base /'
49
+ end
50
+
51
+ # Setup extra options
52
+ #
53
+ # @since 0.2.0
54
+ # @api private
55
+ def setup_extra
56
+ return unless Mwc.config.project.options.any?
57
+
58
+ Mwc.config.project.options.each do |name, value|
59
+ @options.push "-s #{name}=#{value}"
60
+ end
61
+ end
62
+
63
+ # Convert options to string
64
+ #
65
+ # @return [String] the options
66
+ def to_s
67
+ @options.join(' ')
68
+ end
69
+
70
+ # Configure extra javacript
71
+ #
72
+ # @since 0.2.0
73
+ # @api private
74
+ %i[library_js pre_js post_js].each do |type|
75
+ define_method "add_#{type}" do |items|
76
+ items.each do |path|
77
+ @options.push "#{EXTRA_JS_TYPE[type]} #{path}"
78
+ end
79
+ end
80
+ end
81
+
82
+ private
83
+
84
+ # Configure output format
85
+ #
86
+ # @param foramt [String] output format
87
+ #
88
+ # @since 0.1.0
89
+ # @api private
90
+ def output(format)
91
+ @options.push "-o dist/#{Mwc.config.project.name}.#{format}"
92
+ end
93
+ end
94
+ end
data/lib/mwc/config.rb ADDED
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'singleton'
5
+
6
+ require 'mwc/project'
7
+ require 'mwc/mruby'
8
+ require 'mwc'
9
+
10
+ module Mwc
11
+ # The compile preferences
12
+ class Config
13
+ class << self
14
+ extend Forwardable
15
+
16
+ delegate %i[
17
+ exist?
18
+ mruby
19
+ ] => :instance
20
+ end
21
+
22
+ include Singleton
23
+
24
+ attr_reader :project, :mruby
25
+
26
+ # :nodoc:
27
+ def initialize
28
+ @path = Mwc.root.join('.mwcrc')
29
+ @project = Project.new
30
+ @mruby = MRuby.new
31
+
32
+ load_config if exist?
33
+ end
34
+
35
+ # TODO: Move to DSL module
36
+ # Set name
37
+ #
38
+ # @param name [String|NilClass] the name
39
+ #
40
+ # @since 0.1.0
41
+ # @api private
42
+ def name(name = nil)
43
+ return @name if name.nil?
44
+
45
+ @name = name.to_s
46
+ end
47
+
48
+ # Check config file exists
49
+ #
50
+ # @return [TrueClass,FalseClass] exist or not
51
+ #
52
+ # @since 0.1.0
53
+ # @api private
54
+ def exist?
55
+ @path.exist?
56
+ end
57
+
58
+ # Reload config
59
+ #
60
+ # @since 0.1.0
61
+ # @api private
62
+ def reload!
63
+ # TODO: Update path when root changed
64
+ @path = Mwc.root.join('.mwcrc')
65
+ return unless exist?
66
+
67
+ load_config
68
+ end
69
+
70
+ private
71
+
72
+ # Laod .mwcrc config
73
+ #
74
+ # @since 0.1.0
75
+ # @api private
76
+ def load_config
77
+ # TODO: Improve config DSL
78
+ instance_eval(@path.read)
79
+ end
80
+ end
81
+ end
data/lib/mwc/mruby.rb ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mwc'
4
+
5
+ module Mwc
6
+ # MRuby config
7
+ class MRuby
8
+ attr_accessor :version
9
+
10
+ def path
11
+ Mwc.root.join('vendor/mruby')
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mwc
4
+ # The project settings
5
+ class Project
6
+ attr_accessor :name, :shell, :source_map
7
+ attr_reader :options
8
+
9
+ # :nodoc:
10
+ def initialize
11
+ @options = {}
12
+ end
13
+
14
+ # Add customize options
15
+ #
16
+ # @param name [String] the option name
17
+ # @param value [String] the option value
18
+ #
19
+ # @since 0.2.0
20
+ # @api private
21
+ def option(name, value)
22
+ @options[name] = value
23
+ end
24
+ end
25
+ end
data/lib/mwc/server.rb ADDED
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+ require 'forwardable'
5
+ require 'rack'
6
+
7
+ require 'mwc'
8
+
9
+ module Mwc
10
+ # Static assets server
11
+ class Server
12
+ WASM_RULE = /\.(?:wasm)\z/.freeze
13
+ WASM_HEADER = { 'Content-Type' => 'application/wasm' }.freeze
14
+
15
+ def initialize
16
+ @static =
17
+ Rack::Static.new(
18
+ ->(_) { [404, {}, []] },
19
+ root: 'dist', # TODO: Set by config
20
+ index: "#{Mwc.config.project.name}.html",
21
+ urls: [''],
22
+ header_rules: [
23
+ [WASM_RULE, WASM_HEADER]
24
+ ]
25
+ )
26
+ end
27
+
28
+ def call(env)
29
+ @static.call(env)
30
+ end
31
+ end
32
+ end
data/lib/mwc/tasks.rb ADDED
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake/tasklib'
4
+
5
+ require 'mwc/compile_options'
6
+ require 'mwc'
7
+
8
+ module Mwc
9
+ # :nodoc:
10
+ class Tasks < Rake::TaskLib
11
+ SOURCES = FileList['src/**/*.c']
12
+ BINARIES = SOURCES.ext('bc')
13
+ LIBRARY_JS = FileList['src/js/**/*.lib.js']
14
+ PRE_JS = FileList['src/js/**/*.pre.js']
15
+ POST_JS = FileList['src/js/**/*.post.js']
16
+
17
+ # :nodoc:
18
+ def initialize
19
+ return unless mruby_directory.join('Rakefile').exist?
20
+
21
+ namespace :mruby do
22
+ ENV['MRUBY_CONFIG'] = Mwc.root.join('config', 'build.rb').to_s
23
+ # TODO: Prevent load error breaks command
24
+ load mruby_directory.join('Rakefile')
25
+ end
26
+
27
+ compile_binary_task
28
+ compile_wasm_task
29
+ end
30
+
31
+ private
32
+
33
+ # :nodoc:
34
+ def compile_binary_task
35
+ rule '.bc' => SOURCES do |task|
36
+ sh "emcc -I #{mruby_directory.join('include')} -I include -c " \
37
+ "#{task.source} -o #{task.name}"
38
+ end
39
+ end
40
+
41
+ # :nodoc:
42
+ def compile_wasm_task
43
+ %i[wasm html js].each do |format|
44
+ task "mruby.#{format}" => ['mruby:all'].concat(BINARIES) do
45
+ compile(format)
46
+ end
47
+
48
+ desc "Compile sources to #{format} WebAssembly"
49
+ task format => "mruby.#{format}"
50
+ end
51
+ end
52
+
53
+ # :nodoc:
54
+ def compile(format)
55
+ do_compile CompileOptions.new(
56
+ format: format,
57
+ library_js: LIBRARY_JS,
58
+ pre_js: PRE_JS,
59
+ post_js: POST_JS
60
+ )
61
+ end
62
+
63
+ # :nodoc:
64
+ def do_compile(options)
65
+ sh "emcc #{sources.join(' ')} #{options}"
66
+ end
67
+
68
+ # :nodoc:
69
+ def libmruby
70
+ mruby_directory.join('build/wasm/lib/libmruby.bc')
71
+ end
72
+
73
+ # :nodoc:
74
+ def sources
75
+ [libmruby].concat(BINARIES)
76
+ end
77
+
78
+ # :nodoc:
79
+ def mruby_directory
80
+ Mwc.config.mruby.path
81
+ end
82
+ end
83
+ end