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

Update cabal-package.rst w.r.t standalone foreign libs #9320

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

andreabedini
Copy link
Collaborator

@andreabedini andreabedini commented Oct 9, 2023

When describing the options: field for foreign libraries, the user guide currenlty says:

Options for building the foreign library, typically specific to the specified type of foreign library. Currently we only support standalone here. A standalone dynamic library is one that does not have any dependencies on other (Haskell) shared libraries; without the standalone option the generated library would have dependencies on the Haskell runtime library (libHSrts), the base library (libHSbase), etc. Currently, standalone must be used on Windows and must not be used on any other platform.

The phrase "standalone must be used on Windows and must not be used on any other platform" lacks enough details to let the user (or FWIW future contributors :P) understand what the issue is and what happens otherwise.

E.g.

  • When I tried to produce a standalone library on linux, the only issue I ran into was the old RPATH hack we have since removed (in Remove RPATH workaround #9164). If boot packages are built with -fPIC, producing a standalone foreign library seems to work without issues.

  • I do not have any knowledge of what can happen not using standalone on Windows (there's even a runtime assertion so one cannot check without modifying cabal). If it is something intrinsic to linking on window, I am wondering: would it make sense to make this automatic? is it worth having the user explictly write options: standalone?

The origin of the phrase seems to be Edsko's commit introducing foreign-libraries: 382143a. The commit message does not provide any further explanation other than "it is not supported":

Add support for foreign libraries.

A stanza for a platform library looks something like

    platform-library test-package
      type:                native-shared

      if os(Windows)
        options: standalone
        mod-def-file: TestPackage.def

      other-modules:       MyPlatformLib.Hello
                           MyPlatformLib.SomeBindings
      build-depends:       base >=4.7 && <4.9
      hs-source-dirs:      src
      c-sources:           csrc/MyPlatformLibWrapper.c
      default-language:    Haskell2010

where native-shared means that we want to build a native shared library
(.so on Linux, .dylib on OSX, .dll on Windows). The parser also
recognizes native-static but this is not currently supported anywhere.
The standalone option means that the we merge all library dependencies
into the dynamic library (i.e., ghc options -shared -static), rather
than make the created dynamic library just record its dependencies (ghc
options -shared -dynamic); it is currently compulsory on Windows and
unsupported anywhere else. The mod-def-file can be used to specify a
module definition file, and is also Windows specific.

There is a bit of refactoring in Build: gbuild is the old buildOrReplExe
and now deals with both executables and platform libraries.

EDIT: what about macOS? We cannot just ignore it.

EDIT 2: AFAIU this just relies on passing the right flags to GHC, so it's GHC doing the linking. In that case, whether it is supported or not is GHC responsibility more than cabal's.

@@ -1324,6 +1324,7 @@ A typical stanza for a foreign library looks like
lib-version-info: 6:3:2

if os(Windows)
-- standalone *must* be used on Windows.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

What happens otherwise?

(``libHSbase``), etc. Currently, ``standalone`` *must* be used on Windows
and *must not* be used on any other platform.
(``libHSbase``), etc.
The ``standalone`` option *must* be used on Windows (FIXME: why? is so why is this not automatic?).
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

On Linux, ghc boot packages need to have been compiled with -fPIC otherwise they won't be able to be statically linked in.

@andreabedini
Copy link
Collaborator Author

Tagging @bgamari and @angerman as linking experts.

@andreabedini andreabedini self-assigned this Oct 9, 2023
@andreabedini
Copy link
Collaborator Author

Ah, the good old

Error:     Ambiguous module name ‘System.Directory’:
      it was found in multiple packages:
      directory-1.3.8.1 directory-1.3.8.1
  |
3 | import System.Directory
  | ^^^^^^^^^^^^^^^^^^^^^^^

<interactive>:338:31: error:
    Not in scope: ‘Main.main’
    No module named ‘Main’ is imported.

@andreabedini andreabedini changed the title Update cabal-package.rst w.r.t standalone foreign librs Update cabal-package.rst w.r.t standalone foreign libs Oct 12, 2023
@andreabedini andreabedini force-pushed the andreabedini-standalone-foreign-libs branch from 5375e31 to 568a42b Compare November 21, 2023 02:54
@andreabedini
Copy link
Collaborator Author

@BinderDavid @malteneus Would you mind looking at this from a documentation point-of-view?
@Mikolaj @ulysses4ever @Kleidukos What should we do here? I think standalone foreign-libs work on Linux but I haven't managed to track down the origin of the original statement.

@andreabedini andreabedini marked this pull request as ready for review November 21, 2023 02:56
@andreabedini
Copy link
Collaborator Author

These are some notes from the investigation I did some months ago
https://gist.github.com/andreabedini/a3b012345124854c2fe58380dfe3d4ae

@@ -1356,8 +1357,7 @@ A typical stanza for a foreign library looks like
have any dependencies on other (Haskell) shared libraries; without
the ``standalone`` option the generated library would have dependencies
on the Haskell runtime library (``libHSrts``), the base library
(``libHSbase``), etc. Currently, ``standalone`` *must* be used on Windows
and *must not* be used on any other platform.
(``libHSbase``), etc. The ``standalone`` option *must* be used on Windows.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Still does not say why this must be used on windows. I mean sure, we do not have dynamic linking on window (for Haskell libraries) at all! So if you do not pass standalone you end up with only the library you are building, but it lacks all the dependencies. (I think).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It does not say why because I did not know why. What you say sounds reasonable, perhaps we should do some tests.

@@ -1326,6 +1326,7 @@ A typical stanza for a foreign library looks like
lib-version-info: 6:3:2

if os(Windows)
-- standalone *must* be used on Windows.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
-- standalone *must* be used on Windows.
-- standalone *must* be used on Windows. See (pkg-field:: options: foreign library option list)

no idea how to make that a link with rST.

@angerman
Copy link
Collaborator

We should probably note that option: standalone might change in the future on windows if and once we support dynamic libraries? (Again assuming my understanding is correct).

This does highlight an issue I experienced with linking static windows libraries when going from 8.10 to 9.6 (and thus also newer cabal) I think.

@ulysses4ever
Copy link
Collaborator

@andreabedini do you see a path forward here? @angerman were all of your comments addressed?

@ulysses4ever
Copy link
Collaborator

@ulysses4ever What should we do here? I think standalone foreign-libs work on Linux but I haven't managed to track down the origin of the original statement.

I have not a slightest idea about foreign libs, I'm sorry to say!

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

Successfully merging this pull request may close these issues.

None yet

4 participants