1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-01-04 03:11:55 +02:00

feat(nfpm): support libraries (#4587)

This adds `nfpm.libdirs` to allow to set where to put libraries built,
as well as include them in the search for artifacts when building the
package.

closes #4346

---

PS: I'm not sure about the default dirs, let me know what you think!

---------

Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
This commit is contained in:
Carlos Alexandro Becker 2024-01-31 07:26:25 -03:00 committed by GitHub
parent fd86f66de9
commit 765d534c2e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 336 additions and 26 deletions

View File

@ -53,6 +53,15 @@ func (Pipe) Default(ctx *context.Context) error {
if fpm.Bindir == "" {
fpm.Bindir = "/usr/bin"
}
if fpm.Libdirs.Header == "" {
fpm.Libdirs.Header = "/usr/include"
}
if fpm.Libdirs.CShared == "" {
fpm.Libdirs.CShared = "/usr/lib"
}
if fpm.Libdirs.CArchive == "" {
fpm.Libdirs.CArchive = "/usr/lib"
}
if fpm.PackageName == "" {
fpm.PackageName = ctx.Config.ProjectName
}
@ -85,7 +94,12 @@ func (Pipe) Run(ctx *context.Context) error {
func doRun(ctx *context.Context, fpm config.NFPM) error {
filters := []artifact.Filter{
artifact.ByType(artifact.Binary),
artifact.Or(
artifact.ByType(artifact.Binary),
artifact.ByType(artifact.Header),
artifact.ByType(artifact.CArchive),
artifact.ByType(artifact.CShared),
),
artifact.Or(
artifact.ByGoos("linux"),
artifact.ByGoos("ios"),
@ -139,11 +153,11 @@ func isSupportedTermuxArch(arch string) bool {
return false
}
func create(ctx *context.Context, fpm config.NFPM, format string, binaries []*artifact.Artifact) error {
func create(ctx *context.Context, fpm config.NFPM, format string, artifacts []*artifact.Artifact) error {
// TODO: improve mips handling on nfpm
infoArch := binaries[0].Goarch + binaries[0].Goarm + binaries[0].Gomips // key used for the ConventionalFileName et al
arch := infoArch + binaries[0].Goamd64 // unique arch key
infoPlatform := binaries[0].Goos
infoArch := artifacts[0].Goarch + artifacts[0].Goarm + artifacts[0].Gomips // key used for the ConventionalFileName et al
arch := infoArch + artifacts[0].Goamd64 // unique arch key
infoPlatform := artifacts[0].Goos
if infoPlatform == "ios" {
if format == "deb" {
infoPlatform = "iphoneos-arm64"
@ -165,7 +179,10 @@ func create(ctx *context.Context, fpm config.NFPM, format string, binaries []*ar
)
infoArch = replacer.Replace(infoArch)
arch = replacer.Replace(arch)
fpm.Bindir = filepath.Join("/data/data/com.termux/files", fpm.Bindir)
fpm.Bindir = termuxPrefixedDir(fpm.Bindir)
fpm.Libdirs.Header = termuxPrefixedDir(fpm.Libdirs.Header)
fpm.Libdirs.CArchive = termuxPrefixedDir(fpm.Libdirs.CArchive)
fpm.Libdirs.CShared = termuxPrefixedDir(fpm.Libdirs.CShared)
}
overridden, err := mergeOverrides(fpm, format)
@ -179,7 +196,7 @@ func create(ctx *context.Context, fpm config.NFPM, format string, binaries []*ar
}
t := tmpl.New(ctx).
WithArtifact(binaries[0]).
WithArtifact(artifacts[0]).
WithExtraFields(tmpl.Fields{
"Release": fpm.Release,
"Epoch": fpm.Epoch,
@ -222,6 +239,21 @@ func create(ctx *context.Context, fpm config.NFPM, format string, binaries []*ar
return err
}
libdirs := config.Libdirs{}
libdirs.Header, err = t.Apply(fpm.Libdirs.Header)
if err != nil {
return err
}
libdirs.CShared, err = t.Apply(fpm.Libdirs.CShared)
if err != nil {
return err
}
libdirs.CArchive, err = t.Apply(fpm.Libdirs.CArchive)
if err != nil {
return err
}
contents := files.Contents{}
for _, content := range overridden.Contents {
src, err := t.Apply(content.Source)
@ -253,10 +285,13 @@ func create(ctx *context.Context, fpm config.NFPM, format string, binaries []*ar
// FPM meta package should not contain binaries at all
if !fpm.Meta {
for _, binary := range binaries {
src := binary.Path
dst := filepath.Join(fpm.Bindir, binary.Name)
log.WithField("src", src).WithField("dst", dst).Debug("adding binary to package")
for _, art := range artifacts {
src := art.Path
dst := filepath.Join(artifactPackageDir(fpm.Bindir, libdirs, art), art.Name)
log.WithField("src", src).
WithField("dst", dst).
WithField("type", art.Type.String()).
Debug("adding artifact to package")
contents = append(contents, &files.Content{
Source: filepath.ToSlash(src),
Destination: filepath.ToSlash(dst),
@ -416,11 +451,11 @@ func create(ctx *context.Context, fpm config.NFPM, format string, binaries []*ar
Type: artifact.LinuxPackage,
Name: packageFilename,
Path: path,
Goos: binaries[0].Goos,
Goarch: binaries[0].Goarch,
Goarm: binaries[0].Goarm,
Gomips: binaries[0].Gomips,
Goamd64: binaries[0].Goamd64,
Goos: artifacts[0].Goos,
Goarch: artifacts[0].Goarch,
Goarm: artifacts[0].Goarm,
Gomips: artifacts[0].Gomips,
Goamd64: artifacts[0].Goamd64,
Extra: map[string]interface{}{
artifact.ExtraID: fpm.ID,
artifact.ExtraFormat: format,
@ -481,3 +516,26 @@ func getPassphraseFromEnv(ctx *context.Context, packager string, nfpmID string)
return passphrase
}
func termuxPrefixedDir(dir string) string {
if dir == "" {
return ""
}
return filepath.Join("/data/data/com.termux/files", dir)
}
func artifactPackageDir(bindir string, libdirs config.Libdirs, art *artifact.Artifact) string {
switch art.Type {
case artifact.Binary:
return bindir
case artifact.Header:
return libdirs.Header
case artifact.CShared:
return libdirs.CShared
case artifact.CArchive:
return libdirs.CArchive
default:
// should never happen
return ""
}
}

View File

@ -98,9 +98,18 @@ func TestRunPipe(t *testing.T) {
require.NoError(t, os.Mkdir(dist, 0o755))
require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
binPath := filepath.Join(dist, "mybin", "mybin")
f, err := os.Create(binPath)
require.NoError(t, err)
require.NoError(t, f.Close())
foohPath := filepath.Join(dist, "foo.h")
foosoPath := filepath.Join(dist, "foo.so")
fooaPath := filepath.Join(dist, "foo.a")
for _, name := range []string{binPath, foosoPath, foohPath, fooaPath} {
f, err := os.Create(name)
require.NoError(t, err)
require.NoError(t, f.Close())
}
libPrefix := `/usr/lib
{{- if eq .Arch "amd64" }}64{{- end -}}
`
ctx := testctx.NewWithCfg(config.Project{
ProjectName: "mybin",
Dist: dist,
@ -113,7 +122,7 @@ func TestRunPipe(t *testing.T) {
{
ID: "someid",
Bindir: "/usr/bin",
Builds: []string{"default"},
Builds: []string{"default", "lib1", "lib2", "lib3"},
Formats: []string{"deb", "rpm", "apk", "termux.deb", "archlinux"},
Section: "somesection",
Priority: "standard",
@ -123,6 +132,11 @@ func TestRunPipe(t *testing.T) {
Vendor: "asdf",
Homepage: "https://goreleaser.com/{{ .Env.PRO }}",
Changelog: "./testdata/changelog.yaml",
Libdirs: config.Libdirs{
Header: libPrefix + "/headers",
CArchive: libPrefix + "/c-archives",
CShared: libPrefix + "/c-shareds",
},
NFPMOverridables: config.NFPMOverridables{
FileNameTemplate: defaultNameTemplate + "-{{ .Release }}-{{ .Epoch }}",
PackageName: "foo",
@ -201,6 +215,39 @@ func TestRunPipe(t *testing.T) {
artifact.ExtraID: "default",
},
})
ctx.Artifacts.Add(&artifact.Artifact{
Name: "foo.h",
Path: foohPath,
Goarch: goarch,
Goos: goos,
Goarm: goarm,
Type: artifact.Header,
Extra: map[string]interface{}{
artifact.ExtraID: "lib1",
},
})
ctx.Artifacts.Add(&artifact.Artifact{
Name: "foo.so",
Path: foosoPath,
Goarch: goarch,
Goos: goos,
Goarm: goarm,
Type: artifact.CShared,
Extra: map[string]interface{}{
artifact.ExtraID: "lib2",
},
})
ctx.Artifacts.Add(&artifact.Artifact{
Name: "foo.a",
Path: fooaPath,
Goarch: goarch,
Goos: goos,
Goarm: goarm,
Type: artifact.CArchive,
Extra: map[string]interface{}{
artifact.ExtraID: "lib3",
},
})
}
case "amd64":
for _, goamd64 := range []string{"v1", "v2", "v3", "v4"} {
@ -215,6 +262,39 @@ func TestRunPipe(t *testing.T) {
artifact.ExtraID: "default",
},
})
ctx.Artifacts.Add(&artifact.Artifact{
Name: "foo.h",
Path: foohPath,
Goarch: goarch,
Goos: goos,
Goamd64: goamd64,
Type: artifact.Header,
Extra: map[string]interface{}{
artifact.ExtraID: "lib1",
},
})
ctx.Artifacts.Add(&artifact.Artifact{
Name: "foo.so",
Path: foosoPath,
Goarch: goarch,
Goos: goos,
Goamd64: goamd64,
Type: artifact.CShared,
Extra: map[string]interface{}{
artifact.ExtraID: "lib2",
},
})
ctx.Artifacts.Add(&artifact.Artifact{
Name: "foo.a",
Path: fooaPath,
Goarch: goarch,
Goos: goos,
Goamd64: goamd64,
Type: artifact.CArchive,
Extra: map[string]interface{}{
artifact.ExtraID: "lib3",
},
})
}
case "mips":
for _, gomips := range []string{"softfloat", "hardfloat"} {
@ -229,6 +309,39 @@ func TestRunPipe(t *testing.T) {
artifact.ExtraID: "default",
},
})
ctx.Artifacts.Add(&artifact.Artifact{
Name: "foo.h",
Path: foohPath,
Goarch: goarch,
Goos: goos,
Gomips: gomips,
Type: artifact.Header,
Extra: map[string]interface{}{
artifact.ExtraID: "lib1",
},
})
ctx.Artifacts.Add(&artifact.Artifact{
Name: "foo.so",
Path: foosoPath,
Goarch: goarch,
Goos: goos,
Gomips: gomips,
Type: artifact.CShared,
Extra: map[string]interface{}{
artifact.ExtraID: "lib2",
},
})
ctx.Artifacts.Add(&artifact.Artifact{
Name: "foo.a",
Path: fooaPath,
Goarch: goarch,
Goos: goos,
Gomips: gomips,
Type: artifact.CArchive,
Extra: map[string]interface{}{
artifact.ExtraID: "lib3",
},
})
}
default:
ctx.Artifacts.Add(&artifact.Artifact{
@ -241,6 +354,36 @@ func TestRunPipe(t *testing.T) {
artifact.ExtraID: "default",
},
})
ctx.Artifacts.Add(&artifact.Artifact{
Name: "foo.h",
Path: foohPath,
Goarch: goarch,
Goos: goos,
Type: artifact.Header,
Extra: map[string]interface{}{
artifact.ExtraID: "lib1",
},
})
ctx.Artifacts.Add(&artifact.Artifact{
Name: "foo.so",
Path: foosoPath,
Goarch: goarch,
Goos: goos,
Type: artifact.CShared,
Extra: map[string]interface{}{
artifact.ExtraID: "lib2",
},
})
ctx.Artifacts.Add(&artifact.Artifact{
Name: "foo.a",
Path: fooaPath,
Goarch: goarch,
Goos: goos,
Type: artifact.CArchive,
Extra: map[string]interface{}{
artifact.ExtraID: "lib3",
},
})
}
}
}
@ -286,13 +429,30 @@ func TestRunPipe(t *testing.T) {
"./testdata/folder",
"./testdata/testfile-" + pkg.Goarch + pkg.Goamd64 + pkg.Goarm + pkg.Gomips + ".txt",
binPath,
foohPath,
fooaPath,
foosoPath,
}, sources(artifact.ExtraOr(*pkg, extraFiles, files.Contents{})))
bin := "/usr/bin/subdir/"
header := "/usr/lib/headers"
carchive := "/usr/lib/c-archives"
cshared := "/usr/lib/c-shareds"
if pkg.Goarch == "amd64" {
header = "/usr/lib64/headers"
carchive = "/usr/lib64/c-archives"
cshared = "/usr/lib64/c-shareds"
}
if format == termuxFormat {
bin = filepath.Join("/data/data/com.termux/files", bin)
header = filepath.Join("/data/data/com.termux/files", header)
cshared = filepath.Join("/data/data/com.termux/files", cshared)
carchive = filepath.Join("/data/data/com.termux/files", carchive)
}
bin = filepath.Join(bin, "mybin")
header = filepath.Join(header, "foo.h")
cshared = filepath.Join(cshared, "foo.so")
carchive = filepath.Join(carchive, "foo.a")
require.ElementsMatch(t, []string{
"/var/log/foobar",
"/usr/share/testfile.txt",
@ -303,6 +463,9 @@ func TestRunPipe(t *testing.T) {
"/etc/nope3_mybin.conf",
"/etc/folder",
bin,
header,
carchive,
cshared,
}, destinations(artifact.ExtraOr(*pkg, extraFiles, files.Contents{})))
}
require.Len(t, ctx.Config.NFPMs[0].Contents, 8, "should not modify the config file list")

View File

@ -536,7 +536,7 @@ type BuildDetailsOverride struct {
}
type BuildDetails struct {
Buildmode string `yaml:"buildmode,omitempty" json:"buildmode,omitempty"`
Buildmode string `yaml:"buildmode,omitempty" json:"buildmode,omitempty" jsonschema:"enum=c-archive,enum=c-shared,enum=,default="`
Ldflags StringArray `yaml:"ldflags,omitempty" json:"ldflags,omitempty"`
Tags FlagArray `yaml:"tags,omitempty" json:"tags,omitempty"`
Flags FlagArray `yaml:"flags,omitempty" json:"flags,omitempty"`
@ -786,10 +786,17 @@ type NFPM struct {
Description string `yaml:"description,omitempty" json:"description,omitempty"`
License string `yaml:"license,omitempty" json:"license,omitempty"`
Bindir string `yaml:"bindir,omitempty" json:"bindir,omitempty"`
Libdirs Libdirs `yaml:"libdirs,omitempty" json:"libdirs,omitempty"`
Changelog string `yaml:"changelog,omitempty" json:"changelog,omitempty"`
Meta bool `yaml:"meta,omitempty" json:"meta,omitempty"` // make package without binaries - only deps
}
type Libdirs struct {
Header string `yaml:"header,omitempty" json:"header,omitempty"`
CArchive string `yaml:"carchive,omitempty" json:"carchive,omitempty"`
CShared string `yaml:"cshared,omitempty" json:"cshared,omitempty"`
}
// NFPMScripts is used to specify maintainer scripts.
type NFPMScripts struct {
PreInstall string `yaml:"preinstall,omitempty" json:"preinstall,omitempty"`

View File

@ -94,9 +94,27 @@ nfpms:
- fish
# Path that the binaries should be installed.
#
# Default: '/usr/bin'
bindir: /usr/bin
# Paths to the directories where to put specific types of libraries that
# GoReleaser built.
#
# This should be used together with `builds.buildmode`
#
# Since: v1.24.
# Templates: allowed
libdirs:
# Default: '/usr/include'
headers: /usr/include/something
# Default: '/usr/lib'
cshared: /usr/lib/foo
# Default: '/usr/lib'
carchive: /usr/lib/foobar
# Version Epoch.
# Default: extracted from `version` if it is semver compatible
epoch: 2

74
www/docs/static/schema.json generated vendored
View File

@ -261,13 +261,13 @@
"region": {
"type": "string"
},
"disableSSL": {
"disable_ssl": {
"type": "boolean"
},
"folder": {
"type": "string"
},
"kmskey": {
"kms_key": {
"type": "string"
},
"ids": {
@ -294,6 +294,29 @@
"type": "boolean"
}
]
},
"s3_force_path_style": {
"type": "boolean"
},
"acl": {
"type": "string"
},
"cache_control": {
"items": {
"type": "string"
},
"type": "array"
},
"content_disposition": {
"type": "string"
},
"disableSSL": {
"type": "boolean",
"description": "use disable_ssl instead"
},
"kmskey": {
"type": "string",
"description": "use kms_key instead"
}
},
"additionalProperties": false,
@ -380,7 +403,13 @@
"type": "boolean"
},
"buildmode": {
"type": "string"
"type": "string",
"enum": [
"c-archive",
"c-shared",
""
],
"default": ""
},
"ldflags": {
"$ref": "#/$defs/StringArray"
@ -438,7 +467,13 @@
"type": "string"
},
"buildmode": {
"type": "string"
"type": "string",
"enum": [
"c-archive",
"c-shared",
""
],
"default": ""
},
"ldflags": {
"$ref": "#/$defs/StringArray"
@ -491,7 +526,7 @@
],
"default": ""
},
"skip": {
"disable": {
"oneOf": [
{
"type": "string"
@ -519,6 +554,17 @@
},
"abbrev": {
"type": "integer"
},
"skip": {
"oneOf": [
{
"type": "string"
},
{
"type": "boolean"
}
],
"description": "use disable instead"
}
},
"additionalProperties": false,
@ -1499,6 +1545,21 @@
"additionalProperties": false,
"type": "object"
},
"Libdirs": {
"properties": {
"header": {
"type": "string"
},
"carchive": {
"type": "string"
},
"cshared": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
},
"LinkedIn": {
"properties": {
"enabled": {
@ -1699,6 +1760,9 @@
"bindir": {
"type": "string"
},
"libdirs": {
"$ref": "#/$defs/Libdirs"
},
"changelog": {
"type": "string"
},