1*6dbdd20aSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2020 The Android Open Source Project 3*6dbdd20aSAndroid Build Coastguard Worker# 4*6dbdd20aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 5*6dbdd20aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 6*6dbdd20aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 7*6dbdd20aSAndroid Build Coastguard Worker# 8*6dbdd20aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 9*6dbdd20aSAndroid Build Coastguard Worker# 10*6dbdd20aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*6dbdd20aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 12*6dbdd20aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*6dbdd20aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 14*6dbdd20aSAndroid Build Coastguard Worker# limitations under the License. 15*6dbdd20aSAndroid Build Coastguard Worker""" 16*6dbdd20aSAndroid Build Coastguard WorkerWrites the perfetto_version{.gen.h, .ts} files. 17*6dbdd20aSAndroid Build Coastguard Worker 18*6dbdd20aSAndroid Build Coastguard WorkerThis tool is run as part of a genrule from GN, SoonG and Bazel builds. It 19*6dbdd20aSAndroid Build Coastguard Workergenerates a source header (or in the case of --ts_out a TypeScript file) that 20*6dbdd20aSAndroid Build Coastguard Workercontains: 21*6dbdd20aSAndroid Build Coastguard Worker- The version number (e.g. v9.0) obtained parsing the CHANGELOG file. 22*6dbdd20aSAndroid Build Coastguard Worker- The git HEAD's commit-ish (e.g. 6b330b772b0e973f79c70ba2e9bb2b0110c6715d) 23*6dbdd20aSAndroid Build Coastguard Worker 24*6dbdd20aSAndroid Build Coastguard WorkerThe latter is concatenated to the version number to disambiguate builds made 25*6dbdd20aSAndroid Build Coastguard Workerfrom release tags vs builds made from the main branch vs UI builds made from the 26*6dbdd20aSAndroid Build Coastguard Workerui-canary/ui-stable branch. 27*6dbdd20aSAndroid Build Coastguard Worker""" 28*6dbdd20aSAndroid Build Coastguard Worker 29*6dbdd20aSAndroid Build Coastguard Workerimport argparse 30*6dbdd20aSAndroid Build Coastguard Workerimport os 31*6dbdd20aSAndroid Build Coastguard Workerimport re 32*6dbdd20aSAndroid Build Coastguard Workerimport sys 33*6dbdd20aSAndroid Build Coastguard Workerimport subprocess 34*6dbdd20aSAndroid Build Coastguard Worker 35*6dbdd20aSAndroid Build Coastguard Worker# Note: PROJECT_ROOT is not accurate in bazel builds, where this script is 36*6dbdd20aSAndroid Build Coastguard Worker# executed in the bazel sandbox. 37*6dbdd20aSAndroid Build Coastguard WorkerPROJECT_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) 38*6dbdd20aSAndroid Build Coastguard WorkerSCM_REV_NOT_AVAILABLE = 'N/A' 39*6dbdd20aSAndroid Build Coastguard Worker 40*6dbdd20aSAndroid Build Coastguard Worker 41*6dbdd20aSAndroid Build Coastguard Workerdef get_latest_release(changelog_path): 42*6dbdd20aSAndroid Build Coastguard Worker """Returns a string like 'v9.0'. 43*6dbdd20aSAndroid Build Coastguard Worker 44*6dbdd20aSAndroid Build Coastguard Worker It does so by searching the latest version mentioned in the CHANGELOG.""" 45*6dbdd20aSAndroid Build Coastguard Worker if not changelog_path: 46*6dbdd20aSAndroid Build Coastguard Worker if os.path.exists('CHANGELOG'): 47*6dbdd20aSAndroid Build Coastguard Worker changelog_path = 'CHANGELOG' 48*6dbdd20aSAndroid Build Coastguard Worker else: 49*6dbdd20aSAndroid Build Coastguard Worker changelog_path = os.path.join(PROJECT_ROOT, 'CHANGELOG') 50*6dbdd20aSAndroid Build Coastguard Worker with open(changelog_path) as f: 51*6dbdd20aSAndroid Build Coastguard Worker for line in f.readlines(): 52*6dbdd20aSAndroid Build Coastguard Worker m = re.match(r'^(v\d+[.]\d+)\s.*$', line) 53*6dbdd20aSAndroid Build Coastguard Worker if m is not None: 54*6dbdd20aSAndroid Build Coastguard Worker return m.group(1) 55*6dbdd20aSAndroid Build Coastguard Worker raise Exception('Failed to fetch Perfetto version from %s' % changelog_path) 56*6dbdd20aSAndroid Build Coastguard Worker 57*6dbdd20aSAndroid Build Coastguard Worker 58*6dbdd20aSAndroid Build Coastguard Workerdef get_git_sha1(commitish): 59*6dbdd20aSAndroid Build Coastguard Worker """Returns the SHA1 of the provided commit-ish""" 60*6dbdd20aSAndroid Build Coastguard Worker commit_sha1 = SCM_REV_NOT_AVAILABLE 61*6dbdd20aSAndroid Build Coastguard Worker git_dir = os.path.join(PROJECT_ROOT, '.git') 62*6dbdd20aSAndroid Build Coastguard Worker if os.path.exists(git_dir): 63*6dbdd20aSAndroid Build Coastguard Worker try: 64*6dbdd20aSAndroid Build Coastguard Worker commit_sha1 = subprocess.check_output(['git', 'rev-parse', commitish], 65*6dbdd20aSAndroid Build Coastguard Worker cwd=PROJECT_ROOT).strip().decode() 66*6dbdd20aSAndroid Build Coastguard Worker except subprocess.CalledProcessError: 67*6dbdd20aSAndroid Build Coastguard Worker pass 68*6dbdd20aSAndroid Build Coastguard Worker return commit_sha1 69*6dbdd20aSAndroid Build Coastguard Worker 70*6dbdd20aSAndroid Build Coastguard Worker 71*6dbdd20aSAndroid Build Coastguard Workerdef write_if_unchanged(path, content): 72*6dbdd20aSAndroid Build Coastguard Worker prev_content = None 73*6dbdd20aSAndroid Build Coastguard Worker if os.path.exists(path): 74*6dbdd20aSAndroid Build Coastguard Worker with open(path, 'r') as fprev: 75*6dbdd20aSAndroid Build Coastguard Worker prev_content = fprev.read() 76*6dbdd20aSAndroid Build Coastguard Worker if prev_content == content: 77*6dbdd20aSAndroid Build Coastguard Worker return 0 78*6dbdd20aSAndroid Build Coastguard Worker with open(path, 'w') as fout: 79*6dbdd20aSAndroid Build Coastguard Worker fout.write(content) 80*6dbdd20aSAndroid Build Coastguard Worker 81*6dbdd20aSAndroid Build Coastguard Worker 82*6dbdd20aSAndroid Build Coastguard Workerdef main(): 83*6dbdd20aSAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 84*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('--check_git', action='store_true') 85*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument( 86*6dbdd20aSAndroid Build Coastguard Worker '--no_git', 87*6dbdd20aSAndroid Build Coastguard Worker action='store_true', 88*6dbdd20aSAndroid Build Coastguard Worker help='Skips running git rev-parse, emits only the version from CHANGELOG') 89*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('--cpp_out', help='Path of the generated .h file.') 90*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('--ts_out', help='Path of the generated .ts file.') 91*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('--stdout', help='Write to stdout', action='store_true') 92*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('--changelog', help='Path to CHANGELOG.') 93*6dbdd20aSAndroid Build Coastguard Worker args = parser.parse_args() 94*6dbdd20aSAndroid Build Coastguard Worker 95*6dbdd20aSAndroid Build Coastguard Worker if args.check_git: 96*6dbdd20aSAndroid Build Coastguard Worker has_git = os.path.exists(os.path.join(PROJECT_ROOT, '.git', 'HEAD')) 97*6dbdd20aSAndroid Build Coastguard Worker print('1' if has_git else '0') 98*6dbdd20aSAndroid Build Coastguard Worker return 0 99*6dbdd20aSAndroid Build Coastguard Worker 100*6dbdd20aSAndroid Build Coastguard Worker release = get_latest_release(args.changelog) 101*6dbdd20aSAndroid Build Coastguard Worker 102*6dbdd20aSAndroid Build Coastguard Worker if args.no_git: 103*6dbdd20aSAndroid Build Coastguard Worker head_sha1 = SCM_REV_NOT_AVAILABLE 104*6dbdd20aSAndroid Build Coastguard Worker else: 105*6dbdd20aSAndroid Build Coastguard Worker head_sha1 = get_git_sha1('HEAD') # SCM_REV_NOT_AVAILABLE on failure. 106*6dbdd20aSAndroid Build Coastguard Worker 107*6dbdd20aSAndroid Build Coastguard Worker if head_sha1 == SCM_REV_NOT_AVAILABLE: 108*6dbdd20aSAndroid Build Coastguard Worker version = release # e.g., 'v9.0'. 109*6dbdd20aSAndroid Build Coastguard Worker else: 110*6dbdd20aSAndroid Build Coastguard Worker sha1_abbrev = head_sha1[:9] 111*6dbdd20aSAndroid Build Coastguard Worker version = f'{release}-{sha1_abbrev}' # e.g., 'v9.0-adeadbeef'. 112*6dbdd20aSAndroid Build Coastguard Worker 113*6dbdd20aSAndroid Build Coastguard Worker if args.cpp_out: 114*6dbdd20aSAndroid Build Coastguard Worker guard = '%s_' % args.cpp_out.upper() 115*6dbdd20aSAndroid Build Coastguard Worker guard = re.sub(r'[^\w]', '_', guard) 116*6dbdd20aSAndroid Build Coastguard Worker lines = [] 117*6dbdd20aSAndroid Build Coastguard Worker lines.append('// Generated by %s' % os.path.basename(__file__)) 118*6dbdd20aSAndroid Build Coastguard Worker lines.append('') 119*6dbdd20aSAndroid Build Coastguard Worker lines.append('#ifndef %s' % guard) 120*6dbdd20aSAndroid Build Coastguard Worker lines.append('#define %s' % guard) 121*6dbdd20aSAndroid Build Coastguard Worker lines.append('') 122*6dbdd20aSAndroid Build Coastguard Worker lines.append('#define PERFETTO_VERSION_STRING() "%s"' % version) 123*6dbdd20aSAndroid Build Coastguard Worker lines.append('#define PERFETTO_VERSION_SCM_REVISION() "%s"' % head_sha1) 124*6dbdd20aSAndroid Build Coastguard Worker lines.append('') 125*6dbdd20aSAndroid Build Coastguard Worker lines.append('#endif // %s' % guard) 126*6dbdd20aSAndroid Build Coastguard Worker lines.append('') 127*6dbdd20aSAndroid Build Coastguard Worker content = '\n'.join(lines) 128*6dbdd20aSAndroid Build Coastguard Worker write_if_unchanged(args.cpp_out, content) 129*6dbdd20aSAndroid Build Coastguard Worker 130*6dbdd20aSAndroid Build Coastguard Worker if args.ts_out: 131*6dbdd20aSAndroid Build Coastguard Worker lines = [] 132*6dbdd20aSAndroid Build Coastguard Worker lines.append('export const VERSION = "%s";' % version) 133*6dbdd20aSAndroid Build Coastguard Worker lines.append('export const SCM_REVISION = "%s";' % head_sha1) 134*6dbdd20aSAndroid Build Coastguard Worker content = '\n'.join(lines) 135*6dbdd20aSAndroid Build Coastguard Worker write_if_unchanged(args.ts_out, content) 136*6dbdd20aSAndroid Build Coastguard Worker 137*6dbdd20aSAndroid Build Coastguard Worker if args.stdout: 138*6dbdd20aSAndroid Build Coastguard Worker print(version) 139*6dbdd20aSAndroid Build Coastguard Worker 140*6dbdd20aSAndroid Build Coastguard Worker 141*6dbdd20aSAndroid Build Coastguard Workerif __name__ == '__main__': 142*6dbdd20aSAndroid Build Coastguard Worker sys.exit(main()) 143