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

Rework QbsProfile #16742

Merged
merged 9 commits into from
Aug 27, 2024
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
3 changes: 2 additions & 1 deletion conan/internal/api/install/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"PremakeDeps": "conan.tools.premake",
"MakeDeps": "conan.tools.gnu",
"SConsDeps": "conan.tools.scons",
"QbsDeps": "conan.tools.qbs"
"QbsDeps": "conan.tools.qbs",
"QbsProfile": "conan.tools.qbs"
}


Expand Down
68 changes: 38 additions & 30 deletions conan/tools/microsoft/visual.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,36 +127,9 @@ def generate(self, scope="build"):
if vs_install_path == "": # Empty string means "disable"
return

msvc_update = conanfile.conf.get("tools.microsoft:msvc_update")
if compiler == "clang":
# The vcvars only needed for LLVM/Clang and VS ClangCL, who define runtime
if not conanfile.settings.get_safe("compiler.runtime"):
# NMake Makefiles will need vcvars activated, for VS target, defined with runtime
return
toolset_version = conanfile.settings.get_safe("compiler.runtime_version")
vs_version = {"v140": "14",
"v141": "15",
"v142": "16",
"v143": "17",
"v144": "17"}.get(toolset_version)
if vs_version is None:
raise ConanException("Visual Studio Runtime version (v140-v144) not defined")
vcvars_ver = {"v140": "14.0",
"v141": "14.1",
"v142": "14.2",
"v143": "14.3",
"v144": "14.4"}.get(toolset_version)
if vcvars_ver and msvc_update is not None:
vcvars_ver += f"{msvc_update}"
else:
vs_version = vs_ide_version(conanfile)
if int(vs_version) <= 14:
vcvars_ver = None
else:
compiler_version = str(conanfile.settings.compiler.version)
compiler_update = msvc_update or conanfile.settings.get_safe("compiler.update", "")
# The equivalent of compiler 19.26 is toolset 14.26
vcvars_ver = "14.{}{}".format(compiler_version[-1], compiler_update)
vs_version, vcvars_ver = _vcvars_versions(conanfile)
if vs_version is None:
return

vcvarsarch = _vcvars_arch(conanfile)

Expand Down Expand Up @@ -305,6 +278,41 @@ def _vcvars_path(version, vs_install_path):
return vcpath


def _vcvars_versions(conanfile):
compiler = conanfile.settings.get_safe("compiler")
msvc_update = conanfile.conf.get("tools.microsoft:msvc_update")
if compiler == "clang":
# The vcvars only needed for LLVM/Clang and VS ClangCL, who define runtime
if not conanfile.settings.get_safe("compiler.runtime"):
# NMake Makefiles will need vcvars activated, for VS target, defined with runtime
return None, None
toolset_version = conanfile.settings.get_safe("compiler.runtime_version")
vs_version = {"v140": "14",
"v141": "15",
"v142": "16",
"v143": "17",
"v144": "17"}.get(toolset_version)
if vs_version is None:
raise ConanException("Visual Studio Runtime version (v140-v144) not defined")
vcvars_ver = {"v140": "14.0",
"v141": "14.1",
"v142": "14.2",
"v143": "14.3",
"v144": "14.4"}.get(toolset_version)
if vcvars_ver and msvc_update is not None:
vcvars_ver += f"{msvc_update}"
else:
vs_version = vs_ide_version(conanfile)
if int(vs_version) <= 14:
vcvars_ver = None
else:
compiler_version = str(conanfile.settings.compiler.version)
compiler_update = msvc_update or conanfile.settings.get_safe("compiler.update", "")
# The equivalent of compiler 19.26 is toolset 14.26
vcvars_ver = "14.{}{}".format(compiler_version[-1], compiler_update)
return vs_version, vcvars_ver


