1#!/usr/bin/env python3 2 3"""Gets the current revision and writes it to VCSRevision.h.""" 4 5import argparse 6import os 7import subprocess 8import sys 9 10 11THIS_DIR = os.path.abspath(os.path.dirname(__file__)) 12LLVM_DIR = os.path.dirname(os.path.dirname(os.path.dirname(THIS_DIR))) 13 14 15def which(program): 16 # distutils.spawn.which() doesn't find .bat files, 17 # https://bugs.python.org/issue2200 18 for path in os.environ["PATH"].split(os.pathsep): 19 candidate = os.path.join(path, program) 20 if os.path.isfile(candidate) and os.access(candidate, os.X_OK): 21 return candidate 22 return None 23 24 25def main(): 26 parser = argparse.ArgumentParser(description=__doc__) 27 parser.add_argument( 28 "-d", 29 "--depfile", 30 help="if set, writes a depfile that causes this script " 31 "to re-run each time the current revision changes", 32 ) 33 parser.add_argument( 34 "--write-git-rev", 35 action="store_true", 36 help="if set, writes git revision, else writes #undef", 37 ) 38 parser.add_argument( 39 "--name", 40 action="append", 41 help="if set, writes a depfile that causes this script " 42 "to re-run each time the current revision changes", 43 ) 44 parser.add_argument("vcs_header", help="path to the output file to write") 45 args = parser.parse_args() 46 47 vcsrevision_contents = "" 48 if args.write_git_rev: 49 git, use_shell = which("git"), False 50 if not git: 51 git = which("git.exe") 52 if not git: 53 git, use_shell = which("git.bat"), True 54 git_dir = ( 55 subprocess.check_output( 56 [git, "rev-parse", "--git-dir"], cwd=LLVM_DIR, shell=use_shell 57 ) 58 .decode() 59 .strip() 60 ) 61 if not os.path.isdir(git_dir): 62 print('.git dir not found at "%s"' % git_dir, file=sys.stderr) 63 return 1 64 65 rev = ( 66 subprocess.check_output( 67 [git, "rev-parse", "--short", "HEAD"], cwd=git_dir, shell=use_shell 68 ) 69 .decode() 70 .strip() 71 ) 72 url = ( 73 subprocess.check_output( 74 [git, "remote", "get-url", "origin"], cwd=git_dir, shell=use_shell 75 ) 76 .decode() 77 .strip() 78 ) 79 for name in args.name: 80 vcsrevision_contents += '#define %s_REVISION "%s"\n' % (name, rev) 81 vcsrevision_contents += '#define %s_REPOSITORY "%s"\n' % (name, url) 82 else: 83 for name in args.name: 84 vcsrevision_contents += "#undef %s_REVISION\n" % name 85 vcsrevision_contents += "#undef %s_REPOSITORY\n" % name 86 87 # If the output already exists and is identical to what we'd write, 88 # return to not perturb the existing file's timestamp. 89 if ( 90 os.path.exists(args.vcs_header) 91 and open(args.vcs_header).read() == vcsrevision_contents 92 ): 93 return 0 94 95 # http://neugierig.org/software/blog/2014/11/binary-revisions.html 96 if args.depfile: 97 build_dir = os.getcwd() 98 with open(args.depfile, "w") as depfile: 99 depfile.write( 100 "%s: %s\n" 101 % ( 102 args.vcs_header, 103 os.path.relpath(os.path.join(git_dir, "logs", "HEAD"), build_dir), 104 ) 105 ) 106 open(args.vcs_header, "w").write(vcsrevision_contents) 107 108 109if __name__ == "__main__": 110 sys.exit(main()) 111