~alpine/aports

main/samurai: upgrade to 1.1 v1 APPLIED

Drew DeVault: 1
 main/samurai: upgrade to 1.1

 6 files changed, 4 insertions(+), 471 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.alpinelinux.org/~alpine/aports/patches/3317/mbox | git am -3
Learn more about email & git

[PATCH] main/samurai: upgrade to 1.1 Export this patch

---
 ...uild-when-it-was-pruned-due-to-resta.patch |  86 --------
 ...eck-that-rules-always-have-a-command.patch |  54 -----
 ...-rules-have-rspfile-iff-they-have-rs.patch |  56 -----
 main/samurai/0004-tool-Implement-compdb.patch | 197 ------------------
 ...issing-depfile-as-empty-for-deps-log.patch |  64 ------
 main/samurai/APKBUILD                         |  18 +-
 6 files changed, 4 insertions(+), 471 deletions(-)
 delete mode 100644 main/samurai/0001-Fix-manifest-rebuild-when-it-was-pruned-due-to-resta.patch
 delete mode 100644 main/samurai/0002-parse-Check-that-rules-always-have-a-command.patch
 delete mode 100644 main/samurai/0003-parse-Check-that-rules-have-rspfile-iff-they-have-rs.patch
 delete mode 100644 main/samurai/0004-tool-Implement-compdb.patch
 delete mode 100644 main/samurai/0005-deps-treat-missing-depfile-as-empty-for-deps-log.patch

diff --git a/main/samurai/0001-Fix-manifest-rebuild-when-it-was-pruned-due-to-resta.patch b/main/samurai/0001-Fix-manifest-rebuild-when-it-was-pruned-due-to-resta.patch
deleted file mode 100644
index eaabb4019c..0000000000
--- a/main/samurai/0001-Fix-manifest-rebuild-when-it-was-pruned-due-to-resta.patch
@@ -1,86 +0,0 @@
From c7f1cfd9ed674936e21f99f8c18608b97685d5a7 Mon Sep 17 00:00:00 2001
From: Michael Forney <mforney@mforney.org>
Date: Fri, 17 Jan 2020 12:53:59 -0800
Subject: [PATCH 1/4] Fix manifest rebuild when it was pruned due to restat

If build.ninja depends on an output with `restat = 1`, it may get
pruned if the output did not change. In this case, we can continue
with the build, since the previously loaded manifest is still
correct.

To make sure that we can add new build targets and start a new build
after executing the build for another target, add a function to
reset the build state.

Fixes #31.
---
 build.c | 17 +++++++++++++++++
 build.h |  2 ++
 samu.c  | 10 +++++++---
 3 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/build.c b/build.c
index 7d50d1e..71dda17 100644
--- a/build.c
+++ b/build.c
@@ -32,6 +32,23 @@ static struct edge *work;
 static size_t nstarted, ntotal;
 static bool consoleused;
 
+void
+buildreset(void) {
+	struct edge *e;
+	struct node *n;
+	size_t i;
+
+	for (e = alledges; e; e = e->allnext) {
+		e->flags = 0;
+		for (i = 0; i < e->nout; ++i) {
+			n = e->out[i];
+			free(n->use);
+			n->nuse = 0;
+			n->use = NULL;
+		}
+	}
+}
+
 /* returns whether n1 is newer than n2, or false if n1 is NULL */
 static bool
 isnewer(struct node *n1, struct node *n2)
diff --git a/build.h b/build.h
index fa221bd..6eb1988 100644
--- a/build.h
+++ b/build.h
@@ -7,6 +7,8 @@ struct buildoptions {
 
 extern struct buildoptions buildopts;
 
+/* reset state, so a new build can be executed */
+void buildreset(void);
 /* schedule a particular target to be built */
 void buildadd(struct node *);
 /* execute rules to build the scheduled targets */
diff --git a/samu.c b/samu.c
index a489b0f..f09c808 100644
--- a/samu.c
+++ b/samu.c
@@ -240,9 +240,13 @@ retry:
 		buildadd(n);
 		if (n->dirty) {
 			build();
-			if (++tries > 100)
-				fatal("manifest '%s' dirty after 100 tries", manifest);
-			goto retry;
+			if (n->gen->flags & FLAG_DIRTY_OUT || n->gen->nprune > 0) {
+				if (++tries > 100)
+					fatal("manifest '%s' dirty after 100 tries", manifest);
+				goto retry;
+			}
+			/* manifest was pruned; reset state, then continue with build */
+			buildreset();
 		}
 	}
 
--- 
2.24.0

diff --git a/main/samurai/0002-parse-Check-that-rules-always-have-a-command.patch b/main/samurai/0002-parse-Check-that-rules-always-have-a-command.patch
deleted file mode 100644
index 9256ab9421..0000000000
--- a/main/samurai/0002-parse-Check-that-rules-always-have-a-command.patch
@@ -1,54 +0,0 @@
From 6d510d99dee4135bcb6f973c6e208f05f889bc8d Mon Sep 17 00:00:00 2001
From: Michael Forney <mforney@mforney.org>
Date: Wed, 22 Jan 2020 10:45:07 -0800
Subject: [PATCH 2/4] parse: Check that rules always have a command

This way, we catch the error earlier than build(), and won't have
to repeat the check for the compdb tool.
---
 build.c | 4 ----
 parse.c | 5 +++++
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/build.c b/build.c
index 71dda17..c382c17 100644
--- a/build.c
+++ b/build.c
@@ -231,10 +231,6 @@ jobstart(struct job *j, struct edge *e)
 	}
 	j->edge = e;
 	j->cmd = edgevar(e, "command", true);
-	if (!j->cmd) {
-		warn("rule '%s' has no command", e->rule->name);
-		goto err2;
-	}
 	j->fd = fd[0];
 	argv[2] = j->cmd->s;
 
diff --git a/parse.c b/parse.c
index f8f9509..6d07816 100644
--- a/parse.c
+++ b/parse.c
@@ -35,6 +35,7 @@ parserule(struct scanner *s, struct environment *env)
 	struct rule *r;
 	char *var;
 	struct evalstring *val;
+	bool hascommand = false;
 
 	r = mkrule(scanname(s));
 	scannewline(s);
@@ -42,7 +43,11 @@ parserule(struct scanner *s, struct environment *env)
 		var = scanname(s);
 		parselet(s, &val);
 		ruleaddvar(r, var, val);
+		if (strcmp(var, "command") == 0)
+			hascommand = true;
 	}
+	if (!hascommand)
+		fatal("rule '%s' has no command", r->name);
 	envaddrule(env, r);
 }
 
--- 
2.24.0

diff --git a/main/samurai/0003-parse-Check-that-rules-have-rspfile-iff-they-have-rs.patch b/main/samurai/0003-parse-Check-that-rules-have-rspfile-iff-they-have-rs.patch
deleted file mode 100644
index 3915fc1bd2..0000000000
--- a/main/samurai/0003-parse-Check-that-rules-have-rspfile-iff-they-have-rs.patch
@@ -1,56 +0,0 @@
From f549b757394fdb4ac27e4a4bc42e865e98434361 Mon Sep 17 00:00:00 2001
From: Michael Forney <mforney@mforney.org>
Date: Wed, 22 Jan 2020 11:36:30 -0800
Subject: [PATCH 3/4] parse: Check that rules have $rspfile iff they have
 $rspfile_content

---
 parse.c | 8 +++++++-
 util.c  | 2 +-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/parse.c b/parse.c
index 6d07816..413e5d7 100644
--- a/parse.c
+++ b/parse.c
@@ -35,7 +35,7 @@ parserule(struct scanner *s, struct environment *env)
 	struct rule *r;
 	char *var;
 	struct evalstring *val;
-	bool hascommand = false;
+	bool hascommand = false, hasrspfile = false, hasrspcontent = false;
 
 	r = mkrule(scanname(s));
 	scannewline(s);
@@ -45,9 +45,15 @@ parserule(struct scanner *s, struct environment *env)
 		ruleaddvar(r, var, val);
 		if (strcmp(var, "command") == 0)
 			hascommand = true;
+		else if (strcmp(var, "rspfile") == 0)
+			hasrspfile = true;
+		else if (strcmp(var, "rspfile_content") == 0)
+			hasrspcontent = true;
 	}
 	if (!hascommand)
 		fatal("rule '%s' has no command", r->name);
+	if (hasrspfile != hasrspcontent)
+		fatal("rule '%s' has rspfile and no rspfile_content or vice versa", r->name);
 	envaddrule(env, r);
 }
 
diff --git a/util.c b/util.c
index 8eccf92..39bab18 100644
--- a/util.c
+++ b/util.c
@@ -257,7 +257,7 @@ writefile(const char *name, struct string *s)
 		return -1;
 	}
 	ret = 0;
-	if (s && (fwrite(s->s, 1, s->n, f) != s->n || fflush(f) != 0)) {
+	if (fwrite(s->s, 1, s->n, f) != s->n || fflush(f) != 0) {
 		warn("write %s:", name);
 		ret = -1;
 	}
--- 
2.24.0

diff --git a/main/samurai/0004-tool-Implement-compdb.patch b/main/samurai/0004-tool-Implement-compdb.patch
deleted file mode 100644
index fff96e6804..0000000000
--- a/main/samurai/0004-tool-Implement-compdb.patch
@@ -1,197 +0,0 @@
From 9c1f015c21211c5df5822f70d3d5be81bd54fee2 Mon Sep 17 00:00:00 2001
From: Michael Forney <mforney@mforney.org>
Date: Wed, 22 Jan 2020 11:50:03 -0800
Subject: [PATCH 4/4] tool: Implement compdb

This tool outputs a JSON compilation database[0], which is used for
integration with certain IDEs (for example, GNOME Builder).

Fixes #33.

[0] https://clang.llvm.org/docs/JSONCompilationDatabase.html
---
 samu.1 | 21 +++++++++++--
 tool.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+), 3 deletions(-)

diff --git a/samu.1 b/samu.1
index a4f3f70..0f10e93 100644
--- a/samu.1
+++ b/samu.1
@@ -1,4 +1,4 @@
-.Dd July 3, 2019
+.Dd January 22, 2019
 .Dt SAMU 1
 .Os
 .Sh NAME
@@ -20,6 +20,12 @@
 .Fl t Cm clean
 .Op Fl gr
 .Op Ar target...
+.Nm
+.Op Fl C Ar dir
+.Op Fl f Ar buildfile
+.Fl t Cm compdb
+.Op Fl x
+.Op Ar rule...
 .Sh DESCRIPTION
 .Nm
 loads a build manifest from
@@ -48,6 +54,12 @@ Targets built with
 rules are only removed if
 .Fl g
 is specified.
+.Pp
+If the
+.Cm compdb
+tool is used, a compilation database
+.Lk ( https://clang.llvm.org/docs/JSONCompilationDatabase.html )
+is printed instead.
 .Sh OPTIONS
 .Bl -tag -width Ds
 .It Fl C
@@ -106,9 +118,10 @@ only print a diagnostic message.
 .It Fl t
 Instead of building, invoke a subtool.
 All arguments and flags after the subtool are interpreted by the subtool.
-Currently,
+The currently supported subtools are
 .Cm clean
-is the only subtool.
+and
+.Cm compdb .
 .It Fl g
 When cleaning, also clean outputs of
 .Sy generator
@@ -117,6 +130,8 @@ actions.
 .Ar targets
 are interpreted as rules, and all outputs of actions with the specified rule
 types will be cleaned instead.
+.It Fl x
+When printing a compilation database, replace @$rspfile with $rspfile_content (with <blank> in place of <newline>).
 .El
 .Sh ENVIRONMENT
 .Bl -tag -width SAMUFLAGS
diff --git a/tool.c b/tool.c
index aae97c0..f77931e 100644
--- a/tool.c
+++ b/tool.c
@@ -1,7 +1,10 @@
+#define _POSIX_C_SOURCE 200809L
 #include <errno.h>
+#include <limits.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 #include "arg.h"
 #include "env.h"
 #include "graph.h"
@@ -123,8 +126,104 @@ clean(int argc, char *argv[])
 	return ret;
 }
 
+static void
+printjson(const char *s, size_t n, bool join)
+{
+	size_t i;
+	char c;
+
+	for (i = 0; i < n; ++i) {
+		c = s[i];
+		switch (c) {
+		case '"':
+		case '\\':
+			putchar('\\');
+			break;
+		case '\n':
+			if (join)
+				c = ' ';
+			break;
+		case '\0':
+			return;
+		}
+		putchar(c);
+	}
+}
+
+static int
+compdb(int argc, char *argv[])
+{
+	char dir[PATH_MAX], *p;
+	struct edge *e;
+	struct string *cmd, *rspfile, *content;
+	bool expandrsp = false, first = true;
+	int i;
+	size_t off;
+
+	ARGBEGIN {
+	case 'x':
+		expandrsp = true;
+		break;
+	default:
+		fprintf(stderr, "usage: %s ... -t compdb [-x] rules...\n", argv0);
+		return 2;
+	} ARGEND
+
+	if (!getcwd(dir, sizeof(dir)))
+		fatal("getcwd:");
+
+	putchar('[');
+	for (e = alledges; e; e = e->allnext) {
+		if (e->nin == 0)
+			continue;
+		for (i = 0; i < argc; ++i) {
+			if (strcmp(e->rule->name, argv[i]) == 0) {
+				if (first)
+					first = false;
+				else
+					putchar(',');
+
+				printf("\n  {\n    \"directory\": \"");
+				printjson(dir, -1, false);
+
+				printf("\",\n    \"command\": \"");
+				cmd = edgevar(e, "command", true);
+				rspfile = expandrsp ? edgevar(e, "rspfile", true) : NULL;
+				p = rspfile ? strstr(cmd->s, rspfile->s) : NULL;
+				if (!p || p == cmd->s || p[-1] != '@') {
+					printjson(cmd->s, cmd->n, false);
+				} else {
+					off = p - cmd->s;
+					printjson(cmd->s, off - 1, false);
+					content = edgevar(e, "rspfile_content", true);
+					printjson(content->s, content->n, true);
+					off += rspfile->n;
+					printjson(cmd->s + off, cmd->n - off, false);
+				}
+
+				printf("\",\n    \"file\": \"");
+				printjson(e->in[0]->path->s, -1, false);
+
+				printf("\",\n    \"output\": \"");
+				printjson(e->out[0]->path->s, -1, false);
+
+				printf("\",\n  }");
+				break;
+			}
+		}
+	}
+	puts("\n]");
+
+	fflush(stdout);
+	if (ferror(stdout))
+		fatal("write failed");
+
+	return 0;
+}
+
 static const struct tool tools[] = {
 	{"clean", clean},
+	{"compdb", compdb},
 };
 
 const struct tool *
--- 
2.24.0

diff --git a/main/samurai/0005-deps-treat-missing-depfile-as-empty-for-deps-log.patch b/main/samurai/0005-deps-treat-missing-depfile-as-empty-for-deps-log.patch
deleted file mode 100644
index cdb0cb78b3..0000000000
--- a/main/samurai/0005-deps-treat-missing-depfile-as-empty-for-deps-log.patch
@@ -1,64 +0,0 @@
From 9d15bff89c1566e40569f689696d0393e7659df1 Mon Sep 17 00:00:00 2001
From: Michael Forney <mforney@mforney.org>
Date: Wed, 12 Feb 2020 23:19:05 -0800
Subject: [PATCH] deps: Treat missing depfile as empty for deps log

This matches ninja's behavior. When deps is not set, a missing
depfile causes the output to be dirty. When it is set, an empty set
of dependencies is recorded into the log.
---
 deps.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/deps.c b/deps.c
index 4eef994..1338919 100644
--- a/deps.c
+++ b/deps.c
@@ -296,7 +296,7 @@ depsclose(void)
 }
 
 static struct nodearray *
