1:- module(automake, [automake/0,
2 noautomake/0]). 3
4:- use_module(library(debug), [debug/3]). 5:- use_module(library(make), [make/0]). 6:- use_module(library(time), [alarm/3, remove_alarm/1]). 7
8:- use_foreign_library(foreign(watchdir4pl)). 9
10:- dynamic watches/2. 11
12automake :-
13 noautomake,
14 dir_monitor_init(Monitor),
15 add_new_source_files(Monitor),
16 thread_create(handle_file_changed(Monitor), _, [alias(automake)]).
17
18noautomake :-
19 catch(thread_send_message(automake, done, [timeout(0)]),
20 error(existence_error(message_queue, automake), _),
21 fail), !,
22 thread_join(automake, _).
23noautomake.
24
25handle_file_changed(Monitor) :-
26 dir_monitor_read(Monitor, Event, 0.5), !,
27 catch(handle_event(Event, Monitor),
28 Err,
29 debug(automake, "Error handling event ~w: ~w", [Event, Err])),
30 handle_file_changed(Monitor).
31handle_file_changed(Monitor) :-
32 thread_get_message(automake, _, [timeout(0)]), !,
33 dir_monitor_stop(Monitor).
34handle_file_changed(Monitor) :-
35 add_new_source_files(Monitor),
36 handle_file_changed(Monitor).
37
38:- dynamic make_alarm/1. 39
40handle_event(watchdir(modified, _, _), _) :-
41 maybe_cancel_make,
42 alarm(0.2, do_make, Alarm),
43 assertz(make_alarm(Alarm)).
44handle_event(Event, _) :-
45 debug(automake(debug), "Unknown event ~w", [Event]).
46
48do_make :-
49 retractall(make_alarm(_)),
50 make.
51
52maybe_cancel_make :-
53 make_alarm(Alarm), !,
54 debug(automake(debug), "Cancelling alarm ~w", [Alarm]),
55 remove_alarm(Alarm),
56 retractall(make_alarm(Alarm)).
57maybe_cancel_make.
58
59add_new_source_files(Monitor) :-
60 forall(source_file(File),
61 ( maybe_add_watch(Monitor, File) )).
62
63maybe_add_watch(Monitor, Path) :-
64 watches(Path, _)
65 -> true
66 ; ( debug(automake, "Adding watch for ~w", [Path]),
67 exists_file(Path)
68 -> ( dir_monitor_add(Monitor, Path, W),
69 assertz(watches(Path, W)) )
70 ; true )