Thursday, March 29, 2012

Unity3d: generating files using stringtemplate during the build

In our Unity3d project, we have a need to generate a few files from templates. We use Antlr (3) stringtemplate library to perform the operation. This is how we do it: We first made pre and post build hooks in our custom Editor build that triggers the build:
                PreProcess(dir);
                string res = BuildPipeline.BuildPlayer(scenes,target_dir,build_target,build_options);
                if (res.Length > 0) {
                        throw new Exception("BuildPlayer failure: " + res);
                }
                PostProcess(dir);
We have a directory called EditorTemplates under which we store all files to be used as pre-build templates:
EditorTemplates//Assets/Plugins/Android/AndroidManifest.xml
EditorTemplates//Assets/Script/Version.cs
We extract information from the environment to fill in the template engine.
                Dictionary templateInput = new Dictionary();
                string buildNumber = Environment.GetEnvironmentVariable("BUILD_NUMBER");
                string buildId = Environment.GetEnvironmentVariable("BUILD_ID");
                string user = Environment.GetEnvironmentVariable("USER");
                string buildName = buildNumber;
                if (user != "jenkins") {
                        buildName += "_" + user;
                }
                templateInput.Add("BUILD_NUMBER", buildNumber);
                templateInput.Add("BUILD_NAME", buildName);
                templateInput.Add("BUILD_ID", buildId);
we search those files
       public static IEnumerable GetFiles(string path) {
                Queue queue = new Queue();
                queue.Enqueue(path);
                while (queue.Count > 0) {
                        path = queue.Dequeue();
                        foreach (string subDir in Directory.GetDirectories(path)) {
                                queue.Enqueue(subDir);
                        }
                        string[] files = null;
                        files = Directory.GetFiles(path);
                        if (files != null) {
                                for(int i = 0 ; i < files.Length ; i++) {
                                        yield return files[i];
                                }
                        }
                }
        }
and use Antlr templating to generate the templates, skipping the subversion ones:
                string templateDir = "EditorTemplates";
                foreach(string relativePath in FileSystemUtil.GetFiles(templateDir)) {
                        if (relativePath.Contains(".svn")) continue;
                        GenerateFileFromTemplate(templateDir, relativePath, templateInput);     
                }

        static void GenerateFileFromTemplate(string templateDir, string path, Dictionary dictionary) {
                string targetPath = path.Substring(templateDir.Length + 1);
                StringTemplate ST = new StringTemplate(FileSystemUtil.ReadTxtInFile(path));
                foreach(string key in dictionary.Keys) {
                        ST.SetAttribute(key, dictionary[key]);
                }
                FileSystemUtil.EnsureParentExists(targetPath);
                Console.WriteLine("Generating file {0} from {1}.", targetPath, templateDir);
                FileSystemUtil.SaveTxtInFile(ST.ToString(), targetPath);
        }
Here's the relevant code extract for that operation: https://gist.github.com/2235307

1 comment:

  1. Thank you for useful posting!
    and I have a question. how can I use Antlr (3) stringtemplate for my unity android project?
    is it install with nuget manager?

    ReplyDelete