Skip to content

feat: shared library targets #1138

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

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open

Conversation

perazz
Copy link
Member

@perazz perazz commented May 12, 2025

Introduce a new manifest option to enable building shared libraries:

[library]
shared = true

When enabled, the project, and all dependencies, are compiled as a shared library (.so, .dylib, or .dll depending on the platform) instead of the default static archive. Features:

  • Each package in the dependency graph is built as a separate shared library file (as opposed to the otherwise static option to put everything, code and all dependencies, into a monolithic archive).
  • Dynamic library linking commands are properly sorted by determining the library dependency graph
  • Install option: the shared libraries are installed to lib/ if install.library = true.
  • Naming convention: lib<package_name>.{so, dll, dylib} future-proof for later extension to versioning support
  • fpm run now dynamically updates LD_LIBRARY_PATH to include the library install folders.
  • examples, tests, and updated online documentation also provided at doc: shared library targets fpm-docs#164

Address #681 #655, Supersede #1050.

cc: @certik @urbanjost @arteevraina @henilp105

@perazz perazz force-pushed the dynamic_library branch from 0ee832e to 414f448 Compare May 12, 2025 17:27
Copy link
Contributor

@zoziha zoziha left a comment

Choose a reason for hiding this comment

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

@perazz, it looks great to me! This must be a huge amount of work. I'm also testing the code locally, and it works well.

Adding a shared logical key to the [library] field may pose the following confusion:

When shared = true or shared = false, users are confused if they want to create both static and dynamic link libraries.

This got me thinking about how cargo and meson do:

Cargo sets a crate-type string key in the [lib] field to distinguish or use both dylib and staticlib.

[lib]
# Generate both dynamic and static libraries
crate-type = ["dylib", "staticlib"]

Meson distinguishes between static, shared or both by the default_library macro.

Fpm does not currently have a crate definition and the crate-type key, maybe we need to define a key name for this, default-library, library-type or something else? to support flexible selection and construction of dynamic and static link libraries.

@perazz
Copy link
Member Author

perazz commented May 14, 2025

With this PR, we have:

Feature Meson Cargo fpm (this PR)
Shared build shared: true crate-type = cdylib shared = true
Static build static: true crate-type = staticlib No
Monolithic build No No shared = false (default)
Default behavior Shared + static both Static .rlib per crate Monolithic static archive
Unused object pruning Linker-dependent Only with LTO Only with monolithic
Granularity of control Per-target Crate-type per lib Global package setting

I think we can implement a static build, similar to the shared build (one complete library per package/dependency)
We could have one more option for the static library creation:

[library]
shared = true          # → shared libraries
shared = false         # → per-package static libraries
shared not set         # → monolithic static archive (default)

or similarly

[library]
type = "monolithic"  # monolithic static archive (default)
type = "shared" # shared libraries
type = "static" # static libraries

I would leave building two library types simultaneously as a new feature PR, as it will require far more complex changes to the build system. @zoziha what do you think?

@zoziha
Copy link
Contributor

zoziha commented May 14, 2025

I would leave building two library types simultaneously as a new feature PR

Thank you for your detailed explanation, @perazz . And yes, that would be another PR and it might also be quite complex.

Since this PR has implemented the construction of shared libraries and defined a shared key, do you have any ideas about the TOML key to control the construction in the PR for building both static and shared libraries simultaneously? Will another key be added to control the simultaneous construction? My consideration is that it would be best to have only one TOML key, which may be a string TOML key, to control the construction of all situations of static and shared libraries, keeping it simple like meson and cargo. Currently, it seems that the shared keyword has only three functional states: true, false, <not present>.

Additionally, when generating a shared library (.dll) in the MINGW or CYGWIN environment on Windows OS, an import library (.dll.a) should also be generated:

gfortran -shared -o libmydll.dll mydll.o -Wl,--out-implib,libmydll.dll.a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants