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

Reintroduce 'static' flag #9068

Closed
benz0li opened this issue Sep 8, 2023 · 9 comments
Closed

Reintroduce 'static' flag #9068

benz0li opened this issue Sep 8, 2023 · 9 comments

Comments

@benz0li
Copy link
Contributor

benz0li commented Sep 8, 2023

Using cabal

It is impossible to create a statically linked binary with cabal install: haskell/cabal#7236
ℹ️ This is only possible with cabal build.

Using stack

It is possible to create a statically linked binary with stack install: Using --flag=<executable>:static
👉 E.g. for statically linking stack using stack.

Describe your proposed improvement and the problem it solves.

Unfortunately, I do not know what needs to be changed in order to create a statically linked pandoc binary with stack install.

What I know is that the 'static' flag was removed at some point:

Describe alternatives you've considered.

The supposedly equivalent stack install --ghc-options '-static -optl-static -optl-pthread' pandoc-cli does not work:

[...]
pandoc                           > configure (lib + internal-lib)
pandoc                           > Configuring pandoc-3.1.6.2...
pandoc                           > build (lib + internal-lib)
pandoc                           > Preprocessing library 'xml-light' for pandoc-3.1.6.2..
pandoc                           > Building library 'xml-light' for pandoc-3.1.6.2..
pandoc                           > [1 of 4] Compiling Text.Pandoc.XML.Light.Types
pandoc                           > [2 of 4] Compiling Text.Pandoc.XML.Light.Proc
pandoc                           > [3 of 4] Compiling Text.Pandoc.XML.Light.Output
pandoc                           > [4 of 4] Compiling Text.Pandoc.XML.Light
pandoc                           > /usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: /usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/crtbeginT.o: relocation R_X86_64_32 against hidden symbol `__TMC_END__' can not be used when making a shared object
pandoc                           > /usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: failed to set dynamic section sizes: bad value
pandoc                           > collect2: error: ld returned 1 exit status
pandoc                           > `gcc' failed in phase `Linker'. (Exit code: 1)
Progress 222/225        

Error: [S-7282]
       Stack failed to execute the build plan.
       
       While executing the build plan, Stack encountered the error:
       
       [S-7011]
       While building package pandoc-3.1.6.2 (scroll up to its section to see the error) using:
       /home/vscode/.stack/setup-exe-cache/x86_64-linux/Cabal-simple_6HauvNHV_3.8.1.0_ghc-9.4.5 --verbose=1 --builddir=.stack-work/dist/x86_64-linux/Cabal-3.8.1.0 build lib:pandoc lib:xml-light --ghc-options " -fdiagnostics-color=always"
       Process exited with code: ExitFailure 1 

Cross references:

@jgm
Copy link
Owner

jgm commented Sep 8, 2023

Did you try what the commit above suggests?

cabal's new option
`--enable-executable-static` does the same. On stack
you can add something like this to the options for your
executable in package.yaml:

    ld-options: -static -pthread

@benz0li
Copy link
Contributor Author

benz0li commented Sep 8, 2023

Did you try what the commit above suggests?

cabal's new option
`--enable-executable-static` does the same. On stack
you can add something like this to the options for your
executable in package.yaml:

    ld-options: -static -pthread

I know this works. But why an extra configuration file?

@benz0li
Copy link
Contributor Author

benz0li commented Sep 8, 2023

And yes: I have tried installing https://github.com/commercialhaskell/stack with stack install --ghc-options '-static -optl-static -optl-pthread'.

It does not work either:

[...]
Building all executables for stack once. After a successful build of all of them, only specified executables will be rebuilt.
stack                        > configure (lib + exe)
[1 of 3] Compiling Main             ( /workspaces/commercialhaskell-stack/Setup.hs, /workspaces/commercialhaskell-stack/.stack-work/dist/x86_64-linux/Cabal-3.8.1.0/setup/Main.o )
[2 of 3] Compiling StackSetupShim   ( /home/vscode/.stack/setup-exe-src/setup-shim-6HauvNHV.hs, /workspaces/commercialhaskell-stack/.stack-work/dist/x86_64-linux/Cabal-3.8.1.0/setup/StackSetupShim.o )
[3 of 3] Linking /workspaces/commercialhaskell-stack/.stack-work/dist/x86_64-linux/Cabal-3.8.1.0/setup/setup
Configuring stack-2.12.0...
stack                        > build (lib + exe)
Preprocessing library for stack-2.12.0..
Building library for stack-2.12.0..
[  1 of 178] Compiling Build_stack
[  2 of 178] Compiling Network.HTTP.StackClient
[  3 of 178] Compiling Path.Extended
[  4 of 178] Compiling Path.Extra
[  5 of 178] Compiling Path.Find
[  6 of 178] Compiling Paths_stack
[  7 of 178] Compiling Stack.Prelude
[  8 of 178] Compiling Stack.Options.Utils
[  9 of 178] Compiling Stack.Options.LogLevelParser
[ 10 of 178] Compiling Stack.Ghci.Script
[ 11 of 178] Compiling Stack.FileWatch
[ 12 of 178] Compiling Stack.Constants.UsrLibDirs
[ 13 of 178] Compiling Stack.Constants.StackProgName
[ 14 of 178] Compiling Stack.BuildInfo
/usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: /usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/crtbeginT.o: relocation R_X86_64_32 against hidden symbol `__TMC_END__' can not be used when making a shared object
/usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: failed to set dynamic section sizes: bad value
collect2: error: ld returned 1 exit status
                       
<no location info>: error:
    `gcc' failed in phase `Linker'. (Exit code: 1)
[ 15 of 178] Compiling Options.Applicative.Builder.Extra
[ 16 of 178] Compiling Data.Monoid.Map
[ 17 of 178] Compiling Data.Attoparsec.Combinators
[ 18 of 178] Compiling Data.Attoparsec.Args
[ 19 of 178] Compiling Options.Applicative.Args
[ 20 of 178] Compiling Control.Concurrent.Execute
[ 21 of 178] Compiling Stack.Types.AllowNewerDeps
[ 22 of 178] Compiling Stack.Types.ApplyGhcOptions
[ 23 of 178] Compiling Stack.Types.ApplyProgOptions
[ 24 of 178] Compiling Stack.Types.BuildOpts
[ 25 of 178] Compiling Stack.Options.TestParser
[ 26 of 178] Compiling Stack.Options.PackageParser
[ 27 of 178] Compiling Stack.Options.HaddockParser
[ 28 of 178] Compiling Stack.Options.BenchParser
[ 29 of 178] Compiling Stack.Config.Build
[ 30 of 178] Compiling Stack.Types.CabalConfigKey
[ 31 of 178] Compiling Stack.Types.Casa
[ 32 of 178] Compiling Stack.Types.ColorWhen
[ 33 of 178] Compiling Stack.DefaultColorWhen
[ 34 of 178] Compiling Stack.Types.CompilerBuild
[ 35 of 178] Compiling Stack.Options.GhcBuildParser
[ 36 of 178] Compiling Stack.Types.Curator
[ 37 of 178] Compiling Stack.Types.DockerEntrypoint
[ 38 of 178] Compiling Stack.Types.DownloadInfo
[ 39 of 178] Compiling Stack.Types.DumpLogs
[ 40 of 178] Compiling Stack.Types.EnvSettings
[ 41 of 178] Compiling Stack.Types.ExtraDirs
[ 42 of 178] Compiling Stack.Types.FileDigestCache
[ 43 of 178] Compiling Stack.Types.GHCDownloadInfo
[ 44 of 178] Compiling Stack.Types.GHCVariant
[ 45 of 178] Compiling Stack.Options.GhcVariantParser
[ 46 of 178] Compiling Stack.Types.GhcOptionKey
[ 47 of 178] Compiling Stack.Types.GhcOptions
[ 48 of 178] Compiling Stack.Types.GhcPkgId
[ 49 of 178] Compiling Stack.Types.DumpPackage
[ 50 of 178] Compiling Stack.Types.Cache
[ 51 of 178] Compiling Stack.Types.IsMutable
[ 52 of 178] Compiling Stack.Types.LockFileBehavior
[ 53 of 178] Compiling Stack.Types.NamedComponent
[ 54 of 178] Compiling Stack.Types.Nix
[ 55 of 178] Compiling Stack.Types.PackageName
[ 56 of 178] Compiling Stack.Types.Platform
[ 57 of 178] Compiling Stack.Types.Project
[ 58 of 178] Compiling Stack.Types.ProjectConfig
[ 59 of 178] Compiling Stack.Types.PvpBounds
[ 60 of 178] Compiling Stack.Types.Resolver
[ 61 of 178] Compiling Stack.Options.ResolverParser
[ 62 of 178] Compiling Stack.Types.SCM
[ 63 of 178] Compiling Stack.Types.StackYamlLoc
[ 64 of 178] Compiling Stack.Types.Storage
[ 65 of 178] Compiling Stack.Storage.Util
[ 66 of 178] Compiling Stack.Types.TemplateName
[ 67 of 178] Compiling Stack.Types.UnusedFlags
[ 68 of 178] Compiling Stack.Types.Version
[ 69 of 178] Compiling Stack.Types.ParentMap
[ 70 of 178] Compiling Stack.Types.Dependency
[ 71 of 178] Compiling Stack.Types.Compiler
[ 72 of 178] Compiling Stack.Types.SourceMap
[ 73 of 178] Compiling Stack.Types.CompilerPaths
[ 74 of 178] Compiling Stack.Types.VersionedDownloadInfo
[ 75 of 178] Compiling Stack.Types.SetupInfo
[ 76 of 178] Compiling System.Info.ShortPathName
[ 77 of 178] Compiling System.Permissions
[ 78 of 178] Compiling Stack.Constants
/usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: /usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/crtbeginT.o: relocation R_X86_64_32 against hidden symbol `__TMC_END__' can not be used when making a shared object
/usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: failed to set dynamic section sizes: bad value
collect2: error: ld returned 1 exit status
                       
<no location info>: error:
    `gcc' failed in phase `Linker'. (Exit code: 1)
