Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

qt: use upstream package folder architecture #24193

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 5 additions & 19 deletions recipes/qt/5.x.x/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,9 +613,6 @@
if cross_building(self):
args.append(f"-extprefix {self.package_folder}")
args.append("-v")
args.append("-archdatadir %s" % os.path.join(self.package_folder, "bin", "archdatadir"))
args.append("-datadir %s" % os.path.join(self.package_folder, "bin", "datadir"))
args.append("-sysconfdir %s" % os.path.join(self.package_folder, "bin", "sysconfdir"))
if self.options.commercial:
args.append("-commercial")
else:
Expand Down Expand Up @@ -854,18 +851,7 @@
with chdir(self, "build_folder"):
self.run(f"{self._make_program()} install")
save(self, os.path.join(self.package_folder, "bin", "qt.conf"), """[Paths]
Prefix = ..
ArchData = bin/archdatadir
HostData = bin/archdatadir
Data = bin/datadir
Sysconf = bin/sysconfdir
LibraryExecutables = bin/archdatadir/bin
Plugins = bin/archdatadir/plugins
Imports = bin/archdatadir/imports
Qml2Imports = bin/archdatadir/qml
Translations = bin/datadir/translations
Documentation = bin/datadir/doc
Examples = bin/datadir/examples""")
Prefix = ..""")
copy(self, "*LICENSE*", os.path.join(self.source_folder, "qt5/"), os.path.join(self.package_folder, "licenses"),
excludes="qtbase/examples/*")
for module in self._submodules:
Expand All @@ -877,6 +863,7 @@
rm(self, "*.la*", os.path.join(self.package_folder, "lib"), recursive=True)
rm(self, "*.pdb*", os.path.join(self.package_folder, "lib"), recursive=True)
rm(self, "*.pdb", os.path.join(self.package_folder, "bin"), recursive=True)
rm(self, "*.pdb", os.path.join(self.package_folder, "plugins"), recursive=True)
# "Qt5Bootstrap" is internal Qt library - removing it to avoid linking error, since it contains
# symbols that are also in "Qt5Core.lib". It looks like there is no "Qt5Bootstrap.dll".
for fl in glob.glob(os.path.join(self.package_folder, "lib", "*Qt5Bootstrap*")):
Expand Down Expand Up @@ -946,7 +933,7 @@
filecontents += 'set(CMAKE_AUTOMOC_MACRO_NAMES "Q_OBJECT" "Q_GADGET" "Q_GADGET_EXPORT" "Q_NAMESPACE" "Q_NAMESPACE_EXPORT")\n'
save(self, os.path.join(self.package_folder, self._cmake_core_extras_file), filecontents)

def _create_private_module(module, dependencies=[]):

Check warning on line 936 in recipes/qt/5.x.x/conanfile.py

View workflow job for this annotation

GitHub Actions / Lint changed conanfile.py (v2 migration)

Dangerous default value [] as argument
if "Core" not in dependencies:
dependencies.append("Core")
dependencies_string = ';'.join(f'Qt5::{dependency}' for dependency in dependencies)
Expand Down Expand Up @@ -1015,7 +1002,7 @@
reqs.append(corrected_req)
return reqs

def _create_module(module, requires=[], has_include_dir=True):

Check warning on line 1005 in recipes/qt/5.x.x/conanfile.py

View workflow job for this annotation

GitHub Actions / Lint changed conanfile.py (v2 migration)

Dangerous default value [] as argument
componentname = f"qt{module}"
assert componentname not in self.cpp_info.components, f"Module {module} already present in self.cpp_info.components"
self.cpp_info.components[componentname].set_property("cmake_target_name", f"Qt5::{module}")
Expand Down Expand Up @@ -1049,7 +1036,7 @@
self.cpp_info.components[componentname].names["cmake_find_package_multi"] = pluginname
if not self.options.shared:
self.cpp_info.components[componentname].libs = [libname + libsuffix]
self.cpp_info.components[componentname].libdirs = [os.path.join("bin", "archdatadir", "plugins", plugintype)]
self.cpp_info.components[componentname].libdirs = [os.path.join("plugins", plugintype)]
self.cpp_info.components[componentname].includedirs = []
if "Core" not in requires:
requires.append("Core")
Expand Down Expand Up @@ -1491,7 +1478,7 @@
self.cpp_info.components["qtCore"].frameworks.append("Cocoa") # qtcore requires "_OBJC_CLASS_$_NSApplication" and more, which are in "Cocoa" framework
self.cpp_info.components["qtCore"].frameworks.append("Security") # qtcore requires "_SecRequirementCreateWithString" and more, which are in "Security" framework

self.cpp_info.components["qtCore"].builddirs.append(os.path.join("bin","archdatadir","bin"))
self.cpp_info.components["qtCore"].builddirs.append(os.path.join("bin"))
_add_build_module("qtCore", self._cmake_core_extras_file)
_add_build_module("qtCore", self._cmake_qt5_private_file("Core"))

Expand All @@ -1506,8 +1493,7 @@
os.path.join("lib", "cmake", "Qt5Core", "Qt5CoreConfigExtrasMkspecDir.cmake"))
mkspecs_dir_begin = qt5core_config_extras_mkspec_dir_cmake.find("mkspecs/")
mkspecs_dir_end = qt5core_config_extras_mkspec_dir_cmake.find("\"", mkspecs_dir_begin)
mkspecs_dir = qt5core_config_extras_mkspec_dir_cmake[mkspecs_dir_begin:mkspecs_dir_end].split('/')
mkspecs_path = os.path.join("bin", "archdatadir", *mkspecs_dir)
mkspecs_path = qt5core_config_extras_mkspec_dir_cmake[mkspecs_dir_begin:mkspecs_dir_end]
assert os.path.exists(mkspecs_path)
self.cpp_info.components["qtCore"].includedirs.append(mkspecs_path)

Expand Down
11 changes: 0 additions & 11 deletions recipes/qt/5.x.x/test_package/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,6 @@ def generate(self):
qt_conf = textwrap.dedent(f"""\
[Paths]
Prefix = {qt_install_prefix}
ArchData = bin/archdatadir
HostData = bin/archdatadir
Data = bin/datadir
Sysconf = bin/sysconfdir
LibraryExecutables = bin/archdatadir/bin
Plugins = bin/archdatadir/plugins
Imports = bin/archdatadir/imports
Qml2Imports = bin/archdatadir/qml
Translations = bin/datadir/translations
Documentation = bin/datadir/doc
Examples = bin/datadir/examples
""")
save(self, "qt.conf", qt_conf)

Expand Down
13 changes: 1 addition & 12 deletions recipes/qt/5.x.x/test_v1_package/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,7 @@ def build_requirements(self):

def generate(self):
save(self, "qt.conf", """[Paths]
Prefix = {}
ArchData = bin/archdatadir
HostData = bin/archdatadir
Data = bin/datadir
Sysconf = bin/sysconfdir
LibraryExecutables = bin/archdatadir/bin
Plugins = bin/archdatadir/plugins
Imports = bin/archdatadir/imports
Qml2Imports = bin/archdatadir/qml
Translations = bin/datadir/translations
Documentation = bin/datadir/doc
Examples = bin/datadir/examples""".format(self.dependencies["qt"].package_folder.replace('\\', '/')))
Prefix = {}""".format(self.dependencies["qt"].package_folder.replace('\\', '/')))

def _is_mingw(self):
return self.settings.os == "Windows" and self.settings.compiler == "gcc"
Expand Down
29 changes: 13 additions & 16 deletions recipes/qt/6.x.x/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,13 +480,6 @@ def generate(self):

tc.absolute_paths = True

package_folder = self.package_folder.replace('\\', '/')
tc.variables["INSTALL_MKSPECSDIR"] = f"{package_folder}/res/archdatadir/mkspecs"
tc.variables["INSTALL_ARCHDATADIR"] = f"{package_folder}/res/archdatadir"
tc.variables["INSTALL_LIBEXECDIR"] = f"{package_folder}/bin"
tc.variables["INSTALL_DATADIR"] = f"{package_folder}/res/datadir"
tc.variables["INSTALL_SYSCONFDIR"] = f"{package_folder}/res/sysconfdir"

tc.variables["QT_BUILD_TESTS"] = "OFF"
tc.variables["QT_BUILD_EXAMPLES"] = "OFF"

Expand Down Expand Up @@ -821,7 +814,7 @@ def package(self):
rm(self, "*.la*", os.path.join(self.package_folder, "lib"), recursive=True)
rm(self, "*.pdb*", self.package_folder, recursive=True)
rm(self, "ensure_pro_file.cmake", self.package_folder, recursive=True)
os.remove(os.path.join(self.package_folder, "bin", "qt-cmake-private-install.cmake"))
os.remove(os.path.join(self.package_folder, "libexec" if Version(self.version) >= "6.5.0" and self.settings.os != "Windows" else "bin", "qt-cmake-private-install.cmake"))

for m in os.listdir(os.path.join(self.package_folder, "lib", "cmake")):
if os.path.isfile(os.path.join(self.package_folder, "lib", "cmake", m, f"{m}Macros.cmake")):
Expand Down Expand Up @@ -860,18 +853,22 @@ def package(self):
targets.append("qsb")
if self.options.qtdeclarative:
targets.extend(["qmltyperegistrar", "qmlcachegen", "qmllint", "qmlimportscanner"])
targets.extend(["qmlformat", "qml", "qmlprofiler", "qmlpreview", "qmltestrunner"])
targets.extend(["qmlformat", "qml", "qmlprofiler", "qmlpreview"])
# Note: consider "qmltestrunner", see https://github.com/conan-io/conan-center-index/issues/24276
if self.options.get_safe("qtremoteobjects"):
targets.append("repc")
if self.options.get_safe("qtscxml"):
targets.append("qscxmlc")
for target in targets:
exe_path = None
for path_ in [f"bin/{target}{extension}",
f"lib/{target}{extension}"]:
f"lib/{target}{extension}",
f"libexec/{target}{extension}"]:
if os.path.isfile(os.path.join(self.package_folder, path_)):
exe_path = path_
break
else:
assert False, f"Could not find executable {target}{extension} in {self.package_folder}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When trying to build locally to test this out, I'm finding that I'm hitting this assert. Any idea how to tackle it?

I'm building in

[settings]
arch=armv8
build_type=Release
compiler=apple-clang
compiler.cppstd=gnu17
compiler.libcxx=libc++
compiler.version=15
os=Macos

if that helps :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wanted to test on my side but Qt 6.7.1 build failed, will try with a different version later. Testing with v1 and

[settings]
arch=x86_64
arch_build=x86_64
build_type=Release
compiler=apple-clang
compiler.libcxx=libc++
compiler.version=15
os=Macos
os_build=Macos
[options]
[build_requires]
[env]
[conf]
tools.cmake.cmaketoolchain:generator=Ninja

(Xcode 15.4)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! If using Conan 2.4, you might want to use this fix #24236 for it to compile (Or wait until it gets merged in a few hours/tomorrow and update this PR with the changes)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in my case build error was from Qt, and that PR is about Windows :)

/Applications/Xcode-15.4.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/usr/include/c++/v1/__memory/unique_ptr.h:66:19: error: invalid application of 'sizeof' to an incomplete type 'QQmlJS::Dom::BindingValue'
...
/Users/kambala/.conan/data/qt/6.6.3/_/_/source/src/qtdeclarative/src/qmldom/qqmldomelements_p.h:513:7: note: forward declaration of 'QQmlJS::Dom::BindingValue'
class BindingValue;

