Erlang 使用escript打包多个模块构建一个可执行文件

概念

主模块:作为二进程程序(打包后的文件)的入口模块,需要定义main/1 函数并导出
打包函数(逻辑):示例代码中的hello:build/0
非rebar3 方式打包,直接源码操作。

简单说明

把 a.erl/b.erl 模块打包成一个 可执行文件a或b (只能是打包模块中的文件名)。

在linux可直接执行得到的二进制文件。

在windows下需要使用 escript a 执行 或者 使用bat脚本二次封装。

原理

利用escript提供的功能来完成,具体可看官方文档
主要是escript:create/2 函数。

注意事项

  • 如果打包的模块在打包执行环境中没有beam文件,那就可以用代码编译,再获取beam code
  • 如果打包的模块在打包执行环境中有beam文件,且能成功加载,可使用code:get_object_code 来获取

打包函数可以单独放一个escript脚本,也可以放在打包模块中去,特殊处理一下入口即可。

escript:create(Name)

Name是执行文件的主模块,需要有main函数,如果Name是字符串,则直接创建文件。
举例说明一下,比如Name是"hello",那么会生成 一个"hello"文件,并且打包的文件中要有hello模块,且有hello:main/1,导出。

其他方式

可使用rebar3 来构建可执行程序。

代码示例

escript 或 erl 脚本
hello.escript/hello.erl 都可以

-doc"""
	构建一个可执行文件 直接执行
""".
-module(hello).
-mode(compile).
-export([main/1]).


main(_) ->
	build().

build() ->
	io:format("=======================================================~n"),
	io:format("开始打包...~n"),
	Self = escript:script_name(),
	Name = ?MODULE_STRING,
	F = fun
			(?MODULE, Acc) ->
				%% escript 脚本作为主模块,需要通过手动编译的方式拿到object code
				{ok, _, CodeBin} = compile:file(Self, [binary]),
				FileName = ?MODULE_STRING ++ ".beam",
				io:format("pack ~p~n", [FileName]),
				[{FileName, CodeBin} | Acc];
			(Module, Acc) ->
				{_, CodeBin, FileName} = code:get_object_code(Module),
				io:format("pack ~p~n", [FileName]),
				[{filename:basename(FileName), CodeBin} | Acc]
		end,
	
	Files = lists:foldl(F, [], [?MODULE, module_a,module_b]),
	R = escript:create(Name, [
		shebang,
		{archive, Files, []}
	]),
	case R of
		ok ->
			{ok, CWD} = file:get_cwd(),
			io:format("[OO] 打包完成:~p ~n", [filename:join([CWD, Name])]),
			ok;
		Error ->
			io:format("[XX] 打包失败:~p ~n", [Error]),
			Error
	end,
	ok.
posted @ 2026-02-03 22:25  懒人爱吃鱼  阅读(1)  评论(0)    收藏  举报