Build Tag

This example shows how to tag a build with info from when it was built. Here we include a version number, git hash, timestamp, user, in the generated .java file so it's an accurate reflection of when the code was built. There are several features demonstrated:

Here's the buildTag layer definition file, run at build time:
file: example/buildTag/
package sc.example.buildTag;

   The code here is interpreted, not compiled as it's the layer definition so it runs at build time. 
   When the layer is initialized, we'll run some git commands to create an scmVersion which can then
   be used in a BuildInit annotation (see 
public example.buildTag extends sys.std {
   String scmVersion;

   void init() {
      if (!activated) // Not loaded as part of a build so nothing to do here.
      String branch = FileUtil.execCmd("git symbolic-ref --short HEAD"); // Current branch name only
      if (branch != null) {
         branch = branch.trim();
         String hash = FileUtil.execCmd("git rev-parse --short HEAD").trim();

         // Look at 'git status' and see if there are local changes in this build - if so, summarize them like '3M,2C,1D'
         String status = FileUtil.execCmd("git status -suno --porcelain").trim();
         String repoStatus = ""; 
         if (status.length() > 0) {
            String[] statusLines = status.split("\n");
            int numMods = 0, numAdds = 0, numDels = 0, numOther = 0;
            for (String line:statusLines) {
               char start = line.trim().charAt(0);
               switch (start) {
                  case 'M':
                  case 'A':
                  case 'D':
            if (numMods != 0) 
               repoStatus += numMods + "M";
            if (numAdds != 0)
               repoStatus += repoStatus.length() == 0 ? "" : "," + numAdds + "A";
            if (numDels != 0)
               repoStatus += repoStatus.length() == 0 ? "" : "," + numDels + "D";
            if (numOther != 0)
               repoStatus += repoStatus.length() == 0 ? "" : "," + numOther + "?";
            repoStatus = "+" + repoStatus;
         scmVersion = branch + '@' + hash + repoStatus; 
         scmVersion = "not from git dir";
It defines the layer field 'scmVersion' which is initialized by running git and parsing the result to produce an informative string that includes information about local changes in the repository at the time of the build. The 'init' method is run just after the layer is constructed, before the start and validate methods.

Here's the source for the BuildTag subclass that is generated to include the build info:

file: example/buildTag/
import sc.obj.BuildInit;
import sc.layer.LayerUtil;

  * This file is used to inject values from build-time expressions into the generated code. 
  * We can take the binaries with specific info derived from when it was built. 
object ExBuildTag extends sc.util.BuildTag {
   override @BuildInit("new java.util.Date().toString()") timeStamp;
   override @BuildInit("System.getProperty(\"\")") user;
   override @BuildInit("System.getProperty(\"java.version\")") javaVersion;
   // Want one string for the osVersion.  TODO: maybe call this osVersionStamp?
   override @BuildInit("System.getProperty(\"\") + '.' + System.getProperty(\"os.arch\") + '.' + System.getProperty(\"os.version\")") osVersion;
   // Returns the top-most '' definition of a property or null if there is none
   override @BuildInit("getLayerProperty(\"build\",\"version\")") version;
   override @BuildInit("getLayerProperty(\"build\",\"tag\")") tag;
   override @BuildInit("getLayerProperty(\"build\",\"revision\")") revision;
   override @BuildInit("sc.layer.LayerUtil.incrBuildNumber(\"scc\")") buildNumber;
   // Evaluates a layer variable scmVersion
   override @BuildInit("scmVersion") scmVersion;

To compile a release build, you can override the defaults by adding a command line option: scc -Pbuild.tag=release example.buildTag