From 996cef2bbf838f505db3bc610fdb5fa92df8bb5e Mon Sep 17 00:00:00 2001 From: Giorgio Azzinnaro Date: Sun, 30 Oct 2022 20:43:52 +0100 Subject: [PATCH] feat: build of shared/static libraries * add the correct extension according to the lib type and target os * archive the generated header file --- internal/artifact/artifact.go | 4 ++++ internal/builders/golang/build.go | 31 +++++++++++++++++++++++++++++++ internal/pipe/archive/archive.go | 1 + internal/pipe/build/build.go | 20 ++++++++++++++++++++ internal/pipe/build/build_test.go | 20 ++++++++++++++++++++ www/docs/customization/build.md | 21 +++++++++++++++++++++ 6 files changed, 97 insertions(+) diff --git a/internal/artifact/artifact.go b/internal/artifact/artifact.go index 06434e02c4c1..9c38e7285430 100644 --- a/internal/artifact/artifact.go +++ b/internal/artifact/artifact.go @@ -66,6 +66,8 @@ const ( ScoopManifest // SBOM is a Software Bill of Materials file. SBOM + // Header is a C header file, generated for CGo library builds. + Header ) func (t Type) String() string { @@ -104,6 +106,8 @@ func (t Type) String() string { return "PKGBUILD" case SrcInfo: return "SRCINFO" + case Header: + return "Header" default: return "unknown" } diff --git a/internal/builders/golang/build.go b/internal/builders/golang/build.go index 7d76e1353293..917d164d2012 100644 --- a/internal/builders/golang/build.go +++ b/internal/builders/golang/build.go @@ -192,6 +192,8 @@ func (*Builder) Build(ctx *context.Context, build config.Build, options api.Opti } } + addHeaderArtifactIfLibrary(ctx, build, options) + ctx.Artifacts.Add(artifact) return nil } @@ -366,3 +368,32 @@ func hasMain(file *ast.File) bool { } return false } + +func addHeaderArtifactIfLibrary(ctx *context.Context, build config.Build, options api.Options) { + for _, s := range build.BuildDetails.Flags { + if s == "-buildmode=c-shared" || s == "-buildmode=c-archive" { + fullPathWithoutExt := strings.TrimSuffix(options.Path, options.Ext) + basePath := filepath.Base(fullPathWithoutExt) + fullPath := fullPathWithoutExt + ".h" + headerName := basePath + ".h" + + header := &artifact.Artifact{ + Type: artifact.Header, + Path: fullPath, + Name: headerName, + Goos: options.Goos, + Goarch: options.Goarch, + Goamd64: options.Goamd64, + Goarm: options.Goarm, + Gomips: options.Gomips, + Extra: map[string]interface{}{ + artifact.ExtraBinary: headerName, + artifact.ExtraExt: ".h", + artifact.ExtraID: build.ID, + }, + } + + ctx.Artifacts.Add(header) + } + } +} diff --git a/internal/pipe/archive/archive.go b/internal/pipe/archive/archive.go index e5219ed4b59d..16e973cd6516 100644 --- a/internal/pipe/archive/archive.go +++ b/internal/pipe/archive/archive.go @@ -91,6 +91,7 @@ func (Pipe) Run(ctx *context.Context) error { filter := []artifact.Filter{artifact.Or( artifact.ByType(artifact.Binary), artifact.ByType(artifact.UniversalBinary), + artifact.ByType(artifact.Header), )} if len(archive.Builds) > 0 { filter = append(filter, artifact.ByIDs(archive.Builds...)) diff --git a/internal/pipe/build/build.go b/internal/pipe/build/build.go index a05f42d2ed03..6ca5012fe210 100644 --- a/internal/pipe/build/build.go +++ b/internal/pipe/build/build.go @@ -226,5 +226,25 @@ func extFor(target string, flags config.FlagArray) string { if target == "js_wasm" { return ".wasm" } + if strings.Contains(target, "linux") { + for _, s := range flags { + if s == "-buildmode=c-shared" { + return ".so" + } + if s == "-buildmode=c-archive" { + return ".a" + } + } + } + if strings.Contains(target, "darwin") { + for _, s := range flags { + if s == "-buildmode=c-shared" { + return ".dylib" + } + if s == "-buildmode=c-archive" { + return ".a" + } + } + } return "" } diff --git a/internal/pipe/build/build_test.go b/internal/pipe/build/build_test.go index 7155f8fd9f12..bab335085943 100644 --- a/internal/pipe/build/build_test.go +++ b/internal/pipe/build/build_test.go @@ -446,6 +446,26 @@ func TestExtOthers(t *testing.T) { require.Empty(t, "", extFor("winasdasd_sad", config.FlagArray{})) } +func TestExtLinux(t *testing.T) { + require.Equal(t, "", extFor("linux_amd64", config.FlagArray{})) + require.Equal(t, "", extFor("linux_386", config.FlagArray{})) + require.Equal(t, "", extFor("linux_amd64", config.FlagArray{"-tags=dev", "-v"})) + require.Equal(t, ".so", extFor("linux_amd64", config.FlagArray{"-tags=dev", "-v", "-buildmode=c-shared"})) + require.Equal(t, ".so", extFor("linux_386", config.FlagArray{"-buildmode=c-shared"})) + require.Equal(t, ".a", extFor("linux_amd64", config.FlagArray{"-buildmode=c-archive"})) + require.Equal(t, ".a", extFor("linux_386", config.FlagArray{"-tags=dev", "-v", "-buildmode=c-archive"})) +} + +func TestExtDarwin(t *testing.T) { + require.Equal(t, "", extFor("darwin_amd64", config.FlagArray{})) + require.Equal(t, "", extFor("darwin_arm64", config.FlagArray{})) + require.Equal(t, "", extFor("darwin_amd64", config.FlagArray{"-tags=dev", "-v"})) + require.Equal(t, ".dylib", extFor("darwin_amd64", config.FlagArray{"-tags=dev", "-v", "-buildmode=c-shared"})) + require.Equal(t, ".dylib", extFor("darwin_arm64", config.FlagArray{"-buildmode=c-shared"})) + require.Equal(t, ".a", extFor("darwin_amd64", config.FlagArray{"-buildmode=c-archive"})) + require.Equal(t, ".a", extFor("darwin_arm64", config.FlagArray{"-tags=dev", "-v", "-buildmode=c-archive"})) +} + func TestTemplate(t *testing.T) { ctx := context.New(config.Project{}) ctx.Git = context.GitInfo{ diff --git a/www/docs/customization/build.md b/www/docs/customization/build.md index e260dcde1c79..c8bc03632376 100644 --- a/www/docs/customization/build.md +++ b/www/docs/customization/build.md @@ -517,3 +517,24 @@ will evaluate to the list of first class ports as defined in the Go wiki. You can read more about it [here](https://github.com/golang/go/wiki/PortingPolicy#first-class-ports). + +## Building shared or static libraries + +GoReleaser supports compiling and releasing libraries, by configuring the [Go build mode](https://pkg.go.dev/cmd/go#hdr-Build_modes). + +This can be set with `buildmode` in your build `flags`. It currently supports `c-shared` and `c-archive`. + +GoReleaser will: + +* set the correct file extension for the target OS. +* package the generated header file (`.h`) in the release bundle. + +```yaml +# .goreleaser.yaml +builds: + - + id: "my-library" + + # Configure the buildmode flag to output a shared library + flags: -buildmode=c-shared # or "c-archive" for a static library +```