66
77-define (PROVIDER , compile ).
88-define (NAMESPACE , clojerl ).
9- -define (DEPS , [{default , compile }]).
9+ -define (DEPS , [{default , lock }]).
1010
1111-type config () :: #{ ebin_dir => file :name ()
1212 , protocols_dir => file :name ()
@@ -34,17 +34,29 @@ init(State) ->
3434
3535-spec do (rebar_state :t ()) -> {ok , rebar_state :t ()} | {error , string ()}.
3636do (State ) ->
37- DepsPaths = rebar_state :code_paths (State , all_deps ),
38- ok = code :add_pathsa (DepsPaths ),
39- ok = rebar3_clojerl_utils :ensure_clojerl (State ),
37+ DepsPaths = rebar_state :code_paths (State , all_deps ),
38+ ok = code :add_pathsa (DepsPaths ),
4039
41- AllApps = rebar3_clojerl_utils :all_apps (State ),
42- Apps = rebar3_clojerl_utils :filter_app (AllApps , ? CLOJERL ),
43- Config = #{protocols_dir => protocols_dir (State )},
40+ ProjectApps = rebar_state :project_apps (State ),
41+ Deps = rebar_state :all_deps (State ),
4442
45- restore_duplicates (AllApps ),
46- [compile (AppInfo , Config ) || AppInfo <- Apps ],
47- backup_duplicates (AllApps , Config ),
43+ AppsPaths = [rebar_app_info :ebin_dir (AppInfo ) || AppInfo <- ProjectApps ],
44+ ok = code :add_pathsa (AppsPaths ),
45+
46+ ok = rebar3_clojerl_utils :ensure_clojerl (),
47+
48+ Apps0 = Deps ++ ProjectApps ,
49+ Config = #{protocols_dir => protocols_dir (State )},
50+
51+ % % More than one application might modify existing protocols, so we
52+ % % restore the original backed-up protocol modules before compiling.
53+ try
54+ restore_duplicates (DepsPaths ),
55+ Apps1 = maybe_compile_clojerl (Apps0 , Config ),
56+ [compile (AppInfo , Config ) || AppInfo <- Apps1 ]
57+ after
58+ backup_duplicates (DepsPaths , Config )
59+ end ,
4860
4961 {ok , State }.
5062
@@ -64,13 +76,23 @@ protocols_dir(State) ->
6476 rebar_api :debug (" Protocols dir: ~s " , [ProtoDir ]),
6577 ProtoDir .
6678
79+ -spec maybe_compile_clojerl ([rebar_app_info :t ()], config ()) ->
80+ [rebar_app_info :t ()].
81+ maybe_compile_clojerl (Apps , Config ) ->
82+ case rebar3_clojerl_utils :find_app (Apps , ? CLOJERL ) of
83+ notfound -> Apps ;
84+ {ok , ClojerlApp } ->
85+ compile (ClojerlApp , Config ),
86+ Apps -- [ClojerlApp ]
87+ end .
88+
6789-spec backup_duplicates ([rebar_app_info :t ()], config ()) -> ok .
68- backup_duplicates (Apps , Config ) ->
90+ backup_duplicates (DepsDirs , Config ) ->
6991 ProtoDir = maps :get (protocols_dir , Config ),
7092 BeamFilepaths = rebar_utils :find_files (ProtoDir , " .beam$" ),
7193 BeamFilenames = [filename :basename (F ) || F <- BeamFilepaths ],
7294
73- Dirs = [ rebar_app_info : ebin_dir ( App ) || App <- Apps ] -- [ProtoDir ],
95+ Dirs = DepsDirs -- [ProtoDir ],
7496 rebar_api :debug (" Finding duplicates for:~n~p~n in~n~p " , [BeamFilenames , Dirs ]),
7597 Deleted = [backup_duplicates_from_dir (BeamFilenames , Dir ) || Dir <- Dirs ],
7698
@@ -89,9 +111,8 @@ backup_duplicates_from_dir(BeamFilenames, Dir) ->
89111 ],
90112 {Dir , Filepaths }.
91113
92- -spec restore_duplicates ([rebar_app_info :t ()]) -> ok .
93- restore_duplicates (Apps ) ->
94- Dirs = [rebar_app_info :ebin_dir (App ) || App <- Apps ],
114+ -spec restore_duplicates ([file :name ()]) -> ok .
115+ restore_duplicates (Dirs ) ->
95116 [ begin
96117 DestPath = filename :rootname (Path ),
97118 ok = file :rename (Path , DestPath ),
@@ -132,15 +153,18 @@ update_app_file({Dir, Filepaths}) ->
132153compile (AppInfo , Config0 ) ->
133154 Graph = load_graph (AppInfo ),
134155 Config1 = Config0 #{graph => Graph },
135- try find_files_to_compile (AppInfo , Config1 ) of
156+ try find_files_to_compile (AppInfo ) of
136157 [] ->
137158 false ;
138159 SrcFiles ->
139160 rebar_api :info (" Clojerl Compiling ~s " , [rebar_app_info :name (AppInfo )]),
140- EbinDir = rebar_app_info :ebin_dir (AppInfo ),
161+ rebar_api :debug (" Files to compile: ~p " , [SrcFiles ]),
162+ EbinDir = rebar_app_info :ebin_dir (AppInfo ),
163+ ProtoDir = list_to_binary (maps :get (protocols_dir , Config1 )),
141164 Config2 = Config1 #{ebin_dir => EbinDir },
142165 [ compile_clje (Src , Config2 #{src_dir => SrcDir })
143- || {SrcDir , Src } <- SrcFiles
166+ || {SrcDir , Src } <- SrcFiles ,
167+ should_compile_file (Src , SrcDir , EbinDir , ProtoDir , Graph )
144168 ],
145169 store_graph (AppInfo , Graph ),
146170 true
@@ -150,7 +174,7 @@ compile(AppInfo, Config0) ->
150174
151175-spec compile_clje (file :name (), config ()) -> ok .
152176compile_clje (Src , Config ) ->
153- rebar_api : debug ( " Compiling ~s ..." , [Src ]),
177+ io : format ( " %%% Compiling ~s ...~n " , [Src ]),
154178
155179 SrcDir = list_to_binary (maps :get (src_dir , Config )),
156180 EbinDir = list_to_binary (maps :get (ebin_dir , Config )),
@@ -163,8 +187,9 @@ compile_clje(Src, Config) ->
163187 },
164188 try
165189 ok = 'clojerl.Var' :push_bindings (Bindings ),
166- Targets = clj_compiler :compile_file (list_to_binary (Src )),
167- update_graph (remove_src_dir (Src , SrcDir ), Targets , Graph )
190+ FullSrc = filename :join (SrcDir , Src ),
191+ Targets = clj_compiler :compile_file (FullSrc ),
192+ update_graph (Src , Targets , Graph )
168193 catch
169194 _ :Reason ->
170195 Stacktrace = erlang :get_stacktrace (),
@@ -227,34 +252,29 @@ cljinfo_file(AppInfo) ->
227252% % =============================================================================
228253% % Find files to compile
229254
230- -spec find_files_to_compile (rebar_app_info :t (), config ()) ->
231- [{file :name (), file :name ()}].
232- find_files_to_compile (AppInfo , Config ) ->
233- Graph = maps :get (graph , Config ),
234- ProtoDir = maps :get (protocols_dir , Config ),
255+ -spec find_files_to_compile (rebar_app_info :t ()) -> [{file :name (), file :name ()}].
256+ find_files_to_compile (AppInfo ) ->
235257 OutDir = rebar_app_info :out_dir (AppInfo ),
236- EbinDir = rebar_app_info :ebin_dir (AppInfo ),
237258 CljeSrcDirs = rebar_app_info :get (AppInfo , clje_src_dirs , ? DEFAULT_SRC_DIRS ),
259+ CljeFirst = clje_compile_first (AppInfo ),
260+ CljeExclude = rebar_app_info :get (AppInfo , clje_exclude , []),
238261
239262 SrcDirPaths = [filename :join (OutDir , Dir ) || Dir <- CljeSrcDirs ],
240263 ok = code :add_pathsa (SrcDirPaths ),
241- Fun = fun (SrcDir ) ->
242- find_files_to_compile (SrcDir , EbinDir , ProtoDir , Graph )
243- end ,
244264
245- lists :flatmap (Fun , SrcDirPaths ).
265+ AllFiles = lists :flatmap (fun find_files /1 , SrcDirPaths ),
266+ SortFun = fun ({_ , X }, {_ , Y }) ->
267+ maps :get (X , CljeFirst , - 1 ) > maps :get (Y , CljeFirst , - 1 )
268+ end ,
269+ [ X
270+ || {_ , Src } = X <- lists :sort (SortFun , AllFiles ),
271+ not lists :member (Src , CljeExclude )
272+ ].
246273
247- -spec find_files_to_compile ( file :name ()
248- , file :name ()
249- , file :name ()
250- , digraph :graph ()
251- ) -> [{file :name (), file :name ()}].
252- find_files_to_compile (SrcDir , EbinDirs , ProtoDir , Graph ) ->
274+ -spec find_files (file :name ()) -> [{file :name (), file :name ()}].
275+ find_files (SrcDir ) ->
253276 SrcFiles = rebar_utils :find_files (SrcDir , " .clj[ce]" ),
254- [ {SrcDir , Source }
255- || Source <- SrcFiles ,
256- should_compile_file (Source , SrcDir , EbinDirs , ProtoDir , Graph )
257- ].
277+ [{SrcDir , remove_src_dir (Source , SrcDir )} || Source <- SrcFiles ].
258278
259279-spec should_compile_file ( file :name ()
260280 , file :name ()
@@ -265,12 +285,12 @@ find_files_to_compile(SrcDir, EbinDirs, ProtoDir, Graph) ->
265285should_compile_file (Src , SrcDir , EbinDir , ProtoDir , Graph ) ->
266286 % % Check if the target file is either in the ebin directory or the
267287 % % protocols directory.
288+ FullSrc = filename :join (SrcDir , Src ),
268289 Fun = fun (Target ) ->
269- should_compile (filename :join (ProtoDir , Target ), Src ) andalso
270- should_compile (filename :join (EbinDir , Target ), Src )
290+ should_compile (filename :join (ProtoDir , Target ), FullSrc ) andalso
291+ should_compile (filename :join (EbinDir , Target ), FullSrc )
271292 end ,
272- SrcFilename = remove_src_dir (Src , SrcDir ),
273- case digraph :out_neighbours (Graph , SrcFilename ) of
293+ case digraph :out_neighbours (Graph , Src ) of
274294 [] -> true ;
275295 Targets -> lists :any (Fun , Targets )
276296 end .
@@ -283,3 +303,12 @@ should_compile(Target, Source) ->
283303-spec remove_src_dir (file :name (), file :name ()) -> file :name ().
284304remove_src_dir (Src , SrcDir ) ->
285305 re :replace (Src , [" ^" , SrcDir , " /" ], " " , [global , {return , list }]).
306+
307+ -spec clje_compile_first (rebar_app_info :t ()) -> #{list () => non_neg_integer ()}.
308+ clje_compile_first (AppInfo ) ->
309+ CljeFirst = rebar_app_info :get (AppInfo , clje_compile_first , []),
310+ Fun = fun (X , {Acc , N }) ->
311+ {Acc #{X => N }, N - 1 }
312+ end ,
313+ {Positions , _ } = lists :foldl (Fun , {#{}, length (CljeFirst )}, CljeFirst ),
314+ Positions .
0 commit comments