Erlang进阶(一)
之前演示过简单得学习基本类型/函数声明等, 后续需要构建项目建议先了解 Emakefile:
这里建议默认项目目录构建:
/(根目录) ------- _build(编译打包出来数据)
| |
| |------- release(正式包, 移除调试信息)
| |
| |------- dev(开发包, 本地测试环境)
|
|
|--- config(配置文件目录)
|
|
|--- include(头文件目录)
|
|
|--- src(源代码目录)
| |
| |
| |
| |------- utils(工具目录, 所有常用工具采用 `类型_utils.erl` 编写)
| |
| |
| |------- 项目名.app.src( 工程信息文件 )
| |
| |
| |------- 项目名.erl( 工程入口文件 )
|
|
|
|--- Emakefile(主打包文件)
|
|
|--- Emakefile.dev(开发调试)
|
|
|--- Emakefile.release(正式编译)
Emakefile是erl -make必须的, 这里通过Emakefile.dev|Emakefile.release覆盖Emakefile再去执行命令
这里基本上就是最初的配置目录, Emakefile 配置文件基本如下:
%% 入口文件打包
{
["src/*"],
[debug_info,{outdir, "./_build/dev"},{i, "include"},warn_keywords]
}.
%% 工具打包
{
["src/utils/*"],
[debug_info,{outdir, "./_build/dev"},{i, "include"},warn_keywords]
}.
这里可以配置脚本来帮助你处理创建 ./_build/dev/ebin 目录, 也可以直接打包输出到 ./_build 输出都行,最后调用:
# 启动编译输出
erl -make
之后还有启动脚本和 sasl_log 日志等配置, 后续正式项目工程建议采用这种方式.
behaviour 模板
现在开始切入 behaviour 对应框架模板开始进行正式开发,
OTP(Open Telecom Platform, 开放电信平台) 模板简单来说可以说是官方提供的应用框架, 框架总共有类型:
application: 命令行应用, 最常用的类型supervisor: 进程管理器, 多进程管理器gen_server: Erlang进程管理器, 用于管理 Erlang 进程gen_fsm: 有限状态机, 定义数据状态机gen_event: 通用事件配置, 用于实现自定义事件- …… 其他
其中正式项目用的比较多的是 application|supervisor|gen_server, 这里首先创建第一个游戏项目:
# 游戏项目工程目录构建
mkdir fight
cd fight
# 创建对应的目录
mkdir _build
mkdir _build/dev
mkdir _build/release
mkdir include
mkdir src
mkdir src/utils
mkdir config
# 创建打包文件
touch Emakefile
# 构建第一个项目入口文件
vim src/fight.erl # 项目入口文件
vim src/fight.app.src # 项目入口配置信息
注意: fight.app.src 是工程描述文件, 是必须创建的文件:
%%% 应用入口配置
{application, fight, % fight 为工程名称
[{description, "Fight Game Service"}, %% 工程描述
{vsn, "2024.07.14"}, % 工程版本
{registered, []},
{mod, {fight, []}}, % mod项目启动 module, 也就是 fight.erl 文件
{applications,
[ % 引入的系统应用库
kernel,
stdlib
]},
{env, []},
{modules, []},
{licenses, ["MIT"]}, % 开源许可
{links, []}
]}.
应用启动入口文件(fight.erl)内容如下:
%%%-------------------------------------------------------------------
%%% @author MeteorCat
%%% @copyright (C) 2024, <COMPANY>
%%% @doc
%%% fight游戏服务端启动入口 -> application:main
%%% @end
%%% Created : 14. 7月 2024 下午 07:31
%%%-------------------------------------------------------------------
-module(fight).
-author("MeteorCat").
-behaviour(application).
%% Application callbacks
-export([
start/2,
stop/1,
main/0
]).
%%%===================================================================
%%% Application 回调
%%%===================================================================
%%--------------------------------------------------------------------
%% @private
%% @doc
%% 项目主要回调入口, -spec 代表强类型声明, 后续讲解的方法
%% @end
%%--------------------------------------------------------------------
-spec(start(StartType :: normal | {takeover, node()} | {failover, node()},
StartArgs :: term()) ->
{ok, pid()} |
{ok, pid(), State :: term()} |
{error, Reason :: term()}).
start(_StartType, _StartArgs) ->
io:fwrite("Fight Started~n"),
application:start(crypto), % 启动加密服务
{ok, erlang:self()}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% 程序退出回调
%% @end
%%--------------------------------------------------------------------
-spec(stop(State :: term()) -> term()).
stop(_State) ->
io:fwrite("Fight Close~n"),
application:stop(fight),
application:stop(crypto).
%%%===================================================================
%%% Internal functions
%%%===================================================================
%%% 这里就是应用启动入口
main() ->
io:fwrite("Main Started~n"),
case application:start(fight) of
{error, Reason} ->
io:format("Application::start error -> ~p~n", [Reason]),
{error, Reason};
_ -> ok
end.
以上就是最基础的命令行应用文件入口, 程序启动调用方式:
# 启动项目
erl -pa ./_build/dev -s fight main -noshell
这就是目前构建名为 fight 的命令行程序项目, 这时候暂停下 behaviour 深入,
转而以 behaviour(application) 进阶 Actor实现|并发进程|网络服务 的学习,
后续都会用到其他 behaviour 再去讲解.