1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
|
#!/usr/bin/env python3
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
from qmake2cmake.pro2cmake import Scope, SetOperation, merge_scopes, recursive_evaluate_scope
from qmake2cmake.pro2cmake import main as convert_qmake_to_cmake
from tempfile import TemporaryDirectory
import filecmp
import functools
import os
import pathlib
import pytest
import re
import shutil
import sys
import tempfile
from typing import Callable, Optional
debug_mode = bool(os.environ.get("DEBUG_QMAKE2CMAKE_TEST_CONVERSION"))
test_script_dir = pathlib.Path(__file__).parent.resolve()
test_data_dir = test_script_dir.joinpath("data", "conversion")
default_min_qt_version = "6.2.0"
def compare_expected_output_directories(actual: str, expected: str):
dc = filecmp.dircmp(actual, expected)
assert(dc.diff_files == [])
def convert(base_name: str,
*,
min_qt_version: str = default_min_qt_version,
after_conversion_hook: Optional[Callable[[str], None]] = None):
'''Converts {base_name}.pro to CMake in a temporary directory.
The optional after_conversion_hook is a function that takes the temporary directory as
parameter. It is called after the conversion took place.
'''
pro_file_name = str(base_name) + ".pro"
pro_file_path = test_data_dir.joinpath(pro_file_name)
assert(pro_file_path.exists())
with TemporaryDirectory(prefix="testqmake2cmake") as tmp_dir_str:
tmp_dir = pathlib.Path(tmp_dir_str)
output_file_path = tmp_dir.joinpath("CMakeLists.txt")
convert_qmake_to_cmake(["-o", str(output_file_path), str(pro_file_path),
"--min-qt-version", min_qt_version])
if debug_mode:
output_dir = tempfile.gettempdir() + "/qmake2cmake/" + base_name
if min_qt_version != default_min_qt_version:
output_dir += "-"
output_dir += min_qt_version
if not os.path.isdir(output_dir):
os.mkdir(output_dir)
shutil.copyfile(output_file_path, output_dir + "/CMakeLists.txt")
with open(output_file_path, "r") as f:
assert(f)
content = f.read()
assert(content)
if after_conversion_hook is not None:
after_conversion_hook(tmp_dir)
return content
def convert_and_compare_expected_output(pro_base_name: str, rel_expected_output_dir: str):
abs_expected_output_dir = test_data_dir.joinpath(rel_expected_output_dir)
convert(pro_base_name,
after_conversion_hook=functools.partial(compare_expected_output_directories,
expected=abs_expected_output_dir))
def test_qt_modules():
'''Test the conversion of QT assignments to find_package calls.'''
output = convert("required_qt_modules")
find_package_lines = []
for line in output.split("\n"):
if "find_package(" in line:
find_package_lines.append(line.strip())
assert(["find_package(Qt6 REQUIRED COMPONENTS Network Widgets)"] == find_package_lines)
output = convert("optional_qt_modules")
find_package_lines = []
for line in output.split("\n"):
if "find_package(" in line:
find_package_lines.append(line.strip())
assert(["find_package(Qt6 REQUIRED COMPONENTS Network Widgets)",
"find_package(Qt6 OPTIONAL_COMPONENTS OpenGL)"] == find_package_lines)
def test_qt_version_check():
'''Test the conversion of QT_VERSION checks.'''
output = convert("qt_version_check")
interesting_lines = []
for line in output.split("\n"):
if line.startswith("if(") and "QT_VERSION" in line:
interesting_lines.append(line.strip())
assert(["if(( ( (QT_VERSION_MAJOR GREATER 5) ) AND (QT_VERSION_MINOR LESS 1) ) AND (QT_VERSION_PATCH EQUAL 0))", "if(( ( (QT_VERSION VERSION_GREATER 6.6.5) ) AND (QT_VERSION VERSION_LESS 6.6.7) ) AND (QT_VERSION VERSION_EQUAL 6.6.6))"] == interesting_lines)
def test_subdirs():
'''Test conversion of a TEMPLATE=subdirs project.'''
convert_and_compare_expected_output("subdirs/subdirs", "subdirs/expected")
def test_common_project_types():
output = convert("app")
assert(r"""
qt_add_executable(app WIN32 MACOSX_BUNDLE
main.cpp
)""" in output)
output = convert("app_cmdline")
assert(r"""
qt_add_executable(myapp
main.cpp
)""" in output)
output = convert("app_console")
assert(r"""
qt_add_executable(myapp MACOSX_BUNDLE
main.cpp
)""" in output)
output = convert("app_nonbundle")
assert(r"""
qt_add_executable(myapp WIN32
main.cpp
)""" in output)
output = convert("lib_shared")
assert(r"""
qt_add_library(lib_shared
lib.cpp
)""" in output)
output = convert("lib_static")
assert(r"""
qt_add_library(lib_static STATIC
lib.cpp
)""" in output)
output = convert("plugin_shared")
assert(r"""
qt_add_plugin(plugin_shared)
target_sources(plugin_shared PRIVATE
lib.cpp
)""" in output)
output = convert("plugin_static")
assert(r"""
qt_add_plugin(plugin_static STATIC)
target_sources(plugin_static PRIVATE
lib.cpp
)""" in output)
output = convert("plugin_shared", min_qt_version = "6.5.0")
assert(r"""
qt_add_plugin(plugin_shared
lib.cpp
)""" in output)
output = convert("plugin_static", min_qt_version = "6.5.0")
assert(r"""
qt_add_plugin(plugin_static STATIC
lib.cpp
)""" in output)
def test_qml_modules():
output = convert("app_qml_module")
assert(r"""
qt_add_executable(myapp WIN32 MACOSX_BUNDLE
donkeyengine.cpp donkeyengine.h
main.cpp
)
qt_add_qml_module(myapp
URI DonkeySimulator
VERSION 1.0
QML_FILES
donkey.qml
waggle_ears.js
RESOURCES
bray.ogg
hoofs.ogg
NO_RESOURCE_TARGET_PATH
)
""" in output)
output = convert("lib_qml_module")
assert(r"""
qt_add_library(lib_qml_module
donkeyengine.cpp donkeyengine.h
)
qt_add_qml_module(lib_qml_module
URI DonkeySimulator
VERSION 1.0
QML_FILES
donkey.qml
waggle_ears.js
RESOURCES
bray.ogg
hoofs.ogg
)""" in output)
output = convert("plugin_qml_module")
assert(r"""
qt_add_qml_module(plugin_qml_module
URI DonkeySimulator
VERSION 1.0
QML_FILES
donkey.qml
waggle_ears.js
RESOURCES
bray.ogg
hoofs.ogg
PLUGIN_TARGET plugin_qml_module
)
target_sources(plugin_qml_module PRIVATE
donkeyengine.cpp donkeyengine.h
)""" in output)
def test_install_commands():
output = convert("app_install")
assert(r"""
install(TARGETS app_install
BUNDLE DESTINATION .
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)""" in output)
output = convert("lib_install")
assert(r"""
install(TARGETS lib_install
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)""" in output)
def test_deploy_commands():
output = convert("app", min_qt_version="6.2")
assert(r"""
# Consider using qt_generate_deploy_app_script() for app deployment if
# the project can use Qt 6.3. In that case rerun qmake2cmake with
# --min-qt-version=6.3.
""" in output)
output = convert("app", min_qt_version="6.3")
assert(r"""
qt_generate_deploy_app_script(
TARGET app
FILENAME_VARIABLE deploy_script
NO_UNSUPPORTED_PLATFORM_ERROR
)
install(SCRIPT ${deploy_script})
""" in output)
output = convert("app_qml_module", min_qt_version="6.2")
assert(r"""
# Consider using qt_generate_deploy_app_script() for app deployment if
# the project can use Qt 6.3. In that case rerun qmake2cmake with
# --min-qt-version=6.3.
""" in output)
output = convert("app_qml_module", min_qt_version="6.3")
assert(r"""
qt_generate_deploy_qml_app_script(
TARGET myapp
FILENAME_VARIABLE deploy_script
NO_UNSUPPORTED_PLATFORM_ERROR
DEPLOY_USER_QML_MODULES_ON_UNSUPPORTED_PLATFORM
MACOS_BUNDLE_POST_BUILD
)
install(SCRIPT ${deploy_script})
""" in output)
|