Commit Graph

41583 Commits

Author SHA1 Message Date
Mårten Nordheim
2cf0ba1fba Use pre-compiled headers when building Qt with cmake
Some modules define their own manually-maintained lists, and we can rely
on the headers generated by each module to include in the pch as well
e.g. QtCore/QtCore.

There's also e.g. QtWidgetDepends for QtWidgets, but this only
works for modules, not for tools, examples or other applications.
For now we'll use the Qt<Module>/Qt<Module> headers for the
modules we depend on.

Building with PCH can be disabled with -DBUILD_WITH_PCH=NO, and it only
works for versions of CMake newer than 3.15.20190829.

Change-Id: Iae52bd69acfdfd58f4cd20d3cfa3c7f42775f732
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-09-11 08:25:54 +00:00
Liang Qi
7df0868ad5 cmake: enable tst_qpixmapcache
To verify -DFEATURE_developer_build=ON and QT_FEATURE_private_tests
work as we expected.

Change-Id: Id428dc0da4ee441b3a1a7f433c5bc2ef066dae9e
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-09-10 14:23:23 +00:00
Alexandru Croitor
d289a47c7d Reflow text in cmake/README.md to be less than 100 chars per line
Change-Id: Ie34c03c409a20546ace1ddc84f8813c1772936f7
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-09-10 14:19:51 +00:00
Alexandru Croitor
6720f0204f Don't propagate INSTALL_INTERFACE headers for modules with no syncqt
If syncqt was not executed for a module, it will not have generated
headers, so we should not propagate the include/${module} header
location in that case.

Change-Id: I6dc0628a11ababb4d237215a9f4d3fc331383848
Reviewed-by: Liang Qi <liang.qi@qt.io>
Reviewed-by: Qt CMake Build Bot
2019-09-10 14:19:35 +00:00
Alexandru Croitor
b0dbfc3094 Skip converting certain projects when they are passed to pro2cmake
Specifically skip cmake tests projects (because they are only needed
when Qt is built with qmake).
Also skip test qmake projects in qmake's test suite.
We might find more tests to skip in the future.

Change-Id: I4c3a42db669b31e81fd06206652371b6a70fd8ce
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Reviewed-by: Qt CMake Build Bot
2019-09-09 19:20:57 +00:00
Alexandru Croitor
e87677ad4f Try to detect if project given to pro2cmake is an example
If the project path starts with "examples/" relative to the repo
source directory (which is decided by location of .qmake.conf),
consider the given project file to be an example.

This makes the usage of run_pro2cmake.py easier, specifically by
being able to point it to a repo source directory, and getting most
project conversions correctly.

Change-Id: I93de98f8fc97af509c1f96cdebad3681190a53d1
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
2019-09-09 19:20:49 +00:00
Alexandru Croitor
3215f5457a Handle top level tests, examples and main qmake projects in pro2cmake
The script now detects whether the project file given is a:
- top level qmake project (qtdeclarative.pro)
- top level tests project (qtdeclarative/tests.pro)
- top level examples project (qtdeclarative/examples.pro)

This is done by finding the .qmake.conf file in parent directories of
the given project, and comparing the project's location to the
.qmake.conf location.

For the top level qmake project and the tests project, the script will
now use a predefined block of code that we usually had to copy paste and
change manually. Now only small bits will have to be adjusted manually
(project name and dependencies).

For the examples project, the content is surrounded by the required
build examples commands.

As a result, developers will have to worry less about knowing where to
copy paste from.

Change-Id: I4f751b371e74eeb86e070d58635c3d99b970ab18
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
2019-09-09 19:20:38 +00:00
Ville Voutilainen
1b1248d7cd cmake: Enable building more of the tools tests
This is incomplete. moc has compilation problems, some
advanced parts of qmake tests are not supported by the converter.

Change-Id: Ic389ddfa10a7558f21cf7ba9ead8e58157c760da
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-09-09 10:45:21 +00:00
Alexandru Croitor
bf899ba53b Propagate BUILD_TESTING and BUILD_EXAMPLES
As with qmake, you configure with or without -nomake tests -nomake
examples, and the choice is propagated to other repositories.

Do the same for CMake. It's still possible to opt out to build one
or the other by passing -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF
on the command line, which takes precedence over the value saved to
QtBuildInternalsExtra.

Change-Id: If0fbfa938d88309e7969c9bacc8d0bf86548bf5e
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Reviewed-by: Qt CMake Build Bot
2019-09-06 18:09:18 +00:00
Simon Hausmann
b28c2c9528 Fix unnecessary find_package calls for shared builds, part 2
Fix the silly boolean logic error in commit
9c1b7802d7.

Change-Id: I9dd0d3e8be5cbe75583099686a623d81d3dd87fc
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-09-06 09:45:59 +00:00
Alexandru Croitor
6c00d9075e Use $$source_path/qtbase/cmake modules when doing non-prefix builds
This is similar to qmake, where the .prf files from the source
location of qtbase/mkspecs are used in a non-prefix build.
This means that if a developer changes the source QtBuild.cmake,
and then runs make in qtdeclarative, cmake will reconfigure
qtdeclarative because the timestamp of QtBuild.cmake changed.

Before this change you first had to make && make install in the
qtbase build directory, before qtdeclarative saw the modified
QtBuild.cmake.

This change also makes the module paths be prepended to
CMAKE_MODULE_PATH instead of appended, which means they will
take precedence to any path provided via command line.

Change-Id: I9178d5183a95b3b67bfe1b1fe91d3d3371ffe5c5
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
2019-09-06 09:33:38 +00:00
Simon Hausmann
9c1b7802d7 Avoid unnecessary find_package calls when using Qt with shared builds
Don't create the plugin config files when doing shared builds, otherwise
for example Qt6GuiPlugins.cmake will try to include the xcb plugin cmake
config, which in turn will perform a full-fledged find_package series to
locate xcb. When an application just uses find_package(Qt6Gui), then
that is not needed.

Change-Id: I1890aaa5be8e214151c65fa981f547a73c0ca7fc
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Reviewed-by: Qt CMake Build Bot
2019-09-05 17:25:07 +00:00
Simon Hausmann
bc54f0b164 Fix build of installed header-only modules in non-prefix builds
QtUiTools in qttools is a public module that has only headers, so it's
an interface library in cmake. That means INTERFACE_INCLUDE_DIRECTORIES
cannot contain paths to the source or build directory, unless they are
prefixed with BUILD_INTERFACE, which this patch adds.

Change-Id: I047700f447237dfbe5a901072eb413a159ae537d
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-09-05 13:36:47 +00:00
Ville Voutilainen
b2a11daaa1 cmake: Enable building of the oci plugin
Change-Id: I003d6da10c7e47402fb373d3956817817328cf0f
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Reviewed-by: Qt CMake Build Bot
2019-09-05 08:24:07 +00:00
Simon Hausmann
4ee762cf25 Fix qmlcachegen invocation on Windows, part 2
Fix up the previous commit and use separate COMMAND parameters for
add_custom_command to ensure the expansion of the PATH. The injection
via -E env "/some/dir;%PATH%" does not work as the dollar expansion is
not applied when the ninja command uses cmd /C. This relies now on
undocumented behavior of cmake ;(

Change-Id: I5b5fc88e4c13f8fb6c6bba3131204c2eb35404d6
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-09-04 13:55:34 +00:00
Simon Hausmann
18fc9e1bf8 Fix qtdeclarative build on Windows
Our tools are typically installed into the Qt bin directory, after which
they are useable right away on Windows, since the Qt dlls are located
there, too. An exception to the rule are tools that are built within a
module and used right away. At that point they are in the top-level
bin dir of the build directory, along with "local" DLLS they might need,
but with the Qt dlls out of reach. To cover this case, we need to
prepend a PATH adjusting command when using these with
add_custom_command.

Change-Id: I7f58581f5060c8004b5d1fa1f6f17297256783de
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-09-04 13:18:08 +00:00
Simon Hausmann
85e3bb7aea Remove dead code
Change-Id: Iac7c7c77744b43772faf3402566685a674ab8ff3
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Leander Beernaert <leander.beernaert@qt.io>
2019-09-04 12:29:25 +00:00
Alexandru Croitor
408cdf006a Fix non-prefix builds on Windows
Building qtdeclarative on Windows in a non-prefix build failed due to
usage of include paths of WinMain that don't actually exist.

Mark the library as not having include paths by setting
NO_SYNC_QT.

Change-Id: Ibdb420981069967414a119dedc7a7bfc9d61c253
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
2019-09-04 10:54:43 +00:00
Ville Voutilainen
95c9c5a308 cmake: Enable building of the db2 plugin
Change-Id: I26810cccba5f3128cb47e0bf53b5ec78de2eec8c
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-09-04 09:50:15 +00:00
Leander Beernaert
3f8ba1e55e Disable Examples in static build
Do not build examples in static builds as they are not prepared
for this configuration.

Change-Id: Ia0fd0a6cdfa3733bf13eb2ca8398668f26c0bedf
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-09-03 12:02:20 +00:00
Liang Qi
e0fbb7306d coin: increase the timeout between output for all
Change-Id: I3906a08f5e0cce9abeeafbb67a83d31fbf67c703
Reviewed-by: Toni Saario <toni.saario@qt.io>
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-09-03 11:49:07 +00:00
Simon Hausmann
0ef8753774 Prospective fix for linking problems of qtdeclarative in the CI
In the ICC configuration we can't build the qtbase libraries with ICC
and qtdeclarative with gcc, mixing won't work well. On Windows we've
covered this compiler mixing scenario using our toolchain file, but the
ICC case makes it clear that we have to be consistent about caching the
compiler in the toolchain file across platforms.

Change-Id: Iad2005ab00655f902e5f5cea2f0563d790d8aa93
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-09-03 08:22:03 +00:00
Ville Voutilainen
3ff31ed020 Enable building of the mysql plugin
Change-Id: I8cb97afaaed46ee64b5a133e797179d7ddecdeef
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-09-02 15:16:42 +00:00
Alexandru Croitor
f9842ae7d4 Don't include module syncqt header locations if syncqt was not run
When building QtQmlDevTools we don't generate syncqt headers, but the
non-existent include paths were still added, which means that anything
that used QtQmlDevTools would fail to configure (the standalone tests).

Make sure to only add the include paths if syncqt was executed.

Change-Id: I6d79ecf53e9a5d396e8df801584ce2c9f119f9be
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Reviewed-by: Qt CMake Build Bot
2019-09-02 12:32:01 +00:00
Alexandru Croitor
a5cdca8033 Decide whether to build tools when doing a standalone test build
Needed for qtdeclarative standalone tests.

Change-Id: Ie012528d0d553cb63c2d79f3ded35e45872ee89a
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Reviewed-by: Qt CMake Build Bot
2019-09-02 09:03:16 +00:00
Alexandru Croitor
659d8cf3e5 Fix add_qt_resource to handle resources in static builds properly
Whenever the qml compiler is used to process qml files from a
resource, and there are no resources left after all qml files have
been processed, make sure to propagate the created resource target
to add_qt_resource, so that the target is associated properly with
an export name.

Additionally the generated qml cache loader file uses private Qml
headers. Thus the object library that contains the cpp file should
have qml as a dependency (and not the target that will link to the
object library).

Change-Id: Ib385a900823df3e015492cdd06acd8a0cb9f8e9a
Reviewed-by: Leander Beernaert <leander.beernaert@qt.io>
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
2019-08-30 19:02:52 +00:00
Simon Hausmann
2e3e42587b Fix default platform plugin choice for WASM
The name (key in wasm.json) for the QPA plugin is "wasm", not
"webassembly".

Change-Id: I6a2568d05e4f19408fa95ac59a47acdcf90e11a2
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-30 13:21:44 +00:00
Simon Hausmann
8da5305102 Fix Harfbuzz detection
We use

    qt_find_package(harfbuzz PROVIDED_TARGETS harfbuzz::harfbuzz)

which would set harfbuzz_FOUND. Since variable names are case-sensitive,
this is also the name we must check for in the qt feature condition.

Change-Id: I43420489c3310bc9c3e5cc798a005c8d5b0ab646
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-30 13:21:32 +00:00
Leander Beernaert
4670e0a1fd Override qmlimportscanner path in android deployment settings
Override the default binary path for qmlimportscanner so that it points
to the host build specified via QT_HOST_PATH.

Change-Id: Ib0b47e61315c87ce6225e2d8ca84043cae03357d
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-30 13:12:59 +00:00
Leander Beernaert
eeffac526e Update Android build configuration
Update Android build configuration to be compatible with the multi-arch
android build patch to qmake. We can now build and generate the apk
correctly. Executing on the device/simulator will only work once the
latest changes from 5.14 have been merged in.

We now replace target suffix with ${CMAKE_ANDROID_ARCH_ABI}.[so|a] so
we don't have to deal with handling targets which might have any of the
OUTPUT_NAME properties set.

The dependency and deploy settings generation has also been updated to
append the file contents to a string and then do a single file write
at the end.

Change-Id: Id3c5bd0428141ecaf962124a100390e3a4e41feb
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-30 12:10:26 +00:00
Alexandru Croitor
6c15ad7978 Fix qtdeclarative static builds
qmlplugindump is not build during a Qt static build, so there's no
point in creating custom targets that would run the tool.

Change-Id: Id7d6d44da63312f298f46eab08a5637cb0c97c8f
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
2019-08-30 12:10:07 +00:00
Liang Qi
8367a51c6d Share most common part of module_config.yaml
Change-Id: Ieea5b662e039cff24e26a127b4a3a8610ed588cc
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-30 08:40:02 +00:00
Simon Hausmann
88883dbf60 Fix WASM platform detection
At the moment we only support building with Emscripten, so that's the
system name to look for.

Change-Id: I08782ed0201da1593058bf1fb2ec61d6660802ed
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-30 08:37:28 +00:00
Simon Hausmann
84238ab321 Fix build with Emscripten
Don't try to build the ibus input context plugin when targeting
Emscripten, as there's no ibus there.

Change-Id: I949a09c4bacd3136b632e597dd8048653d0c0fea
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-30 08:37:19 +00:00
Alexandru Croitor
d436023b6a Fix static builds after revamp of add_qt_resource
The first issue is that instead of arg_OUTPUT_TARGET we should use
rcc_OUTPUT_TARGET (there was also a typo in the OUTPUT word).

The second issue came with the fact that the object library targets
that were created for resources had a "Qt6::" namespace prefix in the
exported Targets files, and yet the link generator expression did not
contain the prefix. This failed when building qtsvg in a static build,
because the exported object library could not be found.

The solution is to use the TARGET_NAME generator expression which
takes care of adjusting the name of the target when exported, thus
making the linking work both when building qtbase and when building
qtsvg.

This had the fallout, that all resource object libraries need
to be associated with an export set and installed. This wasn't the case
for plugins, because plugins have an export name of the form
"FooTargets", whereas the export name for the resource object library
is "Qt6FooTargets".

Adjust the export names of plugins to be the same as for modules and
resource library objects (aka contain the "Qt6 prefix").

Change-Id: I1ca28d20c51e4447e5783cc20571a68ec77f6513
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
2019-08-30 08:24:37 +00:00
Maurice Kalinowski
fda455d34d Be more verbose on required environment variables
Make sure to document both variables are required when invoking cmake.
Otherwise, one might be omitted causing side-effects.

Change-Id: I3390df1cb5352ea6113952c99fcedef5336f2fc1
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
2019-08-28 15:51:49 +00:00
Maurice Kalinowski
e5bf0290d9 Add Qt Mqtt to the library mapping
Change-Id: Ifa50161a579647002d3349b49da7012660c59f81
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-28 15:51:44 +00:00
Simon Hausmann
3b04d22241 Fix "mkspec selection" when building with Emscripten
Change-Id: Id9d466221294651c2f8dfde149d82f45b4081238
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-28 14:10:10 +00:00
Simon Hausmann
db61770566 Fix CMake errors around linker flags when targeting WASM
* The -no-undefined linker option only makes sense for shared
      libraries. The WASM build is a static build though.

    * The -gc-sections linker option is only relevant for host tools
      and certainly applicable to the WASM toolchain.

Change-Id: Ib8daec66a6d80f5025887448882dd891e6176268
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-28 13:23:59 +00:00
Simon Hausmann
4e5fc66c04 Fix architecture detection with WASM builds
This is a simple mis-understanding between try_compile assuming interest
in the launching part of the thing we try to compile and our
architecture test being interested in the binary.

Change-Id: Ie972b662b6f34699f566649bb2c1e29da35b58c3
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-28 13:23:50 +00:00
Leander Beernaert
add4c4816c Add missing qml-root-path for Android
Add missing qml root path variable in the deployment configuration file.
Not having this variable will cause androiddeployqt not use the
qml dependency scanner to package all relevant dependencies.

This patch also fixes QT_ANDROID_BUNDLED_FILES files not being
processed.

Change-Id: I5bca33cdbb57098f283b38516b777571806da9e5
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-28 12:29:12 +00:00
Alexandru Croitor
0798ed8a83 Fix subdir handling in pro2cmake
Conditions scopes that had "else" were not handled properly.
The "else" condition should be expanded to its proper negative full
form.

Also every condition "piece" should be wrapped with parentheses before
being passed to sympy simplification, to be sure that boolean
operator precedence is applied properly.

Refactored the code a bit to make it easier to read.

Change-Id: I4726845b867f93c3afbc9362cdce1cd063ccff63
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
2019-08-28 11:15:59 +00:00
Alexandru Croitor
c3ef1a012b Fix handling of more functions in handle_function_value
Essentially pass them through without failing the whole
conversion process.

Change-Id: I7bbd198203f79b45120a7254e2ecdf58e32f9525
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
2019-08-28 11:15:44 +00:00
Alexandru Croitor
5c75f6a21a Fix some corner cases of condition mapping in pro2cmake
no-png is an old unused scope that should be mapped to the png
feature instead.

Map contains(QT_CONFIG, shared) to correct variable check.

Sympy doesn't like dashes in indentifiers, so replace all of them
with a _dash_ token which will be replaced again at the end
of the condition simplifying.

When doing sympy preprocessing, fix mapping of target names that
don't contain double colons.

Change-Id: Id3d37800665c96505b7cbb1d80fdbed59c3ae9c0
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
2019-08-28 11:15:32 +00:00
Alexandru Croitor
3416a83f05 Augment conversion scripts with requirements for qttools part 2
Designer components target names need to be prefixed with Qt.

Change-Id: I13037820b080d88cd670f2db97232509eb868daf
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
2019-08-28 11:15:24 +00:00
Alexandru Croitor
5a5dc6294b Augment conversion scripts with requirements for qttools
The libclang test is implemented as a custom FindWrapLibClang module.
The module does mostly the same things as the configure test in qmake
land.

Change-Id: I965f284baf7daef074e22f033047c35a917c8808
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
2019-08-28 11:15:14 +00:00
Alexandru Croitor
486da5a84d Fix qt_get_module_for_plugin to work with interface libraries
Assume that interface libraries can't have plugins for now, otherwise
we'll need to change the "MODULE_PLUGIN_TYPES" property name to
include INTERFACE_ as a prefix.

Change-Id: I21b64179ded5fd10216d843a21ee149e002793f3
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
2019-08-28 11:15:00 +00:00
Leander Beernaert
ff7101d6c8 Add Support for Android Bearer Jar
This is required to package an apk which depends on QtDelcarative.

Change-Id: I1f6bdeb984f08d73f010fb4210242e5c99f1969f
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-27 16:04:30 +00:00
Leander Beernaert
060784c981 Remove ../ from Targets
Remove repeating '../' pattern from target names, since we generate
the targets in the correct location with CMake.

Change-Id: I89d527a9ad717f742f8d0e5921f378e6ac0a229d
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-26 10:39:40 +00:00
Leander Beernaert
4260b1edc5 Add OUPUT_DIRECTORY option to add_qt_test
From all the observed cases, the parameters given to OUTPUT_DIRECTORY
tend to be CMAKE_CURRENT_BINARY_DIR, which was the default value. This
change is mainly to avoid add_qt_test failing if OUTPUT_DIRECTORY is
specified.

Change-Id: I26b931dd33ad1e991b64c14cc11b4b7a713fc858
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-26 09:39:47 +00:00