11 #include "tm_target.h"
12 #include "tm_crypto.h"
13 #include "tm_update.h"
16 /* A list of targets that were updated during the current run */
17 target_list
*updated_targets
= NULL
;
20 /* Returns true if a file exists and is readable.
22 int file_exists(const char *filename
)
26 if ((fp
= fopen(filename
, "r"))) {
35 /* Used takes a Jim interpreter and a Jim error code.
36 * If there was an error, display an error message and exit.
37 * Otherwise, do nothing.
39 void wrap(Jim_Interp
*interp
, int error
)
41 if (error
== JIM_ERR
) {
42 Jim_MakeErrorMessage(interp
);
43 fprintf(stderr
, "%s\n", Jim_String(Jim_GetResult(interp
)));
44 Jim_FreeInterp(interp
);
50 /* Update a target using the associated rule from tm_rules.
51 * Takes a SQLite database handle representing the sha1sum cache
52 * and the name of the TMakefile being evaluated, along with
53 * the name of the target to update.
55 int update(sqlite3
*db
, const char *tmfile
, const char *target
)
57 unsigned char digest
[CRYPTO_HASH_SIZE
];
58 char newhash
[CRYPTO_HASH_STRING_LENGTH
];
60 const char *fmt
= "INSERT OR REPLACE INTO TMCache (TMakefile, Target, Hash) VALUES (?, ?, ?)";
61 sqlite3_stmt
*stm
= NULL
;
65 rule
= find_rule(target
, tm_rules
);
71 updated_targets
= target_cons(rule
->target
, updated_targets
);
73 if (rule
->type
== TM_EXPLICIT
) {
74 TM_CRYPTO_HASH_DATA(rule
->recipe
, digest
);
75 } else if (rule
->type
== TM_FILENAME
) {
76 TM_CRYPTO_HASH_FILE(target
, digest
);
78 fprintf(stderr
, "WARNING: Unknown rule type %d\n"
79 " Don't know how to update cache for %s\n", rule
->type
, target
);
83 TM_CRYPTO_HASH_TO_STRING(digest
, newhash
);
85 sqlrc
= sqlite3_prepare(db
, fmt
, -1, &stm
, &stmtail
);
86 if (sqlrc
!= SQLITE_OK
) {
87 fprintf(stderr
, "WARNING: Unable to update cache for target %s\n", target
);
91 sqlite3_bind_text(stm
, 1, tmfile
, -1, SQLITE_TRANSIENT
);
92 sqlite3_bind_text(stm
, 2, target
, -1, SQLITE_TRANSIENT
);
93 sqlite3_bind_text(stm
, 3, newhash
, -1, SQLITE_TRANSIENT
);
94 sqlrc
= sqlite3_step(stm
);
95 if (sqlrc
!= SQLITE_DONE
) {
96 fprintf(stderr
, "WARNING: Error updating cache for target %s\n", target
);
97 sqlite3_finalize(stm
);
100 sqlite3_finalize(stm
);
102 Adding this return to squelch compilation warning.
103 Cory should review this code
109 /* Return 1 if target was updated, else return 0.
111 int was_updated(const char *target
)
113 return target_exists(target
, updated_targets
);
117 /* Return 1 if a given target is out of date, else return 0.
118 * Takes a SQLite database handle and the name of the TMakefile
119 * being evaluated along with the name of the target.
121 int needs_update(sqlite3
*db
, const char *tmfile
, const char *target
)
123 unsigned char digest
[CRYPTO_HASH_SIZE
];
124 const char *oldhash
= NULL
;
125 char newhash
[CRYPTO_HASH_STRING_LENGTH
];
126 target_list
*deps
= NULL
;
127 tm_rule
*rule
= NULL
;
128 const char *fmt
= "SELECT Hash FROM TMCache WHERE TMakefile = ? AND Target = ?";
129 const char *stmtail
= NULL
;
130 sqlite3_stmt
*stm
= NULL
;
133 rule
= find_rule(target
, tm_rules
);
139 for (deps
= rule
->deps
; deps
; deps
= deps
->next
) {
140 if (was_updated(deps
->name
)) {
145 sqlrc
= sqlite3_prepare(db
, fmt
, -1, &stm
, &stmtail
);
146 if (sqlrc
!= SQLITE_OK
) {
147 fprintf(stderr
, "WARNING: Unable to prepare database statement.\n"
148 " Assuming %s needs update.\n", target
);
152 sqlite3_bind_text(stm
, 1, tmfile
, -1, SQLITE_TRANSIENT
);
153 sqlite3_bind_text(stm
, 2, target
, -1, SQLITE_TRANSIENT
);
154 sqlrc
= sqlite3_step(stm
);
155 if (sqlrc
!= SQLITE_ROW
) {
156 /* There was no row in the cache for this target, so update it */
160 oldhash
= (const char *)sqlite3_column_text(stm
, 0);
162 fprintf(stderr
, "WARNING: Error getting cache for target %s\n", target
);
166 if (rule
->type
== TM_EXPLICIT
) {
167 TM_CRYPTO_HASH_DATA(rule
->recipe
, digest
);
168 } else if (rule
->type
== TM_FILENAME
) {
169 TM_CRYPTO_HASH_FILE(target
, digest
);
171 fprintf(stderr
, "WARNING: Unexpected rule type %d\n"
172 " Assuming %s needs update.\n", rule
->type
, target
);
175 TM_CRYPTO_HASH_TO_STRING(digest
, newhash
);
177 if (strcmp(oldhash
, newhash
) == 0) {
184 sqlite3_finalize(stm
);
187 sqlite3_finalize(stm
);
191 /* Take a list of targets to check and return a sublist containing only
192 * the targets that are out of date.
193 * Takes a SQLite database handle and the name of the TMakefile being
194 * evaluated along with the list of targets.
196 target_list
*need_update(sqlite3
*db
, const char *tmfile
, target_list
*targets
)
198 target_list
*oodate
= NULL
;
200 for (; targets
; targets
= targets
->next
) {
201 if (needs_update(db
, tmfile
, targets
->name
)) {
202 oodate
= target_cons(targets
->name
, oodate
);
210 /* Update all the rules in sorted_rules that need updating.
211 * Takes a SQLite database handle, a Jim interpreter containing
212 * the recipe definitions, the name of the TMakefile that was
213 * evaluated in the interpreter, the rules to be updated if needed
214 * (in the order they are to be updated), whether or not to force
215 * updates regardless of out-of-date status, and whether or not
216 * we're running in silent mode.
218 void update_rules(sqlite3
*db
, Jim_Interp
*interp
,
220 tm_rule_list
*sorted_rules
,
229 for (; sorted_rules
; sorted_rules
= sorted_rules
->next
) {
230 tm_rule
*rule
= sorted_rules
->rule
;
231 if (rule
->type
== TM_EXPLICIT
) {
232 /* If the rule has a recipe and needs an update */
234 && (force
|| needs_update(db
, tmfile
, rule
->target
))) {
235 /* Execute the recipe for the current rule */
236 const char *fmt
= "recipe::%s {%s} {%s} {%s}";
239 const char *target
= rule
->target
;
240 char *inputs
= target_list_to_string(rule
->deps
);
241 target_list
*oodate_deps
= need_update(db
, tmfile
, rule
->deps
);
242 char *oodate
= target_list_to_string(oodate_deps
);
243 tm_rule_list
*oodate_rules
= find_rules(oodate_deps
, tm_rules
);
245 if (was_updated(target
)) {
249 update_rules(db
, interp
, tmfile
, oodate_rules
, force
, silence
);
252 printf("Making target %s:\n", rule
->target
);
253 len
= strlen(fmt
) + strlen(target
)*2 + strlen(inputs
) + strlen(oodate
) + 1;
255 sprintf(cmd
, fmt
, target
, target
, inputs
, oodate
);
256 wrap(interp
, Jim_Eval(interp
, cmd
));
258 update(db
, tmfile
, rule
->target
);
266 free_rule_list(oodate_rules
);
267 free_target_list(oodate_deps
);
269 rule
->type
= TM_UPDATED
;
271 } else if (rule
->type
== TM_FILENAME
) {
272 /* Check that the file actually exists */
273 if (!file_exists(rule
->target
)) {
274 fprintf(stderr
, "ERROR: Unable to find rule for target %s\n", rule
->target
);
277 if (force
|| needs_update(db
, tmfile
, rule
->target
)) {
278 update(db
, tmfile
, rule
->target
);
279 rule
->type
= TM_UPDATED
;