Merge: Clean nit compilation directory
authorJean Privat <jean@pryen.org>
Sat, 30 May 2015 00:37:30 +0000 (20:37 -0400)
committerJean Privat <jean@pryen.org>
Sat, 30 May 2015 00:37:30 +0000 (20:37 -0400)
This PR cause the compilation directory to be removed after compilation.

This auto-removal is disabled if `--compile-dir` or `--no-cc` is used because it is a sane default I think.
Moreover, the compilation directory is renamed by defaut to `nit_compile` because there is no more point to make it hidden since its presence means an active request (`--no-cc`).

The PR is a bit premature since the boostrap will fail since `rmdir` requires the light FFI, so it is planned to be merged after the regen of c_src.

Close #792

Pull-Request: #1415
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Romain Chanoir <chanoir.romain@courrier.uqam.ca>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>

1  2 
src/compiler/abstract_compiler.nit

@@@ -115,15 -115,12 +115,12 @@@ redef class ToolContex
  end
  
  redef class ModelBuilder
-       # The compilation directory
-       var compile_dir: String
        # Simple indirection to `Toolchain::write_and_make`
        protected fun write_and_make(compiler: AbstractCompiler)
        do
                var platform = compiler.target_platform
                var toolchain = platform.toolchain(toolcontext, compiler)
-               compile_dir = toolchain.compile_dir
+               compiler.toolchain = toolchain
                toolchain.write_and_make
        end
  end
@@@ -145,14 -142,21 +142,21 @@@ class Toolchai
        # Compiler of the target program
        var compiler: AbstractCompiler
  
-       # Directory where to generate all C files
-       fun compile_dir: String
+       # Directory where to generate all files
+       #
+       # The option `--compile_dir` change this directory.
+       fun root_compile_dir: String
        do
                var compile_dir = toolcontext.opt_compile_dir.value
-               if compile_dir == null then compile_dir = ".nit_compile"
+               if compile_dir == null then compile_dir = "nit_compile"
                return compile_dir
        end
  
+       # Directory where to generate all C files
+       #
+       # By default it is `root_compile_dir` but some platform may require that it is a subdirectory.
+       fun compile_dir: String do return root_compile_dir
        # Write all C files and compile them
        fun write_and_make is abstract
  end
@@@ -165,12 -169,16 +169,16 @@@ class MakefileToolchai
        do
                var compile_dir = compile_dir
  
+               # Remove the compilation directory unless explicitly set
+               var auto_remove = toolcontext.opt_compile_dir.value == null
                # Generate the .h and .c files
                # A single C file regroups many compiled rumtime functions
                # Note that we do not try to be clever an a small change in a Nit source file may change the content of all the generated .c files
                var time0 = get_time
                self.toolcontext.info("*** WRITING C ***", 1)
  
+               root_compile_dir.mkdir
                compile_dir.mkdir
  
                var cfiles = new Array[String]
  
                compile_c_code(compile_dir)
  
+               if auto_remove then
+                       sys.system("rm -r -- '{root_compile_dir.escape_to_sh}/'")
+               end
                time1 = get_time
                self.toolcontext.info("*** END COMPILING C: {time1-time0} ***", 2)
        end
                var outpath = real_outpath.escape_to_mk
                if outpath != real_outpath then
                        # If the name is crazy and need escaping, we will do an indirection
-                       # 1. generate the binary in the .nit_compile dir under an escaped name
+                       # 1. generate the binary in the nit_compile dir under an escaped name
                        # 2. copy the binary at the right place in the `all` goal.
                        outpath = mainmodule.c_name
                end
@@@ -496,6 -508,11 +508,11 @@@ abstract class AbstractCompile
        # The modelbuilder used to know the model and the AST
        var modelbuilder: ModelBuilder is protected writable
  
+       # The associated toolchain
+       #
+       # Set by `modelbuilder.write_and_make` and permit sub-routines to access the current toolchain if required.
+       var toolchain: Toolchain is noinit
        # Is hardening asked? (see --hardening)
        fun hardening: Bool do return self.modelbuilder.toolcontext.opt_hardening.value
  
        # Binds the generated C function names to Nit function names
        fun build_c_to_nit_bindings
        do
-               var compile_dir = modelbuilder.compile_dir
+               var compile_dir = toolchain.compile_dir
  
                var stream = new FileWriter.open("{compile_dir}/c_functions_hash.c")
                stream.write("#include <string.h>\n")
@@@ -1455,14 -1472,6 +1472,14 @@@ abstract class AbstractCompilerVisito
                return res
        end
  
 +      # Generate a byte value
 +      fun byte_instance(value: Byte): RuntimeVariable
 +      do
 +              var t = mmodule.byte_type
 +              var res = new RuntimeVariable("((unsigned char){value.to_s})", t, t)
 +              return res
 +      end
 +
        # Generate a char value
        fun char_instance(value: Char): RuntimeVariable
        do
@@@ -1846,8 -1855,6 +1863,8 @@@ redef class MClassTyp
                        return "char"
                else if mclass.name == "Float" then
                        return "double"
 +              else if mclass.name == "Byte" then
 +                      return "unsigned char"
                else if mclass.name == "NativeString" then
                        return "char*"
                else if mclass.name == "NativeArray" then
                        return "c"
                else if mclass.name == "Float" then
                        return "d"
 +              else if mclass.name == "Byte" then
 +                      return "b"
                else if mclass.name == "NativeString" then
                        return "str"
                else if mclass.name == "NativeArray" then
@@@ -2110,9 -2115,6 +2127,9 @@@ redef class AMethPropde
                        else if pname == "to_f" then
                                v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
                                return true
 +                      else if pname == "to_b" then
 +                              v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
 +                              return true
                        else if pname == "ascii" then
                                v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
                                return true
                                v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
                                return true
                        end
 +              else if cname == "Byte" then
 +                      if pname == "output" then
 +                              v.add("printf(\"%x\\n\", {arguments.first});")
 +                              return true
 +                      else if pname == "object_id" then
 +                              v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
 +                              return true
 +                      else if pname == "+" then
 +                              v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
 +                              return true
 +                      else if pname == "-" then
 +                              v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
 +                              return true
 +                      else if pname == "unary -" then
 +                              v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
 +                              return true
 +                      else if pname == "unary +" then
 +                              v.ret(arguments[0])
 +                              return true
 +                      else if pname == "*" then
 +                              v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
 +                              return true
 +                      else if pname == "/" then
 +                              v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
 +                              return true
 +                      else if pname == "%" then
 +                              v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
 +                              return true
 +                      else if pname == "lshift" then
 +                              v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
 +                              return true
 +                      else if pname == "rshift" then
 +                              v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
 +                              return true
 +                      else if pname == "==" then
 +                              v.ret(v.equal_test(arguments[0], arguments[1]))
 +                              return true
 +                      else if pname == "!=" then
 +                              var res = v.equal_test(arguments[0], arguments[1])
 +                              v.ret(v.new_expr("!{res}", ret.as(not null)))
 +                              return true
 +                      else if pname == "<" then
 +                              v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
 +                              return true
 +                      else if pname == ">" then
 +                              v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
 +                              return true
 +                      else if pname == "<=" then
 +                              v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
 +                              return true
 +                      else if pname == ">=" then
 +                              v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
 +                              return true
 +                      else if pname == "to_i" then
 +                              v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
 +                              return true
 +                      else if pname == "to_f" then
 +                              v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
 +                              return true
 +                      else if pname == "ascii" then
 +                              v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
 +                              return true
 +                      end
                else if cname == "Bool" then
                        if pname == "output" then
                                v.add("printf({arguments.first}?\"true\\n\":\"false\\n\");")
                        else if pname == "to_i" then
                                v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
                                return true
 +                      else if pname == "to_b" then
 +                              v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
 +                              return true
                        end
                else if cname == "NativeString" then
                        if pname == "[]" then
@@@ -2866,10 -2802,6 +2883,10 @@@ redef class AIntExp
        redef fun expr(v) do return v.int_instance(self.value.as(not null))
  end
  
 +redef class AByteExpr
 +      redef fun expr(v) do return v.byte_instance(self.value.as(not null))
 +end
 +
  redef class AFloatExpr
        redef fun expr(v) do return v.float_instance("{self.n_float.text}") # FIXME use value, not n_float
  end