blob: b4afb00bcbd5d0d3ce5875aee78323b69e9e4469 [file] [log] [blame]
#!/usr/bin/env python3
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import argparse
from io import TextIOBase
from pathlib import Path
import re
def main():
parser = argparse.ArgumentParser(
description="Generate C header with version macros")
parser.add_argument(
"--library",
required=True,
help="The library name to use in macro prefixes")
parser.add_argument(
"--version",
required=True,
help="The library version number")
parser.add_argument(
"--input",
type=Path,
required=True,
help="Path to the input template file")
parser.add_argument(
"--output",
type=Path,
required=True,
help="Path to the output file to generate")
args = parser.parse_args()
with open(args.input, "r", encoding="utf-8") as input_file, \
open(args.output, "w", encoding="utf-8") as output_file:
write_header(
input_file, output_file, args.library, args.version)
def write_header(
input_file: TextIOBase,
output_file: TextIOBase,
library_name: str,
version: str):
if "-" in version:
version, version_tag = version.split("-")
else:
version_tag = ""
version_major, version_minor, version_micro = [int(v) for v in version.split(".")]
encoded_versions = generate_encoded_versions(library_name)
visibility_macros = generate_visibility_macros(library_name)
availability_macros = generate_availability_macros(library_name)
replacements = {
"VERSION_MAJOR": str(version_major),
"VERSION_MINOR": str(version_minor),
"VERSION_MICRO": str(version_micro),
"VERSION_TAG": version_tag,
"ENCODED_VERSIONS": encoded_versions,
"VISIBILITY_MACROS": visibility_macros,
"AVAILABILITY_MACROS": availability_macros,
}
output_file.write(re.sub(
r"@([A-Z_]+)@", lambda match: replacements[match[1]], input_file.read()))
def generate_visibility_macros(library: str) -> str:
return f"""#if (defined(_WIN32) || defined(__CYGWIN__)) && defined(_MSC_VER) && \
!defined({library}_STATIC_COMPILATION)
# define {library}_EXPORT __declspec(dllexport)
# define {library}_IMPORT __declspec(dllimport)
#else
# define {library}_EXPORT
# define {library}_IMPORT
#endif
#ifdef {library}_COMPILATION
# define {library}_API {library}_EXPORT
#else
# define {library}_API {library}_IMPORT
#endif
#define {library}_EXTERN {library}_API extern"""
def generate_encoded_versions(library: str) -> str:
macros = []
for major_version, minor_version in ALL_VERSIONS:
macros.append(f"""/**
* {library}_VERSION_{major_version}_{minor_version}:
*
* You can use this macro value for compile time API version check.
*
* Since: {major_version}.{minor_version}.0
*/
#define {library}_VERSION_{major_version}_{minor_version} G_ENCODE_VERSION({major_version}, {minor_version})""") # noqa: E501
return "\n\n".join(macros)
def generate_availability_macros(library: str) -> str:
macros = [f"""#define {library}_AVAILABLE_IN_ALL {library}_EXTERN"""]
for major_version, minor_version in ALL_VERSIONS:
macros.append(f"""#if {library}_VERSION_MIN_REQUIRED >= {library}_VERSION_{major_version}_{minor_version}
# define {library}_DEPRECATED_IN_{major_version}_{minor_version} {library}_DEPRECATED
# define {library}_DEPRECATED_IN_{major_version}_{minor_version}_FOR(function) {library}_DEPRECATED_FOR(function)
#else
# define {library}_DEPRECATED_IN_{major_version}_{minor_version}
# define {library}_DEPRECATED_IN_{major_version}_{minor_version}_FOR(function)
#endif
#if {library}_VERSION_MAX_ALLOWED < {library}_VERSION_{major_version}_{minor_version}
# define {library}_AVAILABLE_IN_{major_version}_{minor_version} {library}_EXTERN {library}_UNAVAILABLE({major_version}, {minor_version})
#else
# define {library}_AVAILABLE_IN_{major_version}_{minor_version} {library}_EXTERN
#endif""") # noqa: E501
return "\n\n".join(macros)
ALL_VERSIONS = [
(24, 0),
(23, 0),
(22, 0),
(21, 0),
(20, 0),
(19, 0),
(18, 0),
(17, 0),
(16, 0),
(15, 0),
(14, 0),
(13, 0),
(12, 0),
(11, 0),
(10, 0),
(9, 0),
(8, 0),
(7, 0),
(6, 0),
(5, 0),
(4, 0),
(3, 0),
(2, 0),
(1, 0),
(0, 17),
(0, 16),
(0, 15),
(0, 14),
(0, 13),
(0, 12),
(0, 11),
(0, 10),
]
if __name__ == '__main__':
main()