diff --git a/.plzconfig b/.plzconfig index 96eaf592..ab33e2fe 100644 --- a/.plzconfig +++ b/.plzconfig @@ -175,5 +175,9 @@ Repeatable = true Optional = true Help = Build tags to pass to the Go compiler +[PluginConfig "experiment"] +Optional = true +Help = Value to pass for GOEXPERIMENT + [Plugin "shell"] Target = //plugins:shell diff --git a/build_defs/go.build_defs b/build_defs/go.build_defs index 5a536190..af3f6dd9 100644 --- a/build_defs/go.build_defs +++ b/build_defs/go.build_defs @@ -97,7 +97,10 @@ def _go_toolchain(name:str, srcs:list, labels:list=[], copy_cmd:str, visibility: 'link': f'{name}/pkg/tool/{CONFIG.HOSTOS}_{CONFIG.HOSTARCH}/link', 'cover': f'{name}/pkg/tool/{CONFIG.HOSTOS}_{CONFIG.HOSTARCH}/cover', }, - tools = {"CC": [CONFIG.GO.CC_TOOL]} if CONFIG.GO.CGO_ENABLED else {}, + env = _goexperiment_env(), + tools = ({ + "CC": [CONFIG.GO.CC_TOOL], + } if CONFIG.GO.CGO_ENABLED == "1" else {}) | _goexperiment_env(), binary = True, labels = labels, visibility = visibility, @@ -210,6 +213,7 @@ def go_stdlib(name:str, tags:list=CONFIG.GO.BUILD_TAGS, labels:list=[], visibili "GOOS": CONFIG.OS, "GOARCH": CONFIG.ARCH, "GODEBUG": "installgoroot=all", + "GOEXPERIMENT": CONFIG.GO.EXPERIMENT, }, labels = ["go_pkg_info", "go_stdlib", "go"] + labels, output_is_complete = True, @@ -293,6 +297,7 @@ def go_library(name:str, srcs:list, resources:list=[], asm_srcs:list=None, hdrs: test_only = test_only, deps = deps, ) + link_prefix, _, _ = _module.partition('@') else: # Dummy modinfo so we don't have to provide everything for binary modinfo actions. modinfo = filegroup( @@ -302,6 +307,7 @@ def go_library(name:str, srcs:list, resources:list=[], asm_srcs:list=None, hdrs: requires = ["modinfo"], test_only = test_only, ) + link_prefix = '' deps += [modinfo] # We could just depend on go_src for all our deps but that would mean bringing in srcs for targets outside this @@ -493,6 +499,7 @@ def go_library(name:str, srcs:list, resources:list=[], asm_srcs:list=None, hdrs: outs = outs, cmd = cmds, visibility = visibility, + env = _goexperiment_env(), building_description = "Compiling...", requires = ['go'], provides = provides, @@ -503,6 +510,12 @@ def go_library(name:str, srcs:list, resources:list=[], asm_srcs:list=None, hdrs: exported_deps = exported_deps, ) + +def _goexperiment_env(): + """Returns the GOEXPERIMENT env var, or None if there isn't one.""" + return {"GOEXPERIMENT": CONFIG.GO.EXPERIMENT} if CONFIG.GO.EXPERIMENT else {} + + def _generate_pkg_import_cfg_cmd(name, out, pkg_location, handle_basename_eq_dirname=False): """ Generates a .importconfig file for all .a files within a go pkg directory for use with @@ -648,6 +661,7 @@ def go_binary(name:str, srcs:list=[], resources:list=None, asm_srcs:list=[], out building_description="Linking...", needs_transitive_deps=True, binary=True, + env = _goexperiment_env(), output_is_complete=True, test_only=test_only, tools=tools, @@ -829,6 +843,7 @@ def go_test(name:str, srcs:list, resources:list=None, data:list|dict=None, deps: env["GOCOVERDIR"] = "$TMP_DIR" else: env = {"GOCOVERDIR": "$TMP_DIR"} + env |= _goexperiment_env() return build_rule( name = name, @@ -966,6 +981,7 @@ def go_benchmark(name:str, srcs:list, resources:list=None, data:list|dict=None, visibility=visibility, sandbox=sandbox, build_timeout=timeout, + env = _goexperiment_env(), requires=['go', 'test'], labels=labels, binary=True, @@ -1475,7 +1491,7 @@ def go_module(name:str='', module:str, version:str='', download:str='', deps:lis visibility = visibility, licences = licences, linker_flags = linker_flags, - env = env, + env = env | {"GOEXPERIMENT": CONFIG.GO.EXPERIMENT}, build_tags = build_tags, labels = labels if binary else [], ) diff --git a/test/BUILD b/test/BUILD index ec36ac5d..76e41526 100644 --- a/test/BUILD +++ b/test/BUILD @@ -14,4 +14,4 @@ genrule( deps = exports, visibility=["//test/..."], tools = [CONFIG.E2E.PLEASE_TOOL], -) \ No newline at end of file +) diff --git a/test/goexperiment/BUILD b/test/goexperiment/BUILD new file mode 100644 index 00000000..5a2b9f00 --- /dev/null +++ b/test/goexperiment/BUILD @@ -0,0 +1,7 @@ +subinclude("//test/build_defs:e2e") + +please_repo_e2e_test( + name = "goexperiment_test", + plz_command = "plz test", + repo = "test_repo", +) diff --git a/test/goexperiment/test_repo/.plzconfig b/test/goexperiment/test_repo/.plzconfig new file mode 100644 index 00000000..c287693e --- /dev/null +++ b/test/goexperiment/test_repo/.plzconfig @@ -0,0 +1,10 @@ +[Parse] +BuildFileName = BUILD_FILE +BuildFileName = BUILD +PreloadSubincludes = ///go//build_defs:go + +[Plugin "go"] +ImportPath = github.com/please-build/please-rules/root-test +Target = //plugins:go +Stdlib = //third_party/go:std +experiment = rangefunc diff --git a/test/goexperiment/test_repo/experiment/BUILD_FILE b/test/goexperiment/test_repo/experiment/BUILD_FILE new file mode 100644 index 00000000..3edc9199 --- /dev/null +++ b/test/goexperiment/test_repo/experiment/BUILD_FILE @@ -0,0 +1,4 @@ +go_test( + name = "experiment_test", + srcs = ["experiment_test.go"], +) \ No newline at end of file diff --git a/test/goexperiment/test_repo/experiment/experiment_test.go b/test/goexperiment/test_repo/experiment/experiment_test.go new file mode 100644 index 00000000..f27584e7 --- /dev/null +++ b/test/goexperiment/test_repo/experiment/experiment_test.go @@ -0,0 +1,28 @@ +package experiment_test + +import ( + "iter" + "slices" + "testing" +) + +func EverySecond[T any](x []T) iter.Seq[T] { + return func(yield func(T) bool) { + for i := 0; i < len(x); i += 2 { + if !yield(x[i]) { + return + } + } + } +} + +func TestRangefunc(t *testing.T) { + x := []int{1, 2, 3, 4, 5} + y := []int{} + for it := range EverySecond(x) { + y = append(y, it) + } + if !slices.Equal(y, []int{1, 3, 5}) { + t.Errorf("unexpected y: %v", y) + } +} diff --git a/test/goexperiment/test_repo/go.mod b/test/goexperiment/test_repo/go.mod new file mode 100644 index 00000000..88e94019 --- /dev/null +++ b/test/goexperiment/test_repo/go.mod @@ -0,0 +1 @@ +module github.com/please-build/please-rules/goexperiment-test diff --git a/test/goexperiment/test_repo/plugins/BUILD_FILE b/test/goexperiment/test_repo/plugins/BUILD_FILE new file mode 100644 index 00000000..f197577d --- /dev/null +++ b/test/goexperiment/test_repo/plugins/BUILD_FILE @@ -0,0 +1,4 @@ +plugin_repo( + name = "go", + revision = "master", +) \ No newline at end of file diff --git a/test/goexperiment/test_repo/third_party/go/BUILD_FILE b/test/goexperiment/test_repo/third_party/go/BUILD_FILE new file mode 100644 index 00000000..f6d6b9a1 --- /dev/null +++ b/test/goexperiment/test_repo/third_party/go/BUILD_FILE @@ -0,0 +1,3 @@ +go_stdlib( + name = "std", +)