nitg/pnacl: automate option no_main
[nit.git] / src / abstract_compiler.nit
index c9fe617..831311d 100644 (file)
@@ -20,7 +20,6 @@ module abstract_compiler
 import literal
 import typing
 import auto_super_init
-import frontend
 import platform
 import c_tools
 
@@ -30,6 +29,8 @@ redef class ToolContext
        var opt_output: OptionString = new OptionString("Output file", "-o", "--output")
        # --no-cc
        var opt_no_cc: OptionBool = new OptionBool("Do not invoke C compiler", "--no-cc")
+       # --no-main
+       var opt_no_main: OptionBool = new OptionBool("Do not generate main entry point", "--no-main")
        # --cc-paths
        var opt_cc_path: OptionArray = new OptionArray("Set include path for C header files (may be used more than once)", "--cc-path")
        # --make-flags
@@ -64,7 +65,7 @@ redef class ToolContext
        redef init
        do
                super
-               self.option_context.add_option(self.opt_output, self.opt_no_cc, self.opt_make_flags, self.opt_compile_dir, self.opt_hardening, self.opt_no_shortcut_range)
+               self.option_context.add_option(self.opt_output, self.opt_no_cc, self.opt_no_main, self.opt_make_flags, self.opt_compile_dir, self.opt_hardening, self.opt_no_shortcut_range)
                self.option_context.add_option(self.opt_no_check_covariance, self.opt_no_check_attr_isset, self.opt_no_check_assert, self.opt_no_check_autocast, self.opt_no_check_other)
                self.option_context.add_option(self.opt_typing_test_metrics, self.opt_invocation_metrics, self.opt_isset_checks_metrics)
                self.option_context.add_option(self.opt_stacktrace)
@@ -539,12 +540,19 @@ abstract class AbstractCompiler
                var v = self.new_visitor
                v.add_decl("#include <signal.h>")
                var ost = modelbuilder.toolcontext.opt_stacktrace.value
+               var platform = mainmodule.target_platform
 
                if ost == null then
-                       ost = "nitstack"
+                       if platform != null and not platform.supports_libunwind then
+                               ost = "none"
+                       else
+                               ost = "nitstack"
+                       end
                        modelbuilder.toolcontext.opt_stacktrace.value = ost
                end
 
+               if platform != null and platform.no_main then modelbuilder.toolcontext.opt_no_main.value = true
+
                if ost == "nitstack" or ost == "libunwind" then
                        v.add_decl("#define UNW_LOCAL_ONLY")
                        v.add_decl("#include <libunwind.h>")
@@ -621,7 +629,11 @@ abstract class AbstractCompiler
                v.add_decl("exit(signo);")
                v.add_decl("\}")
 
-               v.add_decl("int main(int argc, char** argv) \{")
+               if modelbuilder.toolcontext.opt_no_main.value then
+                       v.add_decl("int nit_main(int argc, char** argv) \{")
+               else
+                       v.add_decl("int main(int argc, char** argv) \{")
+               end
 
                v.add("signal(SIGABRT, sig_handler);")
                v.add("signal(SIGFPE, sig_handler);")
@@ -2690,3 +2702,44 @@ redef class MModule
        # Note: can return null instead of an empty set
        fun collect_linker_libs: nullable Set[String] do return null
 end
+
+# Create a tool context to handle options and paths
+var toolcontext = new ToolContext
+
+var opt_mixins = new OptionArray("Additionals module to min-in", "-m")
+toolcontext.option_context.add_option(opt_mixins)
+
+toolcontext.tooldescription = "Usage: nitg [OPTION]... file.nit\nCompiles Nit programs."
+
+# We do not add other options, so process them now!
+toolcontext.process_options(args)
+
+# We need a model to collect stufs
+var model = new Model
+# An a model builder to parse files
+var modelbuilder = new ModelBuilder(model, toolcontext)
+
+var arguments = toolcontext.option_context.rest
+if arguments.length > 1 then
+       print "Too much arguments: {arguments.join(" ")}"
+       print toolcontext.tooldescription
+       exit 1
+end
+var progname = arguments.first
+
+# Here we load an process all modules passed on the command line
+var mmodules = modelbuilder.parse([progname])
+mmodules.add_all modelbuilder.parse(opt_mixins.value)
+
+if mmodules.is_empty then return
+modelbuilder.run_phases
+
+var mainmodule
+if mmodules.length == 1 then
+       mainmodule = mmodules.first
+else
+       mainmodule = new MModule(model, null, mmodules.first.name, mmodules.first.location)
+       mainmodule.set_imported_mmodules(mmodules)
+end
+
+toolcontext.run_global_phases(mmodules)