Meta: Update Makefile, makem.sh
This commit is contained in:
parent
6004ab98da
commit
b1d9fcf274
2 changed files with 116 additions and 88 deletions
19
Makefile
19
Makefile
|
|
@ -2,14 +2,27 @@
|
|||
|
||||
# For consistency, we use only var=val options, not hyphen-prefixed options.
|
||||
|
||||
ifdef autoinstall
|
||||
AUTOINSTALL = "--auto-install"
|
||||
# NOTE: I don't like duplicating the arguments here and in makem.sh,
|
||||
# but I haven't been able to find a way to pass arguments which
|
||||
# conflict with Make's own arguments through Make to the script.
|
||||
# Using -- doesn't seem to do it.
|
||||
|
||||
ifdef auto-install
|
||||
AUTO_INSTALL = "--auto-install"
|
||||
endif
|
||||
|
||||
ifdef sandbox
|
||||
SANDBOX = "--sandbox"
|
||||
endif
|
||||
|
||||
ifdef sandbox-dir
|
||||
SANDBOX_DIR = "--sandbox-dir" "$(sandbox-dir)"
|
||||
endif
|
||||
|
||||
ifdef debug
|
||||
DEBUG = "--debug"
|
||||
endif
|
||||
|
||||
# ** Verbosity
|
||||
|
||||
# Since the "-v" in "make -v" gets intercepted by Make itself, we have
|
||||
|
|
@ -29,4 +42,4 @@ endif
|
|||
# directory by that name exists, which can confuse Make.
|
||||
|
||||
%:
|
||||
@./makem.sh $(VERBOSE) $(SANDBOX) $(AUTOINSTALL) $(@)
|
||||
@./makem.sh $(DEBUG) $(VERBOSE) $(SANDBOX) $(SANDBOX_DIR) $(AUTO_INSTALL) $(@)
|
||||
|
|
|
|||
177
makem.sh
177
makem.sh
|
|
@ -44,63 +44,9 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# * Safety
|
||||
# * Functions
|
||||
|
||||
# NOTE: These are disabled by default in this template but should be
|
||||
# enabled when feasible. Documentation is from the Bash man page.
|
||||
|
||||
# ** errexit
|
||||
|
||||
# Exit immediately if a pipeline (which may consist of a single simple
|
||||
# command), a list, or a compound command (see SHELL GRAMMAR above),
|
||||
# exits with a non-zero status. The shell does not exit if the
|
||||
# command that fails is part of the command list immediately following
|
||||
# a while or until keyword, part of the test following the if or elif
|
||||
# reserved words, part of any command executed in a && or || list
|
||||
# except the command follow‐ ing the final && or ||, any command in a
|
||||
# pipeline but the last, or if the command's return value is being
|
||||
# inverted with !. If a compound command other than a subshell
|
||||
# returns a non-zero status because a command failed while -e was
|
||||
# being ignored, the shell does not exit. A trap on ERR, if set, is
|
||||
# executed before the shell exits. This option applies to the shell
|
||||
# environment and each subshell environment separately (see COMMAND
|
||||
# EXECUTION ENVIRONMENT above), and may cause subshells to exit before
|
||||
# executing all the commands in the subshell.
|
||||
|
||||
# If a compound command or shell function executes in a context where
|
||||
# -e is being ignored, none of the commands executed within the
|
||||
# compound command or function body will be affected by the -e
|
||||
# setting, even if -e is set and a command returns a failure status.
|
||||
# If a compound command or shell function sets -e while executing in a
|
||||
# context where -e is ignored, that setting will not have any effect
|
||||
# until the compound command or the command containing the function
|
||||
# call completes.
|
||||
|
||||
# set -o errexit
|
||||
|
||||
# ** nounset
|
||||
|
||||
# Treat unset variables and parameters other than the special
|
||||
# parameters "@" and "*" as an error when performing parameter
|
||||
# expansion. If expansion is attempted on an unset variable or
|
||||
# parameter, the shell prints an error message, and, if not
|
||||
# interactive, exits with a non-zero status.
|
||||
|
||||
# NOTE: When this is not enabled, individual variables can be required
|
||||
# to be set by using "${var:?}" parameter expansion syntax.
|
||||
|
||||
# set -o nounset
|
||||
|
||||
# ** pipefail
|
||||
|
||||
# If set, the return value of a pipeline is the value of the last
|
||||
# (rightmost) command to exit with a non-zero status, or zero if all
|
||||
# commands in the pipeline exit successfully. This option is disabled
|
||||
# by default.
|
||||
|
||||
# set -o pipefail
|
||||
|
||||
# * Elisp
|
||||
# ** Elisp
|
||||
|
||||
# These functions return a path to an elisp file which can be loaded
|
||||
# by Emacs on the command line with -l or --load.
|
||||
|
|
@ -164,8 +110,6 @@ EOF
|
|||
echo $file
|
||||
}
|
||||
|
||||
# * Functions
|
||||
|
||||
# ** Emacs
|
||||
|
||||
function run_emacs {
|
||||
|
|
@ -219,17 +163,27 @@ function project-elisp-files {
|
|||
|
||||
function project-source-files {
|
||||
# Echo list of Elisp files that are not tests.
|
||||
project-elisp-files | egrep -v '^tests?/test-?'
|
||||
project-elisp-files | egrep -v "$test_files_regexp" | feature-files
|
||||
}
|
||||
|
||||
function project-test-files {
|
||||
# Echo list of Elisp test files.
|
||||
project-elisp-files | egrep '^tests?/test-?'
|
||||
project-elisp-files | egrep "$test_files_regexp"
|
||||
}
|
||||
|
||||
function exclude-files {
|
||||
# Filter out paths (STDIN) which should be excluded by default.
|
||||
egrep -v "(/\.cask/|-autoloads.el)"
|
||||
egrep -v "(/\.cask/|-autoloads.el|.dir-locals)"
|
||||
}
|
||||
|
||||
function feature-files {
|
||||
# Read paths on STDIN and echo ones that (provide 'a-feature).
|
||||
while read path
|
||||
do
|
||||
debug "PATH: $path"
|
||||
egrep "^\\(provide '" "$path" &>/dev/null \
|
||||
&& echo "$path"
|
||||
done
|
||||
}
|
||||
|
||||
function load-files-args {
|
||||
|
|
@ -248,30 +202,46 @@ function files_args {
|
|||
done
|
||||
}
|
||||
|
||||
function test-files-p {
|
||||
# Return 0 if $project_test_files is non-empty.
|
||||
[[ "${project_test_files[@]}" ]]
|
||||
}
|
||||
|
||||
function buttercup-tests-p {
|
||||
# Return 0 if Buttercup tests are found.
|
||||
test-files-p || die "No tests found."
|
||||
debug "Checking for Buttercup tests..."
|
||||
|
||||
grep "(require 'buttercup)" $(project-test-files) &>/dev/null
|
||||
grep "(require 'buttercup)" "${project_test_files[@]}" &>/dev/null
|
||||
}
|
||||
|
||||
function ert-tests-p {
|
||||
# Return 0 if ERT tests are found.
|
||||
test-files-p || die "No tests found."
|
||||
debug "Checking for ERT tests..."
|
||||
|
||||
# We check for this rather than "(require 'ert)", because ERT may
|
||||
# already be loaded in Emacs and might not be loaded with
|
||||
# "require" in a test file.
|
||||
grep "(ert-deftest" $(project-test-files) &>/dev/null
|
||||
grep "(ert-deftest" "${project_test_files[@]}" &>/dev/null
|
||||
}
|
||||
|
||||
function dependencies {
|
||||
# Echo list of package dependencies.
|
||||
|
||||
# Search package headers.
|
||||
egrep '^;; Package-Requires: ' $(project-source-files) $(project-test-files) \
|
||||
| egrep -o '\([^([:space:]][^)]*\)' \
|
||||
| egrep -o '^[^[:space:])]+' \
|
||||
| sed -r 's/\(//g' \
|
||||
| egrep -v '^emacs$' # Ignore Emacs version requirement.
|
||||
|
||||
# Search Cask file.
|
||||
if [[ -r Cask ]]
|
||||
then
|
||||
egrep '\(depends-on "[^"]+"' Cask \
|
||||
| sed -r -e 's/\(depends-on "([^"]+)".*/\1/g'
|
||||
fi
|
||||
}
|
||||
|
||||
# ** Utility
|
||||
|
|
@ -390,7 +360,10 @@ Sandbox options:
|
|||
These require emacs-sandbox.sh to be on your PATH. Find it at
|
||||
<https://github.com/alphapapa/emacs-sandbox.sh>.
|
||||
|
||||
--sandbox Run Emacs with emacs-sandbox.sh.
|
||||
-s, --sandbox Run Emacs with emacs-sandbox.sh in a temporary
|
||||
directory (removing directory on exit).
|
||||
-S, --sandbox-dir DIR Use DIR for the sandbox directory (leaving it
|
||||
on exit). Implies -s.
|
||||
--auto-install Automatically install package dependencies.
|
||||
-i, --install PACKAGE Install PACKAGE before running rules.
|
||||
|
||||
|
|
@ -398,7 +371,7 @@ Source files are automatically discovered from git, or may be
|
|||
specified with options.
|
||||
|
||||
Package dependencies are discovered from "Package-Requires" headers in
|
||||
source files.
|
||||
source files and from a Cask file.
|
||||
EOF
|
||||
}
|
||||
|
||||
|
|
@ -507,24 +480,38 @@ function test-ert {
|
|||
|
||||
# * Defaults
|
||||
|
||||
test_files_regexp='^(tests?|t)/'
|
||||
emacs_command="emacs"
|
||||
|
||||
# TODO: Disable color if not outputting to a terminal.
|
||||
color=true
|
||||
errors=0
|
||||
verbose=0
|
||||
|
||||
compile=true
|
||||
|
||||
# MAYBE: Disable color if not outputting to a terminal. (OTOH, the
|
||||
# colorized output is helpful in CI logs, and I don't know if,
|
||||
# e.g. GitHub Actions logging pretends to be a terminal.)
|
||||
color=true
|
||||
|
||||
# TODO: Using the current directory (i.e. a package's repo root directory) in
|
||||
# load-path can cause weird errors in case of--you guessed it--stale .ELC files,
|
||||
# the zombie problem that just won't die. It's incredible how many different ways
|
||||
# this problem presents itself. In this latest example, an old .ELC file, for a
|
||||
# .EL file that had since been renamed, was present on my local system, which meant
|
||||
# that an example .EL file that hadn't been updated was able to "require" that .ELC
|
||||
# file's feature without error. But on another system (in this case, trying to
|
||||
# setup CI using GitHub Actions), the old .ELC was not present, so the example .EL
|
||||
# file was not able to load the feature, which caused a byte-compilation error.
|
||||
|
||||
# In this case, I will prevent such example files from being compiled. But in
|
||||
# general, this can cause weird problems that are tedious to debug. I guess
|
||||
# the best way to fix it would be to actually install the repo's code as a
|
||||
# package into the sandbox, but doing that would require additional tooling,
|
||||
# pulling in something like Quelpa or package-build--and if the default recipe
|
||||
# weren't being used, the actual recipe would have to be fetched off MELPA or
|
||||
# something, which seems like getting too smart for our own good.
|
||||
|
||||
# TODO: Emit a warning if .ELC files that don't match any .EL files are detected.
|
||||
load_path="."
|
||||
|
||||
# TODO: Option to not byte-compile test files.
|
||||
project_byte_compile_files=($(project-elisp-files))
|
||||
project_source_files=($(project-source-files))
|
||||
project_test_files=($(project-test-files))
|
||||
|
||||
package_initialize_file="$(elisp-package-initialize-file)"
|
||||
temp_paths+=("$package_initialize_file")
|
||||
|
||||
# ** Colors
|
||||
|
||||
COLOR_off='\e[0m'
|
||||
|
|
@ -537,9 +524,24 @@ COLOR_purple='\e[0;35m'
|
|||
COLOR_cyan='\e[0;36m'
|
||||
COLOR_white='\e[0;37m'
|
||||
|
||||
# * Project files
|
||||
|
||||
# MAYBE: Option to not byte-compile test files. (OTOH, byte-compiling reveals many
|
||||
# errors that would otherwise go unnoticed, so it's worth it to fix the warnings.)
|
||||
project_source_files=($(project-source-files))
|
||||
project_test_files=($(project-test-files))
|
||||
project_byte_compile_files=("${project_source_files[@]}" "${project_test_files[@]}")
|
||||
|
||||
package_initialize_file="$(elisp-package-initialize-file)"
|
||||
temp_paths+=("$package_initialize_file")
|
||||
|
||||
# * Args
|
||||
|
||||
args=$(getopt -n "$0" -o dhi:svf:C -l auto-install,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,sandbox -- "$@") || { usage; exit 1; }
|
||||
args=$(getopt -n "$0" \
|
||||
-o dhi:sS:vf:C \
|
||||
-l auto-install,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,sandbox,sandbox-dir: \
|
||||
-- "$@") \
|
||||
|| { usage; exit 1; }
|
||||
eval set -- "$args"
|
||||
|
||||
while true
|
||||
|
|
@ -566,6 +568,11 @@ do
|
|||
-s|--sandbox)
|
||||
sandbox=true
|
||||
;;
|
||||
-S|--sandbox-dir)
|
||||
shift
|
||||
sandbox=true
|
||||
sandbox_dir="$1"
|
||||
;;
|
||||
-v|--verbose)
|
||||
((verbose++))
|
||||
;;
|
||||
|
|
@ -609,16 +616,21 @@ then
|
|||
# Setup sandbox.
|
||||
type emacs-sandbox.sh &>/dev/null || die "emacs-sandbox.sh not found."
|
||||
|
||||
config_dir=$(mktemp -d) || die "Unable to make temp dir."
|
||||
temp_paths+=("$config_dir")
|
||||
if ! [[ $sandbox_dir ]]
|
||||
then
|
||||
# No sandbox dir specified: make temp dir and remove it on exit.
|
||||
sandbox_dir=$(mktemp -d) || die "Unable to make temp dir."
|
||||
temp_paths+=("$sandbox_dir")
|
||||
fi
|
||||
|
||||
sandbox_basic_args=(
|
||||
-d "$config_dir"
|
||||
-d "$sandbox_dir"
|
||||
)
|
||||
[[ $debug ]] && sandbox_basic_args+=(--debug)
|
||||
|
||||
if [[ $auto_install ]]
|
||||
then
|
||||
# Add dependencies to package install list.
|
||||
deps=($(dependencies))
|
||||
debug "Installing dependencies: ${deps[@]}"
|
||||
|
||||
|
|
@ -628,11 +640,14 @@ then
|
|||
done
|
||||
fi
|
||||
|
||||
if [[ ${sandbox_install_packages_args[@]} ]]
|
||||
then
|
||||
# Initialize the sandbox (installs packages once rather than for every rule).
|
||||
emacs_command="emacs-sandbox.sh ${sandbox_basic_args[@]} ${sandbox_install_packages_args[@]} -- "
|
||||
debug "Initializing sandbox..."
|
||||
|
||||
run_emacs || die "Unable to initialize sandbox."
|
||||
fi
|
||||
|
||||
# After the sandbox is initialized and packages are installed, set the command
|
||||
# to prevent the package lists from being refreshed on each invocation.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue