2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
7 Runs Coverity Prevent on a build of Chromium.
9 This script should be run in a Visual Studio Command Prompt, so that the
10 INCLUDE, LIB, and PATH environment variables are set properly for Visual
16 coverity.py --target=debug
17 %comspec% /c ""C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat"
18 x86 && C:\Python24\python.exe C:\coverity.py"
20 For a full list of options, pass the '--help' switch.
22 See http://support.microsoft.com/kb/308569 for running this script as a
23 Scheduled Task on Windows XP.
35 # These constants provide default values, but are exposed as command-line
36 # flags. See the --help for more info. Note that for historical reasons
37 # (the script started out as Windows-only and has legacy usages which pre-date
38 # these switches), the constants are all tuned for Windows.
39 # Usage of this script on Linux pretty much requires explicit
40 # --source-dir, --coverity-bin-dir, --coverity-intermediate-dir, and
41 # --coverity-target command line flags.
43 CHROMIUM_SOURCE_DIR
= 'C:\\chromium.latest'
45 # Relative to CHROMIUM_SOURCE_DIR.
46 CHROMIUM_SOLUTION_FILE
= 'src\\chrome\\chrome.sln'
48 # Relative to CHROMIUM_SOURCE_DIR.
49 CHROMIUM_SOLUTION_DIR
= 'src\\chrome'
51 COVERITY_BIN_DIR
= 'C:\\coverity\\prevent-win32-4.5.1\\bin'
53 COVERITY_INTERMEDIATE_DIR
= 'C:\\coverity\\cvbuild\\cr_int'
55 COVERITY_ANALYZE_OPTIONS
= ('--cxx --security --concurrency '
57 '--enable MISSING_LOCK '
58 '--enable DELETE_VOID '
59 '--checker-option PASS_BY_VALUE:size_threshold:16 '
61 'USE_AFTER_FREE:allow_simple_use:false '
62 '--enable-constraint-fpp '
63 '--enable-callgraph-metrics')
65 # Might need to be changed to FQDN
66 COVERITY_REMOTE
= 'chromecoverity-linux1'
68 COVERITY_PORT
= '5467'
70 COVERITY_PRODUCT
= 'Chromium'
72 COVERITY_TARGET
= 'Windows'
74 COVERITY_USER
= 'admin'
75 # looking for a PASSWORD constant? Look at --coverity-password-file instead.
77 # Relative to CHROMIUM_SOURCE_DIR. Contains the pid of this script.
78 LOCK_FILE
= 'coverity.lock'
81 def _ReadPassword(pwfilename
):
82 """Reads the coverity password in from a file where it was stashed"""
83 pwfile
= open(pwfilename
, 'r')
84 password
= pwfile
.readline()
86 return password
.rstrip()
89 def _RunCommand(cmd
, dry_run
, shell
=False, echo_cmd
=True):
90 """Runs the command if dry_run is false, otherwise just prints the command."""
94 return subprocess
.call(cmd
, shell
=shell
)
99 def _ReleaseLock(lock_file
, lock_filename
):
100 """Removes the lockfile. Function-ized so we can bail from anywhere"""
102 os
.remove(lock_filename
)
105 def run_coverity(options
, args
):
106 """Runs all the selected tests for the given build type and target."""
107 # Create the lock file to prevent another instance of this script from
109 lock_filename
= os
.path
.join(options
.source_dir
, LOCK_FILE
)
111 lock_file
= os
.open(lock_filename
,
112 os
.O_CREAT | os
.O_EXCL | os
.O_TRUNC | os
.O_RDWR
)
114 print 'Failed to open lock file:\n ' + str(err
)
117 # Write the pid of this script (the python.exe process) to the lock file.
118 os
.write(lock_file
, str(os
.getpid()))
120 options
.target
= options
.target
.title()
122 start_time
= time
.time()
124 print 'Change directory to ' + options
.source_dir
125 os
.chdir(options
.source_dir
)
127 # The coverity-password filename may have been a relative path.
128 # If so, assume it's relative to the source directory, which means
129 # the time to read the password is after we do the chdir().
130 coverity_password
= _ReadPassword(options
.coverity_password_file
)
133 gclient_exit
= _RunCommand(cmd
, options
.dry_run
, shell
=True)
134 if gclient_exit
!= 0:
135 print 'gclient aborted with status %s' % gclient_exit
136 _ReleaseLock(lock_file
, lock_filename
)
139 print 'Elapsed time: %ds' % (time
.time() - start_time
)
141 # Do a clean build. Remove the build output directory first.
142 if sys
.platform
.startswith('linux'):
143 rm_path
= os
.path
.join(options
.source_dir
,'src','out',options
.target
)
144 elif sys
.platform
== 'win32':
145 rm_path
= os
.path
.join(options
.source_dir
,options
.solution_dir
,
147 elif sys
.platform
== 'darwin':
148 rm_path
= os
.path
.join(options
.source_dir
,'src','xcodebuild')
150 print 'Platform "%s" unrecognized, aborting' % sys
.platform
151 _ReleaseLock(lock_file
, lock_filename
)
155 print 'shutil.rmtree(%s)' % repr(rm_path
)
157 shutil
.rmtree(rm_path
,True)
159 if options
.preserve_intermediate_dir
:
160 print 'Preserving intermediate directory.'
163 print 'shutil.rmtree(%s)' % repr(options
.coverity_intermediate_dir
)
164 print 'os.mkdir(%s)' % repr(options
.coverity_intermediate_dir
)
166 shutil
.rmtree(options
.coverity_intermediate_dir
,True)
167 os
.mkdir(options
.coverity_intermediate_dir
)
169 print 'Elapsed time: %ds' % (time
.time() - start_time
)
171 use_shell_during_make
= False
172 if sys
.platform
.startswith('linux'):
173 use_shell_during_make
= True
175 _RunCommand('pwd', options
.dry_run
, shell
=True)
176 cmd
= '%s/cov-build --dir %s make BUILDTYPE=%s chrome' % (
177 options
.coverity_bin_dir
, options
.coverity_intermediate_dir
,
179 elif sys
.platform
== 'win32':
180 cmd
= ('%s\\cov-build.exe --dir %s devenv.com %s\\%s /build %s '
181 '/project chrome.vcproj') % (
182 options
.coverity_bin_dir
, options
.coverity_intermediate_dir
,
183 options
.source_dir
, options
.solution_file
, options
.target
)
184 elif sys
.platform
== 'darwin':
185 use_shell_during_make
= True
186 os
.chdir('src/chrome')
187 _RunCommand('pwd', options
.dry_run
, shell
=True)
188 cmd
= ('%s/cov-build --dir %s xcodebuild -project chrome.xcodeproj '
189 '-configuration %s -target chrome') % (
190 options
.coverity_bin_dir
, options
.coverity_intermediate_dir
,
194 _RunCommand(cmd
, options
.dry_run
, shell
=use_shell_during_make
)
195 print 'Elapsed time: %ds' % (time
.time() - start_time
)
197 cov_analyze_exe
= os
.path
.join(options
.coverity_bin_dir
,'cov-analyze')
198 cmd
= '%s --dir %s %s' % (cov_analyze_exe
,
199 options
.coverity_intermediate_dir
,
200 options
.coverity_analyze_options
)
201 _RunCommand(cmd
, options
.dry_run
, shell
=use_shell_during_make
)
202 print 'Elapsed time: %ds' % (time
.time() - start_time
)
204 cov_commit_exe
= os
.path
.join(options
.coverity_bin_dir
,'cov-commit-defects')
206 # On Linux we have started using a Target with a space in it, so we want
207 # to quote it. On the other hand, Windows quoting doesn't work quite the
208 # same way. To be conservative, I'd like to avoid quoting an argument
209 # that doesn't need quoting and which we haven't historically been quoting
210 # on that platform. So, only quote the target if we have to.
211 coverity_target
= options
.coverity_target
212 if sys
.platform
!= 'win32':
213 coverity_target
= '"%s"' % coverity_target
215 cmd
= ('%s --dir %s --remote %s --port %s '
219 '--password %s') % (cov_commit_exe
,
220 options
.coverity_intermediate_dir
,
221 options
.coverity_dbhost
,
222 options
.coverity_port
,
223 options
.coverity_product
,
225 options
.coverity_user
,
227 # Avoid echoing the Commit command because it has a password in it
228 _RunCommand(cmd
, options
.dry_run
, shell
=use_shell_during_make
, echo_cmd
=False)
230 print 'Total time: %ds' % (time
.time() - start_time
)
232 _ReleaseLock(lock_file
, lock_filename
)
238 option_parser
= optparse
.OptionParser()
239 option_parser
.add_option('', '--dry-run', action
='store_true', default
=False,
240 help='print but don\'t run the commands')
242 option_parser
.add_option('', '--target', default
='Release',
243 help='build target (Debug or Release)')
245 option_parser
.add_option('', '--source-dir', dest
='source_dir',
246 help='full path to directory ABOVE "src"',
247 default
=CHROMIUM_SOURCE_DIR
)
249 option_parser
.add_option('', '--solution-file', dest
='solution_file',
250 default
=CHROMIUM_SOLUTION_FILE
)
252 option_parser
.add_option('', '--solution-dir', dest
='solution_dir',
253 default
=CHROMIUM_SOLUTION_DIR
)
255 option_parser
.add_option('', '--coverity-bin-dir', dest
='coverity_bin_dir',
256 default
=COVERITY_BIN_DIR
)
258 option_parser
.add_option('', '--coverity-intermediate-dir',
259 dest
='coverity_intermediate_dir',
260 default
=COVERITY_INTERMEDIATE_DIR
)
262 option_parser
.add_option('', '--coverity-analyze-options',
263 dest
='coverity_analyze_options',
264 help=('all cov-analyze options, e.g. "%s"'
265 % COVERITY_ANALYZE_OPTIONS
),
266 default
=COVERITY_ANALYZE_OPTIONS
)
268 option_parser
.add_option('', '--coverity-db-host',
269 dest
='coverity_dbhost',
270 help=('coverity defect db server hostname, e.g. %s'
272 default
=COVERITY_REMOTE
)
274 option_parser
.add_option('', '--coverity-db-port', dest
='coverity_port',
275 help=('port # of coverity web/db server, e.g. %s'
277 default
=COVERITY_PORT
)
279 option_parser
.add_option('', '--coverity-product', dest
='coverity_product',
280 help=('Product name reported to coverity, e.g. %s'
282 default
=COVERITY_PRODUCT
)
284 option_parser
.add_option('', '--coverity-target', dest
='coverity_target',
285 help='Platform Target reported to coverity',
286 default
=COVERITY_TARGET
)
288 option_parser
.add_option('', '--coverity-user', dest
='coverity_user',
289 help='Username used to log into coverity',
290 default
=COVERITY_USER
)
292 option_parser
.add_option('', '--coverity-password-file',
293 dest
='coverity_password_file',
294 help='file containing the coverity password',
295 default
='coverity-password')
297 helpmsg
= ('By default, the intermediate dir is emptied before analysis. '
298 'This switch disables that behavior.')
299 option_parser
.add_option('', '--preserve-intermediate-dir',
300 action
='store_true', help=helpmsg
,
303 options
, args
= option_parser
.parse_args()
304 return run_coverity(options
, args
)
307 if '__main__' == __name__
: