编译器 | compile
compile
模块
编译
模块摘要
Erlang编译器
描述
该模块提供了一个与标准Erlang编译器的接口。它可以生成包含目标代码的新文件,也可以返回可以直接加载的二进制文件。
出口
env_compiler_options()
返回通过环境变量提供的编译器选项ERL_COMPILER_OPTIONS
如果该值是一个列表,则按原样返回。如果它不是一个列表,它就被放入一个列表中。
file(File)
和file(File, [verbose,report_errors,report_warnings])
是一样的。
file(File, Options) -> CompRet
类型
编译文件中的代码File
,这是一个Erlang源代码文件,不包含.erl
扩展名。Options
确定编译器的行为。
如果成功返回{ok,ModuleName}
,或者error
有错误。如果编译成功没有错误,则会创建一个对象代码文件。如果源代码中的模块名称与输出文件的基本名称不同,则认为这是错误的。
可供选择的办法:
basic_validation
该选项是测试模块是否会成功编译的快速方法。这对于想要验证它们发出的代码的代码生成器很有用。没有代码生成。如果启用了erl_lint
警告,则还会返回模块生成的警告(如未使用的变量和函数的警告)。
使用选项strong_validation
来生成编译器将生成的所有警告。
strong_validation
类似于选项basic_validation
。没有生成代码,但会运行更多的编译器传递,以确保生成由优化过程生成的警告(例如,不匹配的子句或保证在运行时出现异常而失败的表达式)。
binary
编译器以二进制形式返回目标代码,而不是创建目标文件。如果成功,编译器会返回{ok,ModuleName,Binary}
。
bin_opt_info
编译器将发出有关二进制匹配优化(成功和不成功)的信息性警告。有关更多信息,请参见bin_opt_info
效率指南中的相关章节。
compressed
编译器会压缩生成的目标代码,这对嵌入式系统很有用。
debug_info
在编译的光束模块Erlang Abstract Format
的debug_info
块中包含调试信息。诸如Debugger,Xref和Cover之类的工具要求包含调试信息。
警告
:源代码可以从调试信息重建。使用加密的调试信息(encrypt_debug_info
)来防止这种情况。
有关详情,请参阅beam_lib(3)
。
{debug_info, {Backend, Data}}
包含自定义调试信息,以编译梁模块中的Backend
自定义Data
模块形式提供。给定的模块必须实现一个debug_info/4
功能,并且负责产生不同的代码表示,如在所描述的debug_info
下beam_lib(3)
。
警告
:源代码可以从调试信息重建。使用加密的调试信息(encrypt_debug_info
)来防止这种情况。
{debug_info_key,KeyString}
{debug_info_key,{Mode,KeyString}}
包含调试信息,但对其进行加密,以便在未提供密钥的情况下无法访问它。(也可以提供选项debug_info
,但不是必需的。)使用此选项是在测试过程中始终提供调试信息并保护源代码的好方法。
Mode
是用于加密调试信息的加密算法的类型。默认(现在是唯一的)类型是des3_cbc
。
有关详情,请参阅beam_lib(3)
。
encrypt_debug_info
类似于debug_info_key
选项,但该键是从.erlang.crypt
档案。
有关详情,请参阅beam_lib(3)
。
deterministic
省略返回列表中的元组options
和source
元组Module:module_info(compile)
。这个选项将使得重现性构建变得更容易。
makedep
生成一个Makefile规则来跟踪标题依赖项。不产生任何目标文件。
默认情况下,写入此规则<File>.Pbeam。但是,如果binary设置了选项,则不会写入任何内容,并返回规则Binary。
例如,如果您有以下模块:
-module(module).
-include_lib("eunit/include/eunit.hrl").
-include("header.hrl").
此选项生成的Makefile规则如下所示:
module.beam: module.erl \
/usr/local/lib/erlang/lib/eunit/include/eunit.hrl \
header.hrl
{makedep_output, Output}
写入生成的规则Output而不是默认值<File>.Pbeam。Output可以是一个文件名或一个io_device()。要写入标准输出,请使用standard_io。但是,如果binary已设置,则不会写入任何内容,Output并将结果返回给调用方{ok, ModuleName, Binary}。
{makedep_target, Target}
更改发送到的规则的名称Target
。
makedep_quote_target
Target
引用特殊字符(1)中的字符。
makedep_add_missing
将丢失的标头视为生成的文件,并将它们添加到依赖项中。
makedep_phony
为每个依赖项添加一个假目标。
'P'
在文件中,经过预处理和解析转换,生成已解析代码的列表。<File>.P没有产生任何目标文件。
'E'
在执行了所有源代码转换之后,在文件中生成代码的列表。<File>.E没有产生任何目标文件。
'S'
生成文件中汇编程序代码的列表。<File>.S没有产生任何目标文件。
report_errors/report_warnings
导致错误/警告发生时打印出来。
report
两者report_errors
和一个简短的表格report_warnings
。
return_errors
如果设置了该标志,{error,ErrorList,WarningList}
则在出现错误时返回。
return_warnings
如果设置了此标志,则另有一个字段,其中包含WarningList
,被添加到在成功时返回的元组中。
warnings_as_errors
导致将警告视为错误。自R13B04以来就支持此选项。
return
两者return_errors
和一个简短的表格return_warnings
。
verbose
导致编译器提供更详细的信息,描述它正在做的事情。
{source,FileName}
设置返回的源的值module_info(compile)
。
{outdir,Dir}
为目标代码设置一个新目录。当前目录用于输出,但在使用此选项指定目录时除外。
export_all
导致导出模块中的所有函数。
{i,Dir}
添加Dir
到包含文件时要搜索的目录列表中。遇到-include
或-include_lib
指令时,编译器搜索以下目录中的头文件:
"."
文件服务器的当前工作目录。
- 已编译文件的基本名称。
- 使用i选项指定的目录。首先搜索指定的目录。
- 一个
warn_xxx
表单,打开警告。
- 一种
nowarn_xxx
形式,关闭警告。
在下面的描述中,列出了用于更改默认值的表单。
{warn_format, Verbosity}
使格式错误的字符串作为参数io:format
和类似函数发出警告。
Verbosity
选择警告的数量:
0
=无警告
1
=对无效格式字符串和不正确参数数的警告
2
=无法检查有效性时的警告,例如,格式字符串参数是变量时。
默认的详细程度是1
。详细程度0
也可以通过选项来选择nowarn_format
。
nowarn_bif_clash
此选项被删除,如果使用该选项将生成致命错误。
警告
从R14A开始,编译器不再调用自动导入的BIF,如果名称与本地函数或显式导入函数冲突,并且发出没有显式模块名称的调用。相反,调用本地或导入函数。仍在接受nowarn_bif_clash
会使调用函数的模块与自动导入的BIF发生冲突,用新旧编译器进行编译,但语义完全不同。这就是为什么删除该选项的原因。
一直不鼓励使用这一选项。从R14A开始,使用它是一个错误。
若要解决BIF冲突,请使用显式模块名称或{no_auto_import,[F/A]}
编译器指令
{nowarn_bif_clash, FAs}
此选项被删除,如果使用该选项将生成致命错误。
警告
一直不鼓励使用这一选项。从R14A开始,使用它是一个错误。
若要解决BIF冲突,请使用显式模块名称或{no_auto_import,[F/A]}
编译器指令
nowarn_export_all
控件的使用关闭警告。export_all
选择。默认情况下,发出警告如果选项export_all
也给出了。
warn_export_vars
对第一次定义原语之后引用的所有隐式导出变量发出警告。默认情况下,编译器只对模式中引用的导出变量发出警告。
nowarn_shadow_vars
关闭函数对象中“新”变量的警告,或使用与一些已经定义的变量同名的列表理解。默认情况下,对这些变量发出警告。
nowarn_unused_function
关闭未使用的本地函数的警告。默认情况下,对导出函数没有直接或间接调用的所有本地函数发出警告。编译器在生成的BEAM文件中不包含未使用的本地函数,但是警告对于保持源代码的干净仍然很有用。
{nowarn_unused_function, FAs}
关闭未使用的本地函数的警告,如nowarn_unused_function
但只适用于上述的局部函数。FAs
是元组{Name,Arity}
或者这样的元组的列表。
nowarn_deprecated_function
关闭调用已弃用函数的警告。缺省情况是为每个对编译器已知的函数的调用发出警告,以便不推荐使用。请注意,编译器不知道属性-deprecated()
,但在Erlang / OTP中使用已组装的已弃用函数列表。要进行更全面的检查,可以使用Xref工具。另请参见xref(3)
功能xref:m/1
,也可通过功能访问c:xm/1
。
{nowarn_deprecated_function, MFAs}
关闭对不推荐函数的调用的警告,如nowarn_deprecated_function
但只适用于上述函数。MFAs
是元组{Module,Name,Arity}
或者这样的元组的列表。
nowarn_deprecated_type
关闭使用不推荐类型的警告。默认情况下,对编译器已知的不推荐类型的每次使用都会发出警告。
nowarn_obsolete_guard
关闭对旧类型测试BIF的调用的警告,例如pid/1
和list/1
...参见Erlang Reference Manual
有关类型测试的完整列表,BIF及其旧的对应项。默认情况下,对旧类型测试BIF的调用发出警告。
warn_unused_import
对未使用的导入函数发出警告。默认情况下,不对未使用的导入函数发出警告。
nowarn_unused_vars
默认情况下,除了以下划线开头的变量(“Prolog样式警告”)外,未使用的变量会发出警告。使用此选项关闭此类警告。
nowarn_unused_record
关闭未使用记录类型的警告。默认情况下,对未使用的本地定义记录类型发出警告。
nowarn_get_stacktrace
关闭使用警告get_stacktrace/0
在将来的发行版中,它可能无法工作。例如,默认情况下,如果get_stacktrace/0
在catch
表情。
编译器在优化和代码生成期间会生成另一类警告。他们警告那些永远不会匹配的模式(例如a=b
),总是评估为假的守卫,以及总是失败的表达(如atom+42
)。
这些警告不能禁用(除非禁用所有警告)。
注
编译器不会警告它没有尝试优化的表达式。例如,编译器尝试评估1/0
,检测到它会导致异常,并发出警告。但是,X/0
由于其中的变量,编译器对类似表达式保持沉默。因此,编译器甚至不尝试评估,因此它不会发出警告。
警告
没有警告并不意味着代码中没有剩余的错误。
注
除include路径({i,Dir}
)外,所有选项都可以在带有属性的文件中给出-compile([Option,...])
。-compile()
在函数定义之后允许属性。
注
选项{nowarn_unused_function, FAs}
,{nowarn_bif_clash, FAs}
和{nowarn_deprecated_function, MFAs}
,只有在文件中给出时才被识别。他们不受选项warn_unused_function
,warn_bif_clash
或warn_deprecated_function
。
对于编译器的调试,或纯粹的好奇心,可以检查每个编译器生成的中间代码。要打印生成列表文件的完整选项列表,请compile:options()
在Erlang shell提示符下输入。选项按照执行顺序打印。如果使用多个列表选项,则表示最早传递的那个选项将生效。
未识别的选项将被忽略。
WarningList
和ErrorList
具有以下格式:
[{FileName,[ErrorInfo]}].
ErrorInfo
将在本节稍后介绍。这里包含文件名,因为编译器使用Erlang预处理器epp
,它允许将代码包含在其他文件中。因此,重要的是要知道错误或警告的行号涉及哪个
文件。
forms(Forms)
和forms(Forms, [verbose,report_errors,report_warnings])
是一样的。
forms(Forms, Options) -> CompRet
类型
与之类似file/1
,但是将形式列表(以Erlang抽象格式表示形式)作为第一个参数。选项binary
是隐含的,也就是说,不生成目标代码文件。对于通常产生列表文件的选项,例如'E',将返回该编译器的内部格式(Erlang术语,通常不是二进制),而不是二进制文件。
format_error(ErrorDescriptor) -> chars()
类型
使用ErrorDescriptor
并返回描述错误的深层字符列表。当处理ErrorInfo
结构(在章节中描述Error Information
)时,通常会隐式地调用此函数。
output_generated(Options) -> true | false
类型
确定编译器是否生成beam
具有给定选项的文件。true
意味着beam
生成一个文件。false
意味着编译器生成一些列表文件,返回一个二进制文件,或仅仅检查源代码的语法。
noenv_file(File, Options) -> CompRet
像file/2
,除了ERL_COMPILER_OPTIONS
没有咨询环境变量。
noenv_forms(Forms, Options) -> CompRet
像forms/2
,除了ERL_COMPILER_OPTIONS
没有咨询环境变量。
noenv_output_generated(Options) -> true | false
类型
就像output_generated/1
,除了环境变量ERL_COMPILER_OPTIONS
没有咨询过。
默认编译器选项
(主机操作系统)环境变量ERL_COMPILER_OPTIONS
可用于给出默认编译器选项。它的值必须是一个有效的Erlang术语。如果该值是一个列表,则按原样使用。如果它不是一个列表,它将被放入一个列表中。
该列表将追加到给任何选项file/2
,forms/2
和output_generated/2
。使用替代函数noenv_file/2
,noenv_forms/2
或者noenv_output_generated/2
如果您不希望查阅环境变量,例如,如果从解析转换内部递归调用编译器。
该列表可以通过检索env_compiler_options/0
。
内联
编译器可以在Erlang模块内部进行函数内联。内联意味着函数的调用被替换为函数体,参数被替换为实际值。语义被保留,除非在内联代码中生成异常。据报异常情况发生在身体被插入的功能中。此外,function_clause
例外情况也转换为类似的case_clause
例外情况
内联函数时,如果导出原函数(通过显式导出或export_all
给出选项),或者不是所有对函数的调用都内联,则保留原函数。
内联不一定会改善运行时间。例如,内联可以增加梁堆栈的使用,这可能会损害递归函数的性能。
内联从来都不是默认的。必须使用编译器选项或-compile()
属性在源模块中。
要启用内联,可以使用该选项inline
让编译器确定要内联哪些函数,或者{inline,[{Name,Arity},...]}
让编译器内联所有对给定函数的调用。如果该选项compile
在Erlang模块中的指令内给出,{Name,Arity}
可写为Name/Arity
。
显式内联的示例:
-compile{inline,[pi/0]}).
pi() -> 3.1416.
隐式内联的示例:
-compile(inline).
该选项{inline_size,Size}
控制允许内联的大型函数的大小。缺省值是24
,它使内联代码的大小与非内联版本大致相同(仅内联了相对较小的函数)。
例子:
%% Aggressive inlining - will increase code size.
-compile(inline).
-compile{inline_size,100}).
列表函数内联
编译器还可以从模块内联各种列表操作函数。list
在STDLIB。
必须使用编译器选项或-compile()
属性在源模块中。
要启用列表功能的内联,请使用选项inline_list_funcs
。
以下功能是内联的:
lists:all/2
lists:any/2
lists:foreach/2
lists:map/2
lists:flatmap/2
lists:filter/2
lists:foldl/3
lists:foldr/3
lists:mapfoldl/3
lists:mapfoldr/3
解析变换
当程序员想要使用Erlang语法但具有不同的语义时,就会使用解析转换。然后将原始Erlang代码转换为其他Erlang代码。
错误信息
大ErrorInfo
前面提到的标准是ErrorInfo
结构,该结构从所有I/O模块返回。它的格式如下:
{ErrorLine, Module, ErrorDescriptor}
ErrorLine
是原子none
如果错误不对应于特定行,例如,如果源文件不存在。
通过以下调用获得一个描述错误的字符串:
Module:format_error(ErrorDescriptor)
另见
epp(3)
, erl_id_trans(3)
, erl_lint(3)
, beam_lib(3)