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

Binary that depends on cloudflare/circl can't be built cross-platform #4154

Open
aaomidi opened this issue Oct 23, 2024 · 9 comments
Open

Binary that depends on cloudflare/circl can't be built cross-platform #4154

aaomidi opened this issue Oct 23, 2024 · 9 comments

Comments

@aaomidi
Copy link

aaomidi commented Oct 23, 2024

What version of rules_go are you using?

0.50.1

What version of gazelle are you using?

0.39.1

What version of Bazel are you using?

7.4.0

Does this issue reproduce with the latest releases of all the above?

Yes

What operating system and processor architecture are you using?

Darwin ARM64

Any other potentially useful information about your toolchain?

This is related to the infamous circl dependency.

What did you do?

I have a go_binary that through a long list of dependencies ends up depending on circl. I do get circl from the BCR:

bazel_dep(
    name = "circl",
    version = "1.3.8",
)

My binary rule is defined as such:

go_binary(
    name = "api",
    embed = [":api_lib"],
    gotags = ["purego"],
    pure = "on",
)

I try to build it like:

bazel build //control-plane/api --platforms=@rules_go//go/toolchain:linux_arm64

My error:

ERROR: /private/var/tmp/_bazel_amir/3dbd0b78d662a8a6e641b2d6e1f7442e/external/bazel_tools/tools/cpp/BUILD:58:19: in cc_toolchain_alias rule @@bazel_tools//tools/cpp:current_cc_toolchain: 
Traceback (most recent call last):
        File "/virtual_builtins_bzl/common/cc/cc_toolchain_alias.bzl", line 26, column 48, in _impl
        File "/virtual_builtins_bzl/common/cc/cc_helper.bzl", line 225, column 17, in _find_cpp_toolchain
Error in fail: Unable to find a CC toolchain using toolchain resolution. Target: @@bazel_tools//tools/cpp:current_cc_toolchain, Platform: @@rules_go~//go/toolchain:linux_arm64, Exec platform: @@bazel_tools//tools:host_platform
ERROR: /private/var/tmp/_bazel_amir/3dbd0b78d662a8a6e641b2d6e1f7442e/external/bazel_tools/tools/cpp/BUILD:58:19: Analysis of target '@@bazel_tools//tools/cpp:current_cc_toolchain' failed

What did you expect to see?

I expected this build to not need the C++ toolchain.

What did you see instead?

An error for C++ toolchain.

@fmeum
Copy link
Member

fmeum commented Oct 23, 2024

Please test whether 87e66bb fixes this for you.

@aaomidi
Copy link
Author

aaomidi commented Oct 23, 2024

I've added the following to my MODULE.bazel

git_override(
    module_name = "rules_go",
    commit = "87e66bb70858570ac668f95662d6070417d5a416",
    remote = "https://github.com/bazel-contrib/rules_go.git",
)

And unfortunately

bazel build //control-plane/api --platforms=@rules_go//go/toolchain:linux_arm64


ERROR: /private/var/tmp/_bazel_amir/3dbd0b78d662a8a6e641b2d6e1f7442e/external/bazel_tools/tools/cpp/BUILD:58:19: in cc_toolchain_alias rule @@bazel_tools//tools/cpp:current_cc_toolchain: 
Traceback (most recent call last):
        File "/virtual_builtins_bzl/common/cc/cc_toolchain_alias.bzl", line 26, column 48, in _impl
        File "/virtual_builtins_bzl/common/cc/cc_helper.bzl", line 225, column 17, in _find_cpp_toolchain
Error in fail: Unable to find a CC toolchain using toolchain resolution. Target: @@bazel_tools//tools/cpp:current_cc_toolchain, Platform: @@rules_go~//go/toolchain:linux_arm64, Exec platform: @@bazel_tools//tools:host_platform
ERROR: /private/var/tmp/_bazel_amir/3dbd0b78d662a8a6e641b2d6e1f7442e/external/bazel_tools/tools/cpp/BUILD:58:19: Analysis of target '@@bazel_tools//tools/cpp:current_cc_toolchain' failed

Fails

I also tried with

bazel build //control-plane/api --platforms=@rules_go//go/toolchain:linux_arm64 --@rules_go//go/config:pure=true

and received a failure

@aaomidi
Copy link
Author

aaomidi commented Oct 23, 2024

This might be a significantly simpler repro.

bazel build --repo_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 --@rules_go//go/config:pure=true @circl//dh/x448:x448 

@aaomidi
Copy link
Author

aaomidi commented Oct 23, 2024

bazel query "somepath(//control-plane/api, @rules_go//:cgo_context_data)"
//control-plane/api:api
@rules_go//:go_context_data
@rules_go//:cgo_context_data

@sallustfire
Copy link
Contributor

bazel query "somepath(//control-plane/api, @rules_go//:cgo_context_data)"
//control-plane/api:api
@rules_go//:go_context_data
@rules_go//:cgo_context_data

What about if you try cquery? @rules_go//:go_context_data does depend on @rules_go//:cgo_context_data depending on transitions.

@aaomidi
Copy link
Author

aaomidi commented Oct 23, 2024

Heh interesting..

//control-plane/api:api (92fba1e)
@rules_go//:go_context_data (8754af7)
@@rules_go~~go_sdk~io_bazel_rules_nogo//:nogo (4bda251)
//ci/analyzers:limited_nogo (4bda251)
//ci/analyzers:limited_nogo_actual (da2a0f7)
@rules_go//:stdlib (f0a298a)
@rules_go//:cgo_context_data (f0a298a)

I disabled nogo and after that cquery returns empty.

However, even after removing nogo:

