예제 #1
0
        static List <ParseWorker> StartParseWorkers(BuildConf conf)
        {
            var parse_workers = new List <ParseWorker>();

            int files_per_worker = conf.files.Count < conf.max_threads ? conf.files.Count : (int)Math.Ceiling((float)conf.files.Count / (float)conf.max_threads);

            int idx = 0;
            int wid = 0;

            while (idx < conf.files.Count)
            {
                int count = (idx + files_per_worker) > conf.files.Count ? (conf.files.Count - idx) : files_per_worker;

                ++wid;

                var pw = new ParseWorker();
                pw.id        = wid;
                pw.self_file = conf.self_file;
                pw.start     = idx;
                pw.inc_path.Add(conf.inc_dir);
                pw.count      = count;
                pw.use_cache  = conf.use_cache;
                pw.cache_dir  = conf.tmp_dir;
                pw.check_deps = conf.check_deps;
                pw.files      = conf.files;

                parse_workers.Add(pw);
                pw.Start();

                idx += count;
            }

            return(parse_workers);
        }
예제 #2
0
        static bool CheckArgsSignatureFile(BuildConf conf)
        {
            var  tmp_args_file = conf.tmp_dir + "/" + Path.GetFileName(conf.res_file) + ".args";
            bool changed       = !File.Exists(tmp_args_file) || (File.Exists(tmp_args_file) && File.ReadAllText(tmp_args_file) != conf.args);

            if (changed)
            {
                File.WriteAllText(tmp_args_file, conf.args);
            }
            return(changed);
        }
예제 #3
0
        int DoExec(BuildConf conf)
        {
            var res_dir = Path.GetDirectoryName(conf.res_file);

            if (res_dir.Length > 0)
            {
                Directory.CreateDirectory(res_dir);
            }

            Directory.CreateDirectory(conf.tmp_dir);

            var args_changed = CheckArgsSignatureFile(conf);

            if (conf.use_cache &&
                !args_changed &&
                !BuildUtil.NeedToRegen(conf.res_file, conf.files)
                )
            {
                Console.WriteLine("BHL no need to re-build");
                return(0);
            }

            var ts = conf.ts;

            if (ts == null)
            {
                ts = new Types();
            }

            conf.userbindings.Register(ts);

            var parse_workers    = StartParseWorkers(conf);
            var compiler_workers = StartAndWaitCompileWorkers(conf, ts, parse_workers);

            var tmp_res_file = conf.tmp_dir + "/" + Path.GetFileName(conf.res_file) + ".tmp";

            if (!WriteCompilationResultToFile(conf, compiler_workers, tmp_res_file))
            {
                return(ERROR_EXIT_CODE);
            }

            if (File.Exists(conf.res_file))
            {
                File.Delete(conf.res_file);
            }
            File.Move(tmp_res_file, conf.res_file);

            conf.postproc.Tally();

            return(0);
        }
예제 #4
0
        public int Exec(BuildConf conf)
        {
            var sw = new Stopwatch();

            sw.Start();

            int code = DoExec(conf);

            sw.Stop();

            Console.WriteLine("BHL build done({0} sec)", Math.Round(sw.ElapsedMilliseconds / 1000.0f, 2));

            return(code);
        }
예제 #5
0
        bool WriteCompilationResultToFile(BuildConf conf, List <CompilerWorker> compiler_workers, string file_path)
        {
            using (FileStream dfs = new FileStream(file_path, FileMode.Create, System.IO.FileAccess.Write))
            {
                var mwriter = new MsgPack.MsgPackWriter(dfs);

                mwriter.Write(ModuleLoader.COMPILE_FMT);
                mwriter.Write(FILE_VERSION);

                int total_modules = 0;
                foreach (var w in compiler_workers)
                {
                    if (w.error == null)
                    {
                        CheckUniqueSymbols(w);
                    }

                    //NOTE: exit in case of error
                    if (w.error != null)
                    {
                        if (conf.err_file == "-")
                        {
                            Console.Error.WriteLine(ErrorUtils.ToJson(w.error));
                        }
                        else
                        {
                            File.WriteAllText(conf.err_file, ErrorUtils.ToJson(w.error));
                        }

                        return(false);
                    }
                    total_modules += w.file2path.Count;
                }
                mwriter.Write(total_modules);

                //NOTE: we'd like to write file binary modules in the same order they were added
                for (int file_idx = 0; file_idx < conf.files.Count; ++file_idx)
                {
                    var file = conf.files[file_idx];

                    foreach (var w in compiler_workers)
                    {
                        if (file_idx >= w.start && file_idx < w.start + w.count)
                        {
                            var path          = w.file2path[file];
                            var compiled_file = w.file2compiled[file];

                            mwriter.Write((byte)conf.module_fmt);
                            mwriter.Write(path.name);

                            if (conf.module_fmt == ModuleBinaryFormat.FMT_BIN)
                            {
                                mwriter.Write(File.ReadAllBytes(compiled_file));
                            }
                            else if (conf.module_fmt == ModuleBinaryFormat.FMT_LZ4)
                            {
                                mwriter.Write(EncodeToLZ4(File.ReadAllBytes(compiled_file)));
                            }
                            else if (conf.module_fmt == ModuleBinaryFormat.FMT_FILE_REF)
                            {
                                mwriter.Write(compiled_file);
                            }
                            else
                            {
                                throw new Exception("Unsupported format: " + conf.module_fmt);
                            }

                            break;
                        }
                    }
                }

                return(true);
            }
        }
예제 #6
0
        static List <CompilerWorker> StartAndWaitCompileWorkers(BuildConf conf, Types ts, List <ParseWorker> parse_workers)
        {
            var compiler_workers = new List <CompilerWorker>();

            var cache = new Cache();

            //1. waiting for parse workers to finish
            foreach (var pw in parse_workers)
            {
                pw.Join();

                //let's create the shared interim result
                foreach (var kv in pw.file2interim)
                {
                    cache.file2interim.Add(kv.Key, kv.Value);
                }
            }

            bool had_errors = false;

            foreach (var pw in parse_workers)
            {
                var cw = new CompilerWorker();
                cw.id        = pw.id;
                cw.cache     = cache;
                cw.inc_dir   = conf.inc_dir;
                cw.cache_dir = pw.cache_dir;
                cw.ts        = ts;
                cw.files     = pw.files;
                cw.start     = pw.start;
                cw.count     = pw.count;
                cw.postproc  = conf.postproc;

                //passing parser error if any
                cw.error = pw.error;

                if (pw.error != null)
                {
                    had_errors = true;
                }

                compiler_workers.Add(cw);
            }

            //2. starting workers which now actually compile the code
            //   if there were no errors
            if (!had_errors)
            {
                foreach (var w in compiler_workers)
                {
                    w.Start();
                }

                foreach (var w in compiler_workers)
                {
                    w.Join();
                }
            }

            return(compiler_workers);
        }
예제 #7
0
        public void Run(string[] args)
        {
            var files = new List <string>();

            string             src_dir               = "";
            string             res_file              = "";
            string             tmp_dir               = "";
            bool               use_cache             = true;
            string             err_file              = "";
            string             postproc_dll_path     = "";
            string             userbindings_dll_path = "";
            int                max_threads           = 1;
            bool               check_deps            = true;
            bool               deterministic         = false;
            bool               debug      = false;
            ModuleBinaryFormat module_fmt = ModuleBinaryFormat.FMT_LZ4;

            var p = new OptionSet()
            {
                { "dir=", "source dir",
                  v => src_dir = v },
                { "files=", "source files list",
                  v => files.AddRange(File.ReadAllText(v).Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None)) },
                { "result=", "result file",
                  v => res_file = v },
                { "tmp-dir=", "tmp dir",
                  v => tmp_dir = v },
                { "C", "don't use cache",
                  v => use_cache = v == null },
                { "N", "don't check import deps",
                  v => check_deps = v == null },
                { "postproc-dll=", "posprocess dll path",
                  v => postproc_dll_path = v },
                { "bindings-dll=", "bindings dll path",
                  v => userbindings_dll_path = v },
                { "error=", "error file",
                  v => err_file = v },
                { "deterministic=", "deterministic build",
                  v => deterministic = v != null },
                { "threads=", "number of threads",
                  v => max_threads = int.Parse(v) },
                { "d", "debug version",
                  v => debug = v != null },
                { "module-fmt=", "binary module format",
                  v => module_fmt = (ModuleBinaryFormat)int.Parse(v) }
            };

            var extra = new List <string>();

            try
            {
                extra = p.Parse(args);
            }
            catch (OptionException e)
            {
                Usage(e.Message);
            }
            files.AddRange(extra);

            if (!Directory.Exists(src_dir))
            {
                Usage("Root source directory is not valid");
            }
            src_dir = Path.GetFullPath(src_dir);

            if (res_file == "")
            {
                Usage("Result file path not set");
            }

            if (tmp_dir == "")
            {
                Usage("Tmp dir not set");
            }

            if (err_file == "")
            {
                Usage("Err file not set");
            }
            if (File.Exists(err_file))
            {
                File.Delete(err_file);
            }

            IUserBindings userbindings = new EmptyUserBindings();

            if (userbindings_dll_path != "")
            {
                var userbindings_assembly = System.Reflection.Assembly.LoadFrom(userbindings_dll_path);
                var userbindings_class    = userbindings_assembly.GetTypes()[0];
                userbindings = System.Activator.CreateInstance(userbindings_class) as IUserBindings;
                if (userbindings == null)
                {
                    Usage("User bindings are invalid");
                }
            }

            IFrontPostProcessor postproc = new EmptyPostProcessor();

            if (postproc_dll_path != "")
            {
                var postproc_assembly = System.Reflection.Assembly.LoadFrom(postproc_dll_path);
                var postproc_class    = postproc_assembly.GetTypes()[0];
                postproc = System.Activator.CreateInstance(postproc_class) as IFrontPostProcessor;
                if (postproc == null)
                {
                    Usage("User postprocessor is invalid");
                }
            }

            if (files.Count == 0)
            {
                Build.AddFilesFromDir(src_dir, files);
            }

            for (int i = files.Count; i-- > 0;)
            {
                if (string.IsNullOrEmpty(files[i]))
                {
                    files.RemoveAt(i);
                }
            }

            if (deterministic)
            {
                files.Sort();
            }

            Console.WriteLine("BHL total files: {0}(debug: {1}, cache: {2})", files.Count, debug, use_cache);
            var conf = new BuildConf();

            conf.args         = string.Join(";", args);
            conf.module_fmt   = module_fmt;
            conf.use_cache    = use_cache;
            conf.self_file    = GetSelfFile();
            conf.check_deps   = check_deps;
            conf.files        = files;
            conf.inc_dir      = src_dir;
            conf.max_threads  = max_threads;
            conf.res_file     = res_file;
            conf.tmp_dir      = tmp_dir;
            conf.err_file     = err_file;
            conf.userbindings = userbindings;
            conf.postproc     = postproc;
            conf.debug        = debug;

            var build = new Build();
            int err   = build.Exec(conf);

            if (err != 0)
            {
                Environment.Exit(err);
            }
        }