void runProgram(String[] args)  throws IOException {
        String vtagmapPath = args[0];
        String packageName = args[1];
        String dirName = args[2] + "/" + packageName.replaceAll("\\.", "/");
        Format format = args.length >= 4 ? Format.valueOf(args[3].toUpperCase()) : Format.SIMPLE;
        File outDir = new File(dirName);
        if (!outDir.isDirectory() && !outDir.mkdirs()) {
            throw new IOException("could not create directory " + outDir);
        }

        String className = format == Format.SIMPLE ? "VespaVersion" : "Vtag";
        String outFile = dirName + "/" + className +".java";
        Path outPath = Path.of(outFile);
        Path tmpPath = Path.of(outFile + ".tmp");
        var out = Files.newOutputStream(tmpPath);
        OutputStreamWriter writer = new OutputStreamWriter(out);
        System.err.println("generating: " + outFile);

        Map<String, String> vtagMap = readVtagMap(vtagmapPath);
        writer.write(String.format("package %s;\n\n", packageName));

        if (format == Format.VTAG) {
            writer.write("import java.time.Instant;\n");
            writer.write("import com.yahoo.component.Version;\n");
        }

        writer.write(String.format("\npublic class %s {\n", className));
        if (!vtagMap.containsKey(V_TAG_PKG)) {
            throw new RuntimeException("V_TAG_PKG not present in map file");
        }
        switch (format) {
            case SIMPLE:
                String version = vtagMap.get(V_TAG_PKG);
                String elements[] = version.split("\\.");
                writer.write(String.format("    public static final int major = %s;\n", elements[0]));
                writer.write(String.format("    public static final int minor = %s;\n", elements[1]));
                writer.write(String.format("    public static final int micro = %s;\n", elements[2]));
                break;
            case VTAG:
                long commitDateSecs = 0;
                for (var entry : vtagMap.entrySet()) {
                    var key = entry.getKey();
                    var value = entry.getValue();
                    try {
                        writer.write(String.format("    public static final String %s = \"%s\";\n", key, value));
                        if ("V_TAG_COMMIT_DATE".equals(key)) {
                            commitDateSecs = Long.parseLong(value);
                        }
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                };
                writer.write("    public static final Version currentVersion = new Version(V_TAG_COMPONENT);\n");
                writer.write("    public static final String commitSha = V_TAG_COMMIT_SHA;\n");
                writer.write("    public static final Instant commitDate = Instant.ofEpochSecond(" + commitDateSecs +");\n");
                break;
        }
        writer.write("}\n");
        writer.close();
        out.close();
        if (Files.exists(outPath)) {
            byte[] tmpBytes = Files.readAllBytes(tmpPath);
            byte[] oldBytes = Files.readAllBytes(outPath);
            if (Arrays.equals(tmpBytes, oldBytes)) {
                Files.delete(tmpPath);
                return;
            }
        }
        Files.deleteIfExists(outPath);
        Files.move(tmpPath, outPath);
    }
This class generates a java class based on the vtag.map file generated by dist/getversion.pl
vespajlib/src/main/java/com/yahoo/vespa/VersionTagger.java