ghc-musl, 用GHC与 musl libc实现 true static 连接

分享于 

9分钟阅读

GitHub

  繁體 雙語
Using GHC with musl libc to get true static linking
  • 源代码名称:ghc-musl
  • 源代码网址:http://www.github.com/nilcons/ghc-musl
  • ghc-musl源代码文档
  • ghc-musl源代码下载
  • Git URL:
    git://www.github.com/nilcons/ghc-musl.git
    Git Clone代码到本地:
    git clone http://www.github.com/nilcons/ghc-musl
    Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/nilcons/ghc-musl
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
    
    用 musl libc编译的 GHC

    这里项目旨在提供一个 Docker 映像,其中包括:

    • 包含一个用 musl libc ( 与标准相比,但更臃肿的glibc ) 编译并定位的GHC
    • 包含一个 Cabal 安装预先配置的Stackage版本,
    • 包含大量预先安装的Hackage软件包。

    这样可以实现以下目的:

    • 编译完全静态相当复杂的Haskell二进制文件,
    • 如果动态链接仍然是必需的或者首选的,那么很容易分发所需的libc和附加. so 文件。
    
    brooks:/tmp $ docker run -v/tmp/x:/tmp/x -it --rm nilcons/ghc-musl
    
    
    /# cd/tmp/x
    
    
    /tmp/x # echo 'main = putStrLn"Hello World!"'> test.hs
    
    
    /tmp/x # ghc --make -O2 -optl-static test
    
    
    [1 of 1] Compiling Main ( test.hs, test.o )
    
    
    Linking test.. .
    
    
    /tmp/x # strip -s test
    
    
    /tmp/x # file test
    
    
    test: ELF 64-bit LSB executable, x86-64, statically linked, stripped
    
    
    /tmp/x # exit
    
    
    brooks:/tmp $ cd/tmp/x
    
    
    brooks:/tmp/x $./test
    
    
    Hello World!
    
    
    brooks:/tmp/x $ ldd./test
    
    
     not a dynamic executable
    
    
    brooks:/tmp/x $ ls -l test
    
    
    -rwxr-xr-x 1 root root 1158408 Jun 10 15:25 test
    
    
    
    

    我们在这里看到,编译发生在从 nilcons/ghc-musl 映像创建的Docker 容器中,然后在主机上使用结果二进制。 这里二进制文件可以移植到任何其他 amd64 gnu/linux发行版,因为它不依赖任何。

    
    brooks:/tmp/x $ strace -e file./test
    
    
    execve("./test", ["./test"], [/* 53 vars */]) = 0
    
    
    Hello World!
    
    
    +++ exited with 0 +++
    
    
    
    brooks:/tmp/x $ strace -e file/bin/true
    
    
    execve("/bin/true", ["/bin/true"], [/* 53 vars */]) = 0
    
    
    access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
    
    
    access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
    
    
    open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
    
    
    access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
    
    
    open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
    
    
    +++ exited with 0 +++
    
    
    
    

    请注意( Debian提供的标准) /bin/true的文件访问操作和我们的Hello World 示例。 /bin/true 可执行文件只执行 5个文件访问操作来返回 0,而我们的可执行文件不执行任何文件操作来完成它的任务。 对于更复杂的可以执行文件,基于,的单独二进制文件将更具挑战性。

    如果你想了解与 static 链接的关于链接的更多问题,请在这里处或者从这里处开始: http://www.systutorials.com/5217/how-to-statically-link-c-and-c-programs-on-linux-with-gcc/

    版本

    在中安装了面向 musl libc的工作 GHC,它可以用于在GHCi中播放,或者编译不依赖于额外库的可执行文件。

    nilcons/ghc-musl:cabal: 作为基础之上的附加层,它还提供 /root/.cabal/bin/cabal 中的cabal-install 可执行文件。 可以使用这里可执行文件轻松地从Hackage安装包。

    nilcons/ghc-musl:stackage: 这里版本包含一个 Cabal 安装,该安装与 Stackage LTS 2.12. Stackage是一个预先测试的Hackage软件包集合: https://www.stackage.org/lts-2.12

    nilcons/ghc-musl:latest: 这个版本安装了大多数Haskell项目使用的一大堆Haskell软件包。 包列表是临时的,请在这里项目上打开一个GitHub问题,以包括你需要的附加库。 我们目前船上的软件包列表可以在 packages.txt 中找到。

    如果你使用 docker run -it --rm nilcons/ghc-musl 命令启动一个新容器,你将获得 latest 版本,包含所有包,最可以能是你想要的。 如果你想要更基本的内容,请直接指定版本 NAME,比如 docker run -it --rm nilcons/ghc-musl:base

    你可以在 DockerHub 找到所有这些版本和标签。

    用例:PrefetchFS的static 编译

    请参见 README.PrefetchFS.md

    用例:nc指标的分配

    请参见 README.nc-indicators.md

    使用案例:完全成熟的Haskell Docker 游乐场

    如果你没有对productionalize的任何内容,你也可以使用 nilcons/ghc-musl:latest 映像在不安装主机的情况下与Haskell一起播放。

    只需使用 docker run -it --rm nilcons/ghc-musl 命令启动一个 shell,你可以在它的中运行 ghci 以获得一个已经运行的数百个库。

    开发人员注释,内部:

    复制 Docker 图像是一个多步骤过程:

    • 这个例子包含了基于Debian的Docker 图像,最后一层包含了一个 tar.gz,在成功的DockerHub构建之后输出是 nilcons/ghc-musl-auto:ghc-cross

    • 这就是真正的东西,它使用来自 ghc-cross 步骤的GHC二进制,并重新编译 GHC,Cabal 和cabal的安装和安装的所有封装包。 成功完成后的输出是 nilcons/ghc-musl-auto:ghc-musl

    • 之后,在脚本中标记版本并推到 nilcons/ghc-musl:*,脚本还将更新文档列表中的包列表。

    因为我们的版本只是相同Dockerfile的构建过程中的不同层,所以最后一步是必要的。 另一种选择是创建一个Dockerfiles链,但目前在DockerHub上没有好的依赖处理机制。 这将有望在未来改变,然后我们将去掉 shell 脚本。

    感谢

    这个项目的想法来自一个reddit帖子: http://www.reddit.com/r/haskell/comments/37m7q7/ghc_musl_easier_static_linking/

    本文提供了计算结果细节的动机,然后在它的上构建和编译整个基础结构。

    当然,如果没有宝贵的 http://www.musl-libc.org/服务,所有这些黑客将是不可能的。

    另外,如果专业构建的http://alpinelinux.org/插件不能用于我们,那么直接使用musl会更加困难。

    最后,我们感谢的组织者as为启动这个项目提供初始的推动。

    进一步工作

    我们希望在图像中包括更多的工具,比如 Hoogle和 for,因这里你可以将它作为编辑器和/或者文档浏览器。

    另外,在 cabalghcghci 和其他相关可执行文件周围编写一些包装器,将调用转发到通过 Docker 卷与主机通信的daemonized Docker 容器可能值得a。

    自然( 也许最紧急的),我们希望目标的GHC不是 7.8.4和各种Stackage版本。 如果这些对你很重要,请向我们提供关于Reddit线程库的的反馈。

    关于我们

    Nilcons是瑞士Zürich的小型咨询和培训商店。

    对于休闲社交网络,请加入我们的Twitter @NilconsHQ 网站。

    有关这里项目的反馈,请使用 Reddit线程

    商业查询请使用 cons@nilcons.com 电子邮件地址。


    STA  STAT  Using  静态  link  LIBC  
    相关文章