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

feat: build of shared/static libraries #3511

Merged
merged 5 commits into from Nov 12, 2022

Conversation

borgoat
Copy link
Contributor

@borgoat borgoat commented Oct 30, 2022

This PR improves the handling of shared or static libraries by GoReleaser. It uses the default behaviour of the Go compiler by appending the right extension to libraries.

  • .so and .a for Linux shared libraries and static libraries respectively
  • .dylib and .a. on Darwin
  • .dll and .lib on Windows (pre-existent)

It does not add any configuration option to .goreleaser.yml, since it leverages the existing buildmode flag.

Additionally, this PR takes care of adding the generated header file into the archive.

Personally I would leverage this change to release some software both as a CLI and as a shared library. I believe others who use CGo or need interoperability with Go from other languages could benefit from this.

This was previously discussed in #3497.

I couldn't quite think of a proper way to add some tests to the header archiving feature. Any recommendation?

@pull-request-size pull-request-size bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Oct 30, 2022
internal/builders/golang/build.go Outdated Show resolved Hide resolved
internal/builders/golang/build.go Outdated Show resolved Hide resolved
internal/pipe/build/build.go Outdated Show resolved Hide resolved
@caarlos0
Copy link
Member

looking good so far! Thank you!

I added a couple of comments, and regarding your question about the archive, you'll need to add the Header artifact type in the filter there:

filter := []artifact.Filter{artifact.Or(

There might be more places, so you can probably search for artifact.Binary and see what's there.

Another thing that comes to mind is that we have the UploadableBinary type, which is just an unarchived binary... I'm not sure that's a use case, but if people want unarchived libraries to be released, we'll need to change that too (also in the archive pipe).

That's all I remember for now about this. BTW feel free to ping me if you need any help, I'm mostly available on discord for quick chats if needed 🙏

And thanks again for your effort and work on this 🤘

@codecov
Copy link

codecov bot commented Oct 31, 2022

Codecov Report

Merging #3511 (e8de882) into main (8794290) will decrease coverage by 0.39%.
The diff coverage is 44.70%.

@@            Coverage Diff             @@
##             main    #3511      +/-   ##
==========================================
- Coverage   84.27%   83.88%   -0.40%     
==========================================
  Files         114      114              
  Lines        9338     9403      +65     
==========================================
+ Hits         7870     7888      +18     
- Misses       1191     1232      +41     
- Partials      277      283       +6     
Impacted Files Coverage Δ
internal/artifact/artifact.go 86.12% <0.00%> (-1.88%) ⬇️
pkg/config/config.go 95.21% <ø> (ø)
internal/builders/golang/build.go 79.80% <26.78%> (-12.12%) ⬇️
internal/pipe/archive/archive.go 93.91% <100.00%> (+0.08%) ⬆️
internal/pipe/build/build.go 87.79% <100.00%> (+0.67%) ⬆️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@caarlos0 caarlos0 added the enhancement New feature or request label Oct 31, 2022
@borgoat
Copy link
Contributor Author

borgoat commented Oct 31, 2022

Thanks for the review @caarlos0 !

I replied to the comments best I could. As for the other points:

I added a couple of comments, and regarding your question about the archive, you'll need to add the Header artifact type in the filter there:

filter := []artifact.Filter{artifact.Or(

There might be more places, so you can probably search for artifact.Binary and see what's there.

I added this line here: https://github.com/goreleaser/goreleaser/pull/3511/files#diff-4b69e49926d4bcaf08f5563b284ff33ac8f7a60a596dc62898ec333253014088R94

Did I miss it in other places though?

Another thing that comes to mind is that we have the UploadableBinary type, which is just an unarchived binary... I'm not sure that's a use case, but if people want unarchived libraries to be released, we'll need to change that too (also in the archive pipe).

I need to think this through: the interesting exception in that scenario would be that the header file looks always the same, so it could be uploaded just once: it is not specific to any target os/arch combo.

@caarlos0
Copy link
Member

caarlos0 commented Nov 2, 2022

Did I miss it in other places though?

I think maybe nfpm if we want to create library packages... but that might be a bigger effort (and maybe worth doing in another pr)

I need to think this through: the interesting exception in that scenario would be that the header file looks always the same, so it could be uploaded just once: it is not specific to any target os/arch combo.

hmmm that seems like a bigger change too.. maybe for now we just assume that libraries will always be archived?

@borgoat
Copy link
Contributor Author

borgoat commented Nov 2, 2022

Did I miss it in other places though?

I think maybe nfpm if we want to create library packages... but that might be a bigger effort (and maybe worth doing in another pr)

I need to think this through: the interesting exception in that scenario would be that the header file looks always the same, so it could be uploaded just once: it is not specific to any target os/arch combo.

hmmm that seems like a bigger change too.. maybe for now we just assume that libraries will always be archived?

I guess that makes sense.. then the only point missing should then be to create 1 or 2 new Artefact types "DynamicLibrary"/"StaticLibrary" for c-shared and c-archive respectively (or just 1 "Library" for both? wdyt?) Anything else I may be missing?

@caarlos0
Copy link
Member

caarlos0 commented Nov 2, 2022

Did I miss it in other places though?

I think maybe nfpm if we want to create library packages... but that might be a bigger effort (and maybe worth doing in another pr)

I need to think this through: the interesting exception in that scenario would be that the header file looks always the same, so it could be uploaded just once: it is not specific to any target os/arch combo.

hmmm that seems like a bigger change too.. maybe for now we just assume that libraries will always be archived?

I guess that makes sense.. then the only point missing should then be to create 1 or 2 new Artefact types "DynamicLibrary"/"StaticLibrary" for c-shared and c-archive respectively (or just 1 "Library" for both? wdyt?) Anything else I may be missing?

I think we can create both 2 new types, in case we need some extra handling somewhere...

I can't think of anything else missing besided that and the nfpm/brew/etc stuff (which we can handle in the future)

@pull-request-size pull-request-size bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Nov 5, 2022
@borgoat
Copy link
Contributor Author

borgoat commented Nov 5, 2022

Given the latest comments, to more easily support the 2 possible artefacts, and considering that the field would not be templateable anyway, I tried to refactor things a bit. I have introduced a buildmode config option instead, and configured all logic based on that. What do you think?

I kept it in a separate commit but can squash later if you like a957da6

Copy link
Member

@caarlos0 caarlos0 left a comment

Choose a reason for hiding this comment

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

just a single comment, I believe we are very close!

Thank you a ton for this!

internal/builders/golang/build.go Show resolved Hide resolved
* add the correct extension according to the lib type and target os
* archive the generated header file
instead of parsing the flags,
use a buildmode option to configure C shared and archive libs
@borgoat
Copy link
Contributor Author

borgoat commented Nov 9, 2022

So, I did now a rebase to main, and tested it further on the field.
I realised I was still missing some cases regarding the file extensions (I'm building with GOOS=android), so I hope you don't mind if I slightly refactored the logic...

Now when setting the buildmode we always fall back to .so and .a for shared and static libs respectively. With overrides for macOS and Windows.

Additionally I found and fixed another bug with the override logic.

By default use .a and .so for static and shared libs respectively.
On macOS/Darwin - use .dylib for shared libraries.
On Windows - use .lib for static and .dll for dynamic libs.
@caarlos0 caarlos0 merged commit 0a536f0 into goreleaser:main Nov 12, 2022
9 of 12 checks passed
@caarlos0
Copy link
Member

This looks awesome, thank you!

@github-actions github-actions bot added this to the v1.13.0 milestone Nov 12, 2022
gal-legit pushed a commit to gal-legit/goreleaser that referenced this pull request Nov 13, 2022
<!--

Hi, thanks for contributing!

Please make sure you read our CONTRIBUTING guide.

Also, add tests and the respective documentation changes as well.

-->


<!-- If applied, this commit will... -->

This PR improves the handling of shared or static libraries by
GoReleaser. It uses the default behaviour of the Go compiler by
appending the right extension to libraries.

* `.so` and `.a` for Linux shared libraries and static libraries
respectively
* `.dylib` and `.a.` on Darwin
* `.dll` and `.lib` on Windows (pre-existent)

It does not add any configuration option to `.goreleaser.yml`, since it
leverages the existing `buildmode` flag.

Additionally, this PR takes care of adding the generated header file
into the archive.

<!-- Why is this change being made? -->

Personally I would leverage this change to release some software both as
a CLI and as a shared library. I believe others who use CGo or need
interoperability with Go from other languages could benefit from this.

<!-- # Provide links to any relevant tickets, URLs or other resources
-->

This was previously discussed in goreleaser#3497.

I couldn't quite think of a proper way to add some tests to the header
archiving feature. Any recommendation?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants