Merge: Distribuable compiledir
authorJean Privat <jean@pryen.org>
Fri, 31 Oct 2014 11:17:55 +0000 (07:17 -0400)
committerJean Privat <jean@pryen.org>
Fri, 31 Oct 2014 11:17:55 +0000 (07:17 -0400)
Unfortunately, Nit is not yet available everywhere.
Therefore, in order to be able to distribute or deploy Nit programs, one easy way is to distribute the generated C code.

This is what we already do with `c_src` that contains modified C code from the compilation of nith.

This PR generalize the approach and allow the compiler to produce some neat and distributable .compile_dir.
Look at the new `mkcsrc` to see how things are simpler now.

Example, you want to disribute `hello_world`:

~~~sh
$ nitg examples/hello_world.nit --semi-global --no-cc --dir hello --compile-dir hello
$ ls -l hello
abstract_collection.sep.0.h
abstract_collection.sep.1.c
array.sep.0.h
array.sep.1.c
c_functions_hash.c
c_functions_hash.h
file_nit.c
file_nit.h
file.sep.0.h
file.sep.1.c
gc_chooser.c
gc_chooser.h
hello_world.classes.0.h
hello_world.classes.1.c
hello_world.main.0.h
hello_world.main.1.c
hello_world.mk
hello_world.sep.0.h
hello_world.sep.1.c
hello_world.types.0.h
hello_world.types.1.c
kernel.sep.0.h
kernel.sep.1.c
Makefile
math_nit.h
math.sep.0.h
math.sep.1.c
nit.common.h
stream.sep.0.h
stream.sep.1.c
string_nit.c
string_nit.h
string.sep.0.h
string.sep.1.c
$ cd hello
$ make
ccache cc -g -O2 -Wno-unused-value -Wno-switch  -c -o hello_world.classes.1.o hello_world.classes.1.c
ccache cc -g -O2 -Wno-unused-value -Wno-switch  -c -o hello_world.main.1.o hello_world.main.1.c
ccache cc -g -O2 -Wno-unused-value -Wno-switch  -c -o hello_world.sep.1.o hello_world.sep.1.c
ccache cc -g -O2 -Wno-unused-value -Wno-switch  -c -o string.sep.1.o string.sep.1.c
ccache cc -g -O2 -Wno-unused-value -Wno-switch  -c -o math.sep.1.o math.sep.1.c
ccache cc -g -O2 -Wno-unused-value -Wno-switch  -c -o kernel.sep.1.o kernel.sep.1.c
ccache cc -g -O2 -Wno-unused-value -Wno-switch  -c -o abstract_collection.sep.1.o abstract_collection.sep.1.c
ccache cc -g -O2 -Wno-unused-value -Wno-switch  -c -o array.sep.1.o array.sep.1.c
ccache cc -g -O2 -Wno-unused-value -Wno-switch  -c -o file.sep.1.o file.sep.1.c
ccache cc -g -O2 -Wno-unused-value -Wno-switch  -c -o stream.sep.1.o stream.sep.1.c
ccache cc -g -O2 -Wno-unused-value -Wno-switch  -c -o hello_world.types.1.o hello_world.types.1.c
ccache cc -g -O2 -Wno-unused-value -Wno-switch  -c -o string_nit.extern.o string_nit.c
ccache cc -g -O2 -Wno-unused-value -Wno-switch  -c -o file_nit.extern.o file_nit.c
ccache cc -g -O2 -Wno-unused-value -Wno-switch  -c -o c_functions_hash.extern.o c_functions_hash.c
ccache cc -g -O2 -Wno-unused-value -Wno-switch -DWITH_LIBGC -c -o gc_chooser.extern.o gc_chooser.c
ccache cc  -o hello_world hello_world.classes.1.o hello_world.main.1.o hello_world.sep.1.o string.sep.1.o math.sep.1.o kernel.sep.1.o abstract_collection.sep.1.o array.sep.1.o file.sep.1.o stream.sep.1.o hello_world.types.1.o string_nit.extern.o file_nit.extern.o c_functions_hash.extern.o gc_chooser.extern.o -lm -lgc  -lunwind
$ ./hello_world
hello world
~~~

Pull-Request: #860

.gitattributes
src/compiler/abstract_compiler.nit
src/mkcsrc

index c373f7c..5345475 100644 (file)
@@ -3,7 +3,6 @@ parser.nit              -diff
 parser_prod.nit                -diff
 lexer.nit              -diff
 tables_nit.c           -diff
-c_src/**/*.[ch]                -diff
-c_src/Makefile         -diff
+c_src/**               -diff
 
 tests/sav/**/*.res     -whitespace
index b5052cb..008e8f1 100644 (file)
@@ -38,6 +38,10 @@ redef class ToolContext
        var opt_cc_path = new OptionArray("Set include path for C header files (may be used more than once)", "--cc-path")
        # --make-flags
        var opt_make_flags = new OptionString("Additional options to make", "--make-flags")
+       # --max-c-lines
+       var opt_max_c_lines = new OptionInt("Maximum number of lines in generated C files. Use 0 for unlimited", 10000, "--max-c-lines")
+       # --group-c-files
+       var opt_group_c_files = new OptionBool("Group all generated code in the same series of files", "--group-c-files")
        # --compile-dir
        var opt_compile_dir = new OptionString("Directory used to generate temporary files", "--compile-dir")
        # --hardening
@@ -76,6 +80,7 @@ redef class ToolContext
                self.option_context.add_option(self.opt_stacktrace)
                self.option_context.add_option(self.opt_no_gcc_directive)
                self.option_context.add_option(self.opt_release)
+               self.option_context.add_option(self.opt_max_c_lines, self.opt_group_c_files)
        end
 
        redef fun process_options(args)
@@ -154,17 +159,20 @@ class MakefileToolchain
        # Path can be added (or removed) by the client
        var cc_paths = new Array[String]
 
+       # The clib directory of Nit
+       # Used to found some common runtime
+       var clib: String is noinit
+
        protected fun gather_cc_paths
        do
                # Look for the the Nit clib path
                var path_env = toolcontext.nit_dir
                if path_env != null then
                        var libname = "{path_env}/clib"
-                       if libname.file_exists then cc_paths.add(libname)
-               end
-
-               if cc_paths.is_empty then
-                       toolcontext.error(null, "Cannot determine the nit clib path. define envvar NIT_DIR.")
+                       if not libname.file_exists then
+                               toolcontext.fatal_error(null, "Cannot determine the nit clib path. define envvar NIT_DIR.")
+                       end
+                       clib = libname
                end
 
                # Add user defined cc_paths
@@ -223,8 +231,8 @@ class MakefileToolchain
                # Add gc_choser.h to aditionnal bodies
                var gc_chooser = new ExternCFile("gc_chooser.c", cc_opt_with_libgc)
                compiler.extern_bodies.add(gc_chooser)
-               compiler.files_to_copy.add "{cc_paths.first}/gc_chooser.c"
-               compiler.files_to_copy.add "{cc_paths.first}/gc_chooser.h"
+               compiler.files_to_copy.add "{clib}/gc_chooser.c"
+               compiler.files_to_copy.add "{clib}/gc_chooser.h"
 
                # FFI
                for m in compiler.mainmodule.in_importation.greaters do
@@ -251,39 +259,21 @@ class MakefileToolchain
                end
                h.close
 
+               var max_c_lines = toolcontext.opt_max_c_lines.value
                for f in compiler.files do
                        var i = 0
-                       var hfile: nullable OFStream = null
                        var count = 0
-                       var cfilename = "{f.name}.0.h"
-                       var cfilepath = "{compile_dir}/{cfilename}"
-                       hfile = new OFStream.open(cfilepath)
-                       hfile.write "#include \"{hfilename}\"\n"
-                       for key in f.required_declarations do
-                               if not compiler.provided_declarations.has_key(key) then
-                                       var node = compiler.requirers_of_declarations.get_or_null(key)
-                                       if node != null then
-                                               node.debug "No provided declaration for {key}"
-                                       else
-                                               print "No provided declaration for {key}"
-                                       end
-                                       abort
-                               end
-                               hfile.write compiler.provided_declarations[key]
-                               hfile.write "\n"
-                       end
-                       hfile.close
                        var file: nullable OFStream = null
                        for vis in f.writers do
                                if vis == compiler.header then continue
                                var total_lines = vis.lines.length + vis.decl_lines.length
                                if total_lines == 0 then continue
                                count += total_lines
-                               if file == null or count > 10000  then
+                               if file == null or (count > max_c_lines and max_c_lines > 0) then
                                        i += 1
                                        if file != null then file.close