just built with -o 'qt/*:essential_modules=False' and all went fine, didn't face that error. Could you post exact conan command you issued and the exact assert message (i.e. which executable wasn't found)?

Also pipeline was green...

Copy link
Contributor

@jcar87 jcar87 Jun 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also pipeline was green...

At the moment this is unfortunately misleading, because the recipe is currently set to build on CI with different options than a user would get, see: #23911

This is wrong and needs to be fixed - however because of the large amount of versions we are maintaining, this would result in very long CI builds.

Will try to troubleshoot this locally, the expectation is that with -o 'qt/*:essential_modules=True' the changes in this PR (which are otherwise great) should not result in failures

Copy link
Contributor

@jcar87 jcar87 Jun 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get this too, with a simple

conan create . --version=6.7.1

keeping in mind that this causes essential_modules=True (by default)


ERROR: qt/6.7.1: Error in package() method, line 871
        assert False, f"Could not find executable {target}{extension} in {self.package_folder}"
        AssertionError: Could not find executable qmltestrunner in /xxx/p/b/qt6f56e4472f231/p

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this being changed from a warning to an assert in this PR?
On master it doesn't find this tool either qmltestrunner , but it is a warning.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qmltestrunner is not a documented qt app as far as I can find, and it seems like its only built when certain conditions are met (including, potentially, the building of tests) - so I've added a commit to remove it from the list of checked executables, until we can work out if this is needed and how to fix this

as a side note, and I appreciate the changes on this PR existed previously, it is very difficult to review pull requests when there are changes that have nothing to do with the PR description :(

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried building with v2 and faced that error as well.

Also input from Eric:

it is meant to avoid regressions, because this PR changed the folder in which executables are packaged
If this assert is triggered for executable qmltestrunner ,then someone should go take a look in the package folder to find where is is stored, and then add the path in this list https://github.com/conan-io/conan-center-index/pull/24193/files#diff-c548829da9d38ae15a8cb4447140bc50ac3f38250d1f348decd9569dc3298b24R862
qmltestrunner may only be built when -o qt/*:qtshadertools=True

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qmltestrunner is not packaged - either before or after the changes in this PR, because it is not being built.

The problem exists outside of the changes in this PR and it unrelated - so let's address the package structure first.

if not exe_path:
self.output.warning(f"Could not find path to {target}{extension}")
filecontents += textwrap.dedent(f"""\
Expand Down Expand Up @@ -946,8 +943,8 @@ def package_info(self):
self.cpp_info.names["cmake_find_package_multi"] = "Qt6"

# consumers will need the QT_PLUGIN_PATH defined in runenv
self.runenv_info.define("QT_PLUGIN_PATH", os.path.join(self.package_folder, "res", "archdatadir", "plugins"))
self.buildenv_info.define("QT_PLUGIN_PATH", os.path.join(self.package_folder, "res", "archdatadir", "plugins"))
self.runenv_info.define("QT_PLUGIN_PATH", os.path.join(self.package_folder, "plugins"))
self.buildenv_info.define("QT_PLUGIN_PATH", os.path.join(self.package_folder, "plugins"))

self.buildenv_info.define("QT_HOST_PATH", self.package_folder)

Expand Down Expand Up @@ -1004,7 +1001,7 @@ def _create_plugin(pluginname, libname, plugintype, requires):
self.cpp_info.components[componentname].names["cmake_find_package_multi"] = pluginname
if not self.options.shared:
self.cpp_info.components[componentname].libs = [libname + libsuffix]
self.cpp_info.components[componentname].libdirs = [os.path.join("res", "archdatadir", "plugins", plugintype)]
self.cpp_info.components[componentname].libdirs = [os.path.join("plugins", plugintype)]
self.cpp_info.components[componentname].includedirs = []
if "Core" not in requires:
requires.append("Core")
Expand All @@ -1027,7 +1024,7 @@ def _create_plugin(pluginname, libname, plugintype, requires):
_create_module("Core", core_reqs)
pkg_config_vars = [
"bindir=${prefix}/bin",
"libexecdir=${prefix}/bin",
"libexecdir=${prefix}/libexec",
"exec_prefix=${prefix}",
]
self.cpp_info.components["qtCore"].set_property("pkg_config_custom_content", "\n".join(pkg_config_vars))
Expand All @@ -1044,7 +1041,7 @@ def _create_plugin(pluginname, libname, plugintype, requires):
self.cpp_info.components["qtPlatform"].set_property("cmake_target_name", "Qt6::Platform")
self.cpp_info.components["qtPlatform"].names["cmake_find_package"] = "Platform"
self.cpp_info.components["qtPlatform"].names["cmake_find_package_multi"] = "Platform"
self.cpp_info.components["qtPlatform"].includedirs = [os.path.join("res", "archdatadir", "mkspecs", self._xplatform())]
self.cpp_info.components["qtPlatform"].includedirs = [os.path.join("mkspecs", self._xplatform())]
if self.options.with_dbus:
_create_module("DBus", ["dbus::dbus"])
if self.settings.os == "Windows":
Expand Down Expand Up @@ -1504,7 +1501,7 @@ def _create_plugin(pluginname, libname, plugintype, requires):
# https://github.com/qt/qtbase/blob/v6.6.1/src/corelib/CMakeLists.txt#L1079-L1082
self.cpp_info.components["qtCore"].frameworks.append("WatchKit")

self.cpp_info.components["qtCore"].builddirs.append(os.path.join("res", "archdatadir", "bin"))
self.cpp_info.components["qtCore"].builddirs.append(os.path.join("bin"))
_add_build_module("qtCore", self._cmake_executables_file)
_add_build_module("qtCore", self._cmake_qt6_private_file("Core"))
if self.settings.os in ["Windows", "iOS"]:
Expand Down
16 changes: 1 addition & 15 deletions recipes/qt/6.x.x/test_package/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,8 @@ def build_requirements(self):

def generate(self):
path = self.dependencies["qt"].package_folder.replace("\\", "/")
folder = os.path.join(path, "bin")
bin_folder = "bin" if self.settings.os == "Windows" else "libexec"
save(self, "qt.conf", f"""[Paths]
Prefix = {path}
ArchData = {folder}/archdatadir
HostData = {folder}/archdatadir
Data = {folder}/datadir
Sysconf = {folder}/sysconfdir
LibraryExecutables = {folder}/archdatadir/{bin_folder}
HostLibraryExecutables = bin
Plugins = {folder}/archdatadir/plugins
Imports = {folder}/archdatadir/imports
Qml2Imports = {folder}/archdatadir/qml
Translations = {folder}/datadir/translations
Documentation = {folder}/datadir/doc
Examples = {folder}/datadir/examples""")
Prefix = {path}""")

VirtualRunEnv(self).generate()
if can_run(self):
Expand Down
13 changes: 1 addition & 12 deletions recipes/qt/6.x.x/test_v1_package/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,7 @@ def build_requirements(self):

def generate(self):
save(self, "qt.conf", """[Paths]
Prefix = {}
ArchData = bin/archdatadir
HostData = bin/archdatadir
Data = bin/datadir
Sysconf = bin/sysconfdir
LibraryExecutables = bin/archdatadir/bin
Plugins = bin/archdatadir/plugins
Imports = bin/archdatadir/imports
Qml2Imports = bin/archdatadir/qml
Translations = bin/datadir/translations
Documentation = bin/datadir/doc
Examples = bin/datadir/examples""".format(self.dependencies["qt"].package_folder.replace('\\', '/')))
Prefix = {}""".format(self.dependencies["qt"].package_folder.replace('\\', '/')))

def _is_mingw(self):
return self.settings.os == "Windows" and self.settings.compiler == "gcc"
Expand Down
Loading