mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Add initial support for API versioning (see #3836)
- Generated files are now created when running cef_create_projects or the new version_manager.py tool. These files are still created in the cef/ source tree (same location as before) but Git ignores them due to the generated .gitignore file. - API hashes are committed to Git as a new cef_api_versions.json file. This file is used for both code generation and CEF version calculation (replacing the previous usage of cef_api_hash.h for this purpose). It will be updated by the CEF admin before merging breaking API changes upstream. - As an added benefit to the above, contributor PRs will no longer contain generated code that is susceptible to frequent merge conflicts. - From a code generation perspective, the main difference is that we now use versioned structs (e.g. cef_browser_0_t instead of cef_browser_t) on the libcef (dll/framework) side. Most of the make_*.py tool changes are related to supporting this. - From the client perspective, you can now define CEF_API_VERSION in the project configuration (or get CEF_EXPERIMENTAL by default). This define will change the API exposed in CEF’s include/ and include/capi header files. All client-side targets including libcef_dll_wrapper will need be recompiled when changing this define. - Examples of the new API-related define usage are provided in cef_api_version_test.h, api_version_test_impl.cc and api_version_unittest.cc. To test: - Run `ceftests --gtest_filter=ApiVersionTest.*` - Add `cef_api_version=13300` to GN_DEFINES. Re-run configure, build and ceftests steps. - Repeat with 13301, 13302, 13303 (all supported test versions).
This commit is contained in:
@ -8,33 +8,41 @@ from cef_parser import *
|
||||
|
||||
def make_capi_global_funcs(funcs, defined_names, translate_map, indent):
|
||||
result = ''
|
||||
first = True
|
||||
for func in funcs:
|
||||
comment = func.get_comment()
|
||||
if first or len(comment) > 0:
|
||||
result += '\n' + format_comment(comment, indent, translate_map)
|
||||
pre, post = get_version_surround(func)
|
||||
result += '\n' + pre
|
||||
if len(comment) > 0:
|
||||
result += format_comment(comment, indent, translate_map)
|
||||
if func.get_retval().get_type().is_result_string():
|
||||
result += indent + '// The resulting string must be freed by calling cef_string_userfree_free().\n'
|
||||
result += indent + 'CEF_EXPORT ' + func.get_capi_proto(defined_names) + ';\n'
|
||||
if first:
|
||||
first = False
|
||||
result += indent + 'CEF_EXPORT ' + func.get_capi_proto(
|
||||
defined_names) + ';\n' + post
|
||||
return result
|
||||
|
||||
|
||||
def make_capi_member_funcs(funcs, defined_names, translate_map, indent):
|
||||
result = ''
|
||||
first = True
|
||||
for func in funcs:
|
||||
comment = func.get_comment()
|
||||
if first or len(comment) > 0:
|
||||
result += '\n' + format_comment(comment, indent, translate_map)
|
||||
pre, post = get_version_surround(func)
|
||||
result += '\n' + pre
|
||||
if len(comment) > 0:
|
||||
result += format_comment(comment, indent, translate_map)
|
||||
if func.get_retval().get_type().is_result_string():
|
||||
result += indent + '// The resulting string must be freed by calling cef_string_userfree_free().\n'
|
||||
parts = func.get_capi_parts()
|
||||
result += indent+parts['retval']+' (CEF_CALLBACK *'+parts['name']+ \
|
||||
')('+', '.join(parts['args'])+');\n'
|
||||
if first:
|
||||
first = False
|
||||
result += indent + parts['retval'] + ' (CEF_CALLBACK *' + parts['name'] + \
|
||||
')(' + ', '.join(parts['args']) + ');\n'
|
||||
if len(post) > 0 and func.has_version_removed():
|
||||
if func.has_version_added():
|
||||
result += '#elif ' + get_version_check({
|
||||
'added': func.get_attrib('removed')
|
||||
})
|
||||
else:
|
||||
result += '#else'
|
||||
result += '\n' + indent + 'uintptr_t ' + parts['name'] + '_removed;\n'
|
||||
result += post
|
||||
return result
|
||||
|
||||
|
||||
@ -61,13 +69,16 @@ def make_capi_header(header, filename):
|
||||
#define $GUARD$
|
||||
#pragma once
|
||||
|
||||
#if defined(BUILDING_CEF_SHARED)
|
||||
#error This file cannot be included DLL-side
|
||||
#endif
|
||||
|
||||
"""
|
||||
|
||||
# Protect against incorrect use of test headers.
|
||||
if filename.startswith('test/'):
|
||||
result += \
|
||||
"""#if !defined(BUILDING_CEF_SHARED) && !defined(WRAPPING_CEF_SHARED) && \\
|
||||
!defined(UNIT_TEST)
|
||||
"""#if !defined(WRAPPING_CEF_SHARED) && !defined(UNIT_TEST)
|
||||
#error This file can be included for unit tests only
|
||||
#endif
|
||||
|
||||
@ -78,7 +89,7 @@ def make_capi_header(header, filename):
|
||||
# identify all includes and forward declarations
|
||||
translated_includes = set([])
|
||||
internal_includes = set([])
|
||||
all_declares = set([])
|
||||
all_declares = {}
|
||||
for cls in classes:
|
||||
includes = cls.get_includes()
|
||||
for include in includes:
|
||||
@ -87,7 +98,7 @@ def make_capi_header(header, filename):
|
||||
# translated CEF API headers.
|
||||
raise Exception('Disallowed include of %s.h from %s' % (include,
|
||||
filename))
|
||||
elif include.startswith('internal/'):
|
||||
elif include.startswith('internal/') or include == 'cef_api_hash':
|
||||
# internal/ headers may be C or C++. Include them as-is.
|
||||
internal_includes.add(include)
|
||||
else:
|
||||
@ -97,7 +108,10 @@ def make_capi_header(header, filename):
|
||||
declare_cls = header.get_class(declare)
|
||||
if declare_cls is None:
|
||||
raise Exception('Unknown class: %s' % declare)
|
||||
all_declares.add(declare_cls.get_capi_name())
|
||||
capi_name = declare_cls.get_capi_name()
|
||||
if not capi_name in all_declares:
|
||||
all_declares[capi_name] = declare_cls.get_version_check() \
|
||||
if declare_cls.has_version() else None
|
||||
|
||||
# output translated includes
|
||||
if len(translated_includes) > 0:
|
||||
@ -122,22 +136,39 @@ extern "C" {
|
||||
"""
|
||||
|
||||
# output forward declarations
|
||||
if len(all_declares) > 0:
|
||||
sorted_declares = sorted(all_declares)
|
||||
if bool(all_declares):
|
||||
sorted_declares = sorted(all_declares.keys())
|
||||
for declare in sorted_declares:
|
||||
cls_version_check = all_declares[declare]
|
||||
if not cls_version_check is None:
|
||||
result += '#if ' + cls_version_check + '\n'
|
||||
result += 'struct _' + declare + ';\n'
|
||||
if not cls_version_check is None:
|
||||
result += '#endif\n'
|
||||
|
||||
# output classes
|
||||
for cls in classes:
|
||||
pre, post = get_version_surround(cls, long=True)
|
||||
if len(pre) > 0:
|
||||
result += '\n' + pre
|
||||
|
||||
comment = cls.get_comment()
|
||||
add_comment = []
|
||||
if comment[-1] != '':
|
||||
add_comment.append('')
|
||||
add_comment.append('NOTE: This struct is allocated %s-side.' % \
|
||||
('client' if cls.is_client_side() else 'DLL'))
|
||||
add_comment.append('')
|
||||
|
||||
# virtual functions are inside the structure
|
||||
classname = cls.get_capi_name()
|
||||
result += '\n' + format_comment(cls.get_comment(), '', translate_map)
|
||||
result += '\n' + format_comment(comment + add_comment, '', translate_map)
|
||||
result += 'typedef struct _'+classname+' {\n'+\
|
||||
' ///\n'+\
|
||||
' /// Base structure.\n'+\
|
||||
' ///\n'+\
|
||||
' '+cls.get_parent_capi_name()+' base;\n'
|
||||
funcs = cls.get_virtual_funcs()
|
||||
funcs = cls.get_virtual_funcs(version_order=True)
|
||||
result += make_capi_member_funcs(funcs, defined_names, translate_map, ' ')
|
||||
result += '} ' + classname + ';\n\n'
|
||||
|
||||
@ -149,6 +180,8 @@ extern "C" {
|
||||
result += make_capi_global_funcs(funcs, defined_names, translate_map,
|
||||
'') + '\n'
|
||||
|
||||
result += post
|
||||
|
||||
# output global functions
|
||||
funcs = header.get_funcs(filename)
|
||||
if len(funcs) > 0:
|
||||
|
Reference in New Issue
Block a user