Merge: nitdoc: does not apply header style to span elements anymore.
[nit.git] / src / compiler / abstract_compiler.nit
index ddd7323..dfe463c 100644 (file)
@@ -120,20 +120,16 @@ redef class ModelBuilder
        # Simple indirection to `Toolchain::write_and_make`
        protected fun write_and_make(compiler: AbstractCompiler)
        do
-               var platform = compiler.mainmodule.target_platform
-               var toolchain
-               if platform == null then
-                       toolchain = new MakefileToolchain(toolcontext)
-               else
-                       toolchain = platform.toolchain(toolcontext)
-               end
+               var platform = compiler.target_platform
+               var toolchain = platform.toolchain(toolcontext)
                compile_dir = toolchain.compile_dir
                toolchain.write_and_make compiler
        end
 end
 
 redef class Platform
-       fun toolchain(toolcontext: ToolContext): Toolchain is abstract
+       # The specific tool-chain associated to the platform
+       fun toolchain(toolcontext: ToolContext): Toolchain do return new MakefileToolchain(toolcontext)
 end
 
 class Toolchain
@@ -189,10 +185,10 @@ class MakefileToolchain
 
        fun write_files(compiler: AbstractCompiler, compile_dir: String, cfiles: Array[String])
        do
-               var platform = compiler.mainmodule.target_platform
-               if self.toolcontext.opt_stacktrace.value == "nitstack" and (platform == null or platform.supports_libunwind) then compiler.build_c_to_nit_bindings
+               var platform = compiler.target_platform
+               if self.toolcontext.opt_stacktrace.value == "nitstack" and platform.supports_libunwind then compiler.build_c_to_nit_bindings
                var cc_opt_with_libgc = "-DWITH_LIBGC"
-               if platform != null and not platform.supports_libgc then cc_opt_with_libgc = ""
+               if not platform.supports_libgc then cc_opt_with_libgc = ""
 
                # Add gc_choser.h to aditionnal bodies
                var gc_chooser = new ExternCFile("gc_chooser.c", cc_opt_with_libgc)
@@ -311,7 +307,7 @@ class MakefileToolchain
        fun write_makefile(compiler: AbstractCompiler, compile_dir: String, cfiles: Array[String])
        do
                var mainmodule = compiler.mainmodule
-               var platform = compiler.mainmodule.target_platform
+               var platform = compiler.target_platform
 
                var outname = outfile(mainmodule)
 
@@ -336,7 +332,7 @@ class MakefileToolchain
                makefile.write("CC = ccache cc\nCXX = ccache c++\nCFLAGS = -g -O2 -Wno-unused-value -Wno-switch -Wno-attributes\nCINCL =\nLDFLAGS ?= \nLDLIBS  ?= -lm {linker_options.join(" ")}\n\n")
 
                var ost = toolcontext.opt_stacktrace.value
-               if (ost == "libunwind" or ost == "nitstack") and (platform == null or platform.supports_libunwind) then makefile.write("NEED_LIBUNWIND := YesPlease\n")
+               if (ost == "libunwind" or ost == "nitstack") and platform.supports_libunwind then makefile.write("NEED_LIBUNWIND := YesPlease\n")
 
                # Dynamic adaptations
                # While `platform` enable complex toolchains, they are statically applied
@@ -371,6 +367,18 @@ class MakefileToolchain
                        dep_rules.add(o)
                end
 
+               # Generate linker script, if any
+               if not compiler.linker_script.is_empty then
+                       var linker_script_path = "{compile_dir}/linker_script"
+                       ofiles.add "linker_script"
+                       var f = new OFStream.open(linker_script_path)
+                       for l in compiler.linker_script do
+                               f.write l
+                               f.write "\n"
+                       end
+                       f.close
+               end
+
                var java_files = new Array[ExternFile]
 
                var pkgconfigs = new Array[String]
@@ -476,11 +484,19 @@ abstract class AbstractCompiler
        # Is hardening asked? (see --hardening)
        fun hardening: Bool do return self.modelbuilder.toolcontext.opt_hardening.value
 
+       # The targeted specific platform
+       var target_platform: Platform is noinit
+
        init
        do
                self.realmainmodule = mainmodule
+               target_platform = mainmodule.target_platform or else new Platform
        end
 
+       # Do the full code generation of the program `mainmodule`
+       # It is the main method usually called after the instantiation
+       fun do_compilation is abstract
+
        # Force the creation of a new file
        # The point is to avoid contamination between must-be-compiled-separately files
        fun new_file(name: String): CodeFile
@@ -507,6 +523,10 @@ abstract class AbstractCompiler
        # Where global declaration are stored (the main .h)
        var header: CodeWriter is writable, noinit
 
+       # Additionnal linker script for `ld`.
+       # Mainly used to do specific link-time symbol resolution
+       var linker_script = new Array[String]
+
        # Provide a declaration that can be requested (before or latter) by a visitor
        fun provide_declaration(key: String, s: String)
        do
@@ -677,11 +697,11 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref );
                var v = self.new_visitor
                v.add_decl("#include <signal.h>")
                var ost = modelbuilder.toolcontext.opt_stacktrace.value
-               var platform = mainmodule.target_platform
+               var platform = target_platform
 
-               if platform != null and not platform.supports_libunwind then ost = "none"
+               if not platform.supports_libunwind then ost = "none"
 
-               var no_main = (platform != null and platform.no_main) or modelbuilder.toolcontext.opt_no_main.value
+               var no_main = platform.no_main or modelbuilder.toolcontext.opt_no_main.value
 
                if ost == "nitstack" or ost == "libunwind" then
                        v.add_decl("#define UNW_LOCAL_ONLY")
@@ -1458,10 +1478,11 @@ abstract class AbstractCompilerVisitor
                self.require_declaration(s)
        end
 
-       # look for a needed .h and .c file for a given .nit source-file
-       # FIXME: bad API, parameter should be a `MModule`, not its source-file
-       fun add_extern(file: String)
+       # Look for a needed .h and .c file for a given module
+       # This is used for the legacy FFI
+       fun add_extern(mmodule: MModule)
        do
+               var file = mmodule.location.file.filename
                file = file.strip_extension(".nit")
                var tryfile = file + ".nit.h"
                if tryfile.file_exists then
@@ -2151,16 +2172,13 @@ redef class AMethPropdef
        do
                var externname
                var at = self.get_single_annotation("extern", v.compiler.modelbuilder)
-               if at != null then
+               if at != null and at.n_args.length == 1 then
                        externname = at.arg_as_string(v.compiler.modelbuilder)
                        if externname == null then return false
                else
                        return false
                end
-               if location.file != null then
-                       var file = location.file.filename
-                       v.add_extern(file)
-               end
+               v.add_extern(mpropdef.mclassdef.mmodule)
                var res: nullable RuntimeVariable = null
                var ret = mpropdef.msignature.return_mtype
                if ret != null then
@@ -2192,10 +2210,7 @@ redef class AMethPropdef
                else
                        return false
                end
-               if location.file != null then
-                       var file = location.file.filename
-                       v.add_extern(file)
-               end
+               v.add_extern(mpropdef.mclassdef.mmodule)
                v.adapt_signature(mpropdef, arguments)
                v.unbox_signature_extern(mpropdef, arguments)
                var ret = arguments.first.mtype