3 # [PR 11661] Note that we hardwire to /usr/bin/python because we
4 # want to the use the system version of Python on Mac OS X.
5 # This one has the scripting bridge enabled.
8 if sys
.version_info
< (3, 6):
9 print "set-xcode-analyzer requires Python 3.6 or later"
20 def FindClangSpecs(path
):
21 print "(+) Searching for xcspec file in: ", path
22 for root
, dirs
, files
in os
.walk(path
):
24 if f
.endswith(".xcspec") and f
.startswith("Clang LLVM"):
25 yield os
.path
.join(root
, f
)
27 def ModifySpec(path
, isBuiltinAnalyzer
, pathToChecker
):
28 t
= tempfile
.NamedTemporaryFile(delete
=False)
32 # First search for CLANG_ANALYZER_EXEC. Newer
33 # versions of Xcode set EXEC_PATH to be CLANG_ANALYZER_EXEC.
34 with
open(path
) as f2
:
36 if line
.find("CLANG_ANALYZER_EXEC") >= 0:
37 pathToChecker
= "$(CLANG_ANALYZER_EXEC)"
39 # Now create a new file.
42 if line
.find("Static Analyzer") >= 0:
45 m
= re
.search(r
'^(\s*ExecPath\s*=\s*")', line
)
47 line
= "".join([m
.group(0), pathToChecker
, '";\n'])
48 # Do not modify further ExecPath's later in the xcspec.
52 print "(+) processing:", path
54 shutil
.copy(t
.name
, path
)
55 os
.chmod(path
, stat
.S_IRUSR | stat
.S_IWUSR | stat
.S_IRGRP | stat
.S_IROTH
)
57 print " (-) Cannot update file:", why
, "\n"
59 print " (-) Cannot update file:", why
, "\n"
63 from optparse
import OptionParser
64 parser
= OptionParser('usage: %prog [options]')
65 parser
.set_description(__doc__
)
66 parser
.add_option("--use-checker-build", dest
="path",
67 help="Use the Clang located at the provided absolute path, e.g. /Users/foo/checker-1")
68 parser
.add_option("--use-xcode-clang", action
="store_const",
69 const
="$(CLANG)", dest
="default",
70 help="Use the Clang bundled with Xcode")
71 (options
, args
) = parser
.parse_args()
72 if options
.path
is None and options
.default
is None:
73 parser
.error("You must specify a version of Clang to use for static analysis. Specify '-h' for details")
75 # determine if Xcode is running
76 for x
in NSWorkspace
.sharedWorkspace().runningApplications():
77 if x
.localizedName().find("Xcode") >= 0:
78 print "(-) You must quit Xcode first before modifying its configuration files."
81 isBuiltinAnalyzer
= False
84 path
= os
.path
.expanduser(options
.path
)
85 if not path
.endswith("clang"):
86 print "(+) Using Clang bundled with checker build:", path
87 path
= os
.path
.join(path
, "bin", "clang");
89 print "(+) Using Clang located at:", path
91 print "(+) Using the Clang bundled with Xcode"
92 path
= options
.default
93 isBuiltinAnalyzer
= True
96 xcode_path
= subprocess
.check_output(["xcode-select", "-print-path"])
97 except AttributeError:
98 # Fall back to the default install location when using Python < 2.7.0
99 xcode_path
= "/Developer"
100 if (xcode_path
.find(".app/") != -1):
101 # Cut off the 'Developer' dir, as the xcspec lies in another part
102 # of the Xcode.app subtree.
103 xcode_path
= xcode_path
.rsplit('/Developer', 1)[0]
106 for x
in FindClangSpecs(xcode_path
):
108 ModifySpec(x
, isBuiltinAnalyzer
, path
)
111 print "(-) No compiler configuration file was found. Xcode's analyzer has not been updated."
113 if __name__
== '__main__':