def _vcvars_arch(conanfile):
"""
Computes the vcvars command line architecture based on conanfile settings (host) and
Expand Down
1 change: 1 addition & 0 deletions conan/tools/qbs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from conan.tools.qbs.qbs import Qbs
from conan.tools.qbs.qbsdeps import QbsDeps
from conan.tools.qbs.qbsprofile import QbsProfile
87 changes: 87 additions & 0 deletions conan/tools/qbs/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
architecture_map = {
'x86': 'x86',
'x86_64': 'x86_64',
'ppc32be': 'ppc',
'ppc32': 'ppc',
'ppc64le': 'ppc64',
'ppc64': 'ppc64',
'armv4': 'arm',
'armv4i': 'arm',
'armv5el': 'arm',
'armv5hf': 'arm',
'armv6': 'arm',
'armv7': 'arm',
'armv7hf': 'arm',
'armv7s': 'arm',
'armv7k': 'arm',
'armv8': 'arm64',
'armv8_32': 'arm64',
'armv8.3': 'arm64',
'sparc': 'sparc',
'sparcv9': 'sparc64',
'mips': 'mips',
'mips64': 'mips64',
'avr': 'avr',
's390': 's390x',
's390x': 's390x',
'asm.js': None,
'wasm': None,
'sh4le': 'sh'
}


build_variant_map = {
'Debug': 'debug',
'Release': 'release',
'RelWithDebInfo': 'profiling',
'MinSizeRel': 'release'
}


optimization_map = {
'MinSizeRel': 'small'
}


cxx_language_version_map = {
'98': 'c++98',
'gnu98': 'c++98',
'11': 'c++11',
'gnu11': 'c++11',
'14': 'c++14',
'gnu14': 'c++14',
'17': 'c++17',
'gnu17': 'c++17',
'20': 'c++20',
'gnu20': 'c++20'
}


target_platform_map = {
'Windows': 'windows',
'WindowsStore': 'windows',
'WindowsCE': 'windows',
'Linux': 'linux',
'Macos': 'macos',
'Android': 'android',
'iOS': 'ios',
'watchOS': 'watchos',
'tvOS': 'tvos',
'visionOS': 'xros',
'FreeBSD': 'freebsd',
'SunOS': 'solaris',
'AIX': 'aix',
'Emscripten': None,
'Arduino': 'none',
'Neutrino': 'qnx',
}


runtime_library_map = {
'static': 'static',
'dynamic': 'dynamic',
'MD': 'dynamic',
'MT': 'static',
'MDd': 'dynamic',
'MTd': 'static',
}
27 changes: 23 additions & 4 deletions conan/tools/qbs/qbs.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import os
import shutil

from conan.tools.build import build_jobs, cmd_args_to_string
from conan.errors import ConanException


def _configuration_dict_to_commandlist(name, config_dict):
command_list = ['config:%s' % name]
for key, value in config_dict.items():
Expand Down Expand Up @@ -57,11 +57,23 @@ def add_configuration(self, name, values):
"""
self._configuration[name] = values

def _qbs_settings_paths(self):
generators_folder = self._conanfile.generators_folder
qbs_settings_path = os.path.join(generators_folder, 'qbs_settings.txt')
if not os.path.exists(qbs_settings_path):
return None, None
return os.path.join(generators_folder, 'conan-qbs-settings-dir'), qbs_settings_path
Copy link
Member

Choose a reason for hiding this comment

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

This settings-dir is something new, I don't fully understand the connection to the QbsProfile.

Copy link
Contributor Author

@ABBAPOH ABBAPOH Aug 27, 2024

Choose a reason for hiding this comment

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

Qbs settings is a collection profiles (as well which profile is default). Profile is similar to Conan profile, just a bunch of toolchain properties.

$ qbs config --list
defaultProfile: "gcc"
profiles.gcc.cpp.compilerWrapper: "/usr/bin/ccache"
profiles.gcc.cpp.toolchainInstallPath: "/usr/bin"
profiles.gcc.qbs.toolchain: "gcc"

Settings are stored in an ini file on win/linux or in a plist file on Mac (in a dir controlled by the --settings-dir flag). Because of that plist, we can't write them directly from Conan (would require a new dependency) so I write settings in an intermediate text file in this dir that is later imported using qbs config --import and converted to an inner (ini/plist) format. I suppose I can change the inner format to JSON or use ini on all platforms in Qbs, but that won't work with old Qbs versions anyway; this hacky solution does.


def _get_common_arguments(self):
return [
args = []
settings_dir, _ = self._qbs_settings_paths()
if settings_dir is not None:
args.extend(['--settings-dir', settings_dir])
args.extend([
'--build-directory', self._conanfile.build_folder,
'--file', self._project_file,
]
])
return args

def resolve(self, parallel=True):
"""
Expand All @@ -70,6 +82,14 @@ def resolve(self, parallel=True):
"conan" module provider automatically adding dependencies to the project.
:param parallel: Whether to use multi-threaded resolving. Defaults to ``True``.
"""
generators_folder = self._conanfile.generators_folder
settings_dir, settings_path = self._qbs_settings_paths()
if settings_dir is not None:
shutil.rmtree(settings_dir, ignore_errors=True)
import_args = ['--settings-dir', settings_dir, '--import', settings_path]
import_cmd = 'qbs config %s' % cmd_args_to_string(import_args)
self._conanfile.run(import_cmd)

args = self._get_common_arguments()

if parallel:
Expand All @@ -80,7 +100,6 @@ def resolve(self, parallel=True):
if self.profile:
args.append('profile:%s' % self.profile)

generators_folder = self._conanfile.generators_folder
if os.path.exists(os.path.join(generators_folder, 'conan-qbs-deps')):
args.append('moduleProviders.conan.installDirectory:' + generators_folder)

Expand Down
Loading