gpt4 book ai didi

linux - 在 Linux 中使用 GHC 的编译、依赖关系和可执行文件大小

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:58:35 25 4
gpt4 key购买 nike

问题 1

出于改进 haskell 编译时间的原因(任何包含的模块都会被编译,无论是否使用底层功能),是否有任何工具可以警告 haskell 程序员包含了不必要的模块?例如,假设我们有以下设置:

NecessaryModule1.hs

module NecessaryModule1 where

addNumber1 :: Int -> Int -> Int
addNumber1 a b = a + b

NecessaryModule2.hs

module NecessaryModule2 where

addNumber2 :: Int -> Int -> Int
addNumber2 a b = a + b

Test.hs

module Test where

import NecessaryModule1
import NecessaryModule2

Main.hs

module Main where
import Test

myadd :: Int->Int->Int
myadd a b = a + b

main::IO()
main = print(myadd 5 6)

然后这样的工具会警告你有不必要的模块:

  • Main.hs : 因为没有使用 Test 的功能
  • Test.hs:因为没有使用 NecessaryModule1 和 NecessaryModule2 的功能


问题 2

如果我通过以下方式编译上面的代码:

ghc -o testProg Main.hs

然后我得到一个大小为 833504 字节的可执行文件。但是,如果我将 Main.hs 更改为:

Main.hs

module Main where
--import Test

myadd :: Int->Int->Int
myadd a b = a + b

main::IO()
main = print(myadd 5 6)

然后可执行文件的大小减少到 833057。鉴于 Main.hs 中未使用 Test 模块的功能,为什么可执行文件的大小存在差异?

最佳答案

Q1 Haskell 无法就未使用的模块向您发出警告,因为它们将来可能会被另一个包导入。但是,当您导入模块时,只有那些您导入的模块会被链接,因此如果您使用从未导入的模块创建可执行文件,除非您明确告诉 cabal,否则该模块将不会包含在可执行文件中。链接它。

当您实际导入一个模块时,如果您通过了 -fwarn-unused-imports 参数,GHC 会警告您不要使用该模块。编译时标记。您还应该考虑使用 -Wall ,这将启用此警告和许多其他有用的警告。使用 -Werror将使 GHC 拒绝编译带有警告的模块,例如未使用的导入或死代码。

你也可以传递标志-split-objs到 GHC,这将使 GHC 每个函数(或多或少)创建一个目标文件,而不是每个模块一个目标文件,从而可以大大减少可执行文件的大小。

Q2 作为其某些功能的一部分,Template Haskell 语言扩展可以浏览模块的本地范围。因此,GHC 有必要在编译模块时包含显式导入的代码,因为可能有一些 TH 功能依赖于它。启用某些级别的优化(如 -O2 )可能应该再次删除未使用的代码,但不能保证。

您可能会考虑使用 -shared 进行编译编译标志,它将使用共享库进行编译并大大减少整体二进制文件的大小,缺点是如果您想在不同的计算机上使用编译后的二进制文件,则必须一起复制库文件。

关于linux - 在 Linux 中使用 GHC 的编译、依赖关系和可执行文件大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12019072/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com