-depsparse(const char *name)
+depsparse(const char *name, bool allowmissing)
 {
 	static struct buffer buf;
 	static struct nodearray deps;
@@ -306,12 +306,15 @@ depsparse(const char *name)
 	int c, n;
 	bool sawcolon;
 
+	deps.len = 0;
 	f = fopen(name, "r");
-	if (!f)
+	if (!f) {
+		if (errno == ENOENT && allowmissing)
+			return &deps;
 		return NULL;
+	}
 	sawcolon = false;
 	buf.len = 0;
-	deps.len = 0;
 	c = getc(f);
 	for (;;) {
 		/* TODO: this parser needs to be rewritten to be made simpler */
@@ -438,9 +441,9 @@ depsload(struct edge *e)
 		depfile = edgevar(e, "depfile", false);
 		if (!depfile)
 			return;
-		deps = depsparse(depfile->s);
+		deps = depsparse(depfile->s, false);
 		if (buildopts.explain && !deps)
-			warn("explain %s: missing or invalid dep file", n->path->s);
+			warn("explain %s: missing or invalid depfile", n->path->s);
 	}
 	if (deps) {
 		edgeadddeps(e, deps->node, deps->len);
@@ -473,7 +476,7 @@ depsrecord(struct edge *e)
 		return;
 	}
 	out = e->out[0];
-	deps = depsparse(depfile->s);
+	deps = depsparse(depfile->s, true);
 	if (!buildopts.keepdepfile)
 		remove(depfile->s);
 	if (!deps)
diff --git a/main/samurai/APKBUILD b/main/samurai/APKBUILD
index cd9777d5e9..c0c9159eeb 100644
--- a/main/samurai/APKBUILD
+++ b/main/samurai/APKBUILD
@@ -1,20 +1,15 @@
# Contributor: Drew DeVault <sir@cmpwn.com>
# Maintainer: Drew DeVault <sir@cmpwn.com>
pkgname=samurai
pkgver=1.0
pkgrel=4
pkgver=1.1
pkgrel=0
pkgdesc="ninja-compatible build tool written in C"
url="https://github.com/michaelforney/samurai"
arch="all"
license="Apache-2.0"
options="!check"  # No test suite.
subpackages="$pkgname-doc"
source="https://github.com/michaelforney/samurai/releases/download/$pkgver/samurai-$pkgver.tar.gz
	0001-Fix-manifest-rebuild-when-it-was-pruned-due-to-resta.patch
	0002-parse-Check-that-rules-always-have-a-command.patch
	0003-parse-Check-that-rules-have-rspfile-iff-they-have-rs.patch
	0004-tool-Implement-compdb.patch
	0005-deps-treat-missing-depfile-as-empty-for-deps-log.patch"
source="https://github.com/michaelforney/samurai/releases/download/$pkgver/samurai-$pkgver.tar.gz"
provides="ninja"
replaces="ninja"

@@ -27,9 +22,4 @@ package() {
	ln -s samu "$pkgdir"/usr/bin/ninja
}

sha512sums="87b2a11a39dc36f3582abdc7c9d358c8fce241fe4155b5177d3e8588d1c040a62eb9daafd2365febbfadd6fcc27a3ceacf6f29ca6f871c822aad6f4bad527a51  samurai-1.0.tar.gz
a53c3a16a5d3115572a9c47d8a939bce6f5c5d05c9d4626a27a11c46a2bcec1497b1ca886d85da7f298340cc34fd6c65e613de9a4d726003b7f202376c267ae9  0001-Fix-manifest-rebuild-when-it-was-pruned-due-to-resta.patch
2e4a061daa55115437af476c5e7721448d6986cf3111f4e94edf82f853e65a3da89e55103abc7f401506d3ea69aca34f3f9602c160bdf98c4c2ae3f38f8294e9  0002-parse-Check-that-rules-always-have-a-command.patch
2558c16c5039bda1fb12f404e740dde780a195a875649cc87a51ccae8cee3e9ceb03befb9ba9301b6ed3cba02fd827ce50131a17aab74a5eacca9841a7e5efdd  0003-parse-Check-that-rules-have-rspfile-iff-they-have-rs.patch
630a59438f8bf71466766b42aced2adf22bb19972b3d871f734b0fa9f09cb7fad8d3a5bc2acc4e690538f9f34339b8516fb1f1642817dbe66812b43095899114  0004-tool-Implement-compdb.patch
03da692b82d4ec07e59600abf46dbdef44957709c10f216465456abd68ab7f259bff06f13f3e069393f69a8689081f69573a1ed6b21755dd9b91841d92d616c4  0005-deps-treat-missing-depfile-as-empty-for-deps-log.patch"
sha512sums="b27302c34d736f483909e57c8b162609eaa4c86571c1167b71a5564b521cc3af2861307a16bb6dca55e80952088989e9526b103160d2ea054d15f4ed85b1cedb  samurai-1.1.tar.gz"
-- 
2.26.0