Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support of CLI in mrbgem build system. #3976

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 47 additions & 0 deletions Rakefile
Expand Up @@ -24,6 +24,8 @@ end
load "#{MRUBY_ROOT}/src/mruby_core.rake"
load "#{MRUBY_ROOT}/mrblib/mrblib.rake"

load "#{MRUBY_ROOT}/tasks/cli.rake"

load "#{MRUBY_ROOT}/tasks/mrbgems.rake"
load "#{MRUBY_ROOT}/tasks/libmruby.rake"

Expand Down Expand Up @@ -57,6 +59,8 @@ depfiles = MRuby.targets['host'].bins.map do |bin|
end

MRuby.each_target do |target|
gem_table = target.gems.generate_gem_table target

gems.map do |gem|
current_dir = gem.dir.relative_path_from(Dir.pwd)
relative_from_root = gem.dir.relative_path_from(MRUBY_ROOT)
Expand All @@ -70,6 +74,49 @@ MRuby.each_target do |target|
exec = exefile("#{build_dir}/bin/#{bin}")
objs = Dir.glob("#{current_dir}/tools/#{bin}/*.{c,cpp,cxx,cc}").map { |f| objfile(f.pathmap("#{current_build_dir}/tools/#{bin}/%n")) }

rbfiles = Dir.glob("#{current_dir}/tools/#{bin}/*.rb").sort
unless rbfiles.empty?
main_script = "#{current_dir}/tools/#{bin}/main.rb"
has_main_script = rbfiles.find { |v| v == main_script }
rbfiles.reject { |v| v == main_script }
rbfiles << main_script if has_main_script

irep_file = "#{current_build_dir}/tools/#{bin}/tool__#{bin}__init.c"
file exec => libfile("#{build_dir}/lib/libmruby_cli_main") if objs.empty?
objs << objfile(irep_file.pathmap("#{current_build_dir}/tools/#{bin}/%n"))
file objs.last => irep_file

file irep_file => rbfiles do |t|
FileUtils.mkdir_p File.dirname irep_file
open(irep_file, 'w') do |f|
f.puts '#include <mruby.h>'
sym_name = 'mrb_main_irep'
mrbc.run f, t.prerequisites, sym_name

dep_list = target.gems.tsort_dependencies([gem.name], gem_table).select(&:generate_functions)
dep_list.each do |d|
f.puts %Q[void GENERATED_TMP_mrb_#{d.funcname}_gem_init(mrb_state *mrb);]
f.puts %Q[void GENERATED_TMP_mrb_#{d.funcname}_gem_final(mrb_state *mrb);]
end
f.puts 'mrb_state *mrb_open_cli() {'

if g.mrb_open_cli_enabled?
f.puts ' mrb_state *mrb = mrb_open_core(mrb_default_allocf, NULL);'
f.puts ' int ai = mrb_gc_arena_save(mrb);'
dep_list.each do |d|
f.puts %Q[ GENERATED_TMP_mrb_#{d.funcname}_gem_init(mrb);]
f.puts %Q[ mrb_state_atexit(mrb, GENERATED_TMP_mrb_#{d.funcname}_gem_final);]
end
f.puts ' mrb_gc_arena_restore(mrb, ai);'
else
f.puts ' mrb_state *mrb = mrb_open();'
end
f.puts ' return mrb;'
f.puts '}'
end
end
end

file exec => objs + target.libraries do |t|
gem_flags = gems.map { |g| g.linker.flags }
gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries }
Expand Down
7 changes: 7 additions & 0 deletions lib/mruby/gem.rb
Expand Up @@ -47,9 +47,16 @@ def initialize(name, &block)
@version = "0.0.0"
@mrblib_dir = "mrblib"
@objs_dir = "src"
@mrb_open_cli = true
MRuby::Gem.current = self
end

def disable_mrb_open_cli
@mrb_open_cli = false
end

def mrb_open_cli_enabled?; @mrb_open_cli end

def setup
return if defined?(@linker) # return if already set up

Expand Down
9 changes: 9 additions & 0 deletions tasks/cli.rake
@@ -0,0 +1,9 @@
MRuby.each_target do
current = File.dirname(__FILE__).relative_path_from(Dir.pwd)
current_build = "#{build_dir}/#{File.dirname(__FILE__).relative_path_from(MRUBY_ROOT)}"
objs = Dir.glob("#{current}/cli/*.c").map { |f| objfile f.pathmap("#{current_build}/cli/%n") }.flatten

file libfile("#{build_dir}/lib/libmruby_cli_main") => objs do |t|
archiver.run t.name, t.prerequisites
end
end
55 changes: 55 additions & 0 deletions tasks/cli/main.c
@@ -0,0 +1,55 @@
#include <stdio.h>
#include <stdlib.h>

#include "mruby.h"
#include "mruby/array.h"
#include "mruby/irep.h"
#include "mruby/variable.h"

/*
irep that will be generated from *.rb files
if there is main.rb in it, main.rb must be loaded after all other scripts is loaded
*/
extern const uint8_t mrb_main_irep[];

extern mrb_state *mrb_open_cli();

int
main(int argc, char **argv)
{
mrb_state* mrb;
mrb_value ARGV;
int i;
int exit_result = EXIT_SUCCESS;

/* open mrb_state */
mrb = mrb_open_cli();
if (mrb == NULL) {
fputs("cannot open mrb_state\n", stderr);
return EXIT_FAILURE;
}

/* set 'ARGV' */
ARGV = mrb_ary_new_capa(mrb, argc - 1);
for (i = 1; i < argc; ++i) {
mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, argv[i]));
}
mrb_define_global_const(mrb, "ARGV", ARGV);

/* set '$0'-> argv[0] */
mrb_gv_set(mrb, mrb_intern_lit(mrb, "$0"), mrb_str_new_cstr(mrb, argv[0]));

/* load and run script */
mrb_load_irep(mrb, mrb_main_irep);

/* check error */
if (mrb->exc) {
mrb_print_error(mrb);
exit_result = EXIT_FAILURE;
}

/* close mrb_state */
mrb_close(mrb);

return exit_result;
}
2 changes: 1 addition & 1 deletion tasks/toolchains/visualcpp.rake
Expand Up @@ -24,7 +24,7 @@ MRuby::Toolchain.new(:visualcpp) do |conf, _params|

conf.linker do |linker|
linker.command = ENV['LD'] || 'link.exe'
linker.flags = [ENV['LDFLAGS'] || %w(/NOLOGO /DEBUG /INCREMENTAL:NO /OPT:ICF /OPT:REF)]
linker.flags = [ENV['LDFLAGS'] || %w(/NOLOGO /DEBUG /INCREMENTAL:NO /OPT:ICF /OPT:REF /SUBSYSTEM:CONSOLE)]
linker.libraries = %w()
linker.library_paths = %w()
linker.option_library = '%s.lib'
Expand Down