qt 6.5.1 original

This commit is contained in:
kleuter
2023-10-29 23:33:08 +01:00
parent 71d22ab6b0
commit 85d238dfda
21202 changed files with 5499099 additions and 0 deletions

View File

View File

@ -0,0 +1,6 @@
# QtCore can't be compiled with -Wl,-no-undefined because it uses the "environ"
# variable and on FreeBSD and OpenBSD, this variable is in the final executable itself.
# OpenBSD 6.0 will include environ in libc.
freebsd|openbsd: QMAKE_LFLAGS_NOUNDEF =
include(animation/animation.pri)

View File

@ -0,0 +1,2 @@
qmake-clean.commands += (cd qmake && $(MAKE) clean ":-(==)-:" '(Foo)' )

View File

@ -0,0 +1,4 @@
!system("dbus-send --session --type=signal / local.AutotestCheck.Hello >$$QMAKE_SYSTEM_NULL_DEVICE 2>&1") {
SOURCES = dbus.cpp
}

View File

@ -0,0 +1,22 @@
linux:!static {
precompile_header {
# we'll get an error if we just use SOURCES +=
no_pch_assembler.commands = $$QMAKE_CC -c $(CFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
no_pch_assembler.dependency_type = TYPE_C
no_pch_assembler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
no_pch_assembler.input = NO_PCH_ASM
no_pch_assembler.name = compiling[no_pch] ${QMAKE_FILE_IN}
silent: no_pch_assembler.commands = @echo compiling[no_pch] ${QMAKE_FILE_IN} && $$no_pch_assembler.commands
CMAKE_ANGLE_GLES2_IMPLIB_RELEASE = libGLESv2.$${QMAKE_EXTENSION_STATICLIB}
HOST_BINS = $$[QT_HOST_BINS]
CMAKE_HOST_DATA_DIR = $$[QT_HOST_DATA/src]/
TR_EXCLUDE += ../3rdparty/*
QMAKE_EXTRA_COMPILERS += no_pch_assembler
NO_PCH_ASM += global/minimum-linux.S
} else {
SOURCES += global/minimum-linux.S
}
HEADERS += global/minimum-linux_p.h
}

View File

@ -0,0 +1,11 @@
a1|a2 {
DEFINES += d
}
b1|b2:b3 {
DEFINES += d
}
c1|c2:c3|c4 {
DEFINES += d
}

View File

@ -0,0 +1,2 @@
write_file("a", contents)|error()

View File

@ -0,0 +1,4 @@
contains(DEFINES,QT_EVAL):include(eval.pri)
HOST_BINS = $$[QT_HOST_BINS]

View File

@ -0,0 +1,4 @@
TARGET = myapp
QT = core network widgets
win32: QT += opengl
SOURCES = main.cpp

View File

@ -0,0 +1,8 @@
QT += core gui
SOURCES += main.cpp
greaterThan(QT_MAJOR_VERSION, 5):lessThan(QT_MINOR_VERSION, 1):equals(QT_PATCH_VERSION, 0) {
DEFINES += SUPER_FRESH_MAJOR_QT_RELEASE
}
greaterThan(QT_VERSION, 6.6.5):lessThan(QT_VERSION, 6.6.7):equals(QT_VERSION, 6.6.6): {
DEFINES += QT_VERSION_OF_THE_BEAST
}

View File

@ -0,0 +1,3 @@
TARGET = myapp
QT = core network widgets
SOURCES = main.cpp

View File

@ -0,0 +1,6 @@
defineTest(pathIsAbsolute) {
p = $$clean_path($$1)
!isEmpty(p):isEqual(p, $$absolute_path($$p)): return(true)
return(false)
}

View File

@ -0,0 +1,6 @@
linux {
SOURCES += a.cpp
} else {
SOURCES += b.cpp
}

View File

@ -0,0 +1,4 @@
osx: A = 1
else: win32: B = 2
else: C = 3

View File

@ -0,0 +1,7 @@
qtConfig(timezone) {
A = 1
} else:win32 {
B = 2
} else {
C = 3
}

View File

@ -0,0 +1,6 @@
qtConfig(timezone) {
A = 1
} else:win32: B = 2
else {
C = 3
}

View File

@ -0,0 +1,10 @@
# comments
qtConfig(timezone) { # bar
A = 1
} else:win32 {
B = 2 # foo
} else { C = 3
# baz
# foobar
}
# endcomment

View File

@ -0,0 +1,11 @@
qtConfig(timezone) \
{
A = \
1
} \
else:win32: \
B = 2
else: \
C \
= 3

View File

@ -0,0 +1,2 @@
msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x65000000

View File

@ -0,0 +1,5 @@
qtConfig(timezone) { A = 1 } else:win32: {\
B = 2 \
} else: \
C \
= 3 \

View File

@ -0,0 +1,2 @@
MODULE_AUX_INCLUDES = \
\$\$QT_MODULE_INCLUDE_BASE/QtANGLE

View File

@ -0,0 +1,11 @@
SOURCES = main.cpp
for (config, SIMD) {
uc = $$upper($$config)
DEFINES += QT_COMPILER_SUPPORTS_$${uc}
add_cflags {
cflags = QMAKE_CFLAGS_$${uc}
!defined($$cflags, var): error("This compiler does not support $${uc}")
QMAKE_CXXFLAGS += $$eval($$cflags)
}
}

View File

@ -0,0 +1,4 @@
pathIsAbsolute($$CMAKE_HOST_DATA_DIR) {
CMAKE_HOST_DATA_DIR = $$[QT_HOST_DATA/src]/
}

View File

@ -0,0 +1,3 @@
A = 42
include(foo) # load foo
B=23

View File

@ -0,0 +1,10 @@
TEMPLATE=subdirs
SUBDIRS=\
qmacstyle \
qstyle \
qstyleoption \
qstylesheetstyle \
!qtConfig(private_tests): SUBDIRS -= \
qstylesheetstyle \

View File

@ -0,0 +1,22 @@
SUBDIRS = \
# dds \
tga \
wbmp
MYVAR = foo # comment
MYVAR = foo2# comment
MYVAR = foo3# comment #
MYVAR = foo4# comment #
##
#
#
##
#
#
#
# #
MYVAR = foo5# comment # #

View File

@ -0,0 +1,3 @@
A = 42
load(foo)# load foo
B=23

View File

@ -0,0 +1,3 @@
equals(a): \
greaterThan(a):flags += 1

View File

@ -0,0 +1,4 @@
A = 42 \
43 \
44
B=23

View File

@ -0,0 +1,2 @@
requires(qtConfig(dlopen))

View File

@ -0,0 +1,5 @@
if(linux*|hurd*):!cross_compile:!static:!*-armcc* {
prog=$$quote(if (/program interpreter: (.*)]/) { print $1; })
DEFINES += ELF_INTERPRETER=\\\"$$system(LC_ALL=C readelf -l /bin/ls | perl -n -e \'$$prog\')\\\"
}

View File

@ -0,0 +1,4 @@
for(d, sd): \
exists($$d/$${d}.pro): \
SUBDIRS += $$d

View File

@ -0,0 +1,3 @@
TEMPLATE = subdirs
SUBDIRS = \
kernel \

View File

@ -0,0 +1,17 @@
win32 {
!winrt {
SOURCES +=io/qstandardpaths_win.cpp
} else {
SOURCES +=io/qstandardpaths_winrt.cpp
}
} else:unix {
mac {
OBJECTIVE_SOURCES += io/qstandardpaths_mac.mm
} else:android {
SOURCES += io/qstandardpaths_android.cpp
} else:haiku {
SOURCES += io/qstandardpaths_haiku.cpp
} else {
SOURCES += io/qstandardpaths_unix.cpp
}
}

View File

@ -0,0 +1,2 @@
unset(f16c_cxx)

View File

@ -0,0 +1,2 @@
TARGET = Dummy
TARGET = $$qtLibraryTarget($$TARGET)

View File

@ -0,0 +1,66 @@
#!/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 pro2cmake import Scope, SetOperation, merge_scopes, recursive_evaluate_scope
from tempfile import TemporaryDirectory
import os
import pathlib
import pytest
import re
import shutil
import subprocess
import tempfile
import typing
debug_mode = bool(os.environ.get("DEBUG_PRO2CMAKE_TEST_CONVERSION"))
test_script_dir = pathlib.Path(__file__).parent.resolve()
pro2cmake_dir = test_script_dir.parent.resolve()
pro2cmake_py = pro2cmake_dir.joinpath("pro2cmake.py")
test_data_dir = test_script_dir.joinpath("data", "conversion")
def convert(base_name: str):
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")
exit_code = subprocess.call([pro2cmake_py, "--is-example", "-o", output_file_path, pro_file_path])
assert(exit_code == 0)
if debug_mode:
shutil.copyfile(output_file_path, tempfile.gettempdir() + "/pro2cmake/CMakeLists.txt")
f = open(output_file_path, "r")
assert(f)
content = f.read()
assert(content)
return content
def test_qt_modules():
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(QT NAMES Qt5 Qt6 REQUIRED COMPONENTS Core)",
"find_package(Qt${QT_VERSION_MAJOR} 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(QT NAMES Qt5 Qt6 REQUIRED COMPONENTS Core)",
"find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Network Widgets)",
"find_package(Qt${QT_VERSION_MAJOR} OPTIONAL_COMPONENTS OpenGL)"] == find_package_lines)
def test_qt_version_check():
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)

View File

@ -0,0 +1,19 @@
#!/usr/bin/env python3
# Copyright (C) 2018 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
from qmake_parser import fixup_linecontinuation
def test_no_change():
input = "test \\\nline2\n line3"
output = "test line2\n line3"
result = fixup_linecontinuation(input)
assert output == result
def test_fix():
input = "test \\\t\nline2\\\n line3\\ \nline4 \\ \t\nline5\\\n\n\n"
output = "test line2 line3 line4 line5 \n\n"
result = fixup_linecontinuation(input)
assert output == result

View File

@ -0,0 +1,160 @@
#!/usr/bin/env python3
# Copyright (C) 2018 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
from condition_simplifier import simplify_condition
def validate_simplify(input: str, expected: str) -> None:
output = simplify_condition(input)
assert output == expected
def validate_simplify_unchanged(input: str) -> None:
validate_simplify(input, input)
def test_simplify_on():
validate_simplify_unchanged('ON')
def test_simplify_off():
validate_simplify_unchanged('OFF')
def test_simplify_not_on():
validate_simplify('NOT ON', 'OFF')
def test_simplify_not_off():
validate_simplify('NOT OFF', 'ON')
def test_simplify_isEmpty():
validate_simplify_unchanged('isEmpty(foo)')
def test_simplify_not_isEmpty():
validate_simplify_unchanged('NOT isEmpty(foo)')
def test_simplify_simple_and():
validate_simplify_unchanged('QT_FEATURE_bar AND QT_FEATURE_foo')
def test_simplify_simple_or():
validate_simplify_unchanged('QT_FEATURE_bar OR QT_FEATURE_foo')
def test_simplify_simple_not():
validate_simplify_unchanged('NOT QT_FEATURE_foo')
def test_simplify_simple_and_reorder():
validate_simplify('QT_FEATURE_foo AND QT_FEATURE_bar', 'QT_FEATURE_bar AND QT_FEATURE_foo')
def test_simplify_simple_or_reorder():
validate_simplify('QT_FEATURE_foo OR QT_FEATURE_bar', 'QT_FEATURE_bar OR QT_FEATURE_foo')
def test_simplify_unix_or_win32():
validate_simplify('WIN32 OR UNIX', 'ON')
def test_simplify_unix_or_win32_or_foobar_or_barfoo():
validate_simplify('WIN32 OR UNIX OR foobar OR barfoo', 'ON')
def test_simplify_not_not_bar():
validate_simplify(' NOT NOT bar ', 'bar')
def test_simplify_not_unix():
validate_simplify('NOT UNIX', 'WIN32')
def test_simplify_not_win32():
validate_simplify('NOT WIN32', 'UNIX')
def test_simplify_unix_and_win32():
validate_simplify('WIN32 AND UNIX', 'OFF')
def test_simplify_unix_or_win32():
validate_simplify('WIN32 OR UNIX', 'ON')
def test_simplify_unix_and_win32_or_foobar_or_barfoo():
validate_simplify('WIN32 AND foobar AND UNIX AND barfoo', 'OFF')
def test_simplify_watchos_and_win32():
validate_simplify('WATCHOS AND WIN32', 'OFF')
def test_simplify_win32_and_watchos():
validate_simplify('WIN32 AND WATCHOS', 'OFF')
def test_simplify_apple_and_appleosx():
validate_simplify('APPLE AND MACOS', 'MACOS')
def test_simplify_apple_or_appleosx():
validate_simplify('APPLE OR MACOS', 'APPLE')
def test_simplify_apple_or_appleosx_level1():
validate_simplify('foobar AND (APPLE OR MACOS )', 'APPLE AND foobar')
def test_simplify_apple_or_appleosx_level1_double():
validate_simplify('foobar AND (APPLE OR MACOS )', 'APPLE AND foobar')
def test_simplify_apple_or_appleosx_level1_double_with_extra_spaces():
validate_simplify('foobar AND (APPLE OR MACOS ) '
'AND ( MACOS OR APPLE )', 'APPLE AND foobar')
def test_simplify_apple_or_appleosx_level2():
validate_simplify('foobar AND ( ( APPLE OR WATCHOS ) '
'OR MACOS ) AND ( MACOS OR APPLE ) '
'AND ( (WIN32 OR WINRT) OR UNIX) ', 'APPLE AND foobar')
def test_simplify_not_apple_and_appleosx():
validate_simplify('NOT APPLE AND MACOS', 'OFF')
def test_simplify_unix_and_bar_or_win32():
validate_simplify('WIN32 AND bar AND UNIX', 'OFF')
def test_simplify_unix_or_bar_or_win32():
validate_simplify('WIN32 OR bar OR UNIX', 'ON')
def test_simplify_complex_true():
validate_simplify('WIN32 OR ( APPLE OR UNIX)', 'ON')
def test_simplify_apple_unix_freebsd():
validate_simplify('( APPLE OR ( UNIX OR FREEBSD ))', 'UNIX')
def test_simplify_apple_unix_freebsd_foobar():
validate_simplify('( APPLE OR ( UNIX OR FREEBSD ) OR foobar)',
'UNIX OR foobar')
def test_simplify_complex_false():
validate_simplify('WIN32 AND foobar AND ( '
'APPLE OR ( UNIX OR FREEBSD ))',
'OFF')
def test_simplify_android_not_apple():
validate_simplify('ANDROID AND NOT MACOS', 'ANDROID')

View File

@ -0,0 +1,32 @@
#!/usr/bin/env python3
# Copyright (C) 2018 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
from pro2cmake import AddOperation, SetOperation, UniqueAddOperation, RemoveOperation
def test_add_operation():
op = AddOperation(['bar', 'buz'])
result = op.process(['foo', 'bar'], ['foo', 'bar'], lambda x: x)
assert ['foo', 'bar', 'bar', 'buz'] == result
def test_uniqueadd_operation():
op = UniqueAddOperation(['bar', 'buz'])
result = op.process(['foo', 'bar'], ['foo', 'bar'], lambda x: x)
assert ['foo', 'bar', 'buz'] == result
def test_set_operation():
op = SetOperation(['bar', 'buz'])
result = op.process(['foo', 'bar'], ['foo', 'bar'], lambda x: x)
assert ['bar', 'buz'] == result
def test_remove_operation():
op = RemoveOperation(['bar', 'buz'])
result = op.process(['foo', 'bar'], ['foo', 'bar'], lambda x: x)
assert ['foo', '-buz'] == result

View File

@ -0,0 +1,343 @@
#!/usr/bin/env python3
# Copyright (C) 2018 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import os
from pro2cmake import map_condition
from qmake_parser import QmakeParser
from condition_simplifier import simplify_condition
_tests_path = os.path.dirname(os.path.abspath(__file__))
def validate_op(key, op, value, to_validate):
assert key == to_validate['key']
assert op == to_validate['operation']['value']
assert value == to_validate.get('value', None)
def validate_single_op(key, op, value, to_validate):
assert len(to_validate) == 1
validate_op(key, op, value, to_validate[0])
def evaluate_condition(to_validate):
assert 'condition' in to_validate
assert 'statements' in to_validate
return (to_validate['condition'],
to_validate['statements'],
to_validate.get('else_statements', {}))
def validate_default_else_test(file_name):
result = parse_file(file_name)
assert len(result) == 1
(cond, if_branch, else_branch) = evaluate_condition(result[0])
assert cond == 'qtConfig(timezone)'
validate_single_op('A', '=', ['1'], if_branch)
assert len(else_branch) == 1
(cond2, if2_branch, else2_branch) = evaluate_condition(else_branch[0])
assert cond2 == 'win32'
validate_single_op('B', '=', ['2'], if2_branch)
validate_single_op('C', '=', ['3'], else2_branch)
def parse_file(file):
p = QmakeParser(debug=True)
result, _ = p.parseFile(file)
print('\n\n#### Parser result:')
print(result)
print('\n#### End of parser result.\n')
print('\n\n####Parser result dictionary:')
print(result.asDict())
print('\n#### End of parser result dictionary.\n')
result_dictionary = result.asDict()
assert len(result_dictionary) == 1
return result_dictionary['statements']
def test_else():
result = parse_file(_tests_path + '/data/else.pro')
assert len(result) == 1
(cond, if_branch, else_branch) = evaluate_condition(result[0])
assert cond == 'linux'
validate_single_op('SOURCES', '+=', ['a.cpp'], if_branch)
validate_single_op('SOURCES', '+=', ['b.cpp'], else_branch)
def test_else2():
result = parse_file(_tests_path + '/data/else2.pro')
assert len(result) == 1
(cond, if_branch, else_branch) = evaluate_condition(result[0])
assert cond == 'osx'
validate_single_op('A', '=', ['1'], if_branch)
assert len(else_branch) == 1
(cond2, if2_branch, else2_branch) = evaluate_condition(else_branch[0])
assert cond2 == 'win32'
validate_single_op('B', '=', ['2'], if2_branch)
validate_single_op('C', '=', ['3'], else2_branch)
def test_else3():
validate_default_else_test(_tests_path + '/data/else3.pro')
def test_else4():
validate_default_else_test(_tests_path + '/data/else4.pro')
def test_else5():
validate_default_else_test(_tests_path + '/data/else5.pro')
def test_else6():
validate_default_else_test(_tests_path + '/data/else6.pro')
def test_else7():
result = parse_file(_tests_path + '/data/else7.pro')
assert len(result) == 1
def test_else8():
validate_default_else_test(_tests_path + '/data/else8.pro')
def test_multiline_assign():
result = parse_file(_tests_path + '/data/multiline_assign.pro')
assert len(result) == 2
validate_op('A', '=', ['42', '43', '44'], result[0])
validate_op('B', '=', ['23'], result[1])
def test_include():
result = parse_file(_tests_path + '/data/include.pro')
assert len(result) == 3
validate_op('A', '=', ['42'], result[0])
include = result[1]
assert len(include) == 1
assert 'included' in include
assert include['included'].get('value', '') == 'foo'
validate_op('B', '=', ['23'], result[2])
def test_load():
result = parse_file(_tests_path + '/data/load.pro')
assert len(result) == 3
validate_op('A', '=', ['42'], result[0])
load = result[1]
assert len(load) == 1
assert load.get('loaded', '') == 'foo'
validate_op('B', '=', ['23'], result[2])
def test_definetest():
result = parse_file(_tests_path + '/data/definetest.pro')
assert len(result) == 1
assert result[0] == []
def test_for():
result = parse_file(_tests_path + '/data/for.pro')
assert len(result) == 2
validate_op('SOURCES', '=', ['main.cpp'], result[0])
assert result[1] == []
def test_single_line_for():
result = parse_file(_tests_path + '/data/single_line_for.pro')
assert len(result) == 1
assert result[0] == []
def test_unset():
result = parse_file(_tests_path + '/data/unset.pro')
assert len(result) == 1
assert result[0] == []
def test_quoted():
result = parse_file(_tests_path + '/data/quoted.pro')
assert len(result) == 1
def test_complex_values():
result = parse_file(_tests_path + '/data/complex_values.pro')
assert len(result) == 1
def test_function_if():
result = parse_file(_tests_path + '/data/function_if.pro')
assert len(result) == 1
def test_realworld_standardpaths():
result = parse_file(_tests_path + '/data/standardpaths.pro')
(cond, if_branch, else_branch) = evaluate_condition(result[0])
assert cond == 'win32'
assert len(if_branch) == 1
assert len(else_branch) == 1
# win32:
(cond1, if_branch1, else_branch1) = evaluate_condition(if_branch[0])
assert cond1 == '!winrt'
assert len(if_branch1) == 1
validate_op('SOURCES', '+=', ['io/qstandardpaths_win.cpp'], if_branch1[0])
assert len(else_branch1) == 1
validate_op('SOURCES', '+=', ['io/qstandardpaths_winrt.cpp'], else_branch1[0])
# unix:
(cond2, if_branch2, else_branch2) = evaluate_condition(else_branch[0])
assert cond2 == 'unix'
assert len(if_branch2) == 1
assert len(else_branch2) == 0
# mac / else:
(cond3, if_branch3, else_branch3) = evaluate_condition(if_branch2[0])
assert cond3 == 'mac'
assert len(if_branch3) == 1
validate_op('OBJECTIVE_SOURCES', '+=', ['io/qstandardpaths_mac.mm'], if_branch3[0])
assert len(else_branch3) == 1
# android / else:
(cond4, if_branch4, else_branch4) = evaluate_condition(else_branch3[0])
assert cond4 == 'android'
assert len(if_branch4) == 1
validate_op('SOURCES', '+=', ['io/qstandardpaths_android.cpp'], if_branch4[0])
assert len(else_branch4) == 1
# haiku / else:
(cond5, if_branch5, else_branch5) = evaluate_condition(else_branch4[0])
assert cond5 == 'haiku'
assert len(if_branch5) == 1
validate_op('SOURCES', '+=', ['io/qstandardpaths_haiku.cpp'], if_branch5[0])
assert len(else_branch5) == 1
validate_op('SOURCES', '+=', ['io/qstandardpaths_unix.cpp'], else_branch5[0])
def test_realworld_comment_scope():
result = parse_file(_tests_path + '/data/comment_scope.pro')
assert len(result) == 2
(cond, if_branch, else_branch) = evaluate_condition(result[0])
assert cond == 'freebsd|openbsd'
assert len(if_branch) == 1
validate_op('QMAKE_LFLAGS_NOUNDEF', '=', [], if_branch[0])
assert 'included' in result[1]
assert result[1]['included'].get('value', '') == 'animation/animation.pri'
def test_realworld_contains_scope():
result = parse_file(_tests_path + '/data/contains_scope.pro')
assert len(result) == 2
def test_realworld_complex_assign():
result = parse_file(_tests_path + '/data/complex_assign.pro')
assert len(result) == 1
validate_op('qmake-clean.commands', '+=', '( cd qmake && $(MAKE) clean ":-(==)-:" \'(Foo)\' )'.split(),
result[0])
def test_realworld_complex_condition():
result = parse_file(_tests_path + '/data/complex_condition.pro')
assert len(result) == 1
(cond, if_branch, else_branch) = evaluate_condition(result[0])
assert cond == '!system("dbus-send --session --type=signal / ' \
'local.AutotestCheck.Hello >$$QMAKE_SYSTEM_NULL_DEVICE ' \
'2>&1")'
assert len(if_branch) == 1
validate_op('SOURCES', '=', ['dbus.cpp'], if_branch[0])
assert len(else_branch) == 0
def test_realworld_sql():
result = parse_file(_tests_path + '/data/sql.pro')
assert len(result) == 2
validate_op('TEMPLATE', '=', ['subdirs'], result[0])
validate_op('SUBDIRS', '=', ['kernel'], result[1])
def test_realworld_qtconfig():
result = parse_file(_tests_path + '/data/escaped_value.pro')
assert len(result) == 1
validate_op('MODULE_AUX_INCLUDES', '=', ['\\$\\$QT_MODULE_INCLUDE_BASE/QtANGLE'], result[0])
def test_realworld_lc():
result = parse_file(_tests_path + '/data/lc.pro')
assert len(result) == 3
def test_realworld_lc_with_comment_in_between():
result = parse_file(_tests_path + '/data/lc_with_comment.pro')
my_var = result[1]['value'][0]
assert my_var == 'foo'
my_var = result[2]['value'][0]
assert my_var == 'foo2'
my_var = result[3]['value'][0]
assert my_var == 'foo3'
my_var = result[4]['value'][0]
assert my_var == 'foo4'
my_var = result[5]['value'][0]
assert my_var == 'foo5'
sub_dirs = result[0]['value']
assert sub_dirs[0] == 'tga'
assert sub_dirs[1] == 'wbmp'
assert len(result) == 6
def test_condition_without_scope():
result = parse_file(_tests_path + '/data/condition_without_scope.pro')
assert len(result) == 1
def test_multi_condition_divided_by_lc():
result = parse_file(_tests_path + '/data/multi_condition_divided_by_lc.pro')
assert len(result) == 1
def test_nested_function_calls():
result = parse_file(_tests_path + '/data/nested_function_calls.pro')
assert len(result) == 1
def test_value_function():
result = parse_file(_tests_path + '/data/value_function.pro')
target = result[0]['value'][0]
assert target == 'Dummy'
value = result[1]['value']
assert value[0] == '$$TARGET'
def test_condition_operator_precedence():
result = parse_file(_tests_path + '/data/condition_operator_precedence.pro')
def validate_simplify(input_str: str, expected: str) -> None:
output = simplify_condition(map_condition(input_str))
assert output == expected
validate_simplify(result[0]["condition"], "a1 OR a2")
validate_simplify(result[1]["condition"], "b3 AND (b1 OR b2)")
validate_simplify(result[2]["condition"], "c4 OR (c1 AND c3) OR (c2 AND c3)")

View File

@ -0,0 +1,318 @@
#!/usr/bin/env python3
# Copyright (C) 2021 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
from pro2cmake import Scope, SetOperation, merge_scopes, recursive_evaluate_scope
import pytest
import typing
ScopeList = typing.List[Scope]
def _map_to_operation(**kwargs):
result = {} # type: typing.Mapping[str, typing.List[SetOperation]]
for (key, value) in kwargs.items():
result[key] = [SetOperation([value])]
return result
def _new_scope(*, parent_scope=None, condition='', **kwargs) -> Scope:
return Scope(parent_scope=parent_scope,
qmake_file='file1', condition=condition, operations=_map_to_operation(**kwargs))
def _evaluate_scopes(scopes: ScopeList) -> ScopeList:
for s in scopes:
if not s.parent:
recursive_evaluate_scope(s)
return scopes
def _validate(input_scopes: ScopeList, output_scopes: ScopeList):
merged_scopes = merge_scopes(input_scopes)
assert merged_scopes == output_scopes
def test_evaluate_one_scope():
scope = _new_scope(condition='QT_FEATURE_foo', test1='bar')
input_scope = scope
recursive_evaluate_scope(scope)
assert scope == input_scope
def test_evaluate_child_scope():
scope = _new_scope(condition='QT_FEATURE_foo', test1='bar')
_new_scope(parent_scope=scope, condition='QT_FEATURE_bar', test2='bar')
input_scope = scope
recursive_evaluate_scope(scope)
assert scope.total_condition == 'QT_FEATURE_foo'
assert len(scope.children) == 1
assert scope.get_string('test1') == 'bar'
assert scope.get_string('test2', 'not found') == 'not found'
child = scope.children[0]
assert child.total_condition == 'QT_FEATURE_bar AND QT_FEATURE_foo'
assert child.get_string('test1', 'not found') == 'not found'
assert child.get_string('test2') == 'bar'
def test_evaluate_two_child_scopes():
scope = _new_scope(condition='QT_FEATURE_foo', test1='bar')
_new_scope(parent_scope=scope, condition='QT_FEATURE_bar', test2='bar')
_new_scope(parent_scope=scope, condition='QT_FEATURE_buz', test3='buz')
input_scope = scope
recursive_evaluate_scope(scope)
assert scope.total_condition == 'QT_FEATURE_foo'
assert len(scope.children) == 2
assert scope.get_string('test1') == 'bar'
assert scope.get_string('test2', 'not found') == 'not found'
assert scope.get_string('test3', 'not found') == 'not found'
child1 = scope.children[0]
assert child1.total_condition == 'QT_FEATURE_bar AND QT_FEATURE_foo'
assert child1.get_string('test1', 'not found') == 'not found'
assert child1.get_string('test2') == 'bar'
assert child1.get_string('test3', 'not found') == 'not found'
child2 = scope.children[1]
assert child2.total_condition == 'QT_FEATURE_buz AND QT_FEATURE_foo'
assert child2.get_string('test1', 'not found') == 'not found'
assert child2.get_string('test2') == ''
assert child2.get_string('test3', 'not found') == 'buz'
def test_evaluate_else_child_scopes():
scope = _new_scope(condition='QT_FEATURE_foo', test1='bar')
_new_scope(parent_scope=scope, condition='QT_FEATURE_bar', test2='bar')
_new_scope(parent_scope=scope, condition='else', test3='buz')
input_scope = scope
recursive_evaluate_scope(scope)
assert scope.total_condition == 'QT_FEATURE_foo'
assert len(scope.children) == 2
assert scope.get_string('test1') == 'bar'
assert scope.get_string('test2', 'not found') == 'not found'
assert scope.get_string('test3', 'not found') == 'not found'
child1 = scope.children[0]
assert child1.total_condition == 'QT_FEATURE_bar AND QT_FEATURE_foo'
assert child1.get_string('test1', 'not found') == 'not found'
assert child1.get_string('test2') == 'bar'
assert child1.get_string('test3', 'not found') == 'not found'
child2 = scope.children[1]
assert child2.total_condition == 'QT_FEATURE_foo AND NOT QT_FEATURE_bar'
assert child2.get_string('test1', 'not found') == 'not found'
assert child2.get_string('test2') == ''
assert child2.get_string('test3', 'not found') == 'buz'
def test_evaluate_invalid_else_child_scopes():
scope = _new_scope(condition='QT_FEATURE_foo', test1='bar')
_new_scope(parent_scope=scope, condition='else', test3='buz')
_new_scope(parent_scope=scope, condition='QT_FEATURE_bar', test2='bar')
input_scope = scope
with pytest.raises(AssertionError):
recursive_evaluate_scope(scope)
def test_merge_empty_scope_list():
_validate([], [])
def test_merge_one_scope():
scopes = [_new_scope(test='foo')]
recursive_evaluate_scope(scopes[0])
_validate(scopes, scopes)
def test_merge_one_on_scope():
scopes = [_new_scope(condition='ON', test='foo')]
recursive_evaluate_scope(scopes[0])
_validate(scopes, scopes)
def test_merge_one_off_scope():
scopes = [_new_scope(condition='OFF', test='foo')]
recursive_evaluate_scope(scopes[0])
_validate(scopes, [])
def test_merge_one_conditioned_scope():
scopes = [_new_scope(condition='QT_FEATURE_foo', test='foo')]
recursive_evaluate_scope(scopes[0])
_validate(scopes, scopes)
def test_merge_two_scopes_with_same_condition():
scopes = [_new_scope(condition='QT_FEATURE_bar', test='foo'),
_new_scope(condition='QT_FEATURE_bar', test2='bar')]
recursive_evaluate_scope(scopes[0])
recursive_evaluate_scope(scopes[1])
result = merge_scopes(scopes)
assert len(result) == 1
r0 = result[0]
assert r0.total_condition == 'QT_FEATURE_bar'
assert r0.get_string('test') == 'foo'
assert r0.get_string('test2') == 'bar'
def test_merge_three_scopes_two_with_same_condition():
scopes = [_new_scope(condition='QT_FEATURE_bar', test='foo'),
_new_scope(condition='QT_FEATURE_baz', test1='buz'),
_new_scope(condition='QT_FEATURE_bar', test2='bar')]
recursive_evaluate_scope(scopes[0])
recursive_evaluate_scope(scopes[1])
recursive_evaluate_scope(scopes[2])
result = merge_scopes(scopes)
assert len(result) == 2
r0 = result[0]
assert r0.total_condition == 'QT_FEATURE_bar'
assert r0.get_string('test') == 'foo'
assert r0.get_string('test2') == 'bar'
assert result[1] == scopes[1]
def test_merge_two_unrelated_on_off_scopes():
scopes = [_new_scope(condition='ON', test='foo'),
_new_scope(condition='OFF', test2='bar')]
recursive_evaluate_scope(scopes[0])
recursive_evaluate_scope(scopes[1])
_validate(scopes, [scopes[0]])
def test_merge_two_unrelated_on_off_scopes():
scopes = [_new_scope(condition='OFF', test='foo'),
_new_scope(condition='ON', test2='bar')]
recursive_evaluate_scope(scopes[0])
recursive_evaluate_scope(scopes[1])
_validate(scopes, [scopes[1]])
def test_merge_parent_child_scopes_with_different_conditions():
scope = _new_scope(condition='FOO', test1='parent')
scopes = [scope, _new_scope(parent_scope=scope, condition='bar', test2='child')]
recursive_evaluate_scope(scope)
_validate(scopes, scopes)
def test_merge_parent_child_scopes_with_same_conditions():
scope = _new_scope(condition='FOO AND bar', test1='parent')
scopes = [scope, _new_scope(parent_scope=scope, condition='FOO AND bar', test2='child')]
recursive_evaluate_scope(scope)
result = merge_scopes(scopes)
assert len(result) == 1
r0 = result[0]
assert r0.parent == None
assert r0.total_condition == 'FOO AND bar'
assert r0.get_string('test1') == 'parent'
assert r0.get_string('test2') == 'child'
def test_merge_parent_child_scopes_with_on_child_condition():
scope = _new_scope(condition='FOO AND bar', test1='parent')
scopes = [scope, _new_scope(parent_scope=scope, condition='ON', test2='child')]
recursive_evaluate_scope(scope)
result = merge_scopes(scopes)
assert len(result) == 1
r0 = result[0]
assert r0.parent == None
assert r0.total_condition == 'FOO AND bar'
assert r0.get_string('test1') == 'parent'
assert r0.get_string('test2') == 'child'
# Real world examples:
# qstandardpaths selection:
def test_qstandardpaths_scopes():
# top level:
scope1 = _new_scope(condition='ON', scope_id=1)
# win32 {
scope2 = _new_scope(parent_scope=scope1, condition='WIN32')
# !winrt {
# SOURCES += io/qstandardpaths_win.cpp
scope3 = _new_scope(parent_scope=scope2, condition='NOT WINRT',
SOURCES='qsp_win.cpp')
# } else {
# SOURCES += io/qstandardpaths_winrt.cpp
scope4 = _new_scope(parent_scope=scope2, condition='else',
SOURCES='qsp_winrt.cpp')
# }
# else: unix {
scope5 = _new_scope(parent_scope=scope1, condition='else')
scope6 = _new_scope(parent_scope=scope5, condition='UNIX')
# mac {
# OBJECTIVE_SOURCES += io/qstandardpaths_mac.mm
scope7 = _new_scope(parent_scope=scope6, condition='MACOS', SOURCES='qsp_mac.mm')
# } else:android {
# SOURCES += io/qstandardpaths_android.cpp
scope8 = _new_scope(parent_scope=scope6, condition='else')
scope9 = _new_scope(parent_scope=scope8, condition='ANDROID AND NOT UNKNOWN_PLATFORM', SOURCES='qsp_android.cpp')
# } else:haiku {
# SOURCES += io/qstandardpaths_haiku.cpp
scope10 = _new_scope(parent_scope=scope8, condition='else')
scope11 = _new_scope(parent_scope=scope10, condition='HAIKU', SOURCES='qsp_haiku.cpp')
# } else {
# SOURCES +=io/qstandardpaths_unix.cpp
scope12 = _new_scope(parent_scope=scope10, condition='else', SOURCES='qsp_unix.cpp')
# }
# }
recursive_evaluate_scope(scope1)
assert scope1.total_condition == 'ON'
assert scope2.total_condition == 'WIN32'
assert scope3.total_condition == 'WIN32 AND NOT WINRT'
assert scope4.total_condition == 'WINRT'
assert scope5.total_condition == 'UNIX'
assert scope6.total_condition == 'UNIX'
assert scope7.total_condition == 'MACOS'
assert scope8.total_condition == 'UNIX AND NOT MACOS'
assert scope9.total_condition == 'ANDROID AND NOT UNKNOWN_PLATFORM'
assert scope10.total_condition == 'UNIX AND NOT MACOS AND (UNKNOWN_PLATFORM OR NOT ANDROID)'
assert scope11.total_condition == 'HAIKU AND (UNKNOWN_PLATFORM OR NOT ANDROID)'
assert scope12.total_condition == 'UNIX AND NOT HAIKU AND NOT MACOS AND (UNKNOWN_PLATFORM OR NOT ANDROID)'
def test_recursive_expansion():
scope = _new_scope(A='Foo',B='$$A/Bar')
assert scope.get_string('A') == 'Foo'
assert scope.get_string('B') == '$$A/Bar'
assert scope._expand_value('$$B/Source.cpp') == ['Foo/Bar/Source.cpp']
assert scope._expand_value('$$B') == ['Foo/Bar']