Abstract EXT2, add JMK Emacs integration
diff --git a/share/jmk/dir-locals.el b/share/jmk/dir-locals.el
new file mode 100644
index 0000000..2648a7e
--- /dev/null
+++ b/share/jmk/dir-locals.el
@@ -0,0 +1,3 @@
+((nil . ((eval
+		  . (setq-local flycheck-clang-args
+						(jmk-arguments-for (expand-file-name buffer-file-name)))))))
diff --git a/share/jmk/jmk-flycheck.el b/share/jmk/jmk-flycheck.el
new file mode 100644
index 0000000..8de4949
--- /dev/null
+++ b/share/jmk/jmk-flycheck.el
@@ -0,0 +1,37 @@
+(defun jmk-find-parent-makefile (p)
+  "Find the parent makefile of file P."
+  (let ((path (or p (expand-file-name "."))))
+	(while (not (or (string= path "/")
+					(file-exists-p (concat path "/Makefile"))))
+	  (setq path (expand-file-name (concat path "/.."))))
+	(unless (string= path "/")
+	  (concat path "/Makefile"))))
+
+(defun jmk-find-makefile (p)
+  "Find the makefile for the source file P.
+/a/b/src/hello.c -> /a/b/src/Makefile
+/a/b/include/hello.h -> /a/b/src/Makefile
+Returns nil if nothing can be found"
+  (if-let ((makefile (jmk-find-parent-makefile p)))
+	  makefile
+	(jmk-find-parent-makefile (replace-regexp-in-string
+							   (regexp-quote "include")
+							   "src" p nil 'literal))))
+
+(defun jmk-arguments-for (p)
+  (if-let (path (jmk-find-makefile p))
+	  (split-string (shell-command-to-string
+					 (concat "make -f " path " show_cflags")) " ")
+	nil))
+
+(defun jmk-includes-for (p)
+  (let* ((args (jmk-arguments-for p))
+		 (includes (cl-remove-if-not (lambda (arg)
+									   (string-prefix-p "-I" arg))
+									 args))
+		 (names (mapcar (lambda (arg)
+						  (string-trim (substring arg 2)))
+						includes)))
+	(message "includes: %s" names)
+	names))
+
diff --git a/share/jmk/jmk.m4 b/share/jmk/jmk.m4
index e251a8b..ce95156 100644
--- a/share/jmk/jmk.m4
+++ b/share/jmk/jmk.m4
@@ -9,9 +9,12 @@
 define(`_foreach', `ifelse(`$2', `()', `',
   `define(`$1', _arg1$2)$3`'$0(`$1', (shift$2), `$3')')')
 
-define(status_log, `	@printf " \e[1;34m%8s\e[m  %s\n" "$1" "$2"')
+define(status_log, `	@printf " \e[1;34m%8s\e[m  %s\n" "$1" "$2" > /dev/stderr')
 define(DO_MAKE, `$(MAKE) --no-print-directory MAKEFILE_DEPTH="$$(( $(MAKEFILE_DEPTH) + 1))"')
 
+define(gtags_path, $(ROOT)/GTAGS)
+define(gen_gtags, ifelse(disable_gtags,true,,cd $(ROOT) && gtags))
+
 define(init,
 `jmk_project := $1
 jmk_target = ifelse(`$#', 2, $2, $1)
@@ -49,10 +52,10 @@
 
 dnl archetype enables a language archetype
 define(archetype,
-    `ifelse($1, c, `.c.o:
+    `ifelse($1, c, `.c.o: gtags_path
 status_log(CC, $<)
 	@$(CC) -c $< -o dollar_at $(CFLAGS)',
-        $1, asm, `.s.o:
+        $1, asm, `.s.o: gtags_path
 status_log(AS, $<)
 	@$(ASM) $(ASMFLAGS) $< -o dollar_at')')
 
@@ -81,14 +84,17 @@
     `ifelse($1, executable,
 `$(jmk_target): $(OBJECTS)
 status_log(LD, dollar_at)
+	@gen_gtags
 	@$(CC) -o dollar_at $^ $(CFLAGS)',
     $1, static_lib,
 `$(jmk_target): $(OBJECTS)
 status_log(AR, dollar_at)
+	@gen_gtags
 	@ar rcs dollar_at $^',
     $1, custom_link,
 `$(jmk_target): $(OBJECTS)
 status_log(LD, dollar_at)
+	@gen_gtags
 	@$(LD) $(LDFLAGS) -o dollar_at $^')')
 
 define(option,
@@ -107,6 +113,13 @@
 status_log(JMK, jmk_build_dir)
 	@cd "jmk_build_dir" && jmk_build_cmd
 
-.PHONY: $(jmk_libs_phony) $(jmk_custom_phony) $(jmk_clean_libs) clean all')
+gtags_path:
+status_log(GTAGS,)
+	gen_gtags
+
+show_cflags:
+	@echo $(CFLAGS)
+
+.PHONY: $(jmk_libs_phony) $(jmk_custom_phony) $(jmk_clean_libs) clean all show_cflags')
 
 divert(0)dnl