Skip to content

Commit

Permalink
qcoro: update to v0.10.0, add workaround for MSVC ABI issue
Browse files Browse the repository at this point in the history
  • Loading branch information
valgur committed Sep 9, 2024
1 parent 906c414 commit 3c9b962
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 85 deletions.
6 changes: 3 additions & 3 deletions recipes/qcoro/all/conandata.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
sources:
"0.4.0":
url: "https://github.com/danvratil/qcoro/archive/refs/tags/v0.4.0.tar.gz"
sha256: "0e68b3f0ce7bf521ffbdd731464d2d60d8d7a39a749b551ed26855a1707d86d1"
"0.10.0":
url: "https://github.com/danvratil/qcoro/archive/refs/tags/v0.10.0.tar.gz"
sha256: "b7c8f00273ad27d85814bf4ec93eb6922c75656800a61d11854d36355a4a1aec"
119 changes: 74 additions & 45 deletions recipes/qcoro/all/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from conan.tools.build import check_min_cppstd
from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
from conan.tools.env import VirtualBuildEnv, VirtualRunEnv
from conan.tools.files import apply_conandata_patches, copy, get, rm
from conan.tools.files import copy, get, rm, replace_in_file, rmdir
from conan.tools.scm import Version

required_conan_version = ">=1.56.0 <2 || >=2.0.6"
Expand Down Expand Up @@ -55,7 +55,7 @@ def layout(self):
cmake_layout(self, src_folder="src")

def requirements(self):
self.requires("qt/6.6.0", transitive_headers=True, transitive_libs=True)
self.requires("qt/[>=6.6.0 <7]", transitive_headers=True, transitive_libs=True)

def validate(self):
if self.settings.compiler.cppstd:
Expand All @@ -64,7 +64,7 @@ def validate(self):
# Special check for clang that can only be linked to libc++
if self.settings.compiler == "clang" and self.settings.compiler.libcxx != "libc++":
raise ConanInvalidConfiguration(
"qcoro requires some C++20 features, which are available in libc++ for clang compiler."
"qcoro requires some C++20 features, which are only available in libc++ for clang compiler."
)

compiler_version = str(self.settings.compiler.version)
Expand All @@ -82,70 +82,99 @@ def build_requirements(self):
def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True)

@property
def _with_qml(self):
return self.dependencies["qt"].options.get_safe("qtdeclarative", False)

@property
def _with_dbus(self):
return self.dependencies["qt"].options.get_safe("with_dbus", False)

@property
def _with_quick(self):
return (self.dependencies["qt"].options.get_safe("gui", False) and
self.dependencies["qt"].options.get_safe("qtshadertools", False))

@property
def _with_websockets(self):
return self.dependencies["qt"].options.get_safe("qtwebsockets", False)

def generate(self):
venv = VirtualBuildEnv(self)
venv.generate()
# Required for Qt's moc
venv = VirtualRunEnv(self)
venv.generate(scope="build")
VirtualBuildEnv(self).generate()
# Required for Qt's moc and qtpaths
VirtualRunEnv(self).generate(scope="build")
tc = CMakeToolchain(self)
tc.variables["QCORO_BUILD_EXAMPLES"] = False
tc.variables["QCORO_ENABLE_ASAN"] = self.options.asan
tc.variables["BUILD_TESTING"] = False
tc.variables["QCORO_WITH_QTDBUS"] = self.dependencies["qt"].options.with_dbus
tc.variables["USE_QT_VERSION"] = self.dependencies["qt"].ref.version.major
tc.variables["QCORO_WITH_QML"] = self._with_qml
tc.variables["QCORO_WITH_QTDBUS"] = self._with_qml
tc.variables["QCORO_WITH_QTQUICK"] = self._with_quick
tc.variables["QCORO_WITH_QTWEBSOCKETS"] = self._with_websockets
tc.generate()
tc = CMakeDeps(self)
tc.generate()

def _patch_sources(self):
replace_in_file(self, os.path.join(self.source_folder, "cmake", "ECMQueryQt.cmake"),
"get_target_property(_qtpaths_executable Qt6::qtpaths LOCATION)",
"set(_qtpaths_executable qtpaths)")

def build(self):
apply_conandata_patches(self)
self._patch_sources()
cmake = CMake(self)
cmake.configure()
cmake.build()

def package(self):
copy(self, "*",
dst=os.path.join(self.package_folder, "licenses"),
src=os.path.join(self.source_folder, "LICENSES"))
src=os.path.join(self.source_folder, "LICENSES"),
dst=os.path.join(self.package_folder, "licenses"))
cmake = CMake(self)
cmake.install()
rmdir(self, os.path.join(self.package_folder, "mkspecs"))
for mask in ["Find*.cmake", "*Config*.cmake", "*-config.cmake", "*Targets*.cmake"]:
rm(self, mask, self.package_folder, recursive=True)

def package_info(self):
self.cpp_info.set_property("cmake_file_name", "QCoro6")

self.cpp_info.builddirs.append(os.path.join("lib", "cmake", "QCoro6Coro"))
macros_cmake_path = os.path.join("lib", "cmake", "QCoro6Coro", "QCoroMacros.cmake")
self.cpp_info.set_property("cmake_build_modules", [macros_cmake_path])

self.cpp_info.components["qcoro-core"].set_property("cmake_target_name", "QCoro::Core")
self.cpp_info.components["qcoro-core"].libs = ["QCoro6Core"]
self.cpp_info.components["qcoro-core"].includedirs.append(os.path.join("include", "qcoro6", "qcoro"))
self.cpp_info.components["qcoro-core"].requires = ["qt::qtCore"]

self.cpp_info.components["qcoro-network"].set_property("cmake_target_name", "QCoro::Network")
self.cpp_info.components["qcoro-network"].libs = ["QCoro6Network"]
self.cpp_info.components["qcoro-network"].requires = ["qt::qtNetwork"]
qt_major = self.dependencies["qt"].ref.version.major
name = f"QCoro{qt_major}"
self.cpp_info.set_property("cmake_file_name", name)
self.cpp_info.set_property("cmake_target_name", f"{name}::{name}")

def _add_module(module_name, requires=None, interface=False):
component = self.cpp_info.components[module_name.lower()]
component.set_property("cmake_target_name", f"{name}::{module_name}")
if not interface:
component.libs = [f"{name}{module_name}"]
component.includedirs.append(os.path.join("include", f"qcoro{qt_major}", "qcoro"))
component.requires = requires or []
# TODO: Legacy, to be removed on Conan 2.0
component.names["cmake_find_package"] = module_name
component.names["cmake_find_package_multi"] = module_name

_add_module("Coro", interface=True)
_add_module("Core", requires=["coro", "qt::qtCore"])
_add_module("Network", requires=["coro", "core", "qt::qtCore", "qt::qtNetwork"])
if is_apple_os(self):
self.cpp_info.components["qcoro-network"].frameworks = ["CFNetwork"]

if self.dependencies["qt"].options.with_dbus:
self.cpp_info.components["qcoro-dbus"].set_property("cmake_target_name", "QCoro::DBus")
self.cpp_info.components["qcoro-dbus"].libs = ["QCoroDBus"]
self.cpp_info.components["qcoro-core"].requires = ["qt::qtDBus"]
self.cpp_info.components["network"].frameworks = ["CFNetwork"]
_add_module("Test", requires=["qt::qtTest"], interface=True)
if self._with_dbus:
_add_module("DBus", requires=["coro", "core", "qt::qtCore", "qt::qtDBus"])
if self._with_qml:
_add_module("Qml", requires=["coro", "qt::qtCore", "qt::qtQml"])
if self._with_quick:
_add_module("Quick", requires=["coro", "core", "qt::qtCore", "qt::qtGui", "qt::qtQuick"])
if self._with_websockets:
_add_module("WebSockets", requires=["coro", "core", "qt::qtCore", "qt::qtNetwork", "qt::qtWebSockets"])

self.cpp_info.builddirs.append(os.path.join("lib", "cmake", f"{name}Coro"))
macros_cmake_path = os.path.join("lib", "cmake", f"{name}Coro", "QCoroMacros.cmake")
self.cpp_info.set_property("cmake_build_modules", [macros_cmake_path])

# TODO: Legacy, to be removed on Conan 2.0
self.cpp_info.filenames["cmake_find_package"] = "QCoro6"
self.cpp_info.filenames["cmake_find_package_multi"] = "QCoro6"
self.cpp_info.names["cmake_find_package"] = "QCoro"
self.cpp_info.names["cmake_find_package_multi"] = "QCoro"
self.cpp_info.components["qcoro-core"].names["cmake_find_package"] = "Core"
self.cpp_info.components["qcoro-core"].names["cmake_find_package_multi"] = "Core"
self.cpp_info.components["qcoro-network"].names["cmake_find_package"] = "Network"
self.cpp_info.components["qcoro-network"].names["cmake_find_package_multi"] = "Network"
if self.dependencies["qt"].options.with_dbus:
self.cpp_info.components["qcoro-dbus"].names["cmake_find_package"] = "DBus"
self.cpp_info.components["qcoro-dbus"].names["cmake_find_package_multi"] = "DBus"
self.cpp_info.components["qcoro-core"].build_modules["cmake_find_package"].append(macros_cmake_path)
self.cpp_info.components["qcoro-core"].build_modules["cmake_find_package_multi"].append(macros_cmake_path)
self.cpp_info.names["cmake_find_package"] = name
self.cpp_info.names["cmake_find_package_multi"] = name
self.cpp_info.components["core"].build_modules["cmake_find_package"].append(macros_cmake_path)
self.cpp_info.components["core"].build_modules["cmake_find_package_multi"].append(macros_cmake_path)
13 changes: 9 additions & 4 deletions recipes/qcoro/all/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ project(test_package CXX)
find_package(QCoro6 REQUIRED COMPONENTS Core)
qcoro_enable_coroutines()

if(MSVC)
# Qt6Core.lib(qlocale_win.cpp.obj) : error LNK2038: mismatch detected for '_COROUTINE_ABI': value '1' doesn't match value '2' in test_package.obj
# https://stackoverflow.com/questions/70348706/error-lnk2038-mismatch-detected-for-coroutine-abi-value-2-doesnt-match-v
# https://devblogs.microsoft.com/oldnewthing/20230111-00/?p=107694
add_compile_definitions(_ALLOW_COROUTINE_ABI_MISMATCH)
endif()

add_executable(${PROJECT_NAME} test_package.cpp)
target_link_libraries(${PROJECT_NAME} QCoro::Core
Qt6::Core
Qt6::Concurrent)
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 20)
target_link_libraries(${PROJECT_NAME} QCoro6::Core Qt6::Concurrent)
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)
35 changes: 3 additions & 32 deletions recipes/qcoro/all/test_package/test_package.cpp
Original file line number Diff line number Diff line change
@@ -1,41 +1,12 @@
// SPDX-FileCopyrightText: 2021 Daniel Vrátil <[email protected]>
//
// SPDX-License-Identifier: MIT

#include "qcorofuture.h"

#include <QCoreApplication>
#include <QTimer>
#include <qcorofuture.h>
#include <QtConcurrent>

#include <iostream>
#include <random>

QCoro::Task<> startTask() {
const auto data = co_await QtConcurrent::run([]() {
QVector<std::uint64_t> data;
std::random_device rd{};
std::mt19937 gen{rd()};
data.reserve(10'000'000);
for (int i = 0; i < 10'000'000; ++i) {
data.push_back(gen());
}
return data;
return 0;
});

std::cout << "Generated " << data.size() << " random numbers" << std::endl;

const auto sum = co_await QtConcurrent::filteredReduced<std::uint64_t>(
data, [](const auto &) { return true; },
[](std::uint64_t &interm, std::uint64_t val) { interm += val; },
QtConcurrent::UnorderedReduce);

std::cout << "Calculated result: " << sum << std::endl;
qApp->quit();
}

int main(int argc, char **argv) {
QCoreApplication app(argc, argv);
QTimer::singleShot(0, startTask);
return app.exec();
return 0;
}
2 changes: 1 addition & 1 deletion recipes/qcoro/config.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
versions:
"0.4.0":
"0.10.0":
folder: all

0 comments on commit 3c9b962

Please sign in to comment.