mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 11:26:16 +01:00
dcfc9f689e
There is currently no `dllimport` attribute on any of our function, which prevents MSVC to optimize function calls. To fix that issue, we need to redeclare all our visibility macros for each of our libraries, because when compiling e.g. GIO code, we need dllimport in GLIB headers and dllexport in GIO headers. That means they cannot use the same GLIB_AVAILABLE_* macro. Since that's a lot of boilerplate to copy/paste after each version bump, this MR generate all those macros using a python script. Also simplify the meson side by using `gnu_symbol_visibility : 'hidden'` keyword argument instead of passing the cflag manually. This leaves only API index to add manually into glib-docs.xml when bumping GLib version. That file cannot be generated because Meson does not allow passing a buit file to gnome.gtkdoc()'s main_xml kwarg unfortunately.
172 lines
7.3 KiB
Python
Executable File
172 lines
7.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
#
|
|
# Copyright © 2022 Collabora Inc.
|
|
#
|
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
#
|
|
# Original author: Xavier Claessens <xclaesse@gmail.com>
|
|
|
|
import argparse
|
|
import textwrap
|
|
from pathlib import Path
|
|
|
|
def gen_versions_macros(args, current_minor_version):
|
|
with args.out_path.open('w', encoding='utf-8') as ofile, \
|
|
args.in_path.open('r', encoding='utf-8') as ifile:
|
|
for line in ifile.readlines():
|
|
if '@GLIB_VERSIONS@' in line:
|
|
for minor in range(2, current_minor_version + 2, 2):
|
|
ofile.write(textwrap.dedent(f'''\
|
|
/**
|
|
* GLIB_VERSION_2_{minor}:
|
|
*
|
|
* A macro that evaluates to the 2.{minor} version of GLib, in a format
|
|
* that can be used by the C pre-processor.
|
|
*
|
|
* Since: 2.{max(minor, 32)}
|
|
*/
|
|
#define GLIB_VERSION_2_{minor} (G_ENCODE_VERSION (2, {minor}))
|
|
'''))
|
|
else:
|
|
ofile.write(line)
|
|
|
|
def gen_doc_sections(args, current_minor_version):
|
|
with args.out_path.open('w', encoding='utf-8') as ofile, \
|
|
args.in_path.open('r', encoding='utf-8') as ifile:
|
|
for line in ifile.readlines():
|
|
if '@GLIB_VERSIONS@' in line:
|
|
for minor in range(2, current_minor_version + 2, 2):
|
|
ofile.write(textwrap.dedent(f'''\
|
|
GLIB_VERSION_2_{minor}
|
|
'''))
|
|
else:
|
|
ofile.write(line)
|
|
|
|
def gen_visibility_macros(args, current_minor_version):
|
|
'''
|
|
Generates a set of macros for each minor stable version of GLib
|
|
|
|
- GLIB_VAR
|
|
|
|
- GLIB_DEPRECATED
|
|
- GLIB_DEPRECATED_IN_…
|
|
- GLIB_DEPRECATED_MACRO_IN_…
|
|
- GLIB_DEPRECATED_ENUMERATOR_IN_…
|
|
- GLIB_DEPRECATED_TYPE_IN_…
|
|
|
|
- GLIB_AVAILABLE_IN_ALL
|
|
- GLIB_AVAILABLE_IN_…
|
|
- GLIB_AVAILABLE_STATIC_INLINE_IN_…
|
|
- GLIB_AVAILABLE_MACRO_IN_…
|
|
- GLIB_AVAILABLE_ENUMERATOR_IN_…
|
|
- GLIB_AVAILABLE_TYPE_IN_…
|
|
|
|
- GLIB_UNAVAILABLE(maj,min)
|
|
- GLIB_UNAVAILABLE_STATIC_INLINE(maj,min)
|
|
|
|
The GLIB namespace can be replaced with one of GOBJECT, GIO, GMODULE.
|
|
'''
|
|
|
|
ns = args.namespace
|
|
with args.out_path.open('w', encoding='utf-8') as f:
|
|
f.write(textwrap.dedent(f'''\
|
|
#pragma once
|
|
|
|
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined({ns}_STATIC_COMPILATION)
|
|
# define _{ns}_EXPORT __declspec(dllexport)
|
|
# define _{ns}_IMPORT __declspec(dllimport)
|
|
#elif __GNUC__ >= 4
|
|
# define _{ns}_EXPORT __attribute__((visibility("default")))
|
|
# define _{ns}_IMPORT
|
|
#else
|
|
# define _{ns}_EXPORT
|
|
# define _{ns}_IMPORT
|
|
#endif
|
|
#ifdef {ns}_COMPILATION
|
|
# define _{ns}_API _{ns}_EXPORT
|
|
#else
|
|
# define _{ns}_API _{ns}_IMPORT
|
|
#endif
|
|
|
|
#define _{ns}_EXTERN _{ns}_API extern
|
|
|
|
#define {ns}_VAR _{ns}_EXTERN
|
|
#define {ns}_AVAILABLE_IN_ALL _{ns}_EXTERN
|
|
|
|
#ifdef GLIB_DISABLE_DEPRECATION_WARNINGS
|
|
#define {ns}_DEPRECATED _{ns}_EXTERN
|
|
#define {ns}_DEPRECATED_FOR(f) _{ns}_EXTERN
|
|
#define {ns}_UNAVAILABLE(maj,min) _{ns}_EXTERN
|
|
#define {ns}_UNAVAILABLE_STATIC_INLINE(maj,min)
|
|
#else
|
|
#define {ns}_DEPRECATED G_DEPRECATED _{ns}_EXTERN
|
|
#define {ns}_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) _{ns}_EXTERN
|
|
#define {ns}_UNAVAILABLE(maj,min) G_UNAVAILABLE(maj,min) _{ns}_EXTERN
|
|
#define {ns}_UNAVAILABLE_STATIC_INLINE(maj,min) G_UNAVAILABLE(maj,min)
|
|
#endif
|
|
'''))
|
|
for minor in range(26, current_minor_version + 2, 2):
|
|
f.write(textwrap.dedent(f'''
|
|
#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_{minor}
|
|
#define {ns}_DEPRECATED_IN_2_{minor} {ns}_DEPRECATED
|
|
#define {ns}_DEPRECATED_IN_2_{minor}_FOR(f) {ns}_DEPRECATED_FOR (f)
|
|
#define {ns}_DEPRECATED_MACRO_IN_2_{minor} GLIB_DEPRECATED_MACRO
|
|
#define {ns}_DEPRECATED_MACRO_IN_2_{minor}_FOR(f) GLIB_DEPRECATED_MACRO_FOR (f)
|
|
#define {ns}_DEPRECATED_ENUMERATOR_IN_2_{minor} GLIB_DEPRECATED_ENUMERATOR
|
|
#define {ns}_DEPRECATED_ENUMERATOR_IN_2_{minor}_FOR(f) GLIB_DEPRECATED_ENUMERATOR_FOR (f)
|
|
#define {ns}_DEPRECATED_TYPE_IN_2_{minor} GLIB_DEPRECATED_TYPE
|
|
#define {ns}_DEPRECATED_TYPE_IN_2_{minor}_FOR(f) GLIB_DEPRECATED_TYPE_FOR (f)
|
|
#else
|
|
#define {ns}_DEPRECATED_IN_2_{minor} _{ns}_EXTERN
|
|
#define {ns}_DEPRECATED_IN_2_{minor}_FOR(f) _{ns}_EXTERN
|
|
#define {ns}_DEPRECATED_MACRO_IN_2_{minor}
|
|
#define {ns}_DEPRECATED_MACRO_IN_2_{minor}_FOR(f)
|
|
#define {ns}_DEPRECATED_ENUMERATOR_IN_2_{minor}
|
|
#define {ns}_DEPRECATED_ENUMERATOR_IN_2_{minor}_FOR(f)
|
|
#define {ns}_DEPRECATED_TYPE_IN_2_{minor}
|
|
#define {ns}_DEPRECATED_TYPE_IN_2_{minor}_FOR(f)
|
|
#endif
|
|
|
|
#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_{minor}
|
|
#define {ns}_AVAILABLE_IN_2_{minor} {ns}_UNAVAILABLE (2, {minor})
|
|
#define {ns}_AVAILABLE_STATIC_INLINE_IN_2_{minor} GLIB_UNAVAILABLE_STATIC_INLINE (2, {minor})
|
|
#define {ns}_AVAILABLE_MACRO_IN_2_{minor} GLIB_UNAVAILABLE_MACRO (2, {minor})
|
|
#define {ns}_AVAILABLE_ENUMERATOR_IN_2_{minor} GLIB_UNAVAILABLE_ENUMERATOR (2, {minor})
|
|
#define {ns}_AVAILABLE_TYPE_IN_2_{minor} GLIB_UNAVAILABLE_TYPE (2, {minor})
|
|
#else
|
|
#define {ns}_AVAILABLE_IN_2_{minor} _{ns}_EXTERN
|
|
#define {ns}_AVAILABLE_STATIC_INLINE_IN_2_{minor}
|
|
#define {ns}_AVAILABLE_MACRO_IN_2_{minor}
|
|
#define {ns}_AVAILABLE_ENUMERATOR_IN_2_{minor}
|
|
#define {ns}_AVAILABLE_TYPE_IN_2_{minor}
|
|
#endif
|
|
'''))
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('glib_version', help='Current GLib version')
|
|
subparsers = parser.add_subparsers()
|
|
|
|
versions_parser = subparsers.add_parser('versions-macros', help='Generate versions macros')
|
|
versions_parser.add_argument('in_path', help='input file', type=Path)
|
|
versions_parser.add_argument('out_path', help='output file', type=Path)
|
|
versions_parser.set_defaults(func=gen_versions_macros)
|
|
|
|
doc_parser = subparsers.add_parser('doc-sections', help='Generate glib-sections.txt')
|
|
doc_parser.add_argument('in_path', help='input file', type=Path)
|
|
doc_parser.add_argument('out_path', help='output file', type=Path)
|
|
doc_parser.set_defaults(func=gen_doc_sections)
|
|
|
|
visibility_parser = subparsers.add_parser('visibility-macros', help='Generate visibility macros')
|
|
visibility_parser.add_argument('namespace', help='Macro namespace')
|
|
visibility_parser.add_argument('out_path', help='output file', type=Path)
|
|
visibility_parser.set_defaults(func=gen_visibility_macros)
|
|
|
|
args = parser.parse_args()
|
|
version = [int(i) for i in args.glib_version.split('.')]
|
|
assert version[0] == 2
|
|
args.func(args, version[1])
|
|
|
|
if __name__ == '__main__':
|
|
main()
|