mad_port.erl 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. -module(mad_port).
  2. -copyright('Maxim Sokhatsky').
  3. -compile(export_all).
  4. replace_env(String, []) -> String;
  5. replace_env(String, [{K,V}|Env]) ->
  6. replace_env(re:replace(String, io_lib:format("\\$?{?(~s)}?",[K]), V, [global, {return, list}]),Env).
  7. compile(Dir,Config) ->
  8. case mad_utils:get_value(port_specs, Config, []) of
  9. [] -> [false];
  10. X -> compile_port(Dir,X,Config) end.
  11. compile_port(Dir,Specs0,Config) ->
  12. {_,Flavour} = os:type(),
  13. System = atom_to_list(Flavour),
  14. Specs = [ {O,F} || {Sys,O,F} <- Specs0, Sys == System] ++
  15. [ {O,F} || {O,F} <- Specs0],
  16. filelib:ensure_dir(Dir ++ "/priv/"),
  17. Env = [ {Var,Val} || {Sys,Var,Val} <- mad_utils:get_value(port_env, Config, []), system(Sys,System) ] ++
  18. [ {Var,Val} || {Var,Val} <- mad_utils:get_value(port_env, Config, []) ] ++
  19. [ {"LDFLAGS",[]},{"CFLAGS",[]}],
  20. [ begin
  21. Files = files(Dir,Patern),
  22. Ouput = Dir ++ "/" ++ Out,
  23. case is_compiled(Ouput,Files) of
  24. false -> Template = string:join(Files," ")
  25. ++ " CFLAGS LDFLAGS " ++ ei(Flavour,Out) ++ " -o " ++ Ouput,
  26. Args = string:strip(replace_env(Template,Env),both,32),
  27. %mad:info("Args: ~p~n",[Args]),
  28. %mad:info("Env: ~p~n",[Env]),
  29. {_,Status,Report} = sh:run("cc",string:tokens(Args," "),binary,Dir,Env),
  30. case Status of
  31. 0 -> false;
  32. _ -> mad:info("Port Compilation Error:~n" ++ io_lib:format("~ts",[Report]),[]), true
  33. end;
  34. _ -> %mad:info("No Need recompile ~p~n",[{Ouput,Files}]),
  35. false
  36. end
  37. end || {Out,Patern} <- Specs ].
  38. is_compiled(O,Files) -> lists:foldl(fun(X,false) -> false;
  39. (X, true) -> mad_utils:last_modified(O) >= mad_utils:last_modified(X)
  40. end, true, Files).
  41. system(Sys,System) -> Sys == System orelse match(Sys,System).
  42. match(Re,System) -> case re:run(System, Re, [{capture,none}]) of match -> true; nomatch -> false end.
  43. erts_dir() -> lists:concat([code:root_dir(), "/erts-", erlang:system_info(version)]).
  44. ei_dir(inc) -> case code:lib_dir(erl_interface) of {error,bad_name} -> "";
  45. D -> "-I"++filename:join(D, "include") end;
  46. ei_dir(lib) -> case code:lib_dir(erl_interface) of {error,bad_name} -> "";
  47. D -> "-L"++filename:join(D, "lib") end.
  48. files(Dir,Files) -> [string:join(filelib:wildcard(Dir ++ "/" ++ F)," ")||F<-Files].
  49. ei(Flavour,Out) -> type(Flavour,Out)
  50. ++ ei_dir(inc) ++
  51. " -I"++filename:join(erts_dir(), "include")++ " "
  52. ++ ei_dir(lib) ++
  53. " -L"++filename:join(erts_dir(), "lib").
  54. type(Flavour,Out) -> case {Flavour, filename:extension(Out)} of %% exe or shared
  55. {_, []} -> "";
  56. {darwin, ".so"} -> "-bundle -flat_namespace -undefined suppress "
  57. end.