]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Scripts/UpdateBuildVersions.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / BaseTools / Scripts / UpdateBuildVersions.py
1 ## @file
2 # Update build revisions of the tools when performing a developer build
3 #
4 # This script will modife the C/Include/Common/BuildVersion.h file and the two
5 # Python scripts, Python/Common/BuildVersion.py and Python/UPT/BuildVersion.py.
6 # If SVN is available, the tool will obtain the current checked out version of
7 # the source tree for including the --version commands.
8
9 # Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
10 #
11 # SPDX-License-Identifier: BSD-2-Clause-Patent
12 ##
13 """ This program will update the BuildVersion.py and BuildVersion.h files used to set a tool's version value """
14 from __future__ import absolute_import
15
16 import os
17 import shlex
18 import subprocess
19 import sys
20
21 from argparse import ArgumentParser, SUPPRESS
22 from tempfile import NamedTemporaryFile
23 from types import IntType, ListType
24
25
26 SYS_ENV_ERR = "ERROR : %s system environment variable must be set prior to running this tool.\n"
27
28 __execname__ = "UpdateBuildVersions.py"
29 SVN_REVISION = "$LastChangedRevision: 3 $"
30 SVN_REVISION = SVN_REVISION.replace("$LastChangedRevision:", "").replace("$", "").strip()
31 __copyright__ = "Copyright (c) 2014, Intel Corporation. All rights reserved."
32 VERSION_NUMBER = "0.7.0"
33 __version__ = "Version %s.%s" % (VERSION_NUMBER, SVN_REVISION)
34
35
36 def ParseOptions():
37 """
38 Parse the command-line options.
39 The options for this tool will be passed along to the MkBinPkg tool.
40 """
41 parser = ArgumentParser(
42 usage=("%s [options]" % __execname__),
43 description=__copyright__,
44 conflict_handler='resolve')
45
46 # Standard Tool Options
47 parser.add_argument("--version", action="version",
48 version=__execname__ + " " + __version__)
49 parser.add_argument("-s", "--silent", action="store_true",
50 dest="silent",
51 help="All output will be disabled, pass/fail determined by the exit code")
52 parser.add_argument("-v", "--verbose", action="store_true",
53 dest="verbose",
54 help="Enable verbose output")
55 # Tool specific options
56 parser.add_argument("--revert", action="store_true",
57 dest="REVERT", default=False,
58 help="Revert the BuildVersion files only")
59 parser.add_argument("--svn-test", action="store_true",
60 dest="TEST_SVN", default=False,
61 help="Test if the svn command is available")
62 parser.add_argument("--svnFlag", action="store_true",
63 dest="HAVE_SVN", default=False,
64 help=SUPPRESS)
65
66 return(parser.parse_args())
67
68
69 def ShellCommandResults(CmdLine, Opt):
70 """ Execute the command, returning the output content """
71 file_list = NamedTemporaryFile(delete=False)
72 filename = file_list.name
73 Results = []
74
75 returnValue = 0
76 try:
77 subprocess.check_call(args=shlex.split(CmdLine), stderr=subprocess.STDOUT, stdout=file_list)
78 except subprocess.CalledProcessError as err_val:
79 file_list.close()
80 if not Opt.silent:
81 sys.stderr.write("ERROR : %d : %s\n" % (err_val.returncode, err_val.__str__()))
82 if os.path.exists(filename):
83 sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
84 sys.stderr.flush()
85 returnValue = err_val.returncode
86
87 except IOError as err_val:
88 (errno, strerror) = err_val.args
89 file_list.close()
90 if not Opt.silent:
91 sys.stderr.write("I/O ERROR : %s : %s\n" % (str(errno), strerror))
92 sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
93 if os.path.exists(filename):
94 sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
95 sys.stderr.flush()
96 returnValue = errno
97
98 except OSError as err_val:
99 (errno, strerror) = err_val.args
100 file_list.close()
101 if not Opt.silent:
102 sys.stderr.write("OS ERROR : %s : %s\n" % (str(errno), strerror))
103 sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
104 if os.path.exists(filename):
105 sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
106 sys.stderr.flush()
107 returnValue = errno
108
109 except KeyboardInterrupt:
110 file_list.close()
111 if not Opt.silent:
112 sys.stderr.write("ERROR : Command terminated by user : %s\n" % CmdLine)
113 if os.path.exists(filename):
114 sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
115 sys.stderr.flush()
116 returnValue = 1
117
118 finally:
119 if not file_list.closed:
120 file_list.flush()
121 os.fsync(file_list.fileno())
122 file_list.close()
123
124 if os.path.exists(filename):
125 fd_ = open(filename, 'r')
126 Results = fd_.readlines()
127 fd_.close()
128 os.unlink(filename)
129
130 if returnValue > 0:
131 return returnValue
132
133 return Results
134
135
136 def UpdateBuildVersionPython(Rev, UserModified, opts):
137 """ This routine will update the BuildVersion.h files in the C source tree """
138 for SubDir in ["Common", "UPT"]:
139 PyPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "Python", SubDir)
140 BuildVersionPy = os.path.join(PyPath, "BuildVersion.py")
141 fd_ = open(os.path.normpath(BuildVersionPy), 'r')
142 contents = fd_.readlines()
143 fd_.close()
144 if opts.HAVE_SVN is False:
145 BuildVersionOrig = os.path.join(PyPath, "orig_BuildVersion.py")
146 fd_ = open (BuildVersionOrig, 'w')
147 for line in contents:
148 fd_.write(line)
149 fd_.flush()
150 fd_.close()
151 new_content = []
152 for line in contents:
153 if line.strip().startswith("gBUILD_VERSION"):
154 new_line = "gBUILD_VERSION = \"Developer Build based on Revision: %s\"" % Rev
155 if UserModified:
156 new_line = "gBUILD_VERSION = \"Developer Build based on Revision: %s with Modified Sources\"" % Rev
157 new_content.append(new_line)
158 continue
159 new_content.append(line)
160
161 fd_ = open(os.path.normpath(BuildVersionPy), 'w')
162 for line in new_content:
163 fd_.write(line)
164 fd_.close()
165
166
167 def UpdateBuildVersionH(Rev, UserModified, opts):
168 """ This routine will update the BuildVersion.h files in the C source tree """
169 CPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "C", "Include", "Common")
170 BuildVersionH = os.path.join(CPath, "BuildVersion.h")
171 fd_ = open(os.path.normpath(BuildVersionH), 'r')
172 contents = fd_.readlines()
173 fd_.close()
174 if opts.HAVE_SVN is False:
175 BuildVersionOrig = os.path.join(CPath, "orig_BuildVersion.h")
176 fd_ = open(BuildVersionOrig, 'w')
177 for line in contents:
178 fd_.write(line)
179 fd_.flush()
180 fd_.close()
181
182 new_content = []
183 for line in contents:
184 if line.strip().startswith("#define"):
185 new_line = "#define __BUILD_VERSION \"Developer Build based on Revision: %s\"" % Rev
186 if UserModified:
187 new_line = "#define __BUILD_VERSION \"Developer Build based on Revision: %s with Modified Sources\"" % \
188 Rev
189 new_content.append(new_line)
190 continue
191 new_content.append(line)
192
193 fd_ = open(os.path.normpath(BuildVersionH), 'w')
194 for line in new_content:
195 fd_.write(line)
196 fd_.close()
197
198
199 def RevertCmd(Filename, Opt):
200 """ This is the shell command that does the SVN revert """
201 CmdLine = "svn revert %s" % Filename.replace("\\", "/").strip()
202 try:
203 subprocess.check_output(args=shlex.split(CmdLine))
204 except subprocess.CalledProcessError as err_val:
205 if not Opt.silent:
206 sys.stderr.write("Subprocess ERROR : %s\n" % err_val)
207 sys.stderr.flush()
208
209 except IOError as err_val:
210 (errno, strerror) = err_val.args
211 if not Opt.silent:
212 sys.stderr.write("I/O ERROR : %d : %s\n" % (str(errno), strerror))
213 sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
214 sys.stderr.flush()
215
216 except OSError as err_val:
217 (errno, strerror) = err_val.args
218 if not Opt.silent:
219 sys.stderr.write("OS ERROR : %d : %s\n" % (str(errno), strerror))
220 sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
221 sys.stderr.flush()
222
223 except KeyboardInterrupt:
224 if not Opt.silent:
225 sys.stderr.write("ERROR : Command terminated by user : %s\n" % CmdLine)
226 sys.stderr.flush()
227
228 if Opt.verbose:
229 sys.stdout.write("Reverted this file: %s\n" % Filename)
230 sys.stdout.flush()
231
232
233 def GetSvnRevision(opts):
234 """ Get the current revision of the BaseTools/Source tree, and check if any of the files have been modified """
235 Revision = "Unknown"
236 Modified = False
237
238 if opts.HAVE_SVN is False:
239 sys.stderr.write("WARNING: the svn command-line tool is not available.\n")
240 return (Revision, Modified)
241
242 SrcPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source")
243 # Check if there are modified files.
244 Cwd = os.getcwd()
245 os.chdir(SrcPath)
246
247 StatusCmd = "svn st -v --depth infinity --non-interactive"
248 contents = ShellCommandResults(StatusCmd, opts)
249 os.chdir(Cwd)
250 if isinstance(contents, ListType):
251 for line in contents:
252 if line.startswith("M "):
253 Modified = True
254 break
255
256 # Get the repository revision of BaseTools/Source
257 InfoCmd = "svn info %s" % SrcPath.replace("\\", "/").strip()
258 Revision = 0
259 contents = ShellCommandResults(InfoCmd, opts)
260 if isinstance(contents, IntType):
261 return 0, Modified
262 for line in contents:
263 line = line.strip()
264 if line.startswith("Revision:"):
265 Revision = line.replace("Revision:", "").strip()
266 break
267
268 return (Revision, Modified)
269
270
271 def CheckSvn(opts):
272 """
273 This routine will return True if an svn --version command succeeds, or False if it fails.
274 If it failed, SVN is not available.
275 """
276 OriginalSilent = opts.silent
277 opts.silent = True
278 VerCmd = "svn --version"
279 contents = ShellCommandResults(VerCmd, opts)
280 opts.silent = OriginalSilent
281 if isinstance(contents, IntType):
282 if opts.verbose:
283 sys.stdout.write("SVN does not appear to be available.\n")
284 sys.stdout.flush()
285 return False
286
287 if opts.verbose:
288 sys.stdout.write("Found %s" % contents[0])
289 sys.stdout.flush()
290 return True
291
292
293 def CopyOrig(Src, Dest, Opt):
294 """ Overwrite the Dest File with the Src File content """
295 try:
296 fd_ = open(Src, 'r')
297 contents = fd_.readlines()
298 fd_.close()
299 fd_ = open(Dest, 'w')
300 for line in contents:
301 fd_.write(line)
302 fd_.flush()
303 fd_.close()
304 except IOError:
305 if not Opt.silent:
306 sys.stderr.write("Unable to restore this file: %s\n" % Dest)
307 sys.stderr.flush()
308 return 1
309
310 os.remove(Src)
311 if Opt.verbose:
312 sys.stdout.write("Restored this file: %s\n" % Src)
313 sys.stdout.flush()
314
315 return 0
316
317
318 def CheckOriginals(Opts):
319 """
320 If SVN was not available, then the tools may have made copies of the original BuildVersion.* files using
321 orig_BuildVersion.* for the name. If they exist, replace the existing BuildVersion.* file with the corresponding
322 orig_BuildVersion.* file.
323 Returns 0 if this succeeds, or 1 if the copy function fails. It will also return 0 if the orig_BuildVersion.* file
324 does not exist.
325 """
326 CPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "C", "Include", "Common")
327 BuildVersionH = os.path.join(CPath, "BuildVersion.h")
328 OrigBuildVersionH = os.path.join(CPath, "orig_BuildVersion.h")
329 if not os.path.exists(OrigBuildVersionH):
330 return 0
331 if CopyOrig(OrigBuildVersionH, BuildVersionH, Opts):
332 return 1
333 for SubDir in ["Common", "UPT"]:
334 PyPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "Python", SubDir)
335 BuildVersionPy = os.path.join(PyPath, "BuildVersion.h")
336 OrigBuildVersionPy = os.path.join(PyPath, "orig_BuildVersion.h")
337 if not os.path.exists(OrigBuildVersionPy):
338 return 0
339 if CopyOrig(OrigBuildVersionPy, BuildVersionPy, Opts):
340 return 1
341
342 return 0
343
344
345 def RevertBuildVersionFiles(opts):
346 """
347 This routine will attempt to perform an SVN --revert on each of the BuildVersion.* files
348 """
349 if not opts.HAVE_SVN:
350 if CheckOriginals(opts):
351 return 1
352 return 0
353 # SVN is available
354 BuildVersionH = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "C", "Include", "Common", "BuildVersion.h")
355 RevertCmd(BuildVersionH, opts)
356 for SubDir in ["Common", "UPT"]:
357 BuildVersionPy = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "Python", SubDir, "BuildVersion.py")
358 RevertCmd(BuildVersionPy, opts)
359
360 def UpdateRevisionFiles():
361 """ Main routine that will update the BuildVersion.py and BuildVersion.h files."""
362 options = ParseOptions()
363 # Check the working environment
364 if "WORKSPACE" not in os.environ.keys():
365 sys.stderr.write(SYS_ENV_ERR % 'WORKSPACE')
366 return 1
367 if 'BASE_TOOLS_PATH' not in os.environ.keys():
368 sys.stderr.write(SYS_ENV_ERR % 'BASE_TOOLS_PATH')
369 return 1
370 if not os.path.exists(os.environ['BASE_TOOLS_PATH']):
371 sys.stderr.write("Unable to locate the %s directory." % os.environ['BASE_TOOLS_PATH'])
372 return 1
373
374
375 options.HAVE_SVN = CheckSvn(options)
376 if options.TEST_SVN:
377 return (not options.HAVE_SVN)
378 # done processing the option, now use the option.HAVE_SVN as a flag. True = Have it, False = Don't have it.
379 if options.REVERT:
380 # Just revert the tools an exit
381 RevertBuildVersionFiles(options)
382 else:
383 # Revert any changes in the BuildVersion.* files before setting them again.
384 RevertBuildVersionFiles(options)
385 Revision, Modified = GetSvnRevision(options)
386 if options.verbose:
387 sys.stdout.write("Revision: %s is Modified: %s\n" % (Revision, Modified))
388 sys.stdout.flush()
389 UpdateBuildVersionH(Revision, Modified, options)
390 UpdateBuildVersionPython(Revision, Modified, options)
391
392 return 0
393
394
395 if __name__ == "__main__":
396 sys.exit(UpdateRevisionFiles())
397
398