186f29464SPedro Giffuni#!/usr/bin/env python 29f22d7c2SAndrew Rist# ************************************************************* 39f22d7c2SAndrew Rist# 49f22d7c2SAndrew Rist# Licensed to the Apache Software Foundation (ASF) under one 59f22d7c2SAndrew Rist# or more contributor license agreements. See the NOTICE file 69f22d7c2SAndrew Rist# distributed with this work for additional information 79f22d7c2SAndrew Rist# regarding copyright ownership. The ASF licenses this file 89f22d7c2SAndrew Rist# to you under the Apache License, Version 2.0 (the 99f22d7c2SAndrew Rist# "License"); you may not use this file except in compliance 109f22d7c2SAndrew Rist# with the License. You may obtain a copy of the License at 119f22d7c2SAndrew Rist# 129f22d7c2SAndrew Rist# http://www.apache.org/licenses/LICENSE-2.0 139f22d7c2SAndrew Rist# 149f22d7c2SAndrew Rist# Unless required by applicable law or agreed to in writing, 159f22d7c2SAndrew Rist# software distributed under the License is distributed on an 169f22d7c2SAndrew Rist# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 179f22d7c2SAndrew Rist# KIND, either express or implied. See the License for the 189f22d7c2SAndrew Rist# specific language governing permissions and limitations 199f22d7c2SAndrew Rist# under the License. 209f22d7c2SAndrew Rist# 219f22d7c2SAndrew Rist# ************************************************************* 229f22d7c2SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir# ------------------------------------------------------------------------------ 25cdf0e10cSrcweir# Hacky little delta debug tool to figure out the proper includes for a pch file 26cdf0e10cSrcweir# 27cdf0e10cSrcweir# Usage: 2886f29464SPedro Giffuni# 29cdf0e10cSrcweir# pchdelta.py <pch_target> <dir1> [<dir2> <dir3> ...] 30cdf0e10cSrcweir# 31cdf0e10cSrcweir# <pch_target> File to perform delta debugging on. The section to test 32cdf0e10cSrcweir# is delimeted by '//---MARKER---' lines. 33cdf0e10cSrcweir# <dir1> .. <dirn> Sequence of directories to run dmake in to test if the 34cdf0e10cSrcweir# modification works 35cdf0e10cSrcweir# 36cdf0e10cSrcweir# Examples: 37cdf0e10cSrcweir# 38cdf0e10cSrcweir# pchdelta.py inc/pch/precompiled_sfx2.hxx inc source/dialog 39cdf0e10cSrcweir# 40cdf0e10cSrcweir# Run pchdelta inside sfx2 first building the pch files and then files in 41cdf0e10cSrcweir# source/dialog 42cdf0e10cSrcweir# 43cdf0e10cSrcweir# ------------------------------------------------------------------------------ 44cdf0e10cSrcweir 45cdf0e10cSrcweirimport os 46cdf0e10cSrcweirimport os.path 47cdf0e10cSrcweirimport sys 48cdf0e10cSrcweir 49cdf0e10cSrcweir# C++ 50cdf0e10cSrcweirMARKER="//---MARKER---\n" 51cdf0e10cSrcweir 52cdf0e10cSrcweir# dmake 53cdf0e10cSrcweir#MARKER="#---MARKER---\n" 54cdf0e10cSrcweir 55cdf0e10cSrcweir# ------------------------------------------------------------------------------ 56cdf0e10cSrcweir# Sequentially build all argument directories from scratch 57cdf0e10cSrcweir 58cdf0e10cSrcweirdef testSequenceBuild(dirlist): 59cdf0e10cSrcweir cwd = os.path.abspath(os.getcwd()) 60cdf0e10cSrcweir for path in dirlist: 61cdf0e10cSrcweir os.chdir(path) 62cdf0e10cSrcweir buildcommand = "dmake -u" 63cdf0e10cSrcweir buildcommand += " >>" + cwd + "/buildlog.txt 2>&1" 64cdf0e10cSrcweir buildresult = os.system(buildcommand) 65cdf0e10cSrcweir os.chdir(cwd) 66cdf0e10cSrcweir if buildresult != 0: 67cdf0e10cSrcweir return False 68cdf0e10cSrcweir return True 69cdf0e10cSrcweir 70cdf0e10cSrcweir# ------------------------------------------------------------------------------ 71cdf0e10cSrcweir# Dump out the delta file with corresponding markers 72cdf0e10cSrcweir 73cdf0e10cSrcweirdef writePch(pchname, header, footer, acceptedlines, testlines): 74cdf0e10cSrcweir outputfile = file(pchname, "w") 75cdf0e10cSrcweir outputfile.write(header) 76cdf0e10cSrcweir outputfile.write(MARKER) 77cdf0e10cSrcweir outputfile.write("\n".join(acceptedlines)) 78cdf0e10cSrcweir if len(testlines) > 0: 79cdf0e10cSrcweir outputfile.write("\n\n//---Candidate marker---\n") 80cdf0e10cSrcweir outputfile.write("\n".join(testlines) + "\n") 81cdf0e10cSrcweir outputfile.write("//---Candidate marker end---\n") 82cdf0e10cSrcweir outputfile.write(MARKER) 83cdf0e10cSrcweir outputfile.write(footer) 84cdf0e10cSrcweir outputfile.close() 8586f29464SPedro Giffuni 86cdf0e10cSrcweir 87cdf0e10cSrcweir# ------------------------------------------------------------------------------ 88cdf0e10cSrcweir# Recursive tester routine. Test the segment given and if an error is 89cdf0e10cSrcweir# encountered splits the segment into <fanout> subsegment and recurses. Failing 90cdf0e10cSrcweir# one liners are rejected. The set of accepted lines are built sequentially from 91cdf0e10cSrcweir# the beginning. 92cdf0e10cSrcweir 93cdf0e10cSrcweirdef binaryTest(dirlist, lines, pchname, header, footer, acceptedlines, indent, startpoint): 94cdf0e10cSrcweir linecount = len(lines) 95cdf0e10cSrcweir if linecount == 0: 96cdf0e10cSrcweir return 97cdf0e10cSrcweir # Test if this slice passes the buildtest 98cdf0e10cSrcweir writePch(pchname, header, footer, acceptedlines, lines) 99cdf0e10cSrcweir if testSequenceBuild(dirlist): 100cdf0e10cSrcweir return acceptedlines + lines 101cdf0e10cSrcweir 102cdf0e10cSrcweir # Reject one liners 103cdf0e10cSrcweir if linecount == 1: 104*b0ad9294SPedro Giffuni print(indent + "Rejected: " + lines[0]) 105cdf0e10cSrcweir return acceptedlines 106cdf0e10cSrcweir 107cdf0e10cSrcweir # Recurse with multiline slices 108cdf0e10cSrcweir fanout = 4 109cdf0e10cSrcweir splits = [] 110cdf0e10cSrcweir for i in range(3): 111cdf0e10cSrcweir splits.append(linecount * (i + 1) / fanout) 112cdf0e10cSrcweir splits.append(linecount) 113cdf0e10cSrcweir 114cdf0e10cSrcweir splitstart = 0 115cdf0e10cSrcweir for splitend in splits: 116cdf0e10cSrcweir # avoid splitting in case we have no resulting lines 117cdf0e10cSrcweir if (splitend - splitstart) == 0: 118cdf0e10cSrcweir continue 119cdf0e10cSrcweir splitslice = lines[splitstart:splitend] 120*b0ad9294SPedro Giffuni print(indent + "[" + str(startpoint + splitstart) + ":" + str(startpoint + splitend) + "] (" + str(splitend - splitstart) + ")") 121cdf0e10cSrcweir acceptedlines = binaryTest(dirlist, splitslice, pchname, header, footer, acceptedlines, indent + " ", startpoint + splitstart) 122cdf0e10cSrcweir splitstart = splitend 123cdf0e10cSrcweir 124cdf0e10cSrcweir return acceptedlines 125cdf0e10cSrcweir 126cdf0e10cSrcweir# ------------------------------------------------------------------------------ 127cdf0e10cSrcweir# Main entry point 128cdf0e10cSrcweir 129cdf0e10cSrcweirif len(sys.argv) < 3: 130*b0ad9294SPedro Giffuni print("Usage: " + sys.argv[0] + " <pch_target> <dir1> [<dir2> <dir3> ...]") 131cdf0e10cSrcweir sys.exit(1) 132cdf0e10cSrcweir 133cdf0e10cSrcweirpchname = os.path.abspath(sys.argv[1]) 134cdf0e10cSrcweirdirlist = sys.argv[2:] 135cdf0e10cSrcweir 136cdf0e10cSrcweir# remove old build log file 137cdf0e10cSrcweirif os.path.exists("buildlog.txt"): 138cdf0e10cSrcweir os.remove("buildlog.txt") 139cdf0e10cSrcweir 140cdf0e10cSrcweir# test for corner case of everything working from the start 141cdf0e10cSrcweirif testSequenceBuild(dirlist): 142*b0ad9294SPedro Giffuni print("pch working, nothing to do.") 143cdf0e10cSrcweir sys.exit(0) 144cdf0e10cSrcweir 145cdf0e10cSrcweir# Open the header file for reading 146cdf0e10cSrcweirinputfile = file(pchname, "r+") 147cdf0e10cSrcweirinputdata = inputfile.read() 148cdf0e10cSrcweirinputfile.close() 149cdf0e10cSrcweir 150cdf0e10cSrcweirsegments = inputdata.split(MARKER) 151cdf0e10cSrcweirheader = segments[0] 152cdf0e10cSrcweirfooter = segments[2] 153cdf0e10cSrcweirlines = segments[1].split("\n") 154cdf0e10cSrcweir 155cdf0e10cSrcweirwritePch(pchname + "_backup", header, footer, lines, []) 156cdf0e10cSrcweir 157cdf0e10cSrcweir# test for corner case of no convergence possible 158cdf0e10cSrcweirwritePch(pchname, header, footer, [], []) 159cdf0e10cSrcweirif not testSequenceBuild(dirlist): 160cdf0e10cSrcweir writePch(pchname, header, footer, lines, []) 161*b0ad9294SPedro Giffuni print("Building with no candidate lines failed. Convergence questionable, aborting.") 162cdf0e10cSrcweir sys.exit(0) 163cdf0e10cSrcweir 164cdf0e10cSrcweir# Starting pruning 165*b0ad9294SPedro Giffuniprint("Starting evaluation of " + str(len(lines)) + " lines") 166cdf0e10cSrcweiracceptedlines = binaryTest(dirlist, lines, pchname, header, footer, [], "", 0) 167cdf0e10cSrcweirwritePch(pchname, header, footer, acceptedlines, []) 168