-                                       cfilename = "{f.name}.{i}.c"
-                                       cfilepath = "{compile_dir}/{cfilename}"
+                                       var cfilename = "{f.name}.{i}.c"
+                                       var cfilepath = "{compile_dir}/{cfilename}"
                                        self.toolcontext.info("new C source files to compile: {cfilepath}", 3)
                                        cfiles.add(cfilename)
                                        file = new OFStream.open(cfilepath)
@@ -299,7 +289,28 @@ class MakefileToolchain
                                        file.write "\n"
                                end
                        end
-                       if file != null then file.close
+                       if file == null then continue
+                       file.close
+
+                       var cfilename = "{f.name}.0.h"
+                       var cfilepath = "{compile_dir}/{cfilename}"
+                       var hfile: nullable OFStream = null
+                       hfile = new OFStream.open(cfilepath)
+                       hfile.write "#include \"{hfilename}\"\n"
+                       for key in f.required_declarations do
+                               if not compiler.provided_declarations.has_key(key) then
+                                       var node = compiler.requirers_of_declarations.get_or_null(key)
+                                       if node != null then
+                                               node.debug "No provided declaration for {key}"
+                                       else
+                                               print "No provided declaration for {key}"
+                                       end
+                                       abort
+                               end
+                               hfile.write compiler.provided_declarations[key]
+                               hfile.write "\n"
+                       end
+                       hfile.close
                end
 
                self.toolcontext.info("Total C source files to compile: {cfiles.length}", 2)
@@ -336,8 +347,7 @@ class MakefileToolchain
 
                var outname = outfile(mainmodule)
 
-               var orig_dir = compile_dir.relpath(".")
-               var outpath = orig_dir.join_path(outname).simplify_path
+               var outpath = compile_dir.relpath(outname)
                var makename = makefile_name(mainmodule)
                var makepath = "{compile_dir}/{makename}"
                var makefile = new OFStream.open(makepath)
@@ -419,6 +429,8 @@ class MakefileToolchain
                makefile.write("clean:\n\trm {ofiles.join(" ")} 2>/dev/null\n\n")
                makefile.close
                self.toolcontext.info("Generated makefile: {makepath}", 2)
+
+               makepath.file_copy_to "{compile_dir}/Makefile"
        end
 
        fun compile_c_code(compiler: AbstractCompiler, compile_dir: String)
@@ -472,6 +484,13 @@ abstract class AbstractCompiler
        # The point is to avoid contamination between must-be-compiled-separately files
        fun new_file(name: String): CodeFile
        do
+               if modelbuilder.toolcontext.opt_group_c_files.value then
+                       if self.files.is_empty then
+                               var f = new CodeFile(mainmodule.name)
+                               self.files.add(f)
+                       end
+                       return self.files.first
+               end
                var f = new CodeFile(name)
                self.files.add(f)
                return f
index 7ba4466..7734983 100755 (executable)
@@ -1,26 +1,9 @@
-#!/bin/bash
-cd ..
-out=c_src
-rm -r "$out/" 2> /dev/null
-set -e
-set -x
-src/nitg src/nith.nit --semi-global -v "$@" --compile-dir "$out" -o "$out/nitg" --no-cc
-cp "$out/nith.mk" "$out/Makefile"
-sed -i -e "s#../$out/##g" "$out/Makefile"
+#!/bin/sh
 
-# Copy all direct dependencies
-for f in `grep -h -o '[^ ]*/[^ /]*\.c' "$out/Makefile" | sort -u`; do
-       cp "$out/$f" "$out/"
-       cp "$out/${f%c}h" "$out/"
-done
-for f in `grep -h -o '\.\..*\.h' "$out"/*.[ch] | sort -u`; do
-       cp "$out/$f" "$out/"
-done
+# Regeneration of c_src from the current nitg
 
-# Update references in file
-perl -i -npe 's#"\.\./.*?([^/]*.h)"#"\1"#' "$out"/*.[ch]
-perl -i -npe 's#\S*/([^/]*.[ch])#\1#' "$out/Makefile"
-perl -i -npe 's#\.\./clib#.#' "$out/Makefile"
+rm -r ../c_src
+./nitg nith.nit --semi-global --compile-dir ../c_src --output ../c_src/nitg --no-cc
 
 # Remove old compilation flags
-sed -i -e 's/OLDNITCOPT=.*/OLDNITCOPT=/' src/Makefile
+sed -i -e 's/OLDNITCOPT=.*/OLDNITCOPT=/' Makefile