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

Qbs: Added qbs test lib api and fixed handling spaces #16382

Merged
merged 3 commits into from
Jun 2, 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
4 changes: 3 additions & 1 deletion conan/api/subapi/new.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def get_builtin_template(template_name):
from conan.internal.api.new.autotools_lib import autotools_lib_files
from conan.internal.api.new.autoools_exe import autotools_exe_files
from conan.internal.api.new.local_recipes_index import local_recipes_index_files
from conan.internal.api.new.qbs_lib import qbs_lib_files
new_templates = {"basic": basic_file,
"cmake_lib": cmake_lib_files,
"cmake_exe": cmake_exe_files,
Expand All @@ -41,7 +42,8 @@ def get_builtin_template(template_name):
"autotools_lib": autotools_lib_files,
"autotools_exe": autotools_exe_files,
"alias": alias_file,
"local_recipes_index": local_recipes_index_files}
"local_recipes_index": local_recipes_index_files,
"qbs_lib": qbs_lib_files}
template_files = new_templates.get(template_name)
return template_files

Expand Down
103 changes: 103 additions & 0 deletions conan/internal/api/new/qbs_lib.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main


conanfile_sources = '''
import os

from conan import ConanFile
from conan.tools.qbs import Qbs


class {{package_name}}Recipe(ConanFile):
name = "{{name}}"
version = "{{version}}"

exports_sources = "*.cpp", "*.h", "*.qbs"
settings = "os", "compiler", "arch"
options = {"shared": [True, False]}
default_options = {"shared": False}

def build(self):
qbs = Qbs(self)
qbs.profile = ""
qbs_config = {"products.{{name}}.isShared": "true" if self.options.shared else "false"}
Comment on lines +22 to +23
Copy link
Member

Choose a reason for hiding this comment

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

This can probably be made default inside Qbs, but can be done in a later PR. The best would be to aim to something as CMake with the defaults of automatically managing self.options.shared if existing.

qbs.add_configuration("default", qbs_config)
qbs.build()

def package(self):
qbs = Qbs(self)
qbs.profile = ""
qbs.install()

def package_info(self):
self.cpp_info.libs = ["{{name}}"]
'''

qbs_lib_file = '''
Library {
property bool isShared: true
name: "{{name}}"
type: isShared ? "dynamiclibrary" : "staticlibrary"
files: [ "{{name}}.cpp" ]
Group {
name: "headers"
files: [ "{{name}}.h" ]
qbs.install: true
qbs.installDir: "include"
}
Depends { name: "cpp" }
Depends { name: "bundle" }
bundle.isBundle: false
install: true
qbs.installPrefix: ""
}
'''

test_conanfile_v2 = """import os

from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.qbs import Qbs
from conan.tools.build import cmd_args_to_string

class {{package_name}}TestConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "PkgConfigDeps"
Copy link
Member

Choose a reason for hiding this comment

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

I guess we want to move this later to QbsDeps, isn't it? later PR too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was thinking about it, but that creates a chicken-egg problem in tests - we will test QbsDeps using QbsDeps, is it OK?
I think, pkgconfig is fine here - it works fine in simple cases like this. Also, we don't invoke the pkg-config binary from Qbs (we simply read pc files and create modules, Qbs handles the rest). So no external deps here.

Copy link
Member

Choose a reason for hiding this comment

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

The conan new templates aim to generate the "canonical" and most recommended practice. If the QbsDeps is the generator that you prefer users to use, then it should be in the conan new template, and documented as such.

It is fine to test QbsDeps with the conan new template, as it is actually the closest to the user flow, so very recommended to test it with it.


def requirements(self):
self.requires(self.tested_reference_str)

def build(self):
qbs = Qbs(self)
qbs.profile = ""
qbs.build()
qbs.install()

def test(self):
if can_run(self):
cmd = os.path.join(self.package_folder, "bin", "example")
self.run(cmd_args_to_string([cmd]), env="conanrun")
"""

qbs_test_file = '''
Application {
name: "example"
consoleApplication: true
files: [ "example.cpp" ]
Depends { name: "cpp" }
install: true
qbs.installPrefix: ""
// external dependency via pkg-config
qbsModuleProviders: ["qbspkgconfig"]
moduleProviders.qbspkgconfig.libDirs: path
Depends { name: "{{name}}" }
}
'''

qbs_lib_files = {"conanfile.py": conanfile_sources,
"{{name}}.qbs": qbs_lib_file,
"{{name}}.cpp": source_cpp,
"{{name}}.h": source_h,
"test_package/conanfile.py": test_conanfile_v2,
"test_package/example.cpp": test_main,
"test_package/example.qbs": qbs_test_file}
8 changes: 4 additions & 4 deletions conan/tools/qbs/qbs.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os

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


Expand Down Expand Up @@ -59,7 +59,7 @@ def build(self, products=None):
config = self._configuration[name]
args.extend(_configuration_dict_to_commandlist(name, config))

cmd = 'qbs build %s' % (' '.join(args))
cmd = 'qbs build %s' % cmd_args_to_string(args)
self._conanfile.run(cmd)

def build_all(self):
Expand All @@ -79,7 +79,7 @@ def build_all(self):
config = self._configuration[name]
args.extend(_configuration_dict_to_commandlist(name, config))

cmd = 'qbs build %s' % (' '.join(args))
cmd = 'qbs build %s' % cmd_args_to_string(args)
self._conanfile.run(cmd)

def install(self):
Expand All @@ -92,5 +92,5 @@ def install(self):
for name in self._configuration:
args.append('config:%s' % name)

cmd = 'qbs install %s' % (' '.join(args))
cmd = 'qbs install %s' % cmd_args_to_string(args)
self._conanfile.run(cmd)
1 change: 1 addition & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@
"path": {'Darwin': f'{homebrew_root}/share/android-ndk'}
}
},
"qbs": {"disabled": True},
# TODO: Intel oneAPI is not installed in CI yet. Uncomment this line whenever it's done.
# "intel_oneapi": {
# "default": "2021.3",
Expand Down
14 changes: 14 additions & 0 deletions test/functional/toolchains/qbs/test_qbs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import pytest

from conan.test.utils.tools import TestClient

@pytest.mark.parametrize('shared', [
('False'),
('True'),
])
@pytest.mark.tool("qbs")
def test_api_qbs_create_lib(shared):
client = TestClient()
client.run("new qbs_lib -d name=hello -d version=1.0")
client.run("create . -o:h &:shared={shared}".format(shared=shared))
assert "compiling hello.cpp" in client.out