[英]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)
然后这样的工具会警告你有不必要的模块:
问题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.