Improve styling of util/cmake scripts

flake8 was used to evaluate the file, with a couple of exeptions:
    E501,E266,W503

black was used to reformat the code automatically

The changes were:
* Added a README that explains how to use pipenv and pip,
* Remove unnecessary return statements,
* Remove '\' from the end of the lines,
* Use f-strings (>= 3.6) since we are requiring Python 3.7,
* Commenting unused variables,
* Adding assert when Python >= 3.7 is not being used,
* Wrapping long lines to 100 (Qt Style),
* Re-factoring some lines,
* Re-ordering imports,
* Naming `except` for sympy (SympifyError, TypeError)

Change-Id: Ie05f754e7d8ee4bf427117c58e0eb1b903202933
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
Cristian Maureira-Fredes 2019-09-17 00:11:17 +02:00
parent c1cf305be0
commit 91634c3c9b
10 changed files with 2712 additions and 2008 deletions

54
util/cmake/README.md Normal file
View File

@ -0,0 +1,54 @@
# CMake Utils
This directory holds scripts to help the porting process from `qmake` to `cmake` for Qt6.
# Requirements
* [Python 3.7](https://www.python.org/downloads/),
* `pipenv` or `pip` to manage the modules.
## Python modules
Since Python has many ways of handling projects, you have a couple of options to
install the dependencies of the scripts:
### Using `pipenv`
The dependencies are specified on the `Pipfile`, so you just need to run
`pipenv install` and that will automatically create a virtual environment
that you can activate with a `pipenv shell`.
### Using `pip`
It's highly recommended to use a [virtualenvironment](https://virtualenv.pypa.io/en/latest/)
to avoid conflict with other packages that are already installed: `pip install virtualenv`.
* Create an environment: `virtualenv env`,
* Activate the environment: `source env/bin/activate`
(on Windows: `source env\Scripts\activate.bat`)
* Install the requirements: `pip install -r requirements.txt`
# Contributing to the scripts
You can verify if the styling of a script complaint with PEP8, with a couple of exceptions:
Install [flake8](http://flake8.pycqa.org/en/latest/) (`pip install flake8`) and run it
on the script you want to test:
```
flake8 <file>.py --ignore=E501,E266,W503
```
* `E501`: Line too long (82>79 characters),
* `E266`: Too many leading '#' for block comment,
* `W503`: Line break occurred before a binary operator)
You can also modify the file with an automatic formatter,
like [black](https://black.readthedocs.io/en/stable/) (`pip install black`),
and execute it:
```
black -l 100 <file>.py
```
Using Qt's maximum line length, 100.

View File

@ -32,27 +32,37 @@ from argparse import ArgumentParser
import os import os
import re import re
import subprocess import subprocess
import sys
import typing import typing
def _parse_commandline(): def _parse_commandline():
parser = ArgumentParser(description='Calculate the conversion rate to cmake.') parser = ArgumentParser(description="Calculate the conversion rate to cmake.")
parser.add_argument('--debug', dest='debug', action='store_true', parser.add_argument("--debug", dest="debug", action="store_true", help="Turn on debug output")
help='Turn on debug output') parser.add_argument(
parser.add_argument('source_directory', metavar='<Source Directory>', type=str, "source_directory",
help='The Qt module source directory') metavar="<Source Directory>",
parser.add_argument('binary_directory', metavar='<CMake build direcotry>', type=str, type=str,
help='The CMake build directory (might be empty)') help="The Qt module source directory",
)
parser.add_argument(
"binary_directory",
metavar="<CMake build direcotry>",
type=str,
help="The CMake build directory (might be empty)",
)
return parser.parse_args() return parser.parse_args()
def calculate_baseline(source_directory: str, *, debug: bool=False) -> int: def calculate_baseline(source_directory: str, *, debug: bool = False) -> int:
if debug: if debug:
print('Scanning "{}" for qmake-based tests.'.format(source_directory)) print(f'Scanning "{source_directory}" for qmake-based tests.')
result = subprocess.run('/usr/bin/git grep -E "^\\s*CONFIG\\s*\\+?=.*\\btestcase\\b" | sort -u | wc -l', result = subprocess.run(
shell=True, capture_output=True, cwd=source_directory) '/usr/bin/git grep -E "^\\s*CONFIG\\s*\\+?=.*\\btestcase\\b" | sort -u | wc -l',
shell=True,
capture_output=True,
cwd=source_directory,
)
return int(result.stdout) return int(result.stdout)
@ -60,41 +70,45 @@ def build(source_directory: str, binary_directory: str, *, debug=False) -> None:
abs_source = os.path.abspath(source_directory) abs_source = os.path.abspath(source_directory)
if not os.path.isdir(binary_directory): if not os.path.isdir(binary_directory):
os.makedirs(binary_directory) os.makedirs(binary_directory)
if not os.path.exists(os.path.join(binary_directory, 'CMakeCache.txt')): if not os.path.exists(os.path.join(binary_directory, "CMakeCache.txt")):
if debug: if debug:
print('Running cmake in "{}".'.format(binary_directory)) print(f'Running cmake in "{binary_directory}"')
result = subprocess.run(['/usr/bin/cmake', '-GNinja', abs_source], cwd=binary_directory) result = subprocess.run(["/usr/bin/cmake", "-GNinja", abs_source], cwd=binary_directory)
if debug: if debug:
print('CMake return code: {}.'.format(result.returncode)) print(f"CMake return code: {result.returncode}.")
assert result.returncode == 0 assert result.returncode == 0
if debug: if debug:
print('Running ninja in "{}".'.format(binary_directory)) print(f'Running ninja in "{binary_directory}".')
result = subprocess.run('/usr/bin/ninja', cwd=binary_directory) result = subprocess.run("/usr/bin/ninja", cwd=binary_directory)
if debug: if debug:
print('Ninja return code: {}.'.format(result.returncode)) print(f"Ninja return code: {result.returncode}.")
assert result.returncode == 0 assert result.returncode == 0
def test(binary_directory: str, *, debug=False) -> typing.Tuple[int, int]: def test(binary_directory: str, *, debug=False) -> typing.Tuple[int, int]:
if debug: if debug:
print('Running ctest in "{}".'.format(binary_directory)) print(f'Running ctest in "{binary_directory}".')
result = subprocess.run('/usr/bin/ctest -j 250 | grep "tests passed, "', result = subprocess.run(
shell=True, capture_output=True, cwd=binary_directory) '/usr/bin/ctest -j 250 | grep "tests passed, "',
summary = result.stdout.decode('utf-8').replace('\n', '') shell=True,
capture_output=True,
cwd=binary_directory,
)
summary = result.stdout.decode("utf-8").replace("\n", "")
if debug: if debug:
print('Test summary: {} ({}).'.format(summary, result.returncode)) print(f"Test summary: {summary} ({result.returncode}).")
matches = re.fullmatch(r'\d+% tests passed, (\d+) tests failed out of (\d+)', summary) matches = re.fullmatch(r"\d+% tests passed, (\d+) tests failed out of (\d+)", summary)
if matches: if matches:
if debug: if debug:
print('Matches: failed {}, total {}.'.format(matches.group(1), matches.group(2))) print(f"Matches: failed {matches.group(1)}, total {matches.group(2)}.")
return (int(matches.group(2)), int(matches.group(2)) - int(matches.group(1)), ) return (int(matches.group(2)), int(matches.group(2)) - int(matches.group(1)))
return (0, 0,) return (0, 0)
def main() -> int: def main() -> int:
@ -102,26 +116,26 @@ def main() -> int:
base_line = calculate_baseline(args.source_directory, debug=args.debug) base_line = calculate_baseline(args.source_directory, debug=args.debug)
if base_line <= 0: if base_line <= 0:
print('Could not find the qmake baseline in {}.'.format(args.source_directory)) print(f"Could not find the qmake baseline in {args.source_directory}.")
return 1 return 1
if args.debug: if args.debug:
print('qmake baseline: {} test binaries.'.format(base_line)) print(f"qmake baseline: {base_line} test binaries.")
cmake_total = 0 cmake_total = 0
cmake_success = 0 cmake_success = 0
try: try:
build(args.source_directory, args.binary_directory, debug=args.debug) build(args.source_directory, args.binary_directory, debug=args.debug)
(cmake_total, cmake_success, ) = test(args.binary_directory, debug=args.debug) (cmake_total, cmake_success) = test(args.binary_directory, debug=args.debug)
finally: finally:
if cmake_total == 0: if cmake_total == 0:
print('\n\n\nCould not calculate the cmake state.') print("\n\n\nCould not calculate the cmake state.")
return 2 return 2
else: else:
print('\n\n\nCMake test conversion rate: {:.2%}.'.format(cmake_total / base_line)) print(f"\n\n\nCMake test conversion rate: {cmake_total/base_line:.2f}.")
print('CMake test success rate : {:.2%}.'.format(cmake_success / base_line)) print(f"CMake test success rate : {cmake_success/base_line:.2f}.")
return 0 return 0
if __name__ == '__main__': if __name__ == "__main__":
main() main()

File diff suppressed because it is too large Load Diff

View File

@ -29,14 +29,19 @@
import re import re
import typing import typing
class LibraryMapping: class LibraryMapping:
def __init__(self, soName: str, def __init__(
packageName: typing.Optional[str], self,
targetName: typing.Optional[str], *, soName: str,
resultVariable: typing.Optional[str] = None, packageName: typing.Optional[str],
extra: typing.List[str] = [], targetName: typing.Optional[str],
appendFoundSuffix: bool = True, *,
emit_if: str = '') -> None: resultVariable: typing.Optional[str] = None,
extra: typing.List[str] = [],
appendFoundSuffix: bool = True,
emit_if: str = ""
) -> None:
self.soName = soName self.soName = soName
self.packageName = packageName self.packageName = packageName
self.resultVariable = resultVariable self.resultVariable = resultVariable
@ -49,232 +54,448 @@ class LibraryMapping:
self.emit_if = emit_if self.emit_if = emit_if
def is_qt(self) -> bool: def is_qt(self) -> bool:
return self.packageName == 'Qt' \ return self.packageName == "Qt" or self.packageName == "Qt5" or self.packageName == "Qt6"
or self.packageName == 'Qt5' \
or self.packageName == 'Qt6'
_qt_library_map = [ _qt_library_map = [
# Qt: # Qt:
LibraryMapping('accessibility_support', 'Qt6', 'Qt::AccessibilitySupport', extra = ['COMPONENTS', 'AccessibilitySupport']), LibraryMapping(
LibraryMapping('androidextras', 'Qt6', 'Qt::AndroidExtras', extra = ['COMPONENTS', 'AndroidExtras']), "accessibility_support",
LibraryMapping('animation', 'Qt6', 'Qt::3DAnimation', extra = ['COMPONENTS', '3DAnimation']), "Qt6",
LibraryMapping('application-lib', 'Qt6', 'Qt::AppManApplication', extra = ['COMPONENTS', 'AppManApplication']), "Qt::AccessibilitySupport",
LibraryMapping('bluetooth', 'Qt6', 'Qt::Bluetooth', extra = ['COMPONENTS', 'Bluetooth']), extra=["COMPONENTS", "AccessibilitySupport"],
LibraryMapping('bootstrap', 'Qt6', 'Qt::Bootstrap', extra = ['COMPONENTS', 'Bootstrap']), ),
LibraryMapping(
"androidextras", "Qt6", "Qt::AndroidExtras", extra=["COMPONENTS", "AndroidExtras"]
),
LibraryMapping("animation", "Qt6", "Qt::3DAnimation", extra=["COMPONENTS", "3DAnimation"]),
LibraryMapping(
"application-lib", "Qt6", "Qt::AppManApplication", extra=["COMPONENTS", "AppManApplication"]
),
LibraryMapping("bluetooth", "Qt6", "Qt::Bluetooth", extra=["COMPONENTS", "Bluetooth"]),
LibraryMapping("bootstrap", "Qt6", "Qt::Bootstrap", extra=["COMPONENTS", "Bootstrap"]),
# bootstrap-dbus: Not needed in Qt6! # bootstrap-dbus: Not needed in Qt6!
LibraryMapping('client', 'Qt6', 'Qt::WaylandClient', extra = ['COMPONENTS', 'WaylandClient']), LibraryMapping("client", "Qt6", "Qt::WaylandClient", extra=["COMPONENTS", "WaylandClient"]),
LibraryMapping('clipboard_support', 'Qt6', 'Qt::ClipboardSupport', extra = ['COMPONENTS', 'ClipboardSupport']), LibraryMapping(
LibraryMapping('coap', 'Qt6', 'Qt::Coap', extra = ['COMPONENTS', 'Coap']), "clipboard_support", "Qt6", "Qt::ClipboardSupport", extra=["COMPONENTS", "ClipboardSupport"]
LibraryMapping('common-lib', 'Qt6', 'Qt::AppManCommon', extra = ['COMPONENTS', 'AppManCommon']), ),
LibraryMapping('compositor', 'Qt6', 'Qt::WaylandCompositor', extra = ['COMPONENTS', 'WaylandCompositor']), LibraryMapping("coap", "Qt6", "Qt::Coap", extra=["COMPONENTS", "Coap"]),
LibraryMapping('concurrent', 'Qt6', 'Qt::Concurrent', extra = ['COMPONENTS', 'Concurrent']), LibraryMapping("common-lib", "Qt6", "Qt::AppManCommon", extra=["COMPONENTS", "AppManCommon"]),
LibraryMapping('container', 'Qt6', 'Qt::AxContainer', extra = ['COMPONENTS', 'AxContainer']), LibraryMapping(
LibraryMapping('control', 'Qt6', 'Qt::AxServer', extra = ['COMPONENTS', 'AxServer']), "compositor", "Qt6", "Qt::WaylandCompositor", extra=["COMPONENTS", "WaylandCompositor"]
LibraryMapping('core_headers', 'Qt6', 'Qt::WebEngineCore', extra = ['COMPONENTS', 'WebEngineCore']), ),
LibraryMapping('core', 'Qt6', 'Qt::Core', extra = ['COMPONENTS', 'Core']), LibraryMapping("concurrent", "Qt6", "Qt::Concurrent", extra=["COMPONENTS", "Concurrent"]),
LibraryMapping('coretest', 'Qt6', 'Qt::3DCoreTest', extra = ['COMPONENTS', '3DCoreTest']), LibraryMapping("container", "Qt6", "Qt::AxContainer", extra=["COMPONENTS", "AxContainer"]),
LibraryMapping('crypto-lib', 'Qt6', 'Qt::AppManCrypto', extra = ['COMPONENTS', 'AppManCrypto']), LibraryMapping("control", "Qt6", "Qt::AxServer", extra=["COMPONENTS", "AxServer"]),
LibraryMapping('dbus', 'Qt6', 'Qt::DBus', extra = ['COMPONENTS', 'DBus']), LibraryMapping(
LibraryMapping('designer', 'Qt6', 'Qt::Designer', extra = ['COMPONENTS', 'Designer']), "core_headers", "Qt6", "Qt::WebEngineCore", extra=["COMPONENTS", "WebEngineCore"]
LibraryMapping('designercomponents', 'Qt6', 'Qt::DesignerComponents', extra = ['COMPONENTS', 'DesignerComponents']), ),
LibraryMapping('devicediscovery', 'Qt6', 'Qt::DeviceDiscoverySupport', extra = ['COMPONENTS', 'DeviceDiscoverySupport']), LibraryMapping("core", "Qt6", "Qt::Core", extra=["COMPONENTS", "Core"]),
LibraryMapping('devicediscovery_support', 'Qt6', 'Qt::DeviceDiscoverySupport', extra = ['COMPONENTS', 'DeviceDiscoverySupport']), LibraryMapping("coretest", "Qt6", "Qt::3DCoreTest", extra=["COMPONENTS", "3DCoreTest"]),
LibraryMapping('edid', 'Qt6', 'Qt::EdidSupport', extra = ['COMPONENTS', 'EdidSupport']), LibraryMapping("crypto-lib", "Qt6", "Qt::AppManCrypto", extra=["COMPONENTS", "AppManCrypto"]),
LibraryMapping('edid_support', 'Qt6', 'Qt::EdidSupport', extra = ['COMPONENTS', 'EdidSupport']), LibraryMapping("dbus", "Qt6", "Qt::DBus", extra=["COMPONENTS", "DBus"]),
LibraryMapping('eglconvenience', 'Qt6', 'Qt::EglSupport', extra = ['COMPONENTS', 'EglSupport']), LibraryMapping("designer", "Qt6", "Qt::Designer", extra=["COMPONENTS", "Designer"]),
LibraryMapping('eglfsdeviceintegration', 'Qt6', 'Qt::EglFSDeviceIntegration', extra = ['COMPONENTS', 'EglFSDeviceIntegration']), LibraryMapping(
LibraryMapping('eglfs_kms_support', 'Qt6', 'Qt::EglFsKmsSupport', extra = ['COMPONENTS', 'EglFsKmsSupport']), "designercomponents",
LibraryMapping('egl_support', 'Qt6', 'Qt::EglSupport', extra = ['COMPONENTS', 'EglSupport']), "Qt6",
"Qt::DesignerComponents",
extra=["COMPONENTS", "DesignerComponents"],
),
LibraryMapping(
"devicediscovery",
"Qt6",
"Qt::DeviceDiscoverySupport",
extra=["COMPONENTS", "DeviceDiscoverySupport"],
),
LibraryMapping(
"devicediscovery_support",
"Qt6",
"Qt::DeviceDiscoverySupport",
extra=["COMPONENTS", "DeviceDiscoverySupport"],
),
LibraryMapping("edid", "Qt6", "Qt::EdidSupport", extra=["COMPONENTS", "EdidSupport"]),
LibraryMapping("edid_support", "Qt6", "Qt::EdidSupport", extra=["COMPONENTS", "EdidSupport"]),
LibraryMapping("eglconvenience", "Qt6", "Qt::EglSupport", extra=["COMPONENTS", "EglSupport"]),
LibraryMapping(
"eglfsdeviceintegration",
"Qt6",
"Qt::EglFSDeviceIntegration",
extra=["COMPONENTS", "EglFSDeviceIntegration"],
),
LibraryMapping(
"eglfs_kms_support", "Qt6", "Qt::EglFsKmsSupport", extra=["COMPONENTS", "EglFsKmsSupport"]
),
LibraryMapping("egl_support", "Qt6", "Qt::EglSupport", extra=["COMPONENTS", "EglSupport"]),
# enginio: Not needed in Qt6! # enginio: Not needed in Qt6!
LibraryMapping('eventdispatchers', 'Qt6', 'Qt::EventDispatcherSupport', extra = ['COMPONENTS', 'EventDispatcherSupport']), LibraryMapping(
LibraryMapping('eventdispatcher_support', 'Qt6', 'Qt::EventDispatcherSupport', extra = ['COMPONENTS', 'EventDispatcherSupport']), "eventdispatchers",
LibraryMapping('extras', 'Qt6', 'Qt::3DExtras', extra = ['COMPONENTS', '3DExtras']), "Qt6",
LibraryMapping('fbconvenience', 'Qt6', 'Qt::FbSupport', extra = ['COMPONENTS', 'FbSupport']), "Qt::EventDispatcherSupport",
LibraryMapping('fb_support', 'Qt6', 'Qt::FbSupport', extra = ['COMPONENTS', 'FbSupport']), extra=["COMPONENTS", "EventDispatcherSupport"],
LibraryMapping('fontdatabase_support', 'Qt6', 'Qt::FontDatabaseSupport', extra = ['COMPONENTS', 'FontDatabaseSupport']), ),
LibraryMapping('gamepad', 'Qt6', 'Qt::Gamepad', extra = ['COMPONENTS', 'Gamepad']), LibraryMapping(
LibraryMapping('global', 'Qt6', 'Qt::Core', extra = ['COMPONENTS', 'Core']), # manually added special case "eventdispatcher_support",
LibraryMapping('glx_support', 'Qt6', 'Qt::GlxSupport', extra = ['COMPONENTS', 'GlxSupport']), "Qt6",
LibraryMapping('graphics_support', 'Qt6', 'Qt::GraphicsSupport', extra = ['COMPONENTS', 'GraphicsSupport']), "Qt::EventDispatcherSupport",
LibraryMapping('gsttools', 'Qt6', 'Qt::MultimediaGstTools', extra = ['COMPONENTS', 'MultimediaGstTools']), extra=["COMPONENTS", "EventDispatcherSupport"],
LibraryMapping('gui', 'Qt6', 'Qt::Gui', extra = ['COMPONENTS', 'Gui']), ),
LibraryMapping('help', 'Qt6', 'Qt::Help', extra = ['COMPONENTS', 'Help']), LibraryMapping("extras", "Qt6", "Qt::3DExtras", extra=["COMPONENTS", "3DExtras"]),
LibraryMapping('hunspellinputmethod', 'Qt6', 'Qt::HunspellInputMethod', extra = ['COMPONENTS', 'HunspellInputMethod']), LibraryMapping("fbconvenience", "Qt6", "Qt::FbSupport", extra=["COMPONENTS", "FbSupport"]),
LibraryMapping('input', 'Qt6', 'Qt::InputSupport', extra = ['COMPONENTS', 'InputSupport']), LibraryMapping("fb_support", "Qt6", "Qt::FbSupport", extra=["COMPONENTS", "FbSupport"]),
LibraryMapping('input_support', 'Qt6', 'Qt::InputSupport', extra = ['COMPONENTS', 'InputSupport']), LibraryMapping(
LibraryMapping('installer-lib', 'Qt6', 'Qt::AppManInstaller', extra = ['COMPONENTS', 'AppManInstaller']), "fontdatabase_support",
LibraryMapping('knx', 'Qt6', 'Qt::Knx', extra = ['COMPONENTS', 'Knx']), "Qt6",
LibraryMapping('kmsconvenience', 'Qt6', 'Qt::KmsSupport', extra = ['COMPONENTS', 'KmsSupport']), "Qt::FontDatabaseSupport",
LibraryMapping('kms_support', 'Qt6', 'Qt::KmsSupport', extra = ['COMPONENTS', 'KmsSupport']), extra=["COMPONENTS", "FontDatabaseSupport"],
LibraryMapping('launcher-lib', 'Qt6', 'Qt::AppManLauncher', extra = ['COMPONENTS', 'AppManLauncher']), ),
LibraryMapping('lib', 'Qt6', 'Qt::Designer', extra = ['COMPONENTS', 'Designer']), LibraryMapping("gamepad", "Qt6", "Qt::Gamepad", extra=["COMPONENTS", "Gamepad"]),
LibraryMapping('linuxaccessibility_support', 'Qt6', 'Qt::LinuxAccessibilitySupport', extra = ['COMPONENTS', 'LinuxAccessibilitySupport']), LibraryMapping(
LibraryMapping('location', 'Qt6', 'Qt::Location', extra = ['COMPONENTS', 'Location']), "global", "Qt6", "Qt::Core", extra=["COMPONENTS", "Core"]
LibraryMapping('logic', 'Qt6', 'Qt::3DLogic', extra = ['COMPONENTS', '3DLogic']), ), # manually added special case
LibraryMapping('macextras', 'Qt6', 'Qt::MacExtras', extra = ['COMPONENTS', 'MacExtras']), LibraryMapping("glx_support", "Qt6", "Qt::GlxSupport", extra=["COMPONENTS", "GlxSupport"]),
LibraryMapping('main-lib', 'Qt6', 'Qt::AppManMain', extra = ['COMPONENTS', 'AppManMain']), LibraryMapping(
LibraryMapping('manager-lib', 'Qt6', 'Qt::AppManManager', extra = ['COMPONENTS', 'AppManManager']), "graphics_support", "Qt6", "Qt::GraphicsSupport", extra=["COMPONENTS", "GraphicsSupport"]
LibraryMapping('monitor-lib', 'Qt6', 'Qt::AppManMonitor', extra = ['COMPONENTS', 'AppManMonitor']), ),
LibraryMapping('mqtt', 'Qt6', 'Qt::Mqtt', extra = ['COMPONENTS', 'Mqtt']), LibraryMapping(
LibraryMapping('multimedia', 'Qt6', 'Qt::Multimedia', extra = ['COMPONENTS', 'Multimedia']), "gsttools", "Qt6", "Qt::MultimediaGstTools", extra=["COMPONENTS", "MultimediaGstTools"]
LibraryMapping('multimediawidgets', 'Qt6', 'Qt::MultimediaWidgets', extra = ['COMPONENTS', 'MultimediaWidgets']), ),
LibraryMapping('network', 'Qt6', 'Qt::Network', extra = ['COMPONENTS', 'Network']), LibraryMapping("gui", "Qt6", "Qt::Gui", extra=["COMPONENTS", "Gui"]),
LibraryMapping('networkauth', 'Qt6', 'Qt::NetworkAuth', extra = ['COMPONENTS', 'NetworkAuth']), LibraryMapping("help", "Qt6", "Qt::Help", extra=["COMPONENTS", "Help"]),
LibraryMapping('nfc', 'Qt6', 'Qt::Nfc', extra = ['COMPONENTS', 'Nfc']), LibraryMapping(
LibraryMapping('oauth', 'Qt6', 'Qt::NetworkAuth', extra = ['COMPONENTS', 'NetworkAuth']), "hunspellinputmethod",
LibraryMapping('openglextensions', 'Qt6', 'Qt::OpenGLExtensions', extra = ['COMPONENTS', 'OpenGLExtensions']), "Qt6",
LibraryMapping('opengl', 'Qt6', 'Qt::OpenGL', extra = ['COMPONENTS', 'OpenGL']), "Qt::HunspellInputMethod",
LibraryMapping('package-lib', 'Qt6', 'Qt::AppManPackage', extra = ['COMPONENTS', 'AppManPackage']), extra=["COMPONENTS", "HunspellInputMethod"],
LibraryMapping('packetprotocol', 'Qt6', 'Qt::PacketProtocol', extra = ['COMPONENTS', 'PacketProtocol']), ),
LibraryMapping('particles', 'Qt6', 'Qt::QuickParticles', extra = ['COMPONENTS', 'QuickParticles']), LibraryMapping("input", "Qt6", "Qt::InputSupport", extra=["COMPONENTS", "InputSupport"]),
LibraryMapping('platformcompositor', 'Qt6', 'Qt::PlatformCompositorSupport', extra = ['COMPONENTS', 'PlatformCompositorSupport']), LibraryMapping(
LibraryMapping('platformcompositor_support', 'Qt6', 'Qt::PlatformCompositorSupport', extra = ['COMPONENTS', 'PlatformCompositorSupport']), "input_support", "Qt6", "Qt::InputSupport", extra=["COMPONENTS", "InputSupport"]
LibraryMapping('plugin-interfaces', 'Qt6', 'Qt::AppManPluginInterfaces', extra = ['COMPONENTS', 'AppManPluginInterfaces']), ),
LibraryMapping('positioning', 'Qt6', 'Qt::Positioning', extra = ['COMPONENTS', 'Positioning']), LibraryMapping(
LibraryMapping('positioningquick', 'Qt6', 'Qt::PositioningQuick', extra = ['COMPONENTS', 'PositioningQuick']), "installer-lib", "Qt6", "Qt::AppManInstaller", extra=["COMPONENTS", "AppManInstaller"]
LibraryMapping('printsupport', 'Qt6', 'Qt::PrintSupport', extra = ['COMPONENTS', 'PrintSupport']), ),
LibraryMapping('purchasing', 'Qt6', 'Qt::Purchasing', extra = ['COMPONENTS', 'Purchasing']), LibraryMapping("knx", "Qt6", "Qt::Knx", extra=["COMPONENTS", "Knx"]),
LibraryMapping('qmldebug', 'Qt6', 'Qt::QmlDebug', extra = ['COMPONENTS', 'QmlDebug']), LibraryMapping("kmsconvenience", "Qt6", "Qt::KmsSupport", extra=["COMPONENTS", "KmsSupport"]),
LibraryMapping('qmldevtools', 'Qt6', 'Qt::QmlDevTools', extra = ['COMPONENTS', 'QmlDevTools']), LibraryMapping("kms_support", "Qt6", "Qt::KmsSupport", extra=["COMPONENTS", "KmsSupport"]),
LibraryMapping('qml', 'Qt6', 'Qt::Qml', extra = ['COMPONENTS', 'Qml']), LibraryMapping(
LibraryMapping('qmlmodels', 'Qt6', 'Qt::QmlModels', extra = ['COMPONENTS', 'QmlModels']), "launcher-lib", "Qt6", "Qt::AppManLauncher", extra=["COMPONENTS", "AppManLauncher"]
LibraryMapping('qmltest', 'Qt6', 'Qt::QuickTest', extra = ['COMPONENTS', 'QuickTest']), ),
LibraryMapping('qtmultimediaquicktools', 'Qt6', 'Qt::MultimediaQuick', extra = ['COMPONENTS', 'MultimediaQuick']), LibraryMapping("lib", "Qt6", "Qt::Designer", extra=["COMPONENTS", "Designer"]),
LibraryMapping('quick3danimation', 'Qt6', 'Qt::3DQuickAnimation', extra = ['COMPONENTS', '3DQuickAnimation']), LibraryMapping(
LibraryMapping('quick3dextras', 'Qt6', 'Qt::3DQuickExtras', extra = ['COMPONENTS', '3DQuickExtras']), "linuxaccessibility_support",
LibraryMapping('quick3dinput', 'Qt6', 'Qt::3DQuickInput', extra = ['COMPONENTS', '3DQuickInput']), "Qt6",
LibraryMapping('quick3d', 'Qt6', 'Qt::3DQuick', extra = ['COMPONENTS', '3DQuick']), "Qt::LinuxAccessibilitySupport",
LibraryMapping('quick3drender', 'Qt6', 'Qt::3DQuickRender', extra = ['COMPONENTS', '3DQuickRender']), extra=["COMPONENTS", "LinuxAccessibilitySupport"],
LibraryMapping('quick3dscene2d', 'Qt6', 'Qt::3DQuickScene2D', extra = ['COMPONENTS', '3DQuickScene2D']), ),
LibraryMapping('quickcontrols2', 'Qt6', 'Qt::QuickControls2', extra = ['COMPONENTS', 'QuickControls2']), LibraryMapping("location", "Qt6", "Qt::Location", extra=["COMPONENTS", "Location"]),
LibraryMapping('quick', 'Qt6', 'Qt::Quick', extra = ['COMPONENTS', 'Quick']), LibraryMapping("logic", "Qt6", "Qt::3DLogic", extra=["COMPONENTS", "3DLogic"]),
LibraryMapping('quickshapes', 'Qt6', 'Qt::QuickShapes', extra = ['COMPONENTS', 'QuickShapes']), LibraryMapping("macextras", "Qt6", "Qt::MacExtras", extra=["COMPONENTS", "MacExtras"]),
LibraryMapping('quicktemplates2', 'Qt6', 'Qt::QuickTemplates2', extra = ['COMPONENTS', 'QuickTemplates2']), LibraryMapping("main-lib", "Qt6", "Qt::AppManMain", extra=["COMPONENTS", "AppManMain"]),
LibraryMapping('quickwidgets', 'Qt6', 'Qt::QuickWidgets', extra = ['COMPONENTS', 'QuickWidgets']), LibraryMapping(
LibraryMapping('render', 'Qt6', 'Qt::3DRender', extra = ['COMPONENTS', '3DRender']), "manager-lib", "Qt6", "Qt::AppManManager", extra=["COMPONENTS", "AppManManager"]
LibraryMapping('script', 'Qt6', 'Qt::Script', extra = ['COMPONENTS', 'Script']), ),
LibraryMapping('scripttools', 'Qt6', 'Qt::ScriptTools', extra = ['COMPONENTS', 'ScriptTools']), LibraryMapping(
LibraryMapping('sensors', 'Qt6', 'Qt::Sensors', extra = ['COMPONENTS', 'Sensors']), "monitor-lib", "Qt6", "Qt::AppManMonitor", extra=["COMPONENTS", "AppManMonitor"]
LibraryMapping('serialport', 'Qt6', 'Qt::SerialPort', extra = ['COMPONENTS', 'SerialPort']), ),
LibraryMapping('serialbus', 'Qt6', 'Qt::SerialBus', extra = ['COMPONENTS', 'SerialBus']), LibraryMapping("mqtt", "Qt6", "Qt::Mqtt", extra=["COMPONENTS", "Mqtt"]),
LibraryMapping('services', 'Qt6', 'Qt::ServiceSupport', extra = ['COMPONENTS', 'ServiceSupport']), LibraryMapping("multimedia", "Qt6", "Qt::Multimedia", extra=["COMPONENTS", "Multimedia"]),
LibraryMapping('service_support', 'Qt6', 'Qt::ServiceSupport', extra = ['COMPONENTS', 'ServiceSupport']), LibraryMapping(
LibraryMapping('sql', 'Qt6', 'Qt::Sql', extra = ['COMPONENTS', 'Sql']), "multimediawidgets",
LibraryMapping('svg', 'Qt6', 'Qt::Svg', extra = ['COMPONENTS', 'Svg']), "Qt6",
LibraryMapping('testlib', 'Qt6', 'Qt::Test', extra = ['COMPONENTS', 'Test']), "Qt::MultimediaWidgets",
LibraryMapping('texttospeech', 'Qt6', 'Qt::TextToSpeech', extra = ['COMPONENTS', 'TextToSpeech']), extra=["COMPONENTS", "MultimediaWidgets"],
LibraryMapping('theme_support', 'Qt6', 'Qt::ThemeSupport', extra = ['COMPONENTS', 'ThemeSupport']), ),
LibraryMapping('tts', 'Qt6', 'Qt::TextToSpeech', extra = ['COMPONENTS', 'TextToSpeech']), LibraryMapping("network", "Qt6", "Qt::Network", extra=["COMPONENTS", "Network"]),
LibraryMapping('uiplugin', 'Qt6', 'Qt::UiPlugin', extra = ['COMPONENTS', 'UiPlugin']), LibraryMapping("networkauth", "Qt6", "Qt::NetworkAuth", extra=["COMPONENTS", "NetworkAuth"]),
LibraryMapping('uitools', 'Qt6', 'Qt::UiTools', extra = ['COMPONENTS', 'UiTools']), LibraryMapping("nfc", "Qt6", "Qt::Nfc", extra=["COMPONENTS", "Nfc"]),
LibraryMapping('virtualkeyboard', 'Qt6', 'Qt::VirtualKeyboard', extra = ['COMPONENTS', 'VirtualKeyboard']), LibraryMapping("oauth", "Qt6", "Qt::NetworkAuth", extra=["COMPONENTS", "NetworkAuth"]),
LibraryMapping('vulkan_support', 'Qt6', 'Qt::VulkanSupport', extra = ['COMPONENTS', 'VulkanSupport']), LibraryMapping(
LibraryMapping('waylandclient', 'Qt6', 'Qt::WaylandClient', extra = ['COMPONENTS', 'WaylandClient']), "openglextensions", "Qt6", "Qt::OpenGLExtensions", extra=["COMPONENTS", "OpenGLExtensions"]
LibraryMapping('webchannel', 'Qt6', 'Qt::WebChannel', extra = ['COMPONENTS', 'WebChannel']), ),
LibraryMapping('webengine', 'Qt6', 'Qt::WebEngine', extra = ['COMPONENTS', 'WebEngine']), LibraryMapping("opengl", "Qt6", "Qt::OpenGL", extra=["COMPONENTS", "OpenGL"]),
LibraryMapping('webenginewidgets', 'Qt6', 'Qt::WebEngineWidgets', extra = ['COMPONENTS', 'WebEngineWidgets']), LibraryMapping(
LibraryMapping('websockets', 'Qt6', 'Qt::WebSockets', extra = ['COMPONENTS', 'WebSockets']), "package-lib", "Qt6", "Qt::AppManPackage", extra=["COMPONENTS", "AppManPackage"]
LibraryMapping('webview', 'Qt6', 'Qt::WebView', extra = ['COMPONENTS', 'WebView']), ),
LibraryMapping('widgets', 'Qt6', 'Qt::Widgets', extra = ['COMPONENTS', 'Widgets']), LibraryMapping(
LibraryMapping('window-lib', 'Qt6', 'Qt::AppManWindow', extra = ['COMPONENTS', 'AppManWindow']), "packetprotocol", "Qt6", "Qt::PacketProtocol", extra=["COMPONENTS", "PacketProtocol"]
LibraryMapping('windowsuiautomation_support', 'Qt6', 'Qt::WindowsUIAutomationSupport', extra = ['COMPONENTS', 'WindowsUIAutomationSupport']), ),
LibraryMapping('winextras', 'Qt6', 'Qt::WinExtras', extra = ['COMPONENTS', 'WinExtras']), LibraryMapping(
LibraryMapping('x11extras', 'Qt6', 'Qt::X11Extras', extra = ['COMPONENTS', 'X11Extras']), "particles", "Qt6", "Qt::QuickParticles", extra=["COMPONENTS", "QuickParticles"]
LibraryMapping('xcb_qpa_lib', 'Qt6', 'Qt::XcbQpa', extra = ['COMPONENTS', 'XcbQpa']), ),
LibraryMapping('xkbcommon_support', 'Qt6', 'Qt::XkbCommonSupport', extra = ['COMPONENTS', 'XkbCommonSupport']), LibraryMapping(
LibraryMapping('xmlpatterns', 'Qt6', 'Qt::XmlPatterns', extra = ['COMPONENTS', 'XmlPatterns']), "platformcompositor",
LibraryMapping('xml', 'Qt6', 'Qt::Xml', extra = ['COMPONENTS', 'Xml']), "Qt6",
LibraryMapping('qmlworkerscript', 'Qt6', 'Qt::QmlWorkerScript', extra = ['COMPONENTS', 'QmlWorkerScript']), "Qt::PlatformCompositorSupport",
LibraryMapping('quickparticles', 'Qt6', 'Qt::QuickParticles', extra = ['COMPONENTS', 'QuickParticles']) extra=["COMPONENTS", "PlatformCompositorSupport"],
),
LibraryMapping(
"platformcompositor_support",
"Qt6",
"Qt::PlatformCompositorSupport",
extra=["COMPONENTS", "PlatformCompositorSupport"],
),
LibraryMapping(
"plugin-interfaces",
"Qt6",
"Qt::AppManPluginInterfaces",
extra=["COMPONENTS", "AppManPluginInterfaces"],
),
LibraryMapping("positioning", "Qt6", "Qt::Positioning", extra=["COMPONENTS", "Positioning"]),
LibraryMapping(
"positioningquick", "Qt6", "Qt::PositioningQuick", extra=["COMPONENTS", "PositioningQuick"]
),
LibraryMapping("printsupport", "Qt6", "Qt::PrintSupport", extra=["COMPONENTS", "PrintSupport"]),
LibraryMapping("purchasing", "Qt6", "Qt::Purchasing", extra=["COMPONENTS", "Purchasing"]),
LibraryMapping("qmldebug", "Qt6", "Qt::QmlDebug", extra=["COMPONENTS", "QmlDebug"]),
LibraryMapping("qmldevtools", "Qt6", "Qt::QmlDevTools", extra=["COMPONENTS", "QmlDevTools"]),
LibraryMapping("qml", "Qt6", "Qt::Qml", extra=["COMPONENTS", "Qml"]),
LibraryMapping("qmlmodels", "Qt6", "Qt::QmlModels", extra=["COMPONENTS", "QmlModels"]),
LibraryMapping("qmltest", "Qt6", "Qt::QuickTest", extra=["COMPONENTS", "QuickTest"]),
LibraryMapping(
"qtmultimediaquicktools",
"Qt6",
"Qt::MultimediaQuick",
extra=["COMPONENTS", "MultimediaQuick"],
),
LibraryMapping(
"quick3danimation", "Qt6", "Qt::3DQuickAnimation", extra=["COMPONENTS", "3DQuickAnimation"]
),
LibraryMapping(
"quick3dextras", "Qt6", "Qt::3DQuickExtras", extra=["COMPONENTS", "3DQuickExtras"]
),
LibraryMapping("quick3dinput", "Qt6", "Qt::3DQuickInput", extra=["COMPONENTS", "3DQuickInput"]),
LibraryMapping("quick3d", "Qt6", "Qt::3DQuick", extra=["COMPONENTS", "3DQuick"]),
LibraryMapping(
"quick3drender", "Qt6", "Qt::3DQuickRender", extra=["COMPONENTS", "3DQuickRender"]
),
LibraryMapping(
"quick3dscene2d", "Qt6", "Qt::3DQuickScene2D", extra=["COMPONENTS", "3DQuickScene2D"]
),
LibraryMapping(
"quickcontrols2", "Qt6", "Qt::QuickControls2", extra=["COMPONENTS", "QuickControls2"]
),
LibraryMapping("quick", "Qt6", "Qt::Quick", extra=["COMPONENTS", "Quick"]),
LibraryMapping("quickshapes", "Qt6", "Qt::QuickShapes", extra=["COMPONENTS", "QuickShapes"]),
LibraryMapping(
"quicktemplates2", "Qt6", "Qt::QuickTemplates2", extra=["COMPONENTS", "QuickTemplates2"]
),
LibraryMapping("quickwidgets", "Qt6", "Qt::QuickWidgets", extra=["COMPONENTS", "QuickWidgets"]),
LibraryMapping("render", "Qt6", "Qt::3DRender", extra=["COMPONENTS", "3DRender"]),
LibraryMapping("script", "Qt6", "Qt::Script", extra=["COMPONENTS", "Script"]),
LibraryMapping("scripttools", "Qt6", "Qt::ScriptTools", extra=["COMPONENTS", "ScriptTools"]),
LibraryMapping("sensors", "Qt6", "Qt::Sensors", extra=["COMPONENTS", "Sensors"]),
LibraryMapping("serialport", "Qt6", "Qt::SerialPort", extra=["COMPONENTS", "SerialPort"]),
LibraryMapping("serialbus", "Qt6", "Qt::SerialBus", extra=["COMPONENTS", "SerialBus"]),
LibraryMapping("services", "Qt6", "Qt::ServiceSupport", extra=["COMPONENTS", "ServiceSupport"]),
LibraryMapping(
"service_support", "Qt6", "Qt::ServiceSupport", extra=["COMPONENTS", "ServiceSupport"]
),
LibraryMapping("sql", "Qt6", "Qt::Sql", extra=["COMPONENTS", "Sql"]),
LibraryMapping("svg", "Qt6", "Qt::Svg", extra=["COMPONENTS", "Svg"]),
LibraryMapping("testlib", "Qt6", "Qt::Test", extra=["COMPONENTS", "Test"]),
LibraryMapping("texttospeech", "Qt6", "Qt::TextToSpeech", extra=["COMPONENTS", "TextToSpeech"]),
LibraryMapping(
"theme_support", "Qt6", "Qt::ThemeSupport", extra=["COMPONENTS", "ThemeSupport"]
),
LibraryMapping("tts", "Qt6", "Qt::TextToSpeech", extra=["COMPONENTS", "TextToSpeech"]),
LibraryMapping("uiplugin", "Qt6", "Qt::UiPlugin", extra=["COMPONENTS", "UiPlugin"]),
LibraryMapping("uitools", "Qt6", "Qt::UiTools", extra=["COMPONENTS", "UiTools"]),
LibraryMapping(
"virtualkeyboard", "Qt6", "Qt::VirtualKeyboard", extra=["COMPONENTS", "VirtualKeyboard"]
),
LibraryMapping(
"vulkan_support", "Qt6", "Qt::VulkanSupport", extra=["COMPONENTS", "VulkanSupport"]
),
LibraryMapping(
"waylandclient", "Qt6", "Qt::WaylandClient", extra=["COMPONENTS", "WaylandClient"]
),
LibraryMapping("webchannel", "Qt6", "Qt::WebChannel", extra=["COMPONENTS", "WebChannel"]),
LibraryMapping("webengine", "Qt6", "Qt::WebEngine", extra=["COMPONENTS", "WebEngine"]),
LibraryMapping(
"webenginewidgets", "Qt6", "Qt::WebEngineWidgets", extra=["COMPONENTS", "WebEngineWidgets"]
),
LibraryMapping("websockets", "Qt6", "Qt::WebSockets", extra=["COMPONENTS", "WebSockets"]),
LibraryMapping("webview", "Qt6", "Qt::WebView", extra=["COMPONENTS", "WebView"]),
LibraryMapping("widgets", "Qt6", "Qt::Widgets", extra=["COMPONENTS", "Widgets"]),
LibraryMapping("window-lib", "Qt6", "Qt::AppManWindow", extra=["COMPONENTS", "AppManWindow"]),
LibraryMapping(
"windowsuiautomation_support",
"Qt6",
"Qt::WindowsUIAutomationSupport",
extra=["COMPONENTS", "WindowsUIAutomationSupport"],
),
LibraryMapping("winextras", "Qt6", "Qt::WinExtras", extra=["COMPONENTS", "WinExtras"]),
LibraryMapping("x11extras", "Qt6", "Qt::X11Extras", extra=["COMPONENTS", "X11Extras"]),
LibraryMapping("xcb_qpa_lib", "Qt6", "Qt::XcbQpa", extra=["COMPONENTS", "XcbQpa"]),
LibraryMapping(
"xkbcommon_support", "Qt6", "Qt::XkbCommonSupport", extra=["COMPONENTS", "XkbCommonSupport"]
),
LibraryMapping("xmlpatterns", "Qt6", "Qt::XmlPatterns", extra=["COMPONENTS", "XmlPatterns"]),
LibraryMapping("xml", "Qt6", "Qt::Xml", extra=["COMPONENTS", "Xml"]),
LibraryMapping(
"qmlworkerscript", "Qt6", "Qt::QmlWorkerScript", extra=["COMPONENTS", "QmlWorkerScript"]
),
LibraryMapping(
"quickparticles", "Qt6", "Qt::QuickParticles", extra=["COMPONENTS", "QuickParticles"]
)
# qtzlib: No longer supported. # qtzlib: No longer supported.
] ]
# Note that the library map is adjusted dynamically further down. # Note that the library map is adjusted dynamically further down.
_library_map = [ _library_map = [
# 3rd party: # 3rd party:
LibraryMapping('atspi', 'ATSPI2', 'PkgConfig::ATSPI2'), LibraryMapping("atspi", "ATSPI2", "PkgConfig::ATSPI2"),
LibraryMapping('corewlan', None, None), LibraryMapping("corewlan", None, None),
LibraryMapping('cups', 'Cups', 'Cups::Cups'), LibraryMapping("cups", "Cups", "Cups::Cups"),
LibraryMapping('db2', 'DB2', 'DB2::DB2'), LibraryMapping("db2", "DB2", "DB2::DB2"),
LibraryMapping('dbus', 'WrapDBus1', 'dbus-1', resultVariable="DBus1"), LibraryMapping("dbus", "WrapDBus1", "dbus-1", resultVariable="DBus1"),
LibraryMapping('doubleconversion', None, None), LibraryMapping("doubleconversion", None, None),
LibraryMapping('drm', 'Libdrm', 'Libdrm::Libdrm'), LibraryMapping("drm", "Libdrm", "Libdrm::Libdrm"),
LibraryMapping('egl', 'EGL', 'EGL::EGL'), LibraryMapping("egl", "EGL", "EGL::EGL"),
LibraryMapping('flite', 'Flite', 'Flite::Flite'), LibraryMapping("flite", "Flite", "Flite::Flite"),
LibraryMapping('flite_alsa', 'ALSA', 'ALSA::ALSA'), LibraryMapping("flite_alsa", "ALSA", "ALSA::ALSA"),
LibraryMapping('fontconfig', 'Fontconfig', 'Fontconfig::Fontconfig', resultVariable="FONTCONFIG"), LibraryMapping(
LibraryMapping('freetype', 'WrapFreetype', 'WrapFreetype::WrapFreetype', extra=['REQUIRED']), "fontconfig", "Fontconfig", "Fontconfig::Fontconfig", resultVariable="FONTCONFIG"
LibraryMapping('gbm', 'gbm', 'gbm::gbm'), ),
LibraryMapping('glib', 'GLIB2', 'GLIB2::GLIB2'), LibraryMapping("freetype", "WrapFreetype", "WrapFreetype::WrapFreetype", extra=["REQUIRED"]),
LibraryMapping('gnu_iconv', None, None), LibraryMapping("gbm", "gbm", "gbm::gbm"),
LibraryMapping('gtk3', 'GTK3', 'PkgConfig::GTK3'), LibraryMapping("glib", "GLIB2", "GLIB2::GLIB2"),
LibraryMapping('harfbuzz', 'harfbuzz', 'harfbuzz::harfbuzz'), LibraryMapping("gnu_iconv", None, None),
LibraryMapping('host_dbus', None, None), LibraryMapping("gtk3", "GTK3", "PkgConfig::GTK3"),
LibraryMapping('icu', 'ICU', 'ICU::i18n ICU::uc ICU::data', extra=['COMPONENTS', 'i18n', 'uc', 'data']), LibraryMapping("harfbuzz", "harfbuzz", "harfbuzz::harfbuzz"),
LibraryMapping('journald', 'Libsystemd', 'PkgConfig::Libsystemd'), LibraryMapping("host_dbus", None, None),
LibraryMapping('jpeg', 'JPEG', 'JPEG::JPEG'), # see also libjpeg LibraryMapping(
LibraryMapping('libatomic', 'Atomic', 'Atomic'), "icu", "ICU", "ICU::i18n ICU::uc ICU::data", extra=["COMPONENTS", "i18n", "uc", "data"]
LibraryMapping('libclang', 'WrapLibClang', 'WrapLibClang::WrapLibClang'), ),
LibraryMapping('libdl', None, '${CMAKE_DL_LIBS}'), LibraryMapping("journald", "Libsystemd", "PkgConfig::Libsystemd"),
LibraryMapping('libinput', 'Libinput', 'Libinput::Libinput'), LibraryMapping("jpeg", "JPEG", "JPEG::JPEG"), # see also libjpeg
LibraryMapping('libjpeg', 'JPEG', 'JPEG::JPEG'), # see also jpeg LibraryMapping("libatomic", "Atomic", "Atomic"),
LibraryMapping('libpng', 'PNG', 'PNG::PNG'), LibraryMapping("libclang", "WrapLibClang", "WrapLibClang::WrapLibClang"),
LibraryMapping('libproxy', 'Libproxy', 'PkgConfig::Libproxy'), LibraryMapping("libdl", None, "${CMAKE_DL_LIBS}"),
LibraryMapping('librt', 'WrapRt','WrapRt'), LibraryMapping("libinput", "Libinput", "Libinput::Libinput"),
LibraryMapping('libudev', 'Libudev', 'PkgConfig::Libudev'), LibraryMapping("libjpeg", "JPEG", "JPEG::JPEG"), # see also jpeg
LibraryMapping('lttng-ust', 'LTTngUST', 'LTTng::UST', resultVariable='LTTNGUST'), LibraryMapping("libpng", "PNG", "PNG::PNG"),
LibraryMapping('mtdev', 'Mtdev', 'PkgConfig::Mtdev'), LibraryMapping("libproxy", "Libproxy", "PkgConfig::Libproxy"),
LibraryMapping('mysql', 'MySQL', 'MySQL::MySQL'), LibraryMapping("librt", "WrapRt", "WrapRt"),
LibraryMapping('odbc', 'ODBC', 'ODBC::ODBC'), LibraryMapping("libudev", "Libudev", "PkgConfig::Libudev"),
LibraryMapping('opengl_es2', 'GLESv2', 'GLESv2::GLESv2'), LibraryMapping("lttng-ust", "LTTngUST", "LTTng::UST", resultVariable="LTTNGUST"),
LibraryMapping('opengl', 'OpenGL', 'OpenGL::GL', resultVariable='OpenGL_OpenGL'), LibraryMapping("mtdev", "Mtdev", "PkgConfig::Mtdev"),
LibraryMapping('openssl_headers', 'OpenSSL', 'OpenSSL::SSL_nolink', resultVariable='OPENSSL_INCLUDE_DIR', appendFoundSuffix=False), LibraryMapping("mysql", "MySQL", "MySQL::MySQL"),
LibraryMapping('openssl', 'OpenSSL', 'OpenSSL::SSL'), LibraryMapping("odbc", "ODBC", "ODBC::ODBC"),
LibraryMapping('oci', 'Oracle', 'Oracle::OCI'), LibraryMapping("opengl_es2", "GLESv2", "GLESv2::GLESv2"),
LibraryMapping('pcre2', 'WrapPCRE2', 'WrapPCRE2::WrapPCRE2', extra = ['REQUIRED']), LibraryMapping("opengl", "OpenGL", "OpenGL::GL", resultVariable="OpenGL_OpenGL"),
LibraryMapping('posix_iconv', None, None), LibraryMapping(
LibraryMapping('pps', 'PPS', 'PPS::PPS'), "openssl_headers",
LibraryMapping('psql', 'PostgreSQL', 'PostgreSQL::PostgreSQL'), "OpenSSL",
LibraryMapping('slog2', 'Slog2', 'Slog2::Slog2'), "OpenSSL::SSL_nolink",
LibraryMapping('speechd', 'SpeechDispatcher', 'SpeechDispatcher::SpeechDispatcher'), resultVariable="OPENSSL_INCLUDE_DIR",
LibraryMapping('sqlite2', None, None), # No more sqlite2 support in Qt6! appendFoundSuffix=False,
LibraryMapping('sqlite3', 'SQLite3', 'SQLite::SQLite3'), ),
LibraryMapping('sun_iconv', None, None), LibraryMapping("openssl", "OpenSSL", "OpenSSL::SSL"),
LibraryMapping('tslib', 'Tslib', 'PkgConfig::Tslib'), LibraryMapping("oci", "Oracle", "Oracle::OCI"),
LibraryMapping('udev', 'Libudev', 'PkgConfig::Libudev'), LibraryMapping("pcre2", "WrapPCRE2", "WrapPCRE2::WrapPCRE2", extra=["REQUIRED"]),
LibraryMapping('udev', 'Libudev', 'PkgConfig::Libudev'), # see also libudev! LibraryMapping("posix_iconv", None, None),
LibraryMapping('vulkan', 'Vulkan', 'Vulkan::Vulkan'), LibraryMapping("pps", "PPS", "PPS::PPS"),
LibraryMapping('wayland-server', 'Wayland', 'Wayland::Server'), LibraryMapping("psql", "PostgreSQL", "PostgreSQL::PostgreSQL"),
LibraryMapping('wayland-client', 'Wayland', 'Wayland::Client'), LibraryMapping("slog2", "Slog2", "Slog2::Slog2"),
LibraryMapping('wayland-cursor', 'Wayland', 'Wayland::Cursor'), LibraryMapping("speechd", "SpeechDispatcher", "SpeechDispatcher::SpeechDispatcher"),
LibraryMapping('wayland-egl', 'Wayland', 'Wayland::Egl'), LibraryMapping("sqlite2", None, None), # No more sqlite2 support in Qt6!
LibraryMapping('x11sm', 'X11', '${X11_SM_LIB} ${X11_ICE_LIB}', resultVariable="X11_SM"), LibraryMapping("sqlite3", "SQLite3", "SQLite::SQLite3"),
LibraryMapping('xcb', 'XCB', 'XCB::XCB', extra = ['1.9'], resultVariable='TARGET XCB::XCB', appendFoundSuffix=False), LibraryMapping("sun_iconv", None, None),
LibraryMapping('xcb_glx', 'XCB', 'XCB::GLX', extra = ['COMPONENTS', 'GLX'], resultVariable='XCB_GLX'), LibraryMapping("tslib", "Tslib", "PkgConfig::Tslib"),
LibraryMapping('xcb_icccm', 'XCB', 'XCB::ICCCM', extra = ['COMPONENTS', 'ICCCM'], resultVariable='XCB_ICCCM'), LibraryMapping("udev", "Libudev", "PkgConfig::Libudev"),
LibraryMapping('xcb_image', 'XCB', 'XCB::IMAGE', extra = ['COMPONENTS', 'IMAGE'], resultVariable='XCB_IMAGE'), LibraryMapping("udev", "Libudev", "PkgConfig::Libudev"), # see also libudev!
LibraryMapping('xcb_keysyms', 'XCB', 'XCB::KEYSYMS', extra = ['COMPONENTS', 'KEYSYMS'], resultVariable='XCB_KEYSYMS'), LibraryMapping("vulkan", "Vulkan", "Vulkan::Vulkan"),
LibraryMapping('xcb_randr', 'XCB', 'XCB::RANDR', extra = ['COMPONENTS', 'RANDR'], resultVariable='XCB_RANDR'), LibraryMapping("wayland-server", "Wayland", "Wayland::Server"),
LibraryMapping('xcb_render', 'XCB', 'XCB::RENDER', extra = ['COMPONENTS', 'RENDER'], resultVariable='XCB_RENDER'), LibraryMapping("wayland-client", "Wayland", "Wayland::Client"),
LibraryMapping('xcb_renderutil', 'XCB', 'XCB::RENDERUTIL', extra = ['COMPONENTS', 'RENDERUTIL'], resultVariable='XCB_RENDERUTIL'), LibraryMapping("wayland-cursor", "Wayland", "Wayland::Cursor"),
LibraryMapping('xcb_shape', 'XCB', 'XCB::SHAPE', extra = ['COMPONENTS', 'SHAPE'], resultVariable='XCB_SHAPE'), LibraryMapping("wayland-egl", "Wayland", "Wayland::Egl"),
LibraryMapping('xcb_shm', 'XCB', 'XCB::SHM', extra = ['COMPONENTS', 'SHM'], resultVariable='XCB_SHM'), LibraryMapping("x11sm", "X11", "${X11_SM_LIB} ${X11_ICE_LIB}", resultVariable="X11_SM"),
LibraryMapping('xcb_sync', 'XCB', 'XCB::SYNC', extra = ['COMPONENTS', 'SYNC'], resultVariable='XCB_SYNC'), LibraryMapping(
LibraryMapping('xcb_xfixes', 'XCB', 'XCB::XFIXES', extra = ['COMPONENTS', 'XFIXES'], resultVariable='XCB_XFIXES'), "xcb",
LibraryMapping('xcb_xinerama', 'XCB', 'XCB::XINERAMA', extra = ['COMPONENTS', 'XINERAMA'], resultVariable='XCB_XINERAMA'), "XCB",
LibraryMapping('xcb_xinput', 'XCB', 'XCB::XINPUT', extra = ['COMPONENTS', 'XINPUT'], resultVariable='XCB_XINPUT'), "XCB::XCB",
LibraryMapping('xcb_xkb', 'XCB', 'XCB::XKB', extra = ['COMPONENTS', 'XKB'], resultVariable='XCB_XKB'), extra=["1.9"],
LibraryMapping('xcb_xlib', 'X11_XCB', 'X11::XCB'), resultVariable="TARGET XCB::XCB",
LibraryMapping('xkbcommon_evdev', 'XKB', 'XKB::XKB', extra = ['0.4.1']), # see also xkbcommon appendFoundSuffix=False,
LibraryMapping('xkbcommon_x11', 'XKB', 'XKB::XKB', extra = ['0.4.1']), # see also xkbcommon ),
LibraryMapping('xkbcommon', 'XKB', 'XKB::XKB', extra = ['0.4.1']), LibraryMapping(
LibraryMapping('xlib', 'X11', 'X11::XCB'), # FIXME: Is this correct? "xcb_glx", "XCB", "XCB::GLX", extra=["COMPONENTS", "GLX"], resultVariable="XCB_GLX"
LibraryMapping('xrender', 'XRender', 'PkgConfig::XRender'), ),
LibraryMapping('zlib', 'ZLIB', 'ZLIB::ZLIB', extra=['REQUIRED']), LibraryMapping(
LibraryMapping('zstd', 'ZSTD', 'ZSTD::ZSTD'), "xcb_icccm", "XCB", "XCB::ICCCM", extra=["COMPONENTS", "ICCCM"], resultVariable="XCB_ICCCM"
LibraryMapping('tiff', 'TIFF', 'TIFF::TIFF'), ),
LibraryMapping('webp', 'WrapWebP', 'WrapWebP::WrapWebP'), LibraryMapping(
LibraryMapping('jasper', 'WrapJasper', 'WrapJasper::WrapJasper'), "xcb_image", "XCB", "XCB::IMAGE", extra=["COMPONENTS", "IMAGE"], resultVariable="XCB_IMAGE"
),
LibraryMapping(
"xcb_keysyms",
"XCB",
"XCB::KEYSYMS",
extra=["COMPONENTS", "KEYSYMS"],
resultVariable="XCB_KEYSYMS",
),
LibraryMapping(
"xcb_randr", "XCB", "XCB::RANDR", extra=["COMPONENTS", "RANDR"], resultVariable="XCB_RANDR"
),
LibraryMapping(
"xcb_render",
"XCB",
"XCB::RENDER",
extra=["COMPONENTS", "RENDER"],
resultVariable="XCB_RENDER",
),
LibraryMapping(
"xcb_renderutil",
"XCB",
"XCB::RENDERUTIL",
extra=["COMPONENTS", "RENDERUTIL"],
resultVariable="XCB_RENDERUTIL",
),
LibraryMapping(
"xcb_shape", "XCB", "XCB::SHAPE", extra=["COMPONENTS", "SHAPE"], resultVariable="XCB_SHAPE"
),
LibraryMapping(
"xcb_shm", "XCB", "XCB::SHM", extra=["COMPONENTS", "SHM"], resultVariable="XCB_SHM"
),
LibraryMapping(
"xcb_sync", "XCB", "XCB::SYNC", extra=["COMPONENTS", "SYNC"], resultVariable="XCB_SYNC"
),
LibraryMapping(
"xcb_xfixes",
"XCB",
"XCB::XFIXES",
extra=["COMPONENTS", "XFIXES"],
resultVariable="XCB_XFIXES",
),
LibraryMapping(
"xcb_xinerama",
"XCB",
"XCB::XINERAMA",
extra=["COMPONENTS", "XINERAMA"],
resultVariable="XCB_XINERAMA",
),
LibraryMapping(
"xcb_xinput",
"XCB",
"XCB::XINPUT",
extra=["COMPONENTS", "XINPUT"],
resultVariable="XCB_XINPUT",
),
LibraryMapping(
"xcb_xkb", "XCB", "XCB::XKB", extra=["COMPONENTS", "XKB"], resultVariable="XCB_XKB"
),
LibraryMapping("xcb_xlib", "X11_XCB", "X11::XCB"),
LibraryMapping("xkbcommon_evdev", "XKB", "XKB::XKB", extra=["0.4.1"]), # see also xkbcommon
LibraryMapping("xkbcommon_x11", "XKB", "XKB::XKB", extra=["0.4.1"]), # see also xkbcommon
LibraryMapping("xkbcommon", "XKB", "XKB::XKB", extra=["0.4.1"]),
LibraryMapping("xlib", "X11", "X11::XCB"), # FIXME: Is this correct?
LibraryMapping("xrender", "XRender", "PkgConfig::XRender"),
LibraryMapping("zlib", "ZLIB", "ZLIB::ZLIB", extra=["REQUIRED"]),
LibraryMapping("zstd", "ZSTD", "ZSTD::ZSTD"),
LibraryMapping("tiff", "TIFF", "TIFF::TIFF"),
LibraryMapping("webp", "WrapWebP", "WrapWebP::WrapWebP"),
LibraryMapping("jasper", "WrapJasper", "WrapJasper::WrapJasper"),
] ]
@ -283,10 +504,10 @@ def _adjust_library_map():
# We don't want to get pages of package not found messages on # We don't want to get pages of package not found messages on
# Windows and macOS, and this also improves configure time on # Windows and macOS, and this also improves configure time on
# those platforms. # those platforms.
linux_package_prefixes = ['xcb', 'x11', 'xkb', 'xrender', 'xlib', 'wayland'] linux_package_prefixes = ["xcb", "x11", "xkb", "xrender", "xlib", "wayland"]
for i, _ in enumerate(_library_map): for i, _ in enumerate(_library_map):
if any([_library_map[i].soName.startswith(p) for p in linux_package_prefixes]): if any([_library_map[i].soName.startswith(p) for p in linux_package_prefixes]):
_library_map[i].emit_if = 'config.linux' _library_map[i].emit_if = "config.linux"
_adjust_library_map() _adjust_library_map()
@ -308,7 +529,7 @@ def find_qt_library_mapping(soName: str) -> typing.Optional[LibraryMapping]:
def find_library_info_for_target(targetName: str) -> typing.Optional[LibraryMapping]: def find_library_info_for_target(targetName: str) -> typing.Optional[LibraryMapping]:
qt_target = targetName qt_target = targetName
if targetName.endswith('Private'): if targetName.endswith("Private"):
qt_target = qt_target[:-7] qt_target = qt_target[:-7]
for i in _qt_library_map: for i in _qt_library_map:
@ -323,61 +544,61 @@ def find_library_info_for_target(targetName: str) -> typing.Optional[LibraryMapp
def featureName(input: str) -> str: def featureName(input: str) -> str:
replacement_char = '_' replacement_char = "_"
if input.startswith('c++'): if input.startswith("c++"):
replacement_char = 'x' replacement_char = "x"
return re.sub(r'[^a-zA-Z0-9_]', replacement_char, input) return re.sub(r"[^a-zA-Z0-9_]", replacement_char, input)
def map_qt_library(lib: str) -> str: def map_qt_library(lib: str) -> str:
private = False private = False
if lib.endswith('-private'): if lib.endswith("-private"):
private = True private = True
lib = lib[:-8] lib = lib[:-8]
mapped = find_qt_library_mapping(lib) mapped = find_qt_library_mapping(lib)
qt_name = lib qt_name = lib
if mapped: if mapped:
assert mapped.targetName # Qt libs must have a target name set assert mapped.targetName # Qt libs must have a target name set
qt_name = mapped.targetName qt_name = mapped.targetName
if private: if private:
qt_name += 'Private' qt_name += "Private"
return qt_name return qt_name
platform_mapping = { platform_mapping = {
'win32': 'WIN32', "win32": "WIN32",
'win': 'WIN32', "win": "WIN32",
'unix': 'UNIX', "unix": "UNIX",
'darwin': 'APPLE', "darwin": "APPLE",
'linux': 'LINUX', "linux": "LINUX",
'integrity': 'INTEGRITY', "integrity": "INTEGRITY",
'qnx': 'QNX', "qnx": "QNX",
'vxworks': 'VXWORKS', "vxworks": "VXWORKS",
'hpux': 'HPUX', "hpux": "HPUX",
'nacl': 'NACL', "nacl": "NACL",
'android': 'ANDROID', "android": "ANDROID",
'android-embedded': 'ANDROID_EMBEDDED', "android-embedded": "ANDROID_EMBEDDED",
'uikit': 'APPLE_UIKIT', "uikit": "APPLE_UIKIT",
'tvos': 'APPLE_TVOS', "tvos": "APPLE_TVOS",
'watchos': 'APPLE_WATCHOS', "watchos": "APPLE_WATCHOS",
'winrt': 'WINRT', "winrt": "WINRT",
'wasm': 'WASM', "wasm": "WASM",
'msvc': 'MSVC', "msvc": "MSVC",
'clang': 'CLANG', "clang": "CLANG",
'gcc': 'GCC', "gcc": "GCC",
'icc': 'ICC', "icc": "ICC",
'intel_icc': 'ICC', "intel_icc": "ICC",
'osx': 'APPLE_OSX', "osx": "APPLE_OSX",
'ios': 'APPLE_IOS', "ios": "APPLE_IOS",
'freebsd': 'FREEBSD', "freebsd": "FREEBSD",
'openbsd': 'OPENBSD', "openbsd": "OPENBSD",
'netbsd': 'NETBSD', "netbsd": "NETBSD",
'haiku': 'HAIKU', "haiku": "HAIKU",
'netbsd': 'NETBSD', "netbsd": "NETBSD",
'mac': 'APPLE', "mac": "APPLE",
'macx': 'APPLE_OSX', "macx": "APPLE_OSX",
'macos': 'APPLE_OSX', "macos": "APPLE_OSX",
'macx-icc': '(APPLE_OSX AND ICC)', "macx-icc": "(APPLE_OSX AND ICC)",
} }
@ -387,7 +608,7 @@ def map_platform(platform: str) -> str:
def is_known_3rd_party_library(lib: str) -> bool: def is_known_3rd_party_library(lib: str) -> bool:
if lib.endswith('/nolink') or lib.endswith('_nolink'): if lib.endswith("/nolink") or lib.endswith("_nolink"):
lib = lib[:-7] lib = lib[:-7]
mapping = find_3rd_party_library_mapping(lib) mapping = find_3rd_party_library_mapping(lib)
@ -395,20 +616,19 @@ def is_known_3rd_party_library(lib: str) -> bool:
def map_3rd_party_library(lib: str) -> str: def map_3rd_party_library(lib: str) -> str:
libpostfix = '' libpostfix = ""
if lib.endswith('/nolink'): if lib.endswith("/nolink"):
lib = lib[:-7] lib = lib[:-7]
libpostfix = '_nolink' libpostfix = "_nolink"
mapping = find_3rd_party_library_mapping(lib) mapping = find_3rd_party_library_mapping(lib)
if not mapping or not mapping.targetName: if not mapping or not mapping.targetName:
return lib return lib
return mapping.targetName + libpostfix return mapping.targetName + libpostfix
def generate_find_package_info(lib: LibraryMapping, def generate_find_package_info(
use_qt_find_package: bool=True, *, lib: LibraryMapping, use_qt_find_package: bool = True, *, indent: int = 0, emit_if: str = ""
indent: int = 0, ) -> str:
emit_if: str = '') -> str:
isRequired = False isRequired = False
extra = lib.extra.copy() extra = lib.extra.copy()
@ -418,40 +638,41 @@ def generate_find_package_info(lib: LibraryMapping,
extra.remove("REQUIRED") extra.remove("REQUIRED")
cmake_target_name = lib.targetName cmake_target_name = lib.targetName
assert(cmake_target_name); assert cmake_target_name
# _nolink or not does not matter at this point: # _nolink or not does not matter at this point:
if cmake_target_name.endswith('_nolink') or cmake_target_name.endswith('/nolink'): if cmake_target_name.endswith("_nolink") or cmake_target_name.endswith("/nolink"):
cmake_target_name = cmake_target_name[:-7] cmake_target_name = cmake_target_name[:-7]
if cmake_target_name and use_qt_find_package: if cmake_target_name and use_qt_find_package:
extra += ['PROVIDED_TARGETS', cmake_target_name] extra += ["PROVIDED_TARGETS", cmake_target_name]
result = '' result = ""
one_ind = ' ' one_ind = " "
ind = one_ind * indent ind = one_ind * indent
if use_qt_find_package: if use_qt_find_package:
if extra: if extra:
result = '{}qt_find_package({} {})\n'.format(ind, lib.packageName, ' '.join(extra)) result = "{}qt_find_package({} {})\n".format(ind, lib.packageName, " ".join(extra))
else: else:
result = '{}qt_find_package({})\n'.format(ind, lib.packageName) result = "{}qt_find_package({})\n".format(ind, lib.packageName)
if isRequired: if isRequired:
result += '{}set_package_properties({} PROPERTIES TYPE REQUIRED)\n'.format(ind, lib.packageName) result += "{}set_package_properties({} PROPERTIES TYPE REQUIRED)\n".format(
ind, lib.packageName
)
else: else:
if extra: if extra:
result = '{}find_package({} {})\n'.format(ind, lib.packageName, ' '.join(extra)) result = "{}find_package({} {})\n".format(ind, lib.packageName, " ".join(extra))
else: else:
result = '{}find_package({})\n'.format(ind, lib.packageName) result = "{}find_package({})\n".format(ind, lib.packageName)
# If a package should be found only in certain conditions, wrap # If a package should be found only in certain conditions, wrap
# the find_package call within that condition. # the find_package call within that condition.
if emit_if: if emit_if:
result = "if(({emit_if}) OR QT_FIND_ALL_PACKAGES_ALWAYS)\n" \ result = "if(({emit_if}) OR QT_FIND_ALL_PACKAGES_ALWAYS)\n" "{ind}{result}endif()\n".format(
"{ind}{result}endif()\n".format(emit_if=emit_if, emit_if=emit_if, result=result, ind=one_ind
result=result, )
ind=one_ind)
return result return result

View File

@ -31,6 +31,7 @@ import pyparsing as pp
import json import json
import re import re
from helper import _set_up_py_parsing_nicer_debug_output from helper import _set_up_py_parsing_nicer_debug_output
_set_up_py_parsing_nicer_debug_output(pp) _set_up_py_parsing_nicer_debug_output(pp)
@ -41,7 +42,7 @@ class QMakeSpecificJSONParser:
def create_py_parsing_grammar(self): def create_py_parsing_grammar(self):
# Keep around all whitespace. # Keep around all whitespace.
pp.ParserElement.setDefaultWhitespaceChars('') pp.ParserElement.setDefaultWhitespaceChars("")
def add_element(name: str, value: pp.ParserElement): def add_element(name: str, value: pp.ParserElement):
nonlocal self nonlocal self
@ -57,44 +58,44 @@ class QMakeSpecificJSONParser:
# skip to the next quote, and repeat that until the end of the # skip to the next quote, and repeat that until the end of the
# file. # file.
EOF = add_element('EOF', pp.StringEnd()) EOF = add_element("EOF", pp.StringEnd())
SkipToQuote = add_element('SkipToQuote', pp.SkipTo('"')) SkipToQuote = add_element("SkipToQuote", pp.SkipTo('"'))
SkipToEOF = add_element('SkipToEOF', pp.SkipTo(EOF)) SkipToEOF = add_element("SkipToEOF", pp.SkipTo(EOF))
def remove_newlines_and_whitespace_in_quoted_string(tokens): def remove_newlines_and_whitespace_in_quoted_string(tokens):
first_string = tokens[0] first_string = tokens[0]
replaced_string = re.sub(r'\n[ ]*', ' ', first_string) replaced_string = re.sub(r"\n[ ]*", " ", first_string)
return replaced_string return replaced_string
QuotedString = add_element('QuotedString', pp.QuotedString(quoteChar='"', QuotedString = add_element(
multiline=True, "QuotedString", pp.QuotedString(quoteChar='"', multiline=True, unquoteResults=False)
unquoteResults=False)) )
QuotedString.setParseAction(remove_newlines_and_whitespace_in_quoted_string) QuotedString.setParseAction(remove_newlines_and_whitespace_in_quoted_string)
QuotedTerm = add_element('QuotedTerm', pp.Optional(SkipToQuote) + QuotedString) QuotedTerm = add_element("QuotedTerm", pp.Optional(SkipToQuote) + QuotedString)
Grammar = add_element('Grammar', pp.OneOrMore(QuotedTerm) + SkipToEOF) Grammar = add_element("Grammar", pp.OneOrMore(QuotedTerm) + SkipToEOF)
return Grammar return Grammar
def parse_file_using_py_parsing(self, file: str): def parse_file_using_py_parsing(self, file: str):
print('Pre processing "{}" using py parsing to remove incorrect newlines.'.format(file)) print(f'Pre processing "{file}" using py parsing to remove incorrect newlines.')
try: try:
with open(file, 'r') as file_fd: with open(file, "r") as file_fd:
contents = file_fd.read() contents = file_fd.read()
parser_result = self.grammar.parseString(contents, parseAll=True) parser_result = self.grammar.parseString(contents, parseAll=True)
token_list = parser_result.asList() token_list = parser_result.asList()
joined_string = ''.join(token_list) joined_string = "".join(token_list)
return joined_string return joined_string
except pp.ParseException as pe: except pp.ParseException as pe:
print(pe.line) print(pe.line)
print(' '*(pe.col-1) + '^') print(" " * (pe.col - 1) + "^")
print(pe) print(pe)
raise pe raise pe
def parse(self, file: str): def parse(self, file: str):
pre_processed_string = self.parse_file_using_py_parsing(file) pre_processed_string = self.parse_file_using_py_parsing(file)
print('Parsing "{}" using json.loads().'.format(file)) print(f'Parsing "{file}" using json.loads().')
json_parsed = json.loads(pre_processed_string) json_parsed = json.loads(pre_processed_string)
return json_parsed return json_parsed

File diff suppressed because it is too large Load Diff

View File

@ -47,9 +47,10 @@ from timeit import default_timer
def _parse_commandline(): def _parse_commandline():
parser = ArgumentParser(description='Find pro files for which there are no CMakeLists.txt.') parser = ArgumentParser(description="Find pro files for which there are no CMakeLists.txt.")
parser.add_argument('source_directory', metavar='<src dir>', type=str, parser.add_argument(
help='The source directory') "source_directory", metavar="<src dir>", type=str, help="The source directory"
)
return parser.parse_args() return parser.parse_args()
@ -68,6 +69,7 @@ class Blacklist:
try: try:
# If package is available, use Aho-Corasick algorithm, # If package is available, use Aho-Corasick algorithm,
from ahocorapy.keywordtree import KeywordTree from ahocorapy.keywordtree import KeywordTree
self.tree = KeywordTree(case_insensitive=True) self.tree = KeywordTree(case_insensitive=True)
for p in self.path_parts: for p in self.path_parts:
@ -117,45 +119,58 @@ def check_for_cmake_project(pro_path: str) -> bool:
return os.path.exists(cmake_project_path) return os.path.exists(cmake_project_path)
def compute_stats(src_path: str, pros_with_missing_project: typing.List[str], def compute_stats(
total_pros: int, existing_pros: int, missing_pros: int) -> dict: src_path: str,
pros_with_missing_project: typing.List[str],
total_pros: int,
existing_pros: int,
missing_pros: int,
) -> dict:
stats = {} stats = {}
stats['total projects'] = {'label': 'Total pro files found', stats["total projects"] = {"label": "Total pro files found", "value": total_pros}
'value': total_pros} stats["existing projects"] = {
stats['existing projects'] = {'label': 'Existing CMakeLists.txt files found', "label": "Existing CMakeLists.txt files found",
'value': existing_pros} "value": existing_pros,
stats['missing projects'] = {'label': 'Missing CMakeLists.txt files found', }
'value': missing_pros} stats["missing projects"] = {
stats['missing examples'] = {'label': 'Missing examples', 'value': 0} "label": "Missing CMakeLists.txt files found",
stats['missing tests'] = {'label': 'Missing tests', 'value': 0} "value": missing_pros,
stats['missing src'] = {'label': 'Missing src/**/**', 'value': 0} }
stats['missing plugins'] = {'label': 'Missing plugins', 'value': 0} stats["missing examples"] = {"label": "Missing examples", "value": 0}
stats["missing tests"] = {"label": "Missing tests", "value": 0}
stats["missing src"] = {"label": "Missing src/**/**", "value": 0}
stats["missing plugins"] = {"label": "Missing plugins", "value": 0}
for p in pros_with_missing_project: for p in pros_with_missing_project:
rel_path = os.path.relpath(p, src_path) rel_path = os.path.relpath(p, src_path)
if rel_path.startswith("examples"): if rel_path.startswith("examples"):
stats['missing examples']['value'] += 1 stats["missing examples"]["value"] += 1
elif rel_path.startswith("tests"): elif rel_path.startswith("tests"):
stats['missing tests']['value'] += 1 stats["missing tests"]["value"] += 1
elif rel_path.startswith(os.path.join("src", "plugins")): elif rel_path.startswith(os.path.join("src", "plugins")):
stats['missing plugins']['value'] += 1 stats["missing plugins"]["value"] += 1
elif rel_path.startswith("src"): elif rel_path.startswith("src"):
stats['missing src']['value'] += 1 stats["missing src"]["value"] += 1
for stat in stats: for stat in stats:
if stats[stat]['value'] > 0: if stats[stat]["value"] > 0:
stats[stat]['percentage'] = round(stats[stat]['value'] * 100 / total_pros, 2) stats[stat]["percentage"] = round(stats[stat]["value"] * 100 / total_pros, 2)
return stats return stats
def print_stats(src_path: str, pros_with_missing_project: typing.List[str], stats: dict, def print_stats(
scan_time: float, script_time: float): src_path: str,
pros_with_missing_project: typing.List[str],
stats: dict,
scan_time: float,
script_time: float,
):
if stats['total projects']['value'] == 0: if stats["total projects"]["value"] == 0:
print("No .pro files found. Did you specify a correct source path?") print("No .pro files found. Did you specify a correct source path?")
return return
if stats['total projects']['value'] == stats['existing projects']['value']: if stats["total projects"]["value"] == stats["existing projects"]["value"]:
print("All projects were converted.") print("All projects were converted.")
else: else:
print("Missing CMakeLists.txt files for the following projects: \n") print("Missing CMakeLists.txt files for the following projects: \n")
@ -167,10 +182,12 @@ def print_stats(src_path: str, pros_with_missing_project: typing.List[str], stat
print("\nStatistics: \n") print("\nStatistics: \n")
for stat in stats: for stat in stats:
if stats[stat]['value'] > 0: if stats[stat]["value"] > 0:
print("{:<40}: {} ({}%)".format(stats[stat]['label'], print(
stats[stat]['value'], "{:<40}: {} ({}%)".format(
stats[stat]['percentage'])) stats[stat]["label"], stats[stat]["value"], stats[stat]["percentage"]
)
)
print("\n{:<40}: {:.10f} seconds".format("Scan time", scan_time)) print("\n{:<40}: {:.10f} seconds".format("Scan time", scan_time))
print("{:<40}: {:.10f} seconds".format("Total script time", script_time)) print("{:<40}: {:.10f} seconds".format("Total script time", script_time))
@ -184,9 +201,7 @@ def main():
extension = ".pro" extension = ".pro"
blacklist_names = ["config.tests", "doc", "3rdparty", "angle"] blacklist_names = ["config.tests", "doc", "3rdparty", "angle"]
blacklist_path_parts = [ blacklist_path_parts = [os.path.join("util", "cmake")]
os.path.join("util", "cmake")
]
script_start_time = default_timer() script_start_time = default_timer()
blacklist = Blacklist(blacklist_names, blacklist_path_parts) blacklist = Blacklist(blacklist_names, blacklist_path_parts)
@ -206,13 +221,14 @@ def main():
missing_pros = len(pros_with_missing_project) missing_pros = len(pros_with_missing_project)
existing_pros = total_pros - missing_pros existing_pros = total_pros - missing_pros
stats = compute_stats(src_path, pros_with_missing_project, total_pros, existing_pros, stats = compute_stats(
missing_pros) src_path, pros_with_missing_project, total_pros, existing_pros, missing_pros
)
script_end_time = default_timer() script_end_time = default_timer()
script_time = script_end_time - script_start_time script_time = script_end_time - script_start_time
print_stats(src_path, pros_with_missing_project, stats, scan_time, script_time) print_stats(src_path, pros_with_missing_project, stats, scan_time, script_time)
if __name__ == '__main__': if __name__ == "__main__":
main() main()

View File

@ -0,0 +1,4 @@
pytest; python_version >= '3.7'
mypy; python_version >= '3.7'
pyparsing; python_version >= '3.7'
sympy; python_version >= '3.7'

View File

@ -38,56 +38,70 @@ from argparse import ArgumentParser
def parse_command_line(): def parse_command_line():
parser = ArgumentParser(description='Run pro2cmake on all .pro files recursively in given path.') parser = ArgumentParser(
parser.add_argument('--only-existing', dest='only_existing', action='store_true', description="Run pro2cmake on all .pro files recursively in given path."
help='Run pro2cmake only on .pro files that already have a CMakeLists.txt.') )
parser.add_argument('--only-qtbase-main-modules', dest='only_qtbase_main_modules', action='store_true', parser.add_argument(
help='Run pro2cmake only on the main modules in qtbase.') "--only-existing",
parser.add_argument('--is-example', dest='is_example', action='store_true', dest="only_existing",
help='Run pro2cmake with --is-example flag.') action="store_true",
parser.add_argument('path', metavar='<path>', type=str, help="Run pro2cmake only on .pro files that already have a CMakeLists.txt.",
help='The path where to look for .pro files.') )
parser.add_argument(
"--only-qtbase-main-modules",
dest="only_qtbase_main_modules",
action="store_true",
help="Run pro2cmake only on the main modules in qtbase.",
)
parser.add_argument(
"--is-example",
dest="is_example",
action="store_true",
help="Run pro2cmake with --is-example flag.",
)
parser.add_argument(
"path", metavar="<path>", type=str, help="The path where to look for .pro files."
)
return parser.parse_args() return parser.parse_args()
def find_all_pro_files(base_path: str, args: argparse.Namespace): def find_all_pro_files(base_path: str, args: argparse.Namespace):
def sorter(pro_file: str) -> str: def sorter(pro_file: str) -> str:
""" Sorter that tries to prioritize main pro files in a directory. """ """ Sorter that tries to prioritize main pro files in a directory. """
pro_file_without_suffix = pro_file.rsplit('/', 1)[-1][:-4] pro_file_without_suffix = pro_file.rsplit("/", 1)[-1][:-4]
dir_name = os.path.dirname(pro_file) dir_name = os.path.dirname(pro_file)
if dir_name.endswith('/' + pro_file_without_suffix): if dir_name.endswith("/" + pro_file_without_suffix):
return dir_name return dir_name
return dir_name + "/__" + pro_file return dir_name + "/__" + pro_file
all_files = [] all_files = []
previous_dir_name: str = None previous_dir_name: str = None
print('Finding .pro files.') print("Finding .pro files.")
glob_result = glob.glob(os.path.join(base_path, '**/*.pro'), recursive=True) glob_result = glob.glob(os.path.join(base_path, "**/*.pro"), recursive=True)
def cmake_lists_exists_filter(path): def cmake_lists_exists_filter(path):
path_dir_name = os.path.dirname(path) path_dir_name = os.path.dirname(path)
if os.path.exists(os.path.join(path_dir_name, 'CMakeLists.txt')): if os.path.exists(os.path.join(path_dir_name, "CMakeLists.txt")):
return True return True
return False return False
def qtbase_main_modules_filter(path): def qtbase_main_modules_filter(path):
main_modules = [ main_modules = [
'corelib', "corelib",
'network', "network",
'gui', "gui",
'widgets', "widgets",
'testlib', "testlib",
'printsupport', "printsupport",
'opengl', "opengl",
'sql', "sql",
'dbus', "dbus",
'concurrent', "concurrent",
'xml', "xml",
] ]
path_suffixes = ['src/{}/{}.pro'.format(m, m, '.pro') for m in main_modules] path_suffixes = ["src/{m}/{m}.pro" for m in main_modules]
for path_suffix in path_suffixes: for path_suffix in path_suffixes:
if path.endswith(path_suffix): if path.endswith(path_suffix):
@ -102,7 +116,7 @@ def find_all_pro_files(base_path: str, args: argparse.Namespace):
filter_func = qtbase_main_modules_filter filter_func = qtbase_main_modules_filter
if filter_func: if filter_func:
print('Filtering.') print("Filtering.")
filter_result = [p for p in filter_result if filter_func(p)] filter_result = [p for p in filter_result if filter_func(p)]
for pro_file in sorted(filter_result, key=sorter): for pro_file in sorted(filter_result, key=sorter):
@ -118,14 +132,14 @@ def find_all_pro_files(base_path: str, args: argparse.Namespace):
def run(all_files: typing.List[str], pro2cmake: str, args: argparse.Namespace) -> typing.List[str]: def run(all_files: typing.List[str], pro2cmake: str, args: argparse.Namespace) -> typing.List[str]:
failed_files = [] failed_files = []
files_count = len(all_files) files_count = len(all_files)
workers = (os.cpu_count() or 1) workers = os.cpu_count() or 1
if args.only_qtbase_main_modules: if args.only_qtbase_main_modules:
# qtbase main modules take longer than usual to process. # qtbase main modules take longer than usual to process.
workers = 2 workers = 2
with concurrent.futures.ThreadPoolExecutor(max_workers=workers, initargs=(10,)) as pool: with concurrent.futures.ThreadPoolExecutor(max_workers=workers, initargs=(10,)) as pool:
print('Firing up thread pool executor.') print("Firing up thread pool executor.")
def _process_a_file(data: typing.Tuple[str, int, int]) -> typing.Tuple[int, str, str]: def _process_a_file(data: typing.Tuple[str, int, int]) -> typing.Tuple[int, str, str]:
filename, index, total = data filename, index, total = data
@ -134,18 +148,21 @@ def run(all_files: typing.List[str], pro2cmake: str, args: argparse.Namespace) -
pro2cmake_args.append(sys.executable) pro2cmake_args.append(sys.executable)
pro2cmake_args.append(pro2cmake) pro2cmake_args.append(pro2cmake)
if args.is_example: if args.is_example:
pro2cmake_args.append('--is-example') pro2cmake_args.append("--is-example")
pro2cmake_args.append(os.path.basename(filename)) pro2cmake_args.append(os.path.basename(filename))
result = subprocess.run(pro2cmake_args, result = subprocess.run(
cwd=os.path.dirname(filename), pro2cmake_args,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT) cwd=os.path.dirname(filename),
stdout = 'Converted[{}/{}]: {}\n'.format(index, total, filename) stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
stdout = f"Converted[{index}/{total}]: {filename}\n"
return result.returncode, filename, stdout + result.stdout.decode() return result.returncode, filename, stdout + result.stdout.decode()
for return_code, filename, stdout in pool.map(_process_a_file, for return_code, filename, stdout in pool.map(
zip(all_files, _process_a_file,
range(1, files_count + 1), zip(all_files, range(1, files_count + 1), (files_count for _ in all_files)),
(files_count for _ in all_files))): ):
if return_code: if return_code:
failed_files.append(filename) failed_files.append(filename)
print(stdout) print(stdout)
@ -157,21 +174,23 @@ def main() -> None:
args = parse_command_line() args = parse_command_line()
script_path = os.path.dirname(os.path.abspath(__file__)) script_path = os.path.dirname(os.path.abspath(__file__))
pro2cmake = os.path.join(script_path, 'pro2cmake.py') pro2cmake = os.path.join(script_path, "pro2cmake.py")
base_path = args.path base_path = args.path
all_files = find_all_pro_files(base_path, args) all_files = find_all_pro_files(base_path, args)
files_count = len(all_files) files_count = len(all_files)
failed_files = run(all_files, pro2cmake, args) failed_files = run(all_files, pro2cmake, args)
if len(all_files) == 0: if len(all_files) == 0:
print('No files found.') print("No files found.")
if failed_files: if failed_files:
print('The following files were not successfully ' print(
'converted ({} of {}):'.format(len(failed_files), files_count)) f"The following files were not successfully "
f"converted ({len(failed_files)} of {files_count}):"
)
for f in failed_files: for f in failed_files:
print(' "{}"'.format(f)) print(f' "{f}"')
if __name__ == '__main__': if __name__ == "__main__":
main() main()

View File

@ -93,31 +93,34 @@ import stat
from shutil import copyfile from shutil import copyfile
from shutil import rmtree from shutil import rmtree
from textwrap import dedent
def remove_special_cases(original: str) -> str: def remove_special_cases(original: str) -> str:
# Remove content between the following markers # Remove content between the following markers
# '# special case begin' and '# special case end'. # '# special case begin' and '# special case end'.
# This also remove the markers. # This also remove the markers.
replaced = re.sub(r'\n[^#\n]*?#[^\n]*?special case begin.*?#[^\n]*special case end[^\n]*?\n', replaced = re.sub(
'\n', r"\n[^#\n]*?#[^\n]*?special case begin.*?#[^\n]*special case end[^\n]*?\n",
original, "\n",
0, original,
re.DOTALL) 0,
re.DOTALL,
)
# Remove individual lines that have the "# special case" marker. # Remove individual lines that have the "# special case" marker.
replaced = re.sub(r'\n.*#.*special case[^\n]*\n', '\n', replaced) replaced = re.sub(r"\n.*#.*special case[^\n]*\n", "\n", replaced)
return replaced return replaced
def read_content_from_file(file_path: str) -> str: def read_content_from_file(file_path: str) -> str:
with open(file_path, 'r') as file_fd: with open(file_path, "r") as file_fd:
content = file_fd.read() content = file_fd.read()
return content return content
def write_content_to_file(file_path: str, content: str) -> None: def write_content_to_file(file_path: str, content: str) -> None:
with open(file_path, 'w') as file_fd: with open(file_path, "w") as file_fd:
file_fd.write(content) file_fd.write(content)
@ -126,23 +129,23 @@ def resolve_simple_git_conflicts(file_path: str, debug=False) -> None:
# If the conflict represents the addition of a new content hunk, # If the conflict represents the addition of a new content hunk,
# keep the content and remove the conflict markers. # keep the content and remove the conflict markers.
if debug: if debug:
print('Resolving simple conflicts automatically.') print("Resolving simple conflicts automatically.")
replaced = re.sub(r'\n<<<<<<< HEAD\n=======(.+?)>>>>>>> master\n', r'\1', content, 0, re.DOTALL) replaced = re.sub(r"\n<<<<<<< HEAD\n=======(.+?)>>>>>>> master\n", r"\1", content, 0, re.DOTALL)
write_content_to_file(file_path, replaced) write_content_to_file(file_path, replaced)
def copyfile_log(src: str, dst: str, debug=False): def copyfile_log(src: str, dst: str, debug=False):
if debug: if debug:
print('Copying {} to {}.'.format(src, dst)) print(f"Copying {src} to {dst}.")
copyfile(src, dst) copyfile(src, dst)
def check_if_git_in_path() -> bool: def check_if_git_in_path() -> bool:
is_win = os.name == 'nt' is_win = os.name == "nt"
for path in os.environ['PATH'].split(os.pathsep): for path in os.environ["PATH"].split(os.pathsep):
git_path = os.path.join(path, 'git') git_path = os.path.join(path, "git")
if is_win: if is_win:
git_path += '.exe' git_path += ".exe"
if os.path.isfile(git_path) and os.access(git_path, os.X_OK): if os.path.isfile(git_path) and os.access(git_path, os.X_OK):
return True return True
return False return False
@ -150,31 +153,38 @@ def check_if_git_in_path() -> bool:
def run_process_quiet(args_string: str, debug=False) -> bool: def run_process_quiet(args_string: str, debug=False) -> bool:
if debug: if debug:
print('Running command: "{}\"'.format(args_string)) print(f'Running command: "{args_string}"')
args_list = args_string.split() args_list = args_string.split()
try: try:
subprocess.run(args_list, check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) subprocess.run(args_list, check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
# git merge with conflicts returns with exit code 1, but that's not # git merge with conflicts returns with exit code 1, but that's not
# an error for us. # an error for us.
if 'git merge' not in args_string: if "git merge" not in args_string:
print('Error while running: "{}"\n{}'.format(args_string, e.stdout)) print(
dedent(
f"""\
Error while running: "{args_string}"
{e.stdout}"""
)
)
return False return False
return True return True
def does_file_have_conflict_markers(file_path: str, debug=False) -> bool: def does_file_have_conflict_markers(file_path: str, debug=False) -> bool:
if debug: if debug:
print('Checking if {} has no leftover conflict markers.'.format(file_path)) print(f"Checking if {file_path} has no leftover conflict markers.")
content_actual = read_content_from_file(file_path) content_actual = read_content_from_file(file_path)
if '<<<<<<< HEAD' in content_actual: if "<<<<<<< HEAD" in content_actual:
print('Conflict markers found in {}. ' print(f"Conflict markers found in {file_path}. " "Please remove or solve them first.")
'Please remove or solve them first.'.format(file_path))
return True return True
return False return False
def create_file_with_no_special_cases(original_file_path: str, no_special_cases_file_path: str, debug=False): def create_file_with_no_special_cases(
original_file_path: str, no_special_cases_file_path: str, debug=False
):
""" """
Reads content of original CMakeLists.txt, removes all content Reads content of original CMakeLists.txt, removes all content
between "# special case" markers or lines, saves the result into a between "# special case" markers or lines, saves the result into a
@ -182,35 +192,36 @@ def create_file_with_no_special_cases(original_file_path: str, no_special_cases_
""" """
content_actual = read_content_from_file(original_file_path) content_actual = read_content_from_file(original_file_path)
if debug: if debug:
print('Removing special case blocks from {}.'.format(original_file_path)) print(f"Removing special case blocks from {original_file_path}.")
content_no_special_cases = remove_special_cases(content_actual) content_no_special_cases = remove_special_cases(content_actual)
if debug: if debug:
print('Saving original contents of {} ' print(
'with removed special case blocks to {}'.format(original_file_path, f"Saving original contents of {original_file_path} "
no_special_cases_file_path)) f"with removed special case blocks to {no_special_cases_file_path}"
)
write_content_to_file(no_special_cases_file_path, content_no_special_cases) write_content_to_file(no_special_cases_file_path, content_no_special_cases)
def rm_tree_on_error_handler(func: typing.Callable[..., None], def rm_tree_on_error_handler(func: typing.Callable[..., None], path: str, exception_info: tuple):
path: str, exception_info: tuple):
# If the path is read only, try to make it writable, and try # If the path is read only, try to make it writable, and try
# to remove the path again. # to remove the path again.
if not os.access(path, os.W_OK): if not os.access(path, os.W_OK):
os.chmod(path, stat.S_IWRITE) os.chmod(path, stat.S_IWRITE)
func(path) func(path)
else: else:
print('Error while trying to remove path: {}. Exception: {}'.format(path, exception_info)) print(f"Error while trying to remove path: {path}. Exception: {exception_info}")
class SpecialCaseHandler(object): class SpecialCaseHandler(object):
def __init__(
def __init__(self, self,
original_file_path: str, original_file_path: str,
generated_file_path: str, generated_file_path: str,
base_dir: str, base_dir: str,
keep_temporary_files=False, keep_temporary_files=False,
debug=False) -> None: debug=False,
) -> None:
self.base_dir = base_dir self.base_dir = base_dir
self.original_file_path = original_file_path self.original_file_path = original_file_path
self.generated_file_path = generated_file_path self.generated_file_path = generated_file_path
@ -220,29 +231,28 @@ class SpecialCaseHandler(object):
@property @property
def prev_file_path(self) -> str: def prev_file_path(self) -> str:
return os.path.join(self.base_dir, '.prev_CMakeLists.txt') return os.path.join(self.base_dir, ".prev_CMakeLists.txt")
@property @property
def post_merge_file_path(self) -> str: def post_merge_file_path(self) -> str:
return os.path.join(self.base_dir, 'CMakeLists-post-merge.txt') return os.path.join(self.base_dir, "CMakeLists-post-merge.txt")
@property @property
def no_special_file_path(self) -> str: def no_special_file_path(self) -> str:
return os.path.join(self.base_dir, 'CMakeLists.no-special.txt') return os.path.join(self.base_dir, "CMakeLists.no-special.txt")
def apply_git_merge_magic(self, no_special_cases_file_path: str) -> None: def apply_git_merge_magic(self, no_special_cases_file_path: str) -> None:
# Create new folder for temporary repo, and ch dir into it. # Create new folder for temporary repo, and ch dir into it.
repo = os.path.join(self.base_dir, 'tmp_repo') repo = os.path.join(self.base_dir, "tmp_repo")
repo_absolute_path = os.path.abspath(repo) repo_absolute_path = os.path.abspath(repo)
txt = 'CMakeLists.txt' txt = "CMakeLists.txt"
try: try:
os.mkdir(repo) os.mkdir(repo)
current_dir = os.getcwd() current_dir = os.getcwd()
os.chdir(repo) os.chdir(repo)
except Exception as e: except Exception as e:
print('Failed to create temporary directory for temporary git repo. Exception: {}' print(f"Failed to create temporary directory for temporary git repo. Exception: {e}")
.format(e))
raise e raise e
generated_file_path = os.path.join("..", self.generated_file_path) generated_file_path = os.path.join("..", self.generated_file_path)
@ -252,34 +262,34 @@ class SpecialCaseHandler(object):
try: try:
# Create new repo with the "clean" CMakeLists.txt file. # Create new repo with the "clean" CMakeLists.txt file.
run_process_quiet('git init .', debug=self.debug) run_process_quiet("git init .", debug=self.debug)
run_process_quiet('git config user.name fake', debug=self.debug) run_process_quiet("git config user.name fake", debug=self.debug)
run_process_quiet('git config user.email fake@fake', debug=self.debug) run_process_quiet("git config user.email fake@fake", debug=self.debug)
copyfile_log(no_special_cases_file_path, txt, debug=self.debug) copyfile_log(no_special_cases_file_path, txt, debug=self.debug)
run_process_quiet('git add {}'.format(txt), debug=self.debug) run_process_quiet(f"git add {txt}", debug=self.debug)
run_process_quiet('git commit -m no_special', debug=self.debug) run_process_quiet("git commit -m no_special", debug=self.debug)
run_process_quiet('git checkout -b no_special', debug=self.debug) run_process_quiet("git checkout -b no_special", debug=self.debug)
# Copy the original "modified" file (with the special cases) # Copy the original "modified" file (with the special cases)
# and make a new commit. # and make a new commit.
run_process_quiet('git checkout -b original', debug=self.debug) run_process_quiet("git checkout -b original", debug=self.debug)
copyfile_log(original_file_path, txt, debug=self.debug) copyfile_log(original_file_path, txt, debug=self.debug)
run_process_quiet('git add {}'.format(txt), debug=self.debug) run_process_quiet(f"git add {txt}", debug=self.debug)
run_process_quiet('git commit -m original', debug=self.debug) run_process_quiet("git commit -m original", debug=self.debug)
# Checkout the commit with "clean" file again, and create a # Checkout the commit with "clean" file again, and create a
# new branch. # new branch.
run_process_quiet('git checkout no_special', debug=self.debug) run_process_quiet("git checkout no_special", debug=self.debug)
run_process_quiet('git checkout -b newly_generated', debug=self.debug) run_process_quiet("git checkout -b newly_generated", debug=self.debug)
# Copy the new "modified" file and make a commit. # Copy the new "modified" file and make a commit.
copyfile_log(generated_file_path, txt, debug=self.debug) copyfile_log(generated_file_path, txt, debug=self.debug)
run_process_quiet('git add {}'.format(txt), debug=self.debug) run_process_quiet(f"git add {txt}", debug=self.debug)
run_process_quiet('git commit -m newly_generated', debug=self.debug) run_process_quiet("git commit -m newly_generated", debug=self.debug)
# Merge the "old" branch with modifications into the "new" # Merge the "old" branch with modifications into the "new"
# branch with the newly generated file. # branch with the newly generated file.
run_process_quiet('git merge original', debug=self.debug) run_process_quiet("git merge original", debug=self.debug)
# Resolve some simple conflicts (just remove the markers) # Resolve some simple conflicts (just remove the markers)
# for cases that don't need intervention. # for cases that don't need intervention.
@ -288,7 +298,7 @@ class SpecialCaseHandler(object):
# Copy the resulting file from the merge. # Copy the resulting file from the merge.
copyfile_log(txt, post_merge_file_path) copyfile_log(txt, post_merge_file_path)
except Exception as e: except Exception as e:
print('Git merge conflict resolution process failed. Exception: {}'.format(e)) print(f"Git merge conflict resolution process failed. Exception: {e}")
raise e raise e
finally: finally:
os.chdir(current_dir) os.chdir(current_dir)
@ -298,7 +308,7 @@ class SpecialCaseHandler(object):
if not self.keep_temporary_files: if not self.keep_temporary_files:
rmtree(repo_absolute_path, onerror=rm_tree_on_error_handler) rmtree(repo_absolute_path, onerror=rm_tree_on_error_handler)
except Exception as e: except Exception as e:
print('Error removing temporary repo. Exception: {}'.format(e)) print(f"Error removing temporary repo. Exception: {e}")
def save_next_clean_file(self): def save_next_clean_file(self):
files_are_equivalent = filecmp.cmp(self.generated_file_path, self.post_merge_file_path) files_are_equivalent = filecmp.cmp(self.generated_file_path, self.post_merge_file_path)
@ -316,20 +326,18 @@ class SpecialCaseHandler(object):
failed_once = False failed_once = False
i = 0 i = 0
while not success and i < 20: while not success and i < 20:
success = run_process_quiet("git add {}".format(self.prev_file_path), success = run_process_quiet(f"git add {self.prev_file_path}", debug=self.debug)
debug=self.debug)
if not success: if not success:
failed_once = True failed_once = True
i += 1 i += 1
time.sleep(0.1) time.sleep(0.1)
if failed_once and not success: if failed_once and not success:
print('Retrying git add, the index.lock was probably acquired.') print("Retrying git add, the index.lock was probably acquired.")
if failed_once and success: if failed_once and success:
print('git add succeeded.') print("git add succeeded.")
elif failed_once and not success: elif failed_once and not success:
print('git add failed. Make sure to git add {} yourself.'.format( print(f"git add failed. Make sure to git add {self.prev_file_path} yourself.")
self.prev_file_path))
def handle_special_cases_helper(self) -> bool: def handle_special_cases_helper(self) -> bool:
""" """
@ -348,15 +356,18 @@ class SpecialCaseHandler(object):
return False return False
if self.use_heuristic: if self.use_heuristic:
create_file_with_no_special_cases(self.original_file_path, create_file_with_no_special_cases(
self.no_special_file_path) self.original_file_path, self.no_special_file_path
)
no_special_cases_file_path = self.no_special_file_path no_special_cases_file_path = self.no_special_file_path
else: else:
no_special_cases_file_path = self.prev_file_path no_special_cases_file_path = self.prev_file_path
if self.debug: if self.debug:
print('Using git to reapply special case modifications to newly generated {} ' print(
'file'.format(self.generated_file_path)) f"Using git to reapply special case modifications to newly "
f"generated {self.generated_file_path} file"
)
self.apply_git_merge_magic(no_special_cases_file_path) self.apply_git_merge_magic(no_special_cases_file_path)
self.save_next_clean_file() self.save_next_clean_file()
@ -365,11 +376,13 @@ class SpecialCaseHandler(object):
if not self.keep_temporary_files: if not self.keep_temporary_files:
os.remove(self.post_merge_file_path) os.remove(self.post_merge_file_path)
print('Special case reapplication using git is complete. ' print(
'Make sure to fix remaining conflict markers.') "Special case reapplication using git is complete. "
"Make sure to fix remaining conflict markers."
)
except Exception as e: except Exception as e:
print('Error occurred while trying to reapply special case modifications: {}'.format(e)) print(f"Error occurred while trying to reapply special case modifications: {e}")
return False return False
finally: finally:
if not self.keep_temporary_files and self.use_heuristic: if not self.keep_temporary_files and self.use_heuristic:
@ -386,8 +399,10 @@ class SpecialCaseHandler(object):
keep_special_cases = original_file_exists and git_available keep_special_cases = original_file_exists and git_available
if not git_available: if not git_available:
print('You need to have git in PATH in order to reapply the special ' print(
'case modifications.') "You need to have git in PATH in order to reapply the special "
"case modifications."
)
copy_generated_file = True copy_generated_file = True