|
@@ -1,178 +0,0 @@
|
|
|
--module(mad_compile).
|
|
|
--copyright('Sina Samavati').
|
|
|
--compile(export_all).
|
|
|
--define(COMPILE_OPTS(Inc, Ebin, Opts), [report, {i, Inc}, {outdir, Ebin}] ++ Opts).
|
|
|
-
|
|
|
--type directory() :: string().
|
|
|
--type filename() :: string().
|
|
|
-
|
|
|
-%% compile dependencies
|
|
|
--spec deps(directory(), any(), filename(), [mad_deps:dependency()]) -> ok.
|
|
|
-deps(_, _, _, []) -> ok;
|
|
|
-deps(Cwd, Conf, ConfigFile, [H|T]) ->
|
|
|
- {Name, _} = mad_deps:name_and_repo(H),
|
|
|
- case get(mad_utils:to_atom(Name)) of
|
|
|
- compiled -> ok;
|
|
|
- _ -> dep(Cwd, Conf, ConfigFile, Name) end,
|
|
|
- deps(Cwd, Conf, ConfigFile, T).
|
|
|
-
|
|
|
-%% compile a dependency
|
|
|
--spec dep(directory(), any(), filename(), string()) -> ok.
|
|
|
-dep(Cwd, _Conf, ConfigFile, Name) ->
|
|
|
- io:format("==> ~p~n",[Name]),
|
|
|
- %% check dependencies of the dependency
|
|
|
- DepsDir = filename:join([mad_utils:get_value(deps_dir, _Conf, ["deps"])]),
|
|
|
- DepPath = filename:join([Cwd, DepsDir, Name]),
|
|
|
- DepConfigFile = filename:join(DepPath, ConfigFile),
|
|
|
- Conf = mad_utils:consult(DepConfigFile),
|
|
|
- Conf1 = mad_utils:script(DepConfigFile, Conf),
|
|
|
- deps(Cwd, Conf, ConfigFile, mad_utils:get_value(deps, Conf1, [])),
|
|
|
-
|
|
|
- %% add lib_dirs to path
|
|
|
- LibDirs = mad_utils:lib_dirs(DepPath, Conf1),
|
|
|
- code:add_paths(LibDirs),
|
|
|
-
|
|
|
- SrcDir = filename:join([mad_utils:src(DepPath)]),
|
|
|
- Files = yrl_files(SrcDir) ++ erl_files(SrcDir) ++ app_src_files(SrcDir),
|
|
|
-
|
|
|
- case Files of
|
|
|
- [] -> ok;
|
|
|
- Files ->
|
|
|
- IncDir = mad_utils:include(DepPath),
|
|
|
- EbinDir = mad_utils:ebin(DepPath),
|
|
|
-
|
|
|
- %% create EbinDir and add it to code path
|
|
|
- file:make_dir(EbinDir),
|
|
|
- code:add_path(EbinDir),
|
|
|
-
|
|
|
- Opts = mad_utils:get_value(erl_opts, Conf1, []),
|
|
|
- lists:foreach(compile_fun(IncDir, EbinDir, Opts), Files),
|
|
|
-
|
|
|
- dtl(DepPath,Conf1),
|
|
|
-
|
|
|
- put(mad_utils:to_atom(Name), compiled),
|
|
|
- ok
|
|
|
- end.
|
|
|
-
|
|
|
-
|
|
|
-dtl(Dir,Config) ->
|
|
|
- case mad_utils:get_value(erlydtl_opts, Config, []) of
|
|
|
- [] -> skip;
|
|
|
- X -> compile_erlydtl_files(validate_erlydtl_opts(Dir,X)) end.
|
|
|
-
|
|
|
-
|
|
|
--spec validate_property({atom(), term()}, term()) -> {atom(), term()}.
|
|
|
-validate_property({modules, _}, Modules) -> {modules, Modules};
|
|
|
-validate_property(Else, _) -> Else.
|
|
|
-
|
|
|
--spec compile_fun(directory(), directory(), [compile:option()]) ->
|
|
|
- fun((file:name(),string(),string(),list(tuple(any(),any())),string()) -> ok).
|
|
|
-compile_fun(Inc,Bin,Opt) -> fun(File) -> compile(File,Inc,Bin,Opt,filetype(File)) end.
|
|
|
-
|
|
|
-filetype(File) -> L=length(hd(string:tokens(File,"."))), string:substr(File,L+1,length(File)).
|
|
|
-
|
|
|
-compile(File,Inc,Bin,Opt,".yrl") ->
|
|
|
- ErlFile = yrl_to_erl(File),
|
|
|
- Compiled = is_compiled(ErlFile,File),
|
|
|
- if Compiled == false ->
|
|
|
- yecc:file(File),
|
|
|
- compile(ErlFile,Inc,Bin,Opt,".erl"); true -> ok end;
|
|
|
-compile(File,Inc,Bin,Opt,".erl") ->
|
|
|
- BeamFile = erl_to_beam(Bin, File),
|
|
|
- Compiled = is_compiled(BeamFile, File),
|
|
|
- if Compiled =:= false ->
|
|
|
- io:format("Compiling ~s~n", [File]),
|
|
|
- Opts1 = ?COMPILE_OPTS(Inc, Bin, Opt),
|
|
|
- compile:file(File, Opts1),
|
|
|
- ok;
|
|
|
- true -> ok end;
|
|
|
-compile(File,_Inc,Bin,_Opt,".app.src") ->
|
|
|
- AppFile = filename:join(Bin, app_src_to_app(File)),
|
|
|
- Compiled = is_compiled(AppFile, File),
|
|
|
- if Compiled =:= false ->
|
|
|
- io:format("Writing ~s~n", [AppFile]),
|
|
|
- BeamFiles = filelib:wildcard("*.beam", Bin),
|
|
|
- Modules = [list_to_atom(filename:basename(X, ".beam")) || X <- BeamFiles],
|
|
|
- [Struct|_] = mad_utils:consult(File),
|
|
|
- {application, AppName, Props} = Struct,
|
|
|
- Props1 = add_modules_property(Props),
|
|
|
- Props2 = [validate_property(X, Modules) || X <- Props1],
|
|
|
- Struct1 = {application, AppName, Props2},
|
|
|
- file:write_file(AppFile, io_lib:format("~p.~n", [Struct1])),
|
|
|
- ok;
|
|
|
- true -> ok end;
|
|
|
-compile(File,_Inc,_Bin,_Opt,_) ->
|
|
|
- io:format("Unknown file type: ~p~n",[File]).
|
|
|
-
|
|
|
--spec erl_files(directory()) -> [file:name()].
|
|
|
--spec app_src_files(directory()) -> [file:name()].
|
|
|
--spec app_src_to_app(file:name()) -> file:name().
|
|
|
--spec erl_to_beam(directory(), file:name()) -> file:name().
|
|
|
--spec is_compiled(directory(), file:name()) -> boolean().
|
|
|
--spec add_modules_property([{atom(), term()}]) -> [{atom(), term()}].
|
|
|
--spec sort([file:name()]) -> [file:name()].
|
|
|
--spec sort_by_priority([file:name()], [file:name()], [file:name()], [file:name()]) -> [file:name()].
|
|
|
-
|
|
|
-erl_files(Dir) -> filelib:fold_files(Dir, ".erl", true, fun(F, Acc) -> [F|Acc] end, []).
|
|
|
-yrl_files(Dir) -> filelib:fold_files(Dir, ".yrl", true, fun(F, Acc) -> [F|Acc] end, []).
|
|
|
-app_src_files(Dir) -> filelib:fold_files(Dir, ".app.src", false, fun(F, Acc) -> [F|Acc] end, []).
|
|
|
-
|
|
|
-app_src_to_app(Filename) -> filename:basename(Filename, ".app.src") ++ ".app".
|
|
|
-yrl_to_erl(Filename) -> filename:join(filename:dirname(Filename),filename:basename(Filename, ".yrl")) ++ ".erl".
|
|
|
-erl_to_beam(Bin, Filename) -> filename:join(Bin, filename:basename(Filename, ".erl") ++ ".beam").
|
|
|
-is_compiled(BeamFile, File) -> mad_utils:last_modified(BeamFile) > mad_utils:last_modified(File).
|
|
|
-add_modules_property(Properties) ->
|
|
|
- case lists:keyfind(modules, 1, Properties) of
|
|
|
- {modules, _} -> Properties;
|
|
|
- _ -> Properties ++ [{modules, []}] end.
|
|
|
-
|
|
|
--spec foreach(fun((directory(), filename()) -> ok), [filename()], any(), filename()) -> ok.
|
|
|
-foreach(_, [], _, _) -> ok;
|
|
|
-foreach(Fun, [Dir|T], Config, ConfigFile) ->
|
|
|
- Fun(Dir, Config, ConfigFile),
|
|
|
- foreach(Fun, T, Config, ConfigFile).
|
|
|
-
|
|
|
-get_kv(K, Opts, Default) ->
|
|
|
- V = mad_utils:get_value(K, Opts, Default),
|
|
|
- KV = {K, V},
|
|
|
- {KV, Opts -- [KV]}.
|
|
|
-
|
|
|
-validate_erlydtl_opts(Cwd, Opts) ->
|
|
|
- DefaultDocRoot = filename:join("priv", "templates"),
|
|
|
- {DocRoot, Opts1} = get_kv(doc_root, Opts, DefaultDocRoot),
|
|
|
- {OutDir, Opts2} = get_kv(out_dir, Opts1, "ebin"),
|
|
|
- {CompilerOpts, Opts3} = get_kv(compiler_options, Opts2, []),
|
|
|
- {SourceExt, Opts4} = get_kv(source_ext, Opts3, ".dtl"),
|
|
|
- {ModuleExt, Opts5} = get_kv(module_ext, Opts4, ""),
|
|
|
-
|
|
|
- {_, DocRootDir} = DocRoot,
|
|
|
- DocRoot1 = {doc_root, filename:join(Cwd, DocRootDir)},
|
|
|
- {_, OutDir1} = OutDir,
|
|
|
- OutDir2 = {out_dir, filename:join(Cwd, OutDir1)},
|
|
|
-
|
|
|
- [DocRoot1, OutDir2, CompilerOpts, SourceExt, ModuleExt|Opts5].
|
|
|
-
|
|
|
-module_name(File, Ext, NewExt) ->
|
|
|
- list_to_atom(filename:basename(File, Ext) ++ NewExt).
|
|
|
-
|
|
|
-compile_erlydtl_files(Opts) ->
|
|
|
-
|
|
|
- {{_, DocRoot}, Opts1} = get_kv(doc_root, Opts, ""),
|
|
|
- {{_, SourceExt}, Opts2} = get_kv(source_ext, Opts1, ""),
|
|
|
- {{_, ModuleExt}, Opts3} = get_kv(module_ext, Opts2, ""),
|
|
|
- {{_, OutDir}, _} = get_kv(out_dir, Opts3, ""),
|
|
|
-
|
|
|
- Files = filelib:fold_files(DocRoot, SourceExt, true,
|
|
|
- fun(F, Acc) -> [F|Acc] end, []),
|
|
|
-
|
|
|
- Compile = fun(F) ->
|
|
|
- ModuleName = module_name(F, SourceExt, ModuleExt),
|
|
|
- BeamFile = erl_to_beam(OutDir, atom_to_list(ModuleName)),
|
|
|
- Compiled = is_compiled(BeamFile, F),
|
|
|
- if Compiled =:= false ->
|
|
|
- io:format("DTL Compiling ~s~n", [F]),
|
|
|
- erlydtl:compile(F, ModuleName, Opts3);
|
|
|
- true -> ok end
|
|
|
- end,
|
|
|
-
|
|
|
- lists:foreach(Compile, Files).
|