[124 of 178] Compiling System.Process.Pager
[125 of 178] Compiling System.Terminal
[126 of 178] Compiling System.Uname
Completed 173 action(s).

Error: [S-7282]
       Stack failed to execute the build plan.
       
       While executing the build plan, Stack encountered the error:
       
       [S-7011]
       While building package stack-2.12.0 (scroll up to its section to see the error) using:
       /workspaces/commercialhaskell-stack/.stack-work/dist/x86_64-linux/Cabal-3.8.1.0/setup/setup --verbose=1 --builddir=.stack-work/dist/x86_64-linux/Cabal-3.8.1.0 build lib:stack exe:stack --ghc-options " -fdiagnostics-color=always"
       Process exited with code: ExitFailure 1

Cross reference: https://github.com/benz0li/commercialhaskell-stack/tree/add-dev-containers/.devcontainer#build-and-install-stack (adding --no-install-ghc --system-ghc to the command)

FYI @mpilgrem


With stack install --flag=stack:static it works fine.

@benz0li
Copy link
Contributor Author

benz0li commented Sep 8, 2023

@jgm If you think the current state is user-friendly enough, you can close the issue.

@mpilgrem
Copy link

mpilgrem commented Sep 8, 2023

stack install is a synonym for stack build --copy-bins. It differs from stack build only in that it copies built executable files to a specified location. With Stack, the effect for a package of Cabal flag static (specified on Stack's command line by --flag <package>:static) will depend on the package's Cabal file. In the case of stack.cabal, it causes ld-options: -static -pthread to be set.

@benz0li
Copy link
Contributor Author

benz0li commented Sep 8, 2023

Really interesting: stack install --ghc-options '-static -optl-static -optl-pthread' works on Linux/AArch64.

Tested with the Default Dev Container on my MacBook Pro M2 (arm64 aka AArch64) using Docker Desktop and adding --no-install-ghc --system-ghc to the command.


BTW I assume the following statement to be correct:

[at]Reid Barton is right, regarding the root cause of the problem. The real issue here is that stack is building a shared binary by default. By passing the options -static or ghc-options: -optl-static we are only addressing respectively the ghc layer and ld layer.

stack
 |_ cabal
      |_ ghc
          |_ gcc
              |_ ld (linker)

The correct way to solve the issue is to tell cabal that we want a static binary, as it pilots the build.

The answer on how to do that was provided by sausade1 on reddit: you just have to add the following to your .cabal file in the executable section:

directive:

`ld-options: -static`

This will hint to cabal that we want a static binary and as so it will not pass -shared to ghc.

gcc - Haskell Stack Static Binary relocation R_X86_64_32 against `TMC_END' can not be used when making a shared object - Stack Overflow

Footnotes

  1. https://www.reddit.com/r/haskell/comments/5lk33p/struggling_building_a_static_binary_for_aws/

@jgm
Copy link
Owner

jgm commented Sep 8, 2023

The suggestion, then, would be to reverse this change?
3f278f5

All the old static flag did was set ld-options: -static. I removed this because (a) I didn't want to give people the impression that setting this flag was sufficient for a static build, (b) you can achieve the same effect by adding -optl-static on the command line, (c) the static flag didn't work on macOS and this might confuse people.

I'm still unclear about the value of adding it back... No extra config file is needed; you can specify the option on the command line as you saw above (and presumably also in cabal ghc-options?), at least on Linux ... on macOS you can't get fully static linking anyway.

@benz0li
Copy link
Contributor Author

benz0li commented Sep 11, 2023

The suggestion, then, would be to reverse this change? 3f278f5

Yes, in its functionality.

All the old static flag did was set ld-options: -static. I removed this because (a) I didn't want to give people the impression that setting this flag was sufficient for a static build

Adding ghc-options: -static and ld-options: -static -pthread (where required) for the static flag would.

(b) you can achieve the same effect by adding -optl-static on the command line,

Works with cabal (build only).

Does not work with stack (build/install using --ghc-options '-static -optl-static -optl-pthread')

(c) the static flag didn't work on macOS and this might confuse people.

True. Therefore, pandoc.cabal stated that fully static builds are not possible on macos.

I'm still unclear about the value of adding it back... No extra config file is needed; you can specify the option on the command line as you saw above (and presumably also in cabal ghc-options?), at least on Linux ... on macOS you can't get fully static linking anyway.

Enable building a statically linked pandoc executable via

  1. cabal build --flag=static pandoc-cli
  2. stack build --flag=pandoc:static pandoc-cli

on Linux.

Thank you for reconsidering.

@jgm
Copy link
Owner

jgm commented Sep 11, 2023

Adding ghc-options: -static and ld-options: -static -pthread (where required) for the static flag would.

Well, not exactly. On macOS, you still won't get a fully static build. Nor will you on linux unless you use something like alpine. I didn't want people using this flag and then thinking they had a static build when they didn't. I think that's the confusion I'd hoped to avoid. But yes, the flag might be convenient for people who know what they're doing. On the other hand, such people will know what to do without the flag, too.

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

No branches or pull requests

3 participants