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 toolchain #29

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft

Qt toolchain #29

wants to merge 2 commits into from

Conversation

limdor
Copy link
Contributor

@limdor limdor commented May 15, 2021

No description provided.

limdor added 2 commits May 15, 2021 10:39
Until now the path detected was for the includes, it was assuming
that on Linux the Qt binaries are in the path and that the libraries
are part of the system libraries.
This makes clear that we are only using the include path and this is
the first step to implement Qt rules as a toolchain.
For the moment we print the folders for include, lib, and binary that
are detected and this will later be part of the toolchain.
@limdor limdor marked this pull request as draft May 15, 2021 08:40
# If QT_DIR is defined and it exists, we consider that it is a standalone installation
# Only in the case that is linux and QT_DIR is not defined it is considerd a none standalone
# installation
qt_dir_path = _get_env_var(repository_ctx, "QT_DIR", None)
Copy link

Choose a reason for hiding this comment

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

Is there a reason to not use https://docs.bazel.build/versions/main/skylark/lib/dict.html#get ? It is available at least from 1.0 onward.

Because this uses QT_DIR, I think repository_rule() down below should set environ = ["QT_DIR"] https://docs.bazel.build/versions/main/skylark/lib/globals.html#repository_rule

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As it is right now you are right that get could be used. What happened is that the code evolved. Initially getting the variable was done in a case insensitive way this is why get could have not been used. This should be redone and make clear what behavior is wanted, here the full discussion: #17 (comment)

@lummax
Copy link

lummax commented Jun 30, 2021

I took the liberty to adapt this a little to our use-case at work. This is stripped down to suit our needs, but I am happy to collaborate on this and help with this PR.

BUILD.bazel:

toolchain_type(
    name = "toolchain_type",
    visibility = ["//visibility:public"],
)

qt_toolchain(
    name = "conan_dependencies",
    moc = "@conan_dependencies_qt_installer//:moc",
    rcc = "@conan_dependencies_qt_installer//:rcc",
)

toolchain(
    name = "qt",
    toolchain = ":conan_dependencies",
    toolchain_type = ":toolchain_type",
)

defs.bzl:

load("@rules_cc//cc:defs.bzl", "cc_library")

QT_TOOLCHAIN = "//projects/support/bazel/compilation/qt:toolchain_type"

QtSDK = provider(
    fields = {
        "rcc": "Label for the the `rcc` binary",
        "moc": "Label for the the `moc` binary",
    },
)

def _qt_toolchain_impl(ctx):
    return [
        platform_common.ToolchainInfo(
            qt_sdk = QtSDK(
                rcc = ctx.executable.rcc,
                moc = ctx.executable.moc,
            ),
        ),
    ]

qt_toolchain = rule(
    implementation = _qt_toolchain_impl,
    attrs = {
        "rcc": attr.label(allow_files = True, executable = True, cfg = "exec"),
        "moc": attr.label(allow_files = True, executable = True, cfg = "exec"),
    },
)

def _qt_rcc(ctx):
    qt_sdk = ctx.toolchains[QT_TOOLCHAIN].qt_sdk
    out = ctx.actions.declare_file(ctx.label.name)

    resource_name = ctx.attr.resource_name
    if not resource_name:
        resource_name = out.basename
        if out.extension:
            resource_name = resource_name[:-len(out.extension) - 1]

    args = [
        "--name",
        resource_name,
        "--output",
        out.path,
        ctx.file.qrc.path,
    ]
    ctx.actions.run(
        inputs = ctx.files.files + [ctx.file.qrc],
        outputs = [out],
        arguments = args,
        executable = qt_sdk.rcc,
    )
    return [DefaultInfo(files = depset(direct = [out]))]

qt_rcc = rule(
    implementation = _qt_rcc,
    attrs = {
        "resource_name": attr.string(),
        "files": attr.label_list(allow_files = True),
        "qrc": attr.label(allow_single_file = True, mandatory = True),
    },
    toolchains = [QT_TOOLCHAIN],
)

def _qt_gen_qrc(ctx):
    out = ctx.actions.declare_file(ctx.label.name)

    content = """<!DOCTYPE RCC>
<RCC>
  <qresource>
%s
  </qresource>
</RCC>
"""
    lines = ["    <file>%s</file>" % f.path for f in ctx.files.files]
    ctx.actions.write(out, content % "\n".join(lines))
    return [DefaultInfo(files = depset(direct = [out]))]

qt_gen_qrc = rule(
    implementation = _qt_gen_qrc,
    attrs = {"files": attr.label_list(allow_files = True)},
)

def _qt_moc(ctx):
    qt_sdk = ctx.toolchains[QT_TOOLCHAIN].qt_sdk
    outputs = []

    for hdr in ctx.files.hdrs:
        out = ctx.actions.declare_file(hdr.basename[:-len(hdr.extension)] + ctx.attr.extension)
        outputs.append(out)

        ctx.actions.run(
            inputs = [hdr],
            outputs = [out],
            arguments = [hdr.path, "-o", out.path],
            executable = qt_sdk.moc,
        )

    return [DefaultInfo(files = depset(direct = outputs))]

qt_moc = rule(
    implementation = _qt_moc,
    attrs = {
        "hdrs": attr.label_list(allow_files = True),
        "extension": attr.string(default = "cpp"),
    },
    toolchains = [QT_TOOLCHAIN],
)

PS: thank you @limdor, https://github.com/limdor/bazel-examples/tree/master/linux_toolchain helped tremendously!

@lummax
Copy link

lummax commented Oct 22, 2021

And just for someone else to be able to find it: https://github.com/qt/qtbase/blob/dev/src/tools/rcc/rcc.cpp#L237

One should set SOURCE_DATE_EPOCH to a non-zero value when using rcc for optimal cache reuse.

qt_prefix = qt_dir_path
qt_includes = qt_prefix + "/include"
qt_libs = qt_prefix + "/lib"
qt_bins = qt_prefix + "/bin"
Copy link

Choose a reason for hiding this comment

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

hello, curious about this part, how can we pass bin path to qt_toolchain rule to get moc, rcc and uic path?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants