mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-01-08 08:11:36 +01:00
d65483ae16
The cef_api_hash.h file was previously only updated when the translator tool was run manually. Forgetting to run the translator tool after changing include/internal/cef_types*.h files would result in cef_parser.py incorrectly computing the CEF minor version number for future builds. By updating this file automatically at build time the number of errors should be reduced.
284 lines
8.2 KiB
Python
284 lines
8.2 KiB
Python
# Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
|
|
# reserved. Use of this source code is governed by a BSD-style license that
|
|
# can be found in the LICENSE file.
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import print_function
|
|
from file_util import *
|
|
import os
|
|
import re
|
|
import shutil
|
|
import string
|
|
import sys
|
|
import textwrap
|
|
import time
|
|
import itertools
|
|
import hashlib
|
|
|
|
|
|
class cef_api_hash:
|
|
""" CEF API hash calculator """
|
|
|
|
def __init__(self, headerdir, debugdir=None, verbose=False):
|
|
if headerdir is None or len(headerdir) == 0:
|
|
raise AssertionError("headerdir is not specified")
|
|
|
|
self.__headerdir = headerdir
|
|
self.__debugdir = debugdir
|
|
self.__verbose = verbose
|
|
self.__debug_enabled = not (self.__debugdir is
|
|
None) and len(self.__debugdir) > 0
|
|
|
|
self.platforms = ["windows", "macosx", "linux"]
|
|
|
|
self.platform_files = {
|
|
# List of includes_win_capi from cef_paths2.gypi.
|
|
"windows": [
|
|
"internal/cef_types_win.h",
|
|
],
|
|
# List of includes_mac_capi from cef_paths2.gypi.
|
|
"macosx": [
|
|
"internal/cef_types_mac.h",
|
|
],
|
|
# List of includes_linux_capi from cef_paths2.gypi.
|
|
"linux": [
|
|
"internal/cef_types_linux.h",
|
|
]
|
|
}
|
|
|
|
self.included_files = []
|
|
|
|
# List of include/ and include/internal/ files from cef_paths2.gypi.
|
|
self.excluded_files = [
|
|
# includes_common
|
|
"cef_api_hash.h",
|
|
"cef_base.h",
|
|
"cef_config.h",
|
|
"cef_version.h",
|
|
"internal/cef_export.h",
|
|
"internal/cef_ptr.h",
|
|
"internal/cef_string_wrappers.h",
|
|
"internal/cef_types_wrappers.h",
|
|
# includes_win
|
|
"cef_sandbox_win.h",
|
|
"internal/cef_win.h",
|
|
# includes_mac
|
|
"cef_application_mac.h",
|
|
"cef_sandbox_mac.h",
|
|
"internal/cef_mac.h",
|
|
# includes_linux
|
|
"internal/cef_linux.h",
|
|
]
|
|
|
|
def calculate(self):
|
|
filenames = [
|
|
filename for filename in self.__get_filenames()
|
|
if not filename in self.excluded_files
|
|
]
|
|
|
|
objects = []
|
|
for filename in filenames:
|
|
if self.__verbose:
|
|
print("Processing " + filename + "...")
|
|
content = read_file(os.path.join(self.__headerdir, filename), True)
|
|
platforms = list([
|
|
p for p in self.platforms if self.__is_platform_filename(filename, p)
|
|
])
|
|
|
|
# Parse cef_string.h happens in special case: grab only defined CEF_STRING_TYPE_xxx declaration
|
|
content_objects = None
|
|
if filename == "internal/cef_string.h":
|
|
content_objects = self.__parse_string_type(content)
|
|
else:
|
|
content_objects = self.__parse_objects(content)
|
|
|
|
for o in content_objects:
|
|
o["text"] = self.__prepare_text(o["text"])
|
|
o["platforms"] = platforms
|
|
o["filename"] = filename
|
|
objects.append(o)
|
|
|
|
# objects will be sorted including filename, to make stable universal hashes
|
|
objects = sorted(objects, key=lambda o: o["name"] + "@" + o["filename"])
|
|
|
|
if self.__debug_enabled:
|
|
namelen = max([len(o["name"]) for o in objects])
|
|
filenamelen = max([len(o["filename"]) for o in objects])
|
|
dumpsig = []
|
|
for o in objects:
|
|
dumpsig.append(
|
|
format(o["name"], str(namelen) + "s") + "|" + format(
|
|
o["filename"], "" + str(filenamelen) + "s") + "|" + o["text"])
|
|
self.__write_debug_file("objects.txt", dumpsig)
|
|
|
|
revisions = {}
|
|
|
|
for platform in itertools.chain(["universal"], self.platforms):
|
|
sig = self.__get_final_sig(objects, platform)
|
|
if self.__debug_enabled:
|
|
self.__write_debug_file(platform + ".sig", sig)
|
|
revstr = hashlib.sha1(sig.encode('utf-8')).hexdigest()
|
|
revisions[platform] = revstr
|
|
|
|
return revisions
|
|
|
|
def __parse_objects(self, content):
|
|
""" Returns array of objects in content file. """
|
|
objects = []
|
|
content = re.sub("//.*\n", "", content)
|
|
|
|
# function declarations
|
|
for m in re.finditer(
|
|
"\nCEF_EXPORT\s+?.*?\s+?(\w+)\s*?\(.*?\)\s*?;",
|
|
content,
|
|
flags=re.DOTALL):
|
|
object = {"name": m.group(1), "text": m.group(0).strip()}
|
|
objects.append(object)
|
|
|
|
# structs
|
|
for m in re.finditer(
|
|
"\ntypedef\s+?struct\s+?(\w+)\s+?\{.*?\}\s+?(\w+)\s*?;",
|
|
content,
|
|
flags=re.DOTALL):
|
|
object = {"name": m.group(2), "text": m.group(0).strip()}
|
|
objects.append(object)
|
|
|
|
# enums
|
|
for m in re.finditer(
|
|
"\nenum\s+?(\w+)\s+?\{.*?\}\s*?;", content, flags=re.DOTALL):
|
|
object = {"name": m.group(1), "text": m.group(0).strip()}
|
|
objects.append(object)
|
|
|
|
# typedefs
|
|
for m in re.finditer("\ntypedef\s+?.*?\s+(\w+);", content, flags=0):
|
|
object = {"name": m.group(1), "text": m.group(0).strip()}
|
|
objects.append(object)
|
|
|
|
return objects
|
|
|
|
def __parse_string_type(self, content):
|
|
""" Grab defined CEF_STRING_TYPE_xxx """
|
|
objects = []
|
|
for m in re.finditer(
|
|
"\n\s*?#\s*?define\s+?(CEF_STRING_TYPE_\w+)\s+?.*?\n", content,
|
|
flags=0):
|
|
object = {
|
|
"name": m.group(1),
|
|
"text": m.group(0),
|
|
}
|
|
objects.append(object)
|
|
return objects
|
|
|
|
def __prepare_text(self, text):
|
|
text = text.strip()
|
|
text = re.sub("\s+", " ", text)
|
|
text = re.sub("\(\s+", "(", text)
|
|
return text
|
|
|
|
def __get_final_sig(self, objects, platform):
|
|
sig = []
|
|
|
|
for o in objects:
|
|
if platform == "universal" or platform in o["platforms"]:
|
|
sig.append(o["text"])
|
|
|
|
return "\n".join(sig)
|
|
|
|
def __get_filenames(self):
|
|
""" Returns file names to be processed, relative to headerdir """
|
|
headers = [
|
|
os.path.join(self.__headerdir, filename)
|
|
for filename in self.included_files
|
|
]
|
|
headers = itertools.chain(
|
|
headers, get_files(os.path.join(self.__headerdir, "capi", "*.h")))
|
|
headers = itertools.chain(
|
|
headers, get_files(os.path.join(self.__headerdir, "internal", "*.h")))
|
|
|
|
for v in self.platform_files.values():
|
|
headers = itertools.chain(headers,
|
|
[os.path.join(self.__headerdir, f) for f in v])
|
|
|
|
normalized = [
|
|
os.path.relpath(filename, self.__headerdir) for filename in headers
|
|
]
|
|
normalized = [f.replace('\\', '/').lower() for f in normalized]
|
|
|
|
return list(set(normalized))
|
|
|
|
def __is_platform_filename(self, filename, platform):
|
|
if platform == "universal":
|
|
return True
|
|
if not platform in self.platform_files:
|
|
return False
|
|
listed = False
|
|
for p in self.platforms:
|
|
if filename in self.platform_files[p]:
|
|
if p == platform:
|
|
return True
|
|
else:
|
|
listed = True
|
|
return not listed
|
|
|
|
def __write_debug_file(self, filename, content):
|
|
make_dir(self.__debugdir)
|
|
outfile = os.path.join(self.__debugdir, filename)
|
|
dir = os.path.dirname(outfile)
|
|
make_dir(dir)
|
|
if not isinstance(content, basestring):
|
|
content = "\n".join(content)
|
|
write_file(outfile, content)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
from optparse import OptionParser
|
|
import time
|
|
|
|
disc = """
|
|
This utility calculates CEF API hash.
|
|
"""
|
|
|
|
parser = OptionParser(description=disc)
|
|
parser.add_option(
|
|
'--cpp-header-dir',
|
|
dest='cppheaderdir',
|
|
metavar='DIR',
|
|
help='input directory for C++ header files [required]')
|
|
parser.add_option(
|
|
'--debug-dir',
|
|
dest='debugdir',
|
|
metavar='DIR',
|
|
help='intermediate directory for easy debugging')
|
|
parser.add_option(
|
|
'-v',
|
|
'--verbose',
|
|
action='store_true',
|
|
dest='verbose',
|
|
default=False,
|
|
help='output detailed status information')
|
|
(options, args) = parser.parse_args()
|
|
|
|
# the cppheader option is required
|
|
if options.cppheaderdir is None:
|
|
parser.print_help(sys.stdout)
|
|
sys.exit()
|
|
|
|
# calculate
|
|
c_start_time = time.time()
|
|
|
|
calc = cef_api_hash(options.cppheaderdir, options.debugdir, options.verbose)
|
|
revisions = calc.calculate()
|
|
|
|
c_completed_in = time.time() - c_start_time
|
|
|
|
print("{")
|
|
for k in sorted(revisions.keys()):
|
|
print(format("\"" + k + "\"", ">12s") + ": \"" + revisions[k] + "\"")
|
|
print("}")
|
|
# print
|
|
# print 'Completed in: ' + str(c_completed_in)
|
|
# print
|
|
|
|
# print "Press any key to continue...";
|
|
# sys.stdin.readline();
|