diff --git a/bin/rubyc b/bin/rubyc index e2f1b8956..adb7cb3e1 100644 --- a/bin/rubyc +++ b/bin/rubyc @@ -15,7 +15,6 @@ class Compiler def initialize(argv) @mode = :normal @archs = [] - @frameworks = [] @internal = argv.delete('--internal') # Parse arguments. @@ -24,8 +23,8 @@ class Compiler opts.on('-c', 'Compile and assemble, but do not link') { @dont_link = true } opts.on('-o ', 'Place the output into ') { |output| @output = output } #opts.on('--mode [MODE]', "Select compilation mode (normal or full)") { |mode| @mode = mode.intern } - #opts.on('--framework ', 'Link against ') { |path| @frameworks << path } - opts.on('--static', "Create a standalone static executable") { @static = true } + opts.on('--static', "Create a standalone static executable") { @static = true } + opts.on('--dylib', "Create a dynamic library") { @dylib = true } opts.on('-C', 'Compile, assemble and link a loadable object file') { @bundle = true } opts.on('-a', '--arch ', 'Compile for specified CPU architecture') { |arch| @archs << arch } opts.on('-v', '--version', 'Display the version') { puts RUBY_DESCRIPTION; exit 1 } @@ -74,6 +73,7 @@ class Compiler end if @dont_link or @bundle die "Cannot specify --static when not building an executable" if @static + die "Cannot specify -c or -C when building a dynamic library" if @dylib die "Cannot specify -c and -C at the same time" if @bundle and @dont_link if @files.size > 1 and @output die "Cannot specify -o with -c or -C and multiple input files" @@ -88,18 +88,26 @@ class Compiler compile_object(file, @output) end else + die "Cannot specify --static and --dylib at the same time" if @dylib and @static objs = @files.map do |file| + die "Given input file `#{file} must exist" unless File.exist?(file) case File.extname(file) when '.rb' compile_object(file, nil) when '.o' - die "Given input file `#{file} must exist" unless File.exist?(file) - file + [file, find_init_func(file)] + when '.dylib' + [file, nil] else - die "Given input file `#{file}' must be either a Ruby source file (.rb) or a Mach-O object file (.o)" + die "Given input file `#{file}' must be either a Ruby source file (.rb) or a Mach-O object file (.o) or dynamic library (.dylib)" end end - compile_executable(objs, @output) + if @dylib + die "-o must be specified when building a dynamic library" unless @output + compile_dylib(objs, @output) + else + compile_executable(objs, @output) + end end end @@ -149,6 +157,7 @@ class Compiler output ||= File.join(File.dirname(file), base + '.rbo') + # Generate main file. main_txt = < aot_features; + +extern "C" +bool +rb_vm_aot_feature_load(const char *name) +{ + std::string key(name); + std::map::iterator iter = aot_features.find(name); + if (iter == aot_features.end()) { + return false; + } + void *init_func = iter->second; + ((void *(*)(void *, void *))init_func)((void *)rb_vm_top_self(), NULL); + aot_features.erase(iter); + return true; +} + +extern "C" +void +rb_vm_aot_feature_provide(const char *name, void *init_func) +{ + std::string key(name); + std::map::iterator iter = aot_features.find(key); + if (iter != aot_features.end()) { + printf("WARNING: AOT feature '%s' already registered, new one will be ignored. This could happen if you link your executable against dylibs that contain the same Ruby file.\n", name); + } + aot_features[key] = init_func; +} + extern "C" void Init_PostVM(void) diff --git a/vm.h b/vm.h index e5aee03a5..3e2d39b95 100644 --- a/vm.h +++ b/vm.h @@ -413,6 +413,8 @@ Class rb_vm_get_current_class(void); bool rb_vm_is_multithreaded(void); void rb_vm_set_multithreaded(bool flag); +bool rb_vm_aot_feature_load(const char *name); + static inline VALUE rb_robject_allocate_instance(VALUE klass) { @@ -584,11 +586,13 @@ class RoxorCore { // be empty when we exit and we need to call the remaining finalizers. std::vector finalizers; + // The global lock. + pthread_mutex_t gl; + // State. bool running; bool multithreaded; bool abort_on_exception; - pthread_mutex_t gl; VALUE loaded_features; VALUE load_path; VALUE rand_seed; @@ -803,7 +807,8 @@ class RoxorCore { void invalidate_respond_to_cache(void) { respond_to_cache.clear(); } - bool respond_to(VALUE obj, VALUE klass, SEL sel, bool priv, bool check_override); + bool respond_to(VALUE obj, VALUE klass, SEL sel, bool priv, + bool check_override); private: bool register_bs_boxed(bs_element_type_t type, void *value);