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

dev,generate-cgo: externalize cgo files gen into a seperate binary #104554

Merged
merged 1 commit into from
Jun 8, 2023
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
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@
/pkg/cmd/generate-spatial-ref-sys/ @cockroachdb/spatial
/pkg/cmd/generate-bazel-extra/ @cockroachdb/dev-inf
/pkg/cmd/generate-staticcheck/ @cockroachdb/dev-inf
/pkg/cmd/generate-cgo/ @cockroachdb/dev-inf
/pkg/cmd/geoviz/ @cockroachdb/spatial
/pkg/cmd/github-post/ @cockroachdb/test-eng
/pkg/cmd/github-pull-request-make/ @cockroachdb/dev-inf
Expand Down
2 changes: 1 addition & 1 deletion dev
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fi
set -euo pipefail

# Bump this counter to force rebuilding `dev` on all machines.
DEV_VERSION=73
DEV_VERSION=74

THIS_DIR=$(cd "$(dirname "$0")" && pwd)
BINARY_DIR=$THIS_DIR/bin/dev-versions
Expand Down
3 changes: 3 additions & 0 deletions pkg/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,8 @@ GO_TARGETS = [
"//pkg/cmd/generate-bazel-extra:generate-bazel-extra_test",
"//pkg/cmd/generate-binary:generate-binary",
"//pkg/cmd/generate-binary:generate-binary_lib",
"//pkg/cmd/generate-cgo:generate-cgo",
"//pkg/cmd/generate-cgo:generate-cgo_lib",
"//pkg/cmd/generate-distdir:generate-distdir",
"//pkg/cmd/generate-distdir:generate-distdir_lib",
"//pkg/cmd/generate-logictest:generate-logictest",
Expand Down Expand Up @@ -2621,6 +2623,7 @@ GET_X_DATA_TARGETS = [
"//pkg/cmd/generate-acceptance-tests:get_x_data",
"//pkg/cmd/generate-bazel-extra:get_x_data",
"//pkg/cmd/generate-binary:get_x_data",
"//pkg/cmd/generate-cgo:get_x_data",
"//pkg/cmd/generate-distdir:get_x_data",
"//pkg/cmd/generate-logictest:get_x_data",
"//pkg/cmd/generate-metadata-tables:get_x_data",
Expand Down
83 changes: 7 additions & 76 deletions pkg/cmd/dev/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ import (
"fmt"
"os"
"path/filepath"
"runtime"
"text/template"

"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -272,86 +270,19 @@ func (d *dev) generateTarget(ctx context.Context, target string) error {

func (d *dev) generateCgo(cmd *cobra.Command) error {
ctx := cmd.Context()
args := []string{"build", "//build/bazelutil:test_force_build_cdeps", "//c-deps:libjemalloc", "//c-deps:libproj"}
if runtime.GOOS == "linux" {
args = append(args, "//c-deps:libkrb5")
}
logCommand("bazel", args...)
if err := d.exec.CommandContextInheritingStdStreams(ctx, "bazel", args...); err != nil {
return err
}
workspace, err := d.getWorkspace(ctx)
if err != nil {
return err
}
bazelBin, err := d.getBazelBin(ctx)
if err != nil {
return err
}

const cgoTmpl = `// GENERATED FILE DO NOT EDIT
package {{ .Package }}
// #cgo CPPFLAGS: {{ .CPPFlags }}
// #cgo LDFLAGS: {{ .LDFlags }}
import "C"
`

tpl := template.Must(template.New("source").Parse(cgoTmpl))
archived, err := d.getArchivedCdepString(bazelBin)
if err != nil {
return err
}
// Figure out where to find the c-deps libraries.
var jemallocDir, projDir, krbDir string
if archived != "" {
execRoot, err := d.getExecutionRoot(ctx)
if err != nil {
return err
}
jemallocDir = filepath.Join(execRoot, "external", fmt.Sprintf("archived_cdep_libjemalloc_%s", archived))
projDir = filepath.Join(execRoot, "external", fmt.Sprintf("archived_cdep_libproj_%s", archived))
if runtime.GOOS == "linux" {
krbDir = filepath.Join(execRoot, "external", fmt.Sprintf("archived_cdep_libkrb5_%s", archived))
}
} else {
jemallocDir = filepath.Join(bazelBin, "c-deps/libjemalloc_foreign")
projDir = filepath.Join(bazelBin, "c-deps/libproj_foreign")
if runtime.GOOS == "linux" {
krbDir = filepath.Join(bazelBin, "c-deps/libkrb5_foreign")
}
}
cppFlags := fmt.Sprintf("-I%s", filepath.Join(jemallocDir, "include"))
ldFlags := fmt.Sprintf("-L%s -L%s", filepath.Join(jemallocDir, "lib"), filepath.Join(projDir, "lib"))
if krbDir != "" {
cppFlags += fmt.Sprintf(" -I%s", filepath.Join(krbDir, "include"))
ldFlags += fmt.Sprintf(" -L%s", filepath.Join(krbDir, "lib"))
}

cgoPkgs := []string{
"pkg/cli",
"pkg/cli/clisqlshell",
"pkg/server/status",
"pkg/ccl/gssapiccl",
"pkg/geo/geoproj",
args := []string{
"run",
"//pkg/cmd/generate-cgo:generate-cgo",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should add:

"--run_under=cd [workspace] && ",

Or something like this to make sure the binary is executed in the workspace directory.

fmt.Sprintf("--run_under=cd %s && ", workspace),
}

for _, cgoPkg := range cgoPkgs {
out, err := os.Create(filepath.Join(workspace, cgoPkg, "zcgo_flags.go"))
if err != nil {
return err
}
err = tpl.Execute(out, struct {
Package string
CPPFlags string
LDFlags string
}{Package: filepath.Base(cgoPkg), CPPFlags: cppFlags, LDFlags: ldFlags})
if err != nil {
return err
}
logCommand("bazel", args...)
if err := d.exec.CommandContextInheritingStdStreams(ctx, "bazel", args...); err != nil {
return fmt.Errorf("generating cgo: %w", err)
}

return nil
}

Expand Down
21 changes: 21 additions & 0 deletions pkg/cmd/generate-cgo/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
load("//build/bazelutil/unused_checker:unused.bzl", "get_x_data")
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")

go_library(
name = "generate-cgo_lib",
srcs = ["main.go"],
importpath = "github.com/cockroachdb/cockroach/pkg/cmd/generate-cgo",
visibility = ["//visibility:private"],
deps = [
"@com_github_alessio_shellescape//:shellescape",
"@com_github_cockroachdb_errors//:errors",
],
)

go_binary(
name = "generate-cgo",
embed = [":generate-cgo_lib"],
visibility = ["//visibility:public"],
)

get_x_data(name = "get_x_data")
196 changes: 196 additions & 0 deletions pkg/cmd/generate-cgo/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
// Copyright 2023 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package main

import (
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"text/template"

"github.com/alessio/shellescape"
"github.com/cockroachdb/errors"
)

type configuration struct {
Os string
Arch string
}

var (
workspace string
bazelBin string
archivedCdepConfigurations = []configuration{
{"linux", "amd64"},
{"linux", "arm64"},
{"darwin", "amd64"},
{"darwin", "arm64"},
{"windows", "amd64"},
}
)

func logCommand(cmd string, args ...string) {
var fullArgs []string
fullArgs = append(fullArgs, cmd)
fullArgs = append(fullArgs, args...)
log.Printf("$ %s", shellescape.QuoteCommand(fullArgs))
}

// getArchivedCdepString returns a non-empty string iff the force_build_cdeps
// config is not being used. This string is the name of the cross config used to
// build the pre-built c-deps, minus the "cross" prefix. This can be used to
// locate the pre-built c-dep in
// $EXECUTION_ROOT/external/archived_cdep_{LIB}_{ARCHIVED_CDEP_STRING}.
// If the returned string is empty then force_build_cdeps is set in which case
// the (non-pre-built) libraries can be found in $BAZEL_BIN/c-deps/{LIB}_foreign.
//
// You MUST build //build/bazelutil:test_force_build_cdeps before calling this
// function.
func getArchivedCdepString(bazelBin string) (string, error) {
var ret string
// If force_build_cdeps is set then the prebuilt libraries won't be in
// the archived location anyway.
forceBuildCdeps, err := os.ReadFile(filepath.Join(bazelBin, "build", "bazelutil", "test_force_build_cdeps.txt"))
if err != nil {
return "", err
}
// force_build_cdeps is activated if the length of this file is not 0.
if len(forceBuildCdeps) == 0 {
for _, config := range archivedCdepConfigurations {
if config.Os == runtime.GOOS && config.Arch == runtime.GOARCH {
ret = config.Os
if ret == "darwin" {
ret = "macos"
}
if config.Arch == "arm64" {
ret += "arm"
}
break
}
}
}
return ret, nil
}

func getBazelInfo(info string) (string, error) {
args := []string{"info", info, "--color=no"}
logCommand("bazel", args...)
cmd := exec.Command("bazel", args...)
var outBuf, errBuf strings.Builder
cmd.Stdout = &outBuf
cmd.Stderr = &errBuf
if err := cmd.Run(); err != nil {
return "", errors.Wrapf(err, "Stderr: %s", errBuf.String())
} else {
return strings.TrimSpace(outBuf.String()), nil
}
}

func generateCgo() error {
if workspace == "" || bazelBin == "" {
return errors.New("--workspace and --bazel-bin are required")
}
args := []string{"build", "//build/bazelutil:test_force_build_cdeps", "//c-deps:libjemalloc", "//c-deps:libproj"}
if runtime.GOOS == "linux" {
args = append(args, "//c-deps:libkrb5")
}
logCommand("bazel", args...)
cmd := exec.Command("bazel", args...)
var outBuf, errBuf strings.Builder
cmd.Stdout = &outBuf
cmd.Stderr = &errBuf
if err := cmd.Run(); err != nil {
return errors.Wrapf(err, "Stderr: %s", errBuf.String())
}

const cgoTmpl = `// GENERATED FILE DO NOT EDIT
package {{ .Package }}
// #cgo CPPFLAGS: {{ .CPPFlags }}
// #cgo LDFLAGS: {{ .LDFlags }}
import "C"
`

tpl := template.Must(template.New("source").Parse(cgoTmpl))
archived, err := getArchivedCdepString(bazelBin)
if err != nil {
return err
}
// Figure out where to find the c-deps libraries.
var jemallocDir, projDir, krbDir string
if archived != "" {
execRoot, err := getBazelInfo("execution_root")
if err != nil {
return err
}
jemallocDir = filepath.Join(execRoot, "external", fmt.Sprintf("archived_cdep_libjemalloc_%s", archived))
projDir = filepath.Join(execRoot, "external", fmt.Sprintf("archived_cdep_libproj_%s", archived))
if runtime.GOOS == "linux" {
krbDir = filepath.Join(execRoot, "external", fmt.Sprintf("archived_cdep_libkrb5_%s", archived))
}
} else {
jemallocDir = filepath.Join(bazelBin, "c-deps/libjemalloc_foreign")
projDir = filepath.Join(bazelBin, "c-deps/libproj_foreign")
if runtime.GOOS == "linux" {
krbDir = filepath.Join(bazelBin, "c-deps/libkrb5_foreign")
}
}
cppFlags := fmt.Sprintf("-I%s", filepath.Join(jemallocDir, "include"))
ldFlags := fmt.Sprintf("-L%s -L%s", filepath.Join(jemallocDir, "lib"), filepath.Join(projDir, "lib"))
if krbDir != "" {
cppFlags += fmt.Sprintf(" -I%s", filepath.Join(krbDir, "include"))
ldFlags += fmt.Sprintf(" -L%s", filepath.Join(krbDir, "lib"))
}

cgoPkgs := []string{
"pkg/cli",
"pkg/cli/clisqlshell",
"pkg/server/status",
"pkg/ccl/gssapiccl",
"pkg/geo/geoproj",
}

for _, cgoPkg := range cgoPkgs {
out, err := os.Create(filepath.Join(workspace, cgoPkg, "zcgo_flags.go"))
if err != nil {
return err
}
err = tpl.Execute(out, struct {
Package string
CPPFlags string
LDFlags string
}{Package: filepath.Base(cgoPkg), CPPFlags: cppFlags, LDFlags: ldFlags})
if err != nil {
return err
}
}
return nil
}

func main() {
var err error
workspace, err = getBazelInfo("workspace")
if err != nil {
log.Fatal(err)
}
bazelBin, err = getBazelInfo("bazel-bin")
if err != nil {
log.Fatal(err)
}
if err := generateCgo(); err != nil {
log.Fatal(err)
}
}