aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTharre <tharre3@gmail.com>2014-08-20 03:40:08 +0200
committerTharre <tharre3@gmail.com>2014-08-20 03:40:08 +0200
commit856b72ef61af7f8cafb4abc4cab522da62900322 (patch)
treedc86585969c3f4d372add0e36d685534efb3c808
parent5e5e7e66ee876e2aa62ac336b4e3c7b8ea6af1ce (diff)
downloadredo-856b72ef61af7f8cafb4abc4cab522da62900322.tar.gz
redo-856b72ef61af7f8cafb4abc4cab522da62900322.tar.xz
redo-856b72ef61af7f8cafb4abc4cab522da62900322.zip
Make targets depend on do-files.
This includes two different scenarios, first if the do-files which was used to build the target has changed the target must be rebuilt. Second, if a target was build by a lower priority do-file, like default.fuu.do, then it must be rebuilt if <target>.fuu.do appears. Note that at this point, Redofile as do-file is semi-supported, as it's future is uncertain.
-rw-r--r--src/build.c97
-rw-r--r--src/build.h2
-rw-r--r--src/redo-always.c4
-rw-r--r--src/redo-ifchange.c2
-rw-r--r--src/redo-ifcreate.c4
5 files changed, 68 insertions, 41 deletions
diff --git a/src/build.c b/src/build.c
index bdb400b..193317c 100644
--- a/src/build.c
+++ b/src/build.c
@@ -29,15 +29,14 @@
#define HASHSIZE 20
-const char do_file_ext[] = ".do";
-const char default_name[] = "default";
const char temp_ext[] = ".redoing.tmp";
const char deps_dir[] = "/.redo/deps/";
const char redo_root[] = "REDO_ROOT";
const char redo_parent_target[] = "REDO_PARENT_TARGET";
const char redo_magic[] = "REDO_MAGIC";
-static char *get_do_file(const char *target);
+static struct do_attr *get_dofiles(const char *target);
+static void free_do_attr(struct do_attr *thing);
static char **parse_shebang(char *target, char *dofile, char *temp_output);
static char **parsecmd(char *cmd, size_t *i, size_t keep_free);
static char *get_relpath(const char *target);
@@ -45,22 +44,29 @@ static char *get_dep_path(const char *target);
static void write_dep_hash(const char *target);
static bool dependencies_changed(char buf[], size_t read);
+struct do_attr {
+ char *specific;
+ char *general;
+ char *redofile;
+ char *chosen;
+};
+
/* Build given target, using it's do-file. */
int build_target(const char *target) {
/* get the do-file which we are going to execute */
- char *do_file = get_do_file(target);
- if (!do_file) {
+ struct do_attr *dofiles = get_dofiles(target);
+ if (!dofiles->chosen) {
if (fexists(target)) {
/* if our target file has no do file associated but exists,
then we treat it as a source */
write_dep_hash(target);
- free(do_file);
+ free_do_attr(dofiles);
return 0;
}
log_err("%s couldn't be built because no "
"suitable do-file exists\n", target);
- free(do_file);
+ free_do_attr(dofiles);
return 1;
}
@@ -94,7 +100,7 @@ int build_target(const char *target) {
/* target is now in the cwd so change path accordingly */
char *btarget = xbasename(target);
- char *bdo_file = xbasename(do_file);
+ char *bdo_file = xbasename(dofiles->chosen);
char *btemp_output = xbasename(temp_output);
char **argv = parse_shebang(btarget, bdo_file, btemp_output);
@@ -123,7 +129,7 @@ int build_target(const char *target) {
if (WIFEXITED(status)) {
if (WEXITSTATUS(status)) {
log_err("redo: invoked do-file %s failed: %d\n",
- do_file, WEXITSTATUS(status));
+ dofiles->chosen, WEXITSTATUS(status));
exit(EXIT_FAILURE);
} else {
/* successful */
@@ -138,6 +144,14 @@ int build_target(const char *target) {
exit(EXIT_FAILURE);
}
+ /* depend on the do-file */
+ add_dep(dofiles->chosen, target, 'c');
+ write_dep_hash(dofiles->chosen);
+
+ /* redo-ifcreate on specific if general was chosen */
+ if (dofiles->general == dofiles->chosen)
+ add_dep(dofiles->specific, target, 'e');
+
if (remove_temp) {
if (remove(temp_output))
if (errno != ENOENT)
@@ -150,7 +164,7 @@ int build_target(const char *target) {
}
free(temp_output);
- free(do_file);
+ free_do_attr(dofiles);
return 0;
}
@@ -190,27 +204,33 @@ static char **parse_shebang(char *target, char *dofile, char *temp_output) {
return argv;
}
-/* Returns the right do-file for target. */
-static char *get_do_file(const char *target) {
- /* target + ".do" */
- char *temp = concat(2, target, do_file_ext);
- if (fexists(temp))
- return temp;
- free(temp);
-
- /* default + get_extension(target) + ".do" */
- temp = concat(3, default_name, take_extension(target), do_file_ext);
- if (fexists(temp))
- return temp;
- free(temp);
-
- /* Redofile */
- temp = safe_strdup("Redofile");
- if (fexists(temp))
- return temp;
- free(temp);
-
- return NULL;
+/* Return a struct with all the possible do-files, and the chosen one. */
+static struct do_attr *get_dofiles(const char *target) {
+ struct do_attr *dofiles = safe_malloc(sizeof(struct do_attr));
+
+ dofiles->specific = concat(2, target, ".do");
+ dofiles->general = concat(3, "default", take_extension(target), ".do");
+ dofiles->redofile = safe_strdup("Redofile");
+
+ if (fexists(dofiles->specific))
+ dofiles->chosen = dofiles->specific;
+ else if (fexists(dofiles->general))
+ dofiles->chosen = dofiles->general;
+ else if (fexists(dofiles->redofile))
+ dofiles->chosen = dofiles->redofile;
+ else
+ dofiles->chosen = NULL;
+
+ return dofiles;
+}
+
+/* Free the do_attr struct. */
+static void free_do_attr(struct do_attr *thing) {
+ assert(thing);
+ free(thing->specific);
+ free(thing->general);
+ free(thing->redofile);
+ free(thing);
}
/* Breaks cmd at spaces and stores a pointer to each argument in the returned
@@ -293,12 +313,15 @@ static char *get_dep_path(const char *target) {
return dep_path;
}
-/* Add the dependency target, with the identifier indent. */
-void add_dep(const char *target, int indent) {
- assert(getenv(redo_parent_target));
+/* Add the dependency target, with the identifier ident. If parent is NULL, the
+ * value of the environment variable REDO_PARENT will be taken instead. */
+void add_dep(const char *target, const char *parent, int ident) {
+ if (!parent) {
+ assert(getenv(redo_parent_target));
+ parent = getenv(redo_parent_target);
+ }
- char *parent_target = getenv(redo_parent_target);
- char *dep_path = get_dep_path(parent_target);
+ char *dep_path = get_dep_path(parent);
FILE *fp = fopen(dep_path, "rb+");
if (!fp) {
@@ -317,7 +340,7 @@ void add_dep(const char *target, int indent) {
char *reltarget = get_relpath(target);
- putc(indent, fp);
+ putc(ident, fp);
fputs(reltarget, fp);
putc('\0', fp);
diff --git a/src/build.h b/src/build.h
index ada4df0..c4a6aeb 100644
--- a/src/build.h
+++ b/src/build.h
@@ -11,7 +11,7 @@
#include <stdbool.h>
-extern void add_dep(const char *target, int indent);
+extern void add_dep(const char *target, const char *parent, int ident);
extern bool has_changed(const char *target, int ident, bool is_sub_dependency);
extern int build_target(const char *target);
diff --git a/src/redo-always.c b/src/redo-always.c
index a542c59..352e6c8 100644
--- a/src/redo-always.c
+++ b/src/redo-always.c
@@ -6,11 +6,13 @@
* of the MIT license. See the LICENSE file for details.
*/
+#include <stddef.h>
+
#include "build.h"
int main(int argc, char *argv[]) {
for (int i = 1; i < argc; ++i) {
build_target(argv[i]);
- add_dep(argv[i], 'a');
+ add_dep(argv[i], NULL, 'a');
}
}
diff --git a/src/redo-ifchange.c b/src/redo-ifchange.c
index c6974ac..e95e92e 100644
--- a/src/redo-ifchange.c
+++ b/src/redo-ifchange.c
@@ -21,6 +21,6 @@ int main(int argc, char *argv[]) {
} else {
/*printf("=> yes\n");*/
}
- add_dep(argv[i], 'c');
+ add_dep(argv[i], NULL, 'c');
}
}
diff --git a/src/redo-ifcreate.c b/src/redo-ifcreate.c
index 71c9a22..955ffdc 100644
--- a/src/redo-ifcreate.c
+++ b/src/redo-ifcreate.c
@@ -6,12 +6,14 @@
* of the MIT license. See the LICENSE file for details.
*/
+#include <stddef.h>
+
#include "build.h"
int main(int argc, char *argv[]) {
for (int i = 1; i < argc; ++i) {
if (has_changed(argv[i], 'e', false))
build_target(argv[i]);
- add_dep(argv[i], 'e');
+ add_dep(argv[i], NULL, 'e');
}
}