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

Add support for passing a custom target specification. #836

Merged
merged 13 commits into from
Jul 22, 2021
Merged

Add support for passing a custom target specification. #836

merged 13 commits into from
Jul 22, 2021

Conversation

davidskidmore
Copy link
Contributor

A label doesn't seem to express both a string (as in a triple like x86_64-unkown-none) and a path to a custom target specification (as in something like //path/to/target.json), so this change is propose treating target_json as an override of target_triple.

Copy link
Collaborator

@UebelAndre UebelAndre left a comment

Choose a reason for hiding this comment

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

Is there a way that this code path can be tested in CI? I think the rules should definitely be supportive to custom targets but I'd like to know when a change impacts support for custom code paths. Perhaps something can be added with the existing unit tests?

@UebelAndre
Copy link
Collaborator

Also, to follow up on #770 (comment)

I think this approach makes sense. I would probably add some protections against trying to set both target and target_json but I like the idea of two dedicated attributes for defining the targets, especially after having looked at the Embedonomicon. To me it seems like a natural translation in Bazel and a great addition to the toolchain. But others may know better than I.

Copy link
Member

@hlopko hlopko left a comment

Choose a reason for hiding this comment

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

Thanks for working on this!

rust/toolchain.bzl Show resolved Hide resolved
rust/toolchain.bzl Show resolved Hide resolved
Copy link
Member

@hlopko hlopko left a comment

Choose a reason for hiding this comment

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

LGTM, thank you!

@@ -193,6 +193,8 @@ def _rust_toolchain_impl(ctx):
rustfmt = ctx.file.rustfmt,
cargo = ctx.file.cargo,
clippy_driver = ctx.file.clippy_driver,
target_json = ctx.file.target_json,
target_flag_value = ctx.file.target_json.path if ctx.file.target_json != None else ctx.attr.target_triple,
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
target_flag_value = ctx.file.target_json.path if ctx.file.target_json != None else ctx.attr.target_triple,
target_flag_value = ctx.file.target_json.path if ctx.file.target_json else ctx.attr.target_triple,

@hlopko
Copy link
Member

hlopko commented Jul 19, 2021

Oh actually, +1 to @UebelAndre's comment, could you please add a check in the toolchain.bzl ensuring that target_json and target_triple are not both specified at the same time, and if yes, then fail() with a nice error message?

@davidskidmore
Copy link
Contributor Author

Is there a way that this code path can be tested in CI? I think the rules should definitely be supportive to custom targets but I'd like to know when a change impacts support for custom code paths. Perhaps something can be added with the existing unit tests?

I'm a little out of my depth here, being pretty new to writing bazel build logic. Do you have any suggestions on where the new unit tests would go?

@UebelAndre
Copy link
Collaborator

I'm a little out of my depth here, being pretty new to writing bazel build logic. Do you have any suggestions on where the new unit tests would go?

We have unit tests located in test/unit. But this one might be pretty unique since the change is to the toolchain? I think a transition might be needed to build a target using a newly registered toolchain which exercises this code path. Maybe someone else might have a simpler path forward though?

@davidskidmore
Copy link
Contributor Author

Sorry, but I don't really follow. I've tried throwing together a bare bones unit test:

"""Unit tests for rust toolchains."""

load("@bazel_skylib//lib:unittest.bzl", "analysistest")
load("//rust:toolchain.bzl", "rust_stdlib_filegroup", "rust_toolchain")

def _toolchain_specifies_target_triple_test_impl(ctx):
    env = analysistest.begin(ctx)
    target_under_test = analysistest.target_under_test(env)

    # TODO: assert something

    return analysistest.end(env)

toolchain_specifies_target_triple_test = analysistest.make(_toolchain_specifies_target_triple_test_impl)

def _toolchain_test():
    rust_stdlib_filegroup(
        name = "std_libs_none",
        srcs = [],
    )

    rust_toolchain(
        name = "rust_x86_64_none_impl",
        binary_ext = "",
        dylib_ext = ".so",
        os = "linux",
        rust_lib = ":std_libs_none",
        staticlib_ext = ".a",
        stdlib_linkflags = [],
    )

    toolchain_specifies_target_triple_test(
        name = "toolchain_specifies_target_triple_test",
        target_under_test = ":rust_toolchain",
    )

def toolchain_test_suite(name):
    _toolchain_test()

    native.test_suite(
        name = name,
        tests = [":toolchain_specifies_target_triple_test"],
    )

But bazel isn't handling handle references to rust_toolchain correctly:

ERROR: ~/rules_rust/test/unit/toolchain/BUILD:3:21: in target_under_test attribute of toolchain_specifies_target_triple_test rule //test/unit/toolchain:toolchain_specifies_target_triple_test: rule '//test/unit/toolchain:rust_toolchain' does not exist. Since this rule was created by the macro 'toolchain_test_suite', the error might have been caused by the macro implementation
ERROR: Analysis of target '//test/unit/toolchain:toolchain_specifies_target_triple_test' failed; build aborted: Analysis of target '//test/unit/toolchain:toolchain_specifies_target_triple_test' failed

@hlopko
Copy link
Member

hlopko commented Jul 20, 2021

Oh wow, you actually almost did make it work. In your target_under_test you have ":rust_toolchain", but you actually want ":rust_x86_64_none_impl". Since you started, let's endure :)

So I guess you want to get the ToolchainInfo from the target under test in _toolchain_specifies_target_triple_test_impl and verify that the target_flag_value is as expected, and then add another test with a toolchain that sets target_json and assert different target_flag_value, and presence of target_json file in the provider. That all makes a lot of sense, thank you for the excellence!

@davidskidmore
Copy link
Contributor Author

Thanks for the advice, that was it! I was quite able to get expect_failure working for a unit test that could demonstrate passing both triple and json at the same time, but I think we're in a pretty good place testing wise.

Copy link
Collaborator

@UebelAndre UebelAndre left a comment

Choose a reason for hiding this comment

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

Would it be possible to rename the x86_64-unknown-linux-gun.json file to something like toolchain-test-triple.json? I feel like it'd be better to set values here that would never match naturally to confirm we're not benefiting from any coincidental assumptions. I think the cross platform tests will probably catch this but I still feel it's worth going the extra step here? Could be convinced otherwise though. Let me know what you think 😅

Otherwise, I think this is looking awesome! Thanks for all the work you put into this 🙏

@UebelAndre
Copy link
Collaborator

Also, docs can be fixed by running ./docs/update_docs.sh, The error message in CI should describe the same but hoping this message is easier to find 😄

@davidskidmore
Copy link
Contributor Author

The target specifications are usually named after the target they're for, but I think it makes sense for the tests to use something more unique.

@UebelAndre
Copy link
Collaborator

The target specifications are usually named after the target they're for, but I think it makes sense for the tests to use something more unique.

I agree and would definitely maintain this behavior for any target I define, but yeah, tests should be able to afford the flexibility.

Copy link
Collaborator

@UebelAndre UebelAndre left a comment

Choose a reason for hiding this comment

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

One final nit then otherwise looks good to me!

test/unit/toolchain/toolchain_test.bzl Outdated Show resolved Hide resolved
@hlopko
Copy link
Member

hlopko commented Jul 22, 2021

LGTM, I think this is good to go.

@hlopko hlopko dismissed UebelAndre’s stale review July 22, 2021 06:18

I believe the nit was talked through and decided not to do anything more in this PR.

@hlopko hlopko merged commit 37982c5 into bazelbuild:main Jul 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants