1#!/usr/bin/python
2#==========================================================================
3#
4#   Copyright Insight Software Consortium
5#
6#   Licensed under the Apache License, Version 2.0 (the "License");
7#   you may not use this file except in compliance with the License.
8#   You may obtain a copy of the License at
9#
10#          http://www.apache.org/licenses/LICENSE-2.0.txt
11#
12#   Unless required by applicable law or agreed to in writing, software
13#   distributed under the License is distributed on an "AS IS" BASIS,
14#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15#   See the License for the specific language governing permissions and
16#   limitations under the License.
17#
18#==========================================================================*/
19
20## This script is designed to asssit stripping out the unecessary header includes
21## for all modules.
22
23## To run the script you need to prepare a filelist.txt that list all the  .cxx
24## and .hxx files you would like to process. You also need to set all the inputs
25## inside this script.
26
27
28## Author: Pat Marion.
29## Modified by Xiaoxiao Liu.
30
31########################   Input: need edit ###########################
32sourceDir = "src/ITK" #source tree
33buildDir  = "bin/ITK" #binary tree
34relativeFileList = "filelist.txt" # files to process
35includesToSkip = ["itkVersion.h","<cstring>", "<iostream>", "<fstream>","vnl/vnl_math.h","<string>","itkConfigure.h","<stdlib>","<time.h>"] #keep those headers
36#######################################################################
37
38from __future__ import print_function
39
40import os
41
42def tryCompile(fileName):
43    # Use -B so that the target is always rebuilt
44    return os.system("make -B %s.o" % fileName)
45
46def writeFile(lines, fileName):
47
48    f = open(fileName, 'w')
49    for line in lines:
50        f.write(line)
51        f.write("\n")
52
53def removeLines(lines, removedLines):
54    newLines = []
55    for i, line in enumerate(lines):
56        if i in removedLines: continue
57        newLines.append(line)
58    return newLines
59
60def shouldSkipInclude(line):
61    for includeFile in includesToSkip:
62        if includeFile in line: return True
63    return False
64
65def checkIfDef(line, ifDefCounter):
66    if line.startswith("#ifdef") or line.startswith("if defined"):
67        return ifDefCounter + 1
68    elif line.startswith("#endif") and ifDefCounter > 0:
69        return ifDefCounter - 1
70    return ifDefCounter
71
72def processFile(directory, fileName):
73
74    absFileName = "/".join([sourceDir, directory, fileName])
75    lines = open(absFileName, 'r').read().splitlines()
76    removedLines = []
77    ifDefCounter = 0
78    for i, line in enumerate(lines):
79
80        ifDefCounter = checkIfDef(line, ifDefCounter)
81        if ifDefCounter > 0: continue
82        if line.startswith('#include'):
83            if shouldSkipInclude(line): continue
84
85            print("Try remove:", line)
86            lines[i] = ""
87
88            writeFile(lines, absFileName)
89            returnCode = tryCompile(fileName)
90            if returnCode == 0:
91                removedLines.append(i)
92            else:
93                print("Restoring:", line)
94                lines[i] = line
95
96    # Write final changes to file
97    lines = removeLines(lines, removedLines)
98    writeFile(lines, absFileName)
99
100
101def processDirectory(directory, directoryFileList):
102
103    makeDir = buildDir + "/" + directory
104    try: os.chdir(makeDir)
105    except: return
106
107    for filename in directoryFileList:
108        processFile(directory, filename)
109
110def getFilesByDirectory(fileList):
111
112    filesByDirectory = dict()
113    for filename in fileList:
114        filepath, filename = os.path.split(filename)
115        if not filepath in filesByDirectory:
116            filesByDirectory[filepath] = list()
117        filesByDirectory[filepath].append(filename)
118    return filesByDirectory
119
120def processFileList(fileList):
121
122    filesByDirectory = getFilesByDirectory(fileList)
123    for directory, directoryFileList in filesByDirectory.iteritems():
124        processDirectory(directory, directoryFileList)
125
126
127def main():
128
129    fileList = open(relativeFileList, 'r').read().splitlines()
130    processFileList(fileList)
131
132
133if __name__ == "__main__":
134    main()
135