From a380937f1f36fba9d901e5eaa58119c509ed5f52 Mon Sep 17 00:00:00 2001
From: skullY <skullydazed@gmail.com>
Date: Tue, 21 Apr 2020 13:27:13 -0700
Subject: [PATCH] wip

---
 Makefile                          | 79 +++++++++++---------------
 lib/python/qmk/cli/__init__.py    |  1 +
 lib/python/qmk/cli/makehandler.py | 92 +++++++++++++++++++++++++++++++
 3 files changed, 124 insertions(+), 48 deletions(-)
 create mode 100755 lib/python/qmk/cli/makehandler.py

diff --git a/Makefile b/Makefile
index 9478c14f8c..5ebc22b1bb 100644
--- a/Makefile
+++ b/Makefile
@@ -557,55 +557,38 @@ endef
 # Let's match everything, we handle all the rule parsing ourselves
 .PHONY: %
 %:
-	# Check if we have the CMP tool installed
-	cmp $(ROOT_DIR)/Makefile $(ROOT_DIR)/Makefile >/dev/null 2>&1; if [ $$? -gt 0 ]; then printf "$(MSG_NO_CMP)"; exit 1; fi;
-	# Ensure that python3 is installed. This check can be removed after python is used in more places.
-	if ! python3 --version 1> /dev/null 2>&1; then printf "$(MSG_PYTHON_MISSING)"; fi
-	# Check if the submodules are dirty, and display a warning if they are
-ifndef SKIP_GIT
-	if [ ! -e lib/chibios ]; then git submodule sync lib/chibios && git submodule update --depth 50 --init lib/chibios; fi
-	if [ ! -e lib/chibios-contrib ]; then git submodule sync lib/chibios-contrib && git submodule update --depth 50 --init lib/chibios-contrib; fi
-	if [ ! -e lib/ugfx ]; then git submodule sync lib/ugfx && git submodule update --depth 50 --init lib/ugfx; fi
-	if [ ! -e lib/lufa ]; then git submodule sync lib/lufa && git submodule update --depth 50 --init lib/lufa; fi
-	git submodule status --recursive 2>/dev/null | \
-	while IFS= read -r x; do \
-		case "$$x" in \
-			\ *) ;; \
-			*) printf "$(MSG_SUBMODULE_DIRTY)";break;; \
-		esac \
-	done
-endif
-	rm -f $(ERROR_FILE) > /dev/null 2>&1
-	$(eval $(call PARSE_RULE,$@))
-	$(eval $(call SET_SILENT_MODE))
-	# Run all the commands in the same shell, notice the + at the first line
-	# it has to be there to allow parallel execution of the submake
-	# This always tries to compile everything, even if error occurs in the middle
-	# But we return the error code at the end, to trigger travis failures
-	# The sort at this point is to remove duplicates
-	$(foreach COMMAND,$(sort $(COMMANDS)),$(RUN_COMMAND))
-	if [ -f $(ERROR_FILE) ]; then printf "$(MSG_ERRORS)" & exit 1; fi;
-	$(foreach TEST,$(sort $(TESTS)),$(RUN_TEST))
-	if [ -f $(ERROR_FILE) ]; then printf "$(MSG_ERRORS)" & exit 1; fi;
+#	# Check if we have the CMP tool installed
+#	cmp $(ROOT_DIR)/Makefile $(ROOT_DIR)/Makefile >/dev/null 2>&1; if [ $$? -gt 0 ]; then printf "$(MSG_NO_CMP)"; exit 1; fi;
+#	# Ensure that python3 is installed. This check can be removed after python is used in more places.
+#	if ! python3 --version 1> /dev/null 2>&1; then printf "$(MSG_PYTHON_MISSING)"; fi
+#	# Check if the submodules are dirty, and display a warning if they are
+#ifndef SKIP_GIT
+#	if [ ! -e lib/chibios ]; then git submodule sync lib/chibios && git submodule update --depth 50 --init lib/chibios; fi
+#	if [ ! -e lib/chibios-contrib ]; then git submodule sync lib/chibios-contrib && git submodule update --depth 50 --init lib/chibios-contrib; fi
+#	if [ ! -e lib/ugfx ]; then git submodule sync lib/ugfx && git submodule update --depth 50 --init lib/ugfx; fi
+#	if [ ! -e lib/lufa ]; then git submodule sync lib/lufa && git submodule update --depth 50 --init lib/lufa; fi
+#	git submodule status --recursive 2>/dev/null | \
+#	while IFS= read -r x; do \
+#		case "$$x" in \
+#			\ *) ;; \
+#			*) printf "$(MSG_SUBMODULE_DIRTY)";break;; \
+#		esac \
+#	done
+#endif
+#	rm -f $(ERROR_FILE) > /dev/null 2>&1
+#	$(eval $(call PARSE_RULE,$@))
+#	$(eval $(call SET_SILENT_MODE))
+#	# Run all the commands in the same shell, notice the + at the first line
+#	# it has to be there to allow parallel execution of the submake
+#	# This always tries to compile everything, even if error occurs in the middle
+#	# But we return the error code at the end, to trigger travis failures
+#	# The sort at this point is to remove duplicates
+#	$(foreach COMMAND,$(sort $(COMMANDS)),$(RUN_COMMAND))
+#	if [ -f $(ERROR_FILE) ]; then printf "$(MSG_ERRORS)" & exit 1; fi;
+#	$(foreach TEST,$(sort $(TESTS)),$(RUN_TEST))
+#	if [ -f $(ERROR_FILE) ]; then printf "$(MSG_ERRORS)" & exit 1; fi;
 
-# These no longer work because of the colon system
-
-# All should compile everything
-# .PHONY: all
-# all: all-keyboards test-all
-
-# Define some shortcuts, mostly for compatibility with the old syntax
-# .PHONY: all-keyboards
-# all-keyboards: all\:all\:all
-
-# .PHONY: all-keyboards-defaults
-# all-keyboards-defaults: all\:default
-
-# .PHONY: test
-# test: test-all
-
-# .PHONY: test-clean
-# test-clean: test-all-clean
+	bin/qmk makehandler $@
 
 lib/%:
 	git submodule sync $?
diff --git a/lib/python/qmk/cli/__init__.py b/lib/python/qmk/cli/__init__.py
index 394a1353bc..46c3b4e5b6 100644
--- a/lib/python/qmk/cli/__init__.py
+++ b/lib/python/qmk/cli/__init__.py
@@ -17,6 +17,7 @@ from . import json
 from . import json2c
 from . import list
 from . import kle2json
+from . import makehandler
 from . import new
 from . import pyformat
 from . import pytest
diff --git a/lib/python/qmk/cli/makehandler.py b/lib/python/qmk/cli/makehandler.py
new file mode 100755
index 0000000000..e0d9605f52
--- /dev/null
+++ b/lib/python/qmk/cli/makehandler.py
@@ -0,0 +1,92 @@
+"""Generate a make command from a `keyboard:keymap` pair.
+"""
+import os
+
+from milc import cli
+
+from qmk.path import is_keyboard
+
+def parse_rule(rule):
+    """Parses a QMK make rule into its compononent parts.
+    
+    Expects rule to be in the form `<keyboard>:<keyboard>[:<COMMAND>]`
+    """
+    rule = rule.split(':')
+    if len(rule) == 1:
+        return rule + ['all', '']
+
+    if len(rule) == 2:
+        return rule + ['']
+
+    if len(rule) == 3:
+        return rule
+
+    raise IndexError('rule %s has too many parts!' % rule)
+
+
+@cli.argument('arguments', arg_only=True, nargs='+', help='Make arguments.')
+@cli.subcommand('QMK Hello World.', hidden=True)
+def makehandler(cli):
+    """Turn a `make keyboard:keymap` command into a full make command.
+    """
+    environment = os.environ.copy()  # FIXME: We should sanitize this
+    print('***', 'environment')
+    for key, value in environment.items():
+        cli.log.info('%s=%s', key, value)
+    environment['COLOR'] = '1' if cli.config.general.color else '0'
+    environment['SILENT_MODE'] = '0'
+    environment['VERBOSE'] = '1' if cli.config.general.verbose else '0'
+    compile_targets = []
+
+    # Check submodules and warn if dirty
+    pass
+
+    # Parse the command line (PARSE_RULE)
+    for argument in cli.args.arguments:
+        if "=" in argument:
+            key, value = argument.split('=', 1)
+            environment[key] = value
+
+        else:
+            keyboard, keymap, command = parse_rule(argument)
+            keyboard_env = environment.copy()
+
+            # Check the keyboard
+            if not (keyboard in ['all', 'test'] or is_keyboard(keyboard)):
+                cli.log.error('Invalid keyboard: %s', keyboard)
+                continue
+
+            # Check the keymap
+            if not (keymap in ['all'] or True):  # FIXME: Replace True with is_keymap(keyboard, keymap)
+                cli.log.error('Invalid keymap: %s', keymap)
+                continue
+
+            # Add this compile target
+            keyboard_env['CURRENT_KB'] = keyboard_env['DEFAULT_FOLDER'] = keyboard_env['KEYBOARD_RULE'] = keyboard
+            compile_targets.append([keyboard, keymap, command, keyboard_env])
+
+    # Determine if we should turn on SILENT_MODE.
+    if 'SILENT' in environment:
+        for target in compile_targets:
+            target[3]['SILENT_MODE'] = environment['SILENT']
+    elif len(compile_targets) > 1:
+        for target in compile_targets:
+            target[3]['SILENT_MODE'] = environment['SILENT']
+
+    # Iterate through our compile targets and generate make commands.
+    compiles_ok = True
+    for keyboard, keymap, command, environment in compile_targets:
+        print('***', repr(keyboard), repr(keymap), repr(command))
+        for key, value in environment.items():
+            cli.log.info('%s=%s', key, value)
+
+    if not compiles_ok:
+        cli.log.error('{fg_red}Make finished with errors')
+        exit(1)
+
+    # $(foreach TEST,$(sort $(TESTS)),$(RUN_TEST))
+    tests_ok = False  # FIXME: Set to true when all tests are true
+    
+    if not tests_ok:
+        # printf "$(MSG_ERRORS)" & exit 1
+        pass