bazel build --repo_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 --@rules_go//go/config:pure=true @circl//dh/x448:x448

Fails to build

ERROR: /private/var/tmp/_bazel_amir/3dbd0b78d662a8a6e641b2d6e1f7442e/external/bazel_tools/tools/cpp/BUILD:58:19: in cc_toolchain_alias rule @@bazel_tools//tools/cpp:current_cc_toolchain: 
Traceback (most recent call last):
        File "/virtual_builtins_bzl/common/cc/cc_toolchain_alias.bzl", line 26, column 48, in _impl
        File "/virtual_builtins_bzl/common/cc/cc_helper.bzl", line 225, column 17, in _find_cpp_toolchain
Error in fail: Unable to find a CC toolchain using toolchain resolution. Target: @@bazel_tools//tools/cpp:current_cc_toolchain, Platform: @@bazel_tools//tools:host_platform, Exec platform: @@bazel_tools//tools:host_platform
ERROR: /private/var/tmp/_bazel_amir/3dbd0b78d662a8a6e641b2d6e1f7442e/external/bazel_tools/tools/cpp/BUILD:58:19: Analysis of target '@@bazel_tools//tools/cpp:current_cc_toolchain' failed
INFO: Analyzed target @@circl~//dh/x448:x448 (8 packages loaded, 4748 targets configured).
WARNING: errors encountered while analyzing target '@@circl~//dh/x448:x448', it will not be built.

And unfortunately I can't run:

bazel cquery --@rules_go//go/config:pure=true --repo_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1  "somepath(@circl//dh/x448:x448, @rules_go//:cgo_context_data)"

To see why this is happening since it fails with that same error.

@aaomidi
Copy link
Author

aaomidi commented Oct 23, 2024

So, I've added two patches onto circl to make this work:

--- dh/x25519/BUILD.bazel
+++ dh/x25519/BUILD.bazel
@@ -13,7 +13,6 @@ go_library(
         "key.go",
         "table.go",
     ],
     cgo = True,
-    cdeps = ["//math/fp25519:header"],
     importpath = "github.com/cloudflare/circl/dh/x25519",
     visibility = ["//visibility:public"],

--- dh/x448/BUILD.bazel
+++ dh/x448/BUILD.bazel
@@ -14,7 +14,6 @@ go_library(
         "table.go",
     ],
     cgo = True,
-    cdeps = ["//math/fp448:header"],
     importpath = "github.com/cloudflare/circl/dh/x448",
     visibility = ["//visibility:public"],
     deps = [

How I consume this:

bazel_dep(
    name = "circl",
    version = "1.3.8",
)
single_version_override(
    module_name = "circl",
    patches = [
        "//third_party/patches/circl:nocgo.patch",
    ],
)

With these changes, I can build fine now. I think what's happening is that unfortunately cgo = True in the dependency is forcing the go toolchain to look for C++ toolchain. It seems like what my original request is doesn't properly propagate downstream?

Any help to figure out how to fix this would be appreciated. Maybe I can maintain my own patches, but that seems awfully expensive just for this.

@aaomidi
Copy link
Author

aaomidi commented Oct 23, 2024

I tried a different strategy. In this strategy I do not use circl from BCR and instead:

go_deps.gazelle_override(
    directives = [
        "gazelle:build_tags purego",
        "gazelle:exclude **/*_amd64*",
    ],
    path = "github.com/cloudflare/circl",
)

This allows me to build the go_binary target below:

go_library(
    name = "api_lib",
    srcs = ["main.go"],
    importpath = "github.com/spirl/spirl/control-plane/api",
    deps = ["//control-plane/api/cmd"],
)

go_binary(
    name = "api",
    embed = [":api_lib"],
    gotags = ["purego"],
    pure = "on",  # No CGO
    x_defs = {
        "github.com/spirl/spirl/common/version.version": "${STABLE_VERSION}",
    },
)

However. It does not allow me to build the api_lib target:

Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
external/gazelle~~go_deps~com_github_cloudflare_circl/math/fp25519/fp.go:184:32: undefined: cmov
external/gazelle~~go_deps~com_github_cloudflare_circl/math/fp25519/fp.go:187:33: undefined: cswap
external/gazelle~~go_deps~com_github_cloudflare_circl/math/fp25519/fp.go:190:26: undefined: add
external/gazelle~~go_deps~com_github_cloudflare_circl/math/fp25519/fp.go:193:26: undefined: sub
external/gazelle~~go_deps~com_github_cloudflare_circl/math/fp25519/fp.go:196:26: undefined: addsub
external/gazelle~~go_deps~com_github_cloudflare_circl/math/fp25519/fp.go:199:26: undefined: mul
external/gazelle~~go_deps~com_github_cloudflare_circl/math/fp25519/fp.go:202:23: undefined: sqr
external/gazelle~~go_deps~com_github_cloudflare_circl/math/fp25519/fp.go:205:21: undefined: modp
compilepkg: error running subcommand external/rules_go~~go_sdk~go_sdk/pkg/tool/linux_amd64/compile: exit status 

The reason for this is that I can't define gotags on the go_library.

I do know I can use --define=gotags=purego on the CLI, but that means this would impact every other target. Any ideas on what I can do here?

Why are the build_tags I've defined in the override not actually propagating?

Is this because of bazel-contrib/bazel-gazelle#1262?

@dzbarsky
Copy link
Contributor

Perhaps you could use with_cfg to transition your binary? That way you can set gotags on it from build.bazel instead of affecting everything from CLI?

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

No branches or pull requests

5 participants
@sallustfire @aaomidi @dzbarsky @fmeum and others