繁体   English   中英

Linux中GHC的编译,依赖关系和可执行文件大小

[英]Compilation, dependencies, and executable size with GHC in Linux

问题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.鉴于Test.hm的功能未在Main.hs中使用,为什么可执行文件的大小有所不同?

Q1 Haskell无法警告您未使用的模块,因为将来可能会被其他软件包导入。 导入模块时,只会链接您导入的模块,因此,如果您创建一个永远不会导入模块的可执行文件,除非您明确告诉cabal链接它,否则该模块将不会包含在可执行文件中。

当您实际导入模块时,如果在编译时传递-fwarn-unused-imports标志,GHC可以警告您不使用该模块。 您还应该考虑使用-Wall ,它将启用此警告和许多其他有用的警告。 使用-Werror将使GHC拒绝编译带有警告的模块,例如未使用的导入或死代码。

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

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

您可以考虑使用-shared编译标志进行编译,该标志将使用共享库进行编译并大幅减少整体二进制文件大小,缺点是如果要在另一台计算机上使用已编译的二进制文件,则必须复制库文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM