[FBT] Create fbt package and add fpkg support to it

Signed-off-by: Sameer Rahmani <lxsameer@gnu.org>
This commit is contained in:
Sameer Rahmani 2020-04-16 22:38:20 +01:00
parent d09a6c450a
commit e3c9dbf72c
10 changed files with 498 additions and 129 deletions

3
.gitignore vendored
View File

@ -24,4 +24,5 @@ lib/**/*.elc
tmp/
test-runner/
.fpkg/
/fg42-wm
/fg42-wm
.fpkg-v3

View File

@ -0,0 +1,16 @@
## Summary
<Describe your changes here including your rational, the problem, your solution vice versa>
### QA
<Describe the steps necessary to test your changes>
### Checklist
[ ] Is the linter happy?
[ ] Is the byte compiler happy (no warning) ?
[ ] Is it backward compatible
[ ] Did you document your changes ?
[ ] Did you update the CHANGELOG ?
[ ] Did you actually test your changes ?

137
bin/fbt Executable file
View File

@ -0,0 +1,137 @@
:;exec emacs --no-site-file --no-site-lisp -batch -l "$0" -f main "$(cd "$(dirname "$0")/.." >/dev/null 2>&1 ; pwd -P)" "$@"
;;; FGBuildTool --- The build tool for FG42
;;
;; Copyright (c) 2010-2020 Sameer Rahmani <lxsameer@gnu.org>
;;
;; Author: Sameer Rahmani <lxsameer@gnu.org>
;; URL: https://gitlab.com/FG42/FG42
;; Version: 3.0.0
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;
;;; Commentary:
;; FG42 Build Tool for FBT for short is a tool on top of Emacs to build
;; FG42. To learn how to use it run it via a shell.
;;
;;; Code:
(defvar FG42-VERSION "3.0.0-snapshot"
"The version number of the current build of FG42.")
(defconst fbt-usage "
Usage:
fbt [PARAMS] COMMAND [...]
COMMANDS:
compile [DIR] - Compiles the given DIR to bytecodes (default: \"core\").
build - Builds FG42 by compiling the code and installing dependencies.
clean [DIRS] - Clean up the given list of directories (default: \"code\" \"fbt\").
fpkg [...] - The CLI insterface to FPKG (FG42 Package manager)
lint [DIR] - Run the ELisp linter on the files on the given DIR.
PARAMS:
:d - Turns on the debug mode.
:e expr - Run the given `expr' before any operation.
By default FBT loads the `system.el' file from the root path of `FG42' and looks
for a system with the name `FG42' to use it as the source for the build operations.
You can change this behaviour by running following command:
$ fbt :e '(setq fg42-system 'SOMESYSTEM fg42-system-path \"path/to/a/elisp/file.el\"))' COMMAND...
This way FBT will load an elisp file at \"path/to/a/elisp/file.el\" and looks for a system
called `SOMESYSTEM' in it as the source system for the build operations.
")
(defun read-args (args)
"Parse the given ARGS and return a list of params and args.
The only parameter at the moment is `-e' which basically gets a string
of elisp and eval it before the commant. The return value is a list
which the first element is the string to evaluate and the second one
is the rest of the arguments."
(if (member ":d" args)
(setq debug-on-error t)
(delete ":d" args))
(if (string= (car args) ":e")
(list (cadr args) (cddr args))
(list nil args)))
(defun todo (dir)
"Extract the TODO tags from the comments in the given DIR."
(message "TBD"))
(defun print-help (command)
"Print out a usage instructions and print out the invalid msg for COMMAND."
(when command
(warn "I don't know about '%s' command.\n" command))
(message fbt-usage))
(defun main ()
"Execute a subcommand by looking into input arguments of the script."
(message (version))
(message "\nFG42 Build tool v%s\n\n" FG42-VERSION)
(let* ((fg42-home (car command-line-args-left))
(parsed-args (read-args (cdr command-line-args-left)))
(eval-string (car parsed-args))
(command (caadr parsed-args))
(args (cdadr parsed-args)))
;; FG42 Needs this env var to know where had it been installed
(setenv "FG42_HOME" fg42-home)
(setenv "FG42_VERSION" FG42-VERSION)
(defvar fg42-system-path (concat (file-name-as-directory fg42-home) "system"))
(defvar fg42-system 'FG42)
(add-to-list 'load-path (concat (file-name-as-directory fg42-home) "core"))
(add-to-list 'load-path (concat (file-name-as-directory fg42-home) "fbt"))
;; Load the default system without user configurations
(when eval-string
(eval (car (read-from-string eval-string))))
(load fg42-system-path)
(require 'fbt/utils)
(require 'fbt/compile)
(require 'fbt/lint)
(require 'fbt/fpkg)
(require 'fbt/build)
(let ((system (symbol-value fg42-system)))
;; Add the fpkg path to the load path. For the sake of `straight.el'.
;; This way installed packages will be accessable for build tools as well.
(fpt-fpkg/initialize-load-path system)
(cond
((string= command "fpkg") (funcall #'fbt-fpkg system args))
((string= command "lint") (funcall #'lint (or (car args) "core")))
((string= command "compile") (funcall #'fbt-compile/compile (or (car args) "core")))
((string= command "clean") (funcall #'fbt-build/clean (or args '("core" "fbt"))))
((string= command "build") (funcall #'build args))
(t (print-help command))))))
;; Local Variables:
;; mode: emacs-lisp
;; End:
;;; fbt ends here

View File

@ -1,6 +1,6 @@
#! /bin/sh
export FG42_HOME="$(cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P)"
export FG42_HOME="$(cd "$(dirname "$0")/.." >/dev/null 2>&1 ; pwd -P)"
FG42_WM=false emacs --name FG42 \
--no-site-file --no-site-lisp --no-splash --title FG42 \

127
fbt
View File

@ -1,127 +0,0 @@
:;exec emacs --no-site-file --no-site-lisp -batch -l "$0" -f main "$(cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P)" "$@"
;;; FGBuildTool --- The build tool for FG42
;;
;; Copyright (c) 2010-2020 Sameer Rahmani <lxsameer@gnu.org>
;;
;; Author: Sameer Rahmani <lxsameer@gnu.org>
;; URL: https://gitlab.com/FG42/FG42
;; Version: 3.0.0
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;
;;; Commentary:
;;; Code:
(defvar FG42_VERSION "3.0.0-snapshot"
"The version number of the current build of FG42.")
(defun ->path (dir)
"Return the absolute path to the given DIR with respect to FG42_HOME."
(concat (getenv "FG42_HOME") (format "/%s" dir)))
(defun el-files-in (dir)
"Return a list of elisp files in the given DIR."
(split-string (shell-command-to-string
(format "find %s -iname \"*.el\"" (->path dir))) "\n" t))
(defun lint (dir)
"Run linter on all the elisp files in the given DIR."
(let ((files (el-files-in dir)))
(if files
(dolist (file files)
;; TODO: Setup flycheck here and use it to lint the elisp file.
;; tried to use flymake but it doesn't let you do it manually
(with-temp-buffer
(insert-file-contents file)))
(error "Couldn't find any elisp files"))))
(defun compile (dir)
"Compile all the elisp files in the given DIR regardless of timestamp.
The DIR should be relative to FG42_HOME."
(let ((target (->path dir)))
(message "Compiling '%s'..." target)
(add-to-list 'load-path target)
(byte-recompile-directory target 0 t)))
(defun build (&rest params)
"Compile the core and install the dependencies with the given PARAMS."
(compile "core"))
(defun todo (dir)
"Extract the TODO tags from the comments in the given DIR."
(message "TBD"))
(defun fpkg-init (params)
"Setup fpkg repository with the given PARAMS."
(require 'fg42/fpkg/core)
(fg42-fpkg/initialize FG42))
(defun print-fpkg-help (command)
"Print the usage for fpkg and the possible wrong COMMAND."
(message "Usage:\n")
(message "init - Setup the fpkg repository"))
(defun fpkg (params)
"The main interface to `fpkg' subcommand and PARAMS."
(let ((subcommand (car args))
(args (cdr params)))
(cond
((string= subcommand "init") (funcall #'fpkg-init args))
(t (print-fpkg-help subcommand)))))
(defun print-help (command)
"Print out a usage instructions and print out the invalid msg for COMMAND."
(when command
(warn "I don't know about '%s' command.\n" command))
(message "Usage:\n")
(message "compile [DIR] - Compiles the given DIR to bytecodes (default: \"core\")")
(message "build - Builds FG42 by compiling the code and installing dependencies."))
(defun main ()
"Execute a subcommand by looking into input arguments of the script."
(message (version))
(message "\nFG42 Build tool v%s\n\n" FG42_VERSION)
(let ((fg42-home (car command-line-args-left))
(command (cadr command-line-args-left))
(args (cddr command-line-args-left)))
;; FG42 Needs this env var to know where had it been installed
(setenv "FG42_HOME" fg42-home)
(setenv "FG42_VERSION" FG42_VERSION)
(add-to-list 'load-path (concat (file-name-as-directory fg42-home) "core"))
(load (concat (file-name-as-directory (getenv "FG42_HOME")) "system"))
(cond
((string= command "fpkg") (funcall #'fpkg args))
((string= command "lint") (funcall #'lint (or (car args) "core")))
((string= command "compile") (funcall #'compile (or (car args) "core")))
((string= command "build") (funcall #'build args))
(t (print-help command)))))
;; Local Variables:
;; mode: emacs-lisp
;; End:
;;; fbt ends here

52
fbt/fbt/build.el Normal file
View File

@ -0,0 +1,52 @@
;;; FGBuildTool --- The build tool for FG42
;;
;; Copyright (c) 2010-2020 Sameer Rahmani <lxsameer@gnu.org>
;;
;; Author: Sameer Rahmani <lxsameer@gnu.org>
;; URL: https://gitlab.com/FG42/FG42
;; Version: 3.0.0
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;
;;; Commentary:
;;; Code:
(require 'fbt/utils)
(require 'fbt/compile)
(defun fbt-build/-clean (dir)
"Clean up all the elc files from the given DIR."
(let ((elcs (elc-files-in dir)))
(when elcs
(message
(shell-command-to-string
(format "rm -v %s" (apply #'concat
(mapcar (lambda (x) (format " %s" x)) elcs))))))))
(defun fbt-build/clean (dirs)
"Clean the given DIRS from elc files."
(mapc #'fbt-build/-clean dirs))
(defun fbt-build/build (&rest params)
"Compile the core and install the dependencies with the given PARAMS."
(fbt-compile/compile "core"))
(provide 'fbt/build)
;;; build.el ends here

41
fbt/fbt/compile.el Normal file
View File

@ -0,0 +1,41 @@
;;; FGBuildTool --- The build tool for FG42
;;
;; Copyright (c) 2010-2020 Sameer Rahmani <lxsameer@gnu.org>
;;
;; Author: Sameer Rahmani <lxsameer@gnu.org>
;; URL: https://gitlab.com/FG42/FG42
;; Version: 3.0.0
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;
;;; Commentary:
;;; Code:
(require 'fbt/utils)
(defun fbt-compile/compile (dir)
"Compile all the elisp files in the given DIR regardless of timestamp.
The DIR should be relative to FG42_HOME."
(let ((target (->path dir)))
(message "Compiling '%s'..." target)
(add-to-list 'load-path target)
(message "Load path:\n%s\n" (apply #'concat (mapcar (lambda (x) (format "%s\n" x)) load-path)))
(byte-recompile-directory target 0 t)))
(provide 'fbt/compile)
;;; compile.el ends here

150
fbt/fbt/fpkg.el Normal file
View File

@ -0,0 +1,150 @@
;;; FGBuildTool --- The build tool for FG42
;;
;; Copyright (c) 2010-2020 Sameer Rahmani <lxsameer@gnu.org>
;;
;; Author: Sameer Rahmani <lxsameer@gnu.org>
;; URL: https://gitlab.com/FG42/FG42
;; Version: 3.0.0
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;
;;; Commentary:
;;; Code:
(require 'fg42/system/core)
(require 'fg42/system/api)
(defvar bootstrap-version nil
"`straight.el' bootstrap version. Set it in the `system' level, not here.")
(defvar straight-base-dir)
(defvar straight-repository-branch)
(defvar straight-cache-autoloads)
(defvar straight-check-for-modifications)
(defvar straight-enable-package-integration)
(defvar straight-vc-git-default-clone-depth)
(defvar autoload-compute-prefixes)
(defvar straight-fix-org)
(defvar straight-recipe-repositories)
(defvar straight-recipe-overrides)
(defun fbt-fpkg/-set-straight-values (system)
"Set the default values for some of `straight.el' vars for the SYSTEM."
(setq straight-base-dir (fg42-system/fpkg-path system)
straight-repository-branch "develop"
;; Our autoload process is different.
straight-cache-autoloads nil
;; `straight.el' suppose to be a functional pkg manager but it actually
;; allows user to edit libraries in place which we don't like it.
;; We have our own mechanism to allow users extend FG42 so we don't
;; want `straight.el' to handle it. Frankly it reduces the boot time
;; by a lot.
straight-check-for-modifications nil
straight-enable-package-integration nil
;; We don't want `straight.el' to deep clone the dependencies. Some packages
;; might break this way according to `doom-emacs'
straight-vc-git-default-clone-depth 1
;; We have our own autoload system.
autoload-compute-prefixes nil
straight-fix-org nil))
(defun fbt-fpkg/-install-core-dependencies (system)
"Install the core dependencies of the given SYSTEM.
Core dependencies are thoses packages that the system itself is depends on
and not the extensions."
(mapc #'straight-use-recipes (fg42-system/core-dependencies system)))
(defun fbt-fpkg/initialize (system)
"Initilize the package manager for the given SYSTEM.
Basically fpkg will bootstrap and `straight.el' repositoryu for the given
SYSTEM by fetching the required values from it. Including the path to the
target directory."
(unless (fboundp 'straight--reset-caches)
(let ((bootstrap-file (concat (fg42-system/fpkg-path system)
"straight/repos/straight.el/bootstrap.el"))
(bootstrap-version (fg42-system/fpkg-backend-version system)))
(make-directory (fg42-system/fpkg-path system) t)
(fbt-fpkg/-set-straight-values system)
(or (require 'straight nil t)
(file-readable-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
(format "https://raw.githubusercontent.com/raxod502/straight.el/%s/install.el"
straight-repository-branch)
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp))
(load bootstrap-file nil t)))
(require 'straight))
(straight--reset-caches)
(fbt-fpkg/-install-core-dependencies system)
(setq straight-recipe-repositories nil
straight-recipe-overrides nil)
;; Someday we might have to use our own fork of `straight.el'
(straight-register-package
`(straight :type git :host github
:repo "raxod502/straight.el"
:files ("straight*.el")
:branch ,straight-repository-branch
:no-byte-compile t))
(fg42-system/fpkg-initilized! system))
(defun fbt-fpkg/initialize-once (system)
"Initilize FPKG only once for the given SYSTEM."
(when (not (fg42-system/fpkg-initilized-p system))
(fbt-fpkg/initialize system)
;; TODO: Install `use-package'
;; (straight-use-package 'use-package)
))
(defun fbt-fpkg/init (system params)
"Setup fpkg repository with the given PARAMS for the given SYSTEM."
(fbt-fpkg/initialize-once system))
(defun fbt-fpkg/print-help (command)
"Print the usage for fpkg and the possible wrong COMMAND."
(message "Usage:\n")
(message "init - Setup the fpkg repository"))
(defun fbt-fpkg (system params)
"The main interface to `fpkg' subcommand and PARAMS for the loaded SYSTEM."
(let ((subcommand (car args))
(args (cdr params)))
(cond
((string= subcommand "init") (funcall #'fbt-fpkg/init system args))
(t (fbt-fpkg/print-help subcommand)))))
(defun fpt-fpkg/initialize-load-path (system)
"Setup the required load paths from the given SYSTEM."
(add-to-list 'load-path
(path-join (fg42-system/fpkg-path system)
"straight/repos/straight.el/")))
(provide 'fbt/fpkg)
;;; fpkg.el ends here

42
fbt/fbt/lint.el Normal file
View File

@ -0,0 +1,42 @@
;;; FGBuildTool --- The build tool for FG42
;;
;; Copyright (c) 2010-2020 Sameer Rahmani <lxsameer@gnu.org>
;;
;; Author: Sameer Rahmani <lxsameer@gnu.org>
;; URL: https://gitlab.com/FG42/FG42
;; Version: 3.0.0
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;
;;; Commentary:
;;; Code:
(require 'fbt/utils)
(defun lint (dir)
"Run linter on all the elisp files in the given DIR."
(let ((files (el-files-in dir)))
(if files
(dolist (file files)
;; TODO: Setup flycheck here and use it to lint the elisp file.
;; tried to use flymake but it doesn't let you do it manually
(with-temp-buffer
(insert-file-contents file)))
(error "Couldn't find any elisp files"))))
(provide 'fbt/lint)
;;; lint.el ends here

57
fbt/fbt/utils.el Normal file
View File

@ -0,0 +1,57 @@
;;; FGBuildTool --- The build tool for FG42
;;
;; Copyright (c) 2010-2020 Sameer Rahmani <lxsameer@gnu.org>
;;
;; Author: Sameer Rahmani <lxsameer@gnu.org>
;; URL: https://gitlab.com/FG42/FG42
;; Version: 3.0.0
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;
;;; Commentary:
;;; Code:
(defun ->path (dir)
"Return the absolute path to the given DIR with respect to FG42_HOME."
(concat (getenv "FG42_HOME") (format "/%s" dir)))
(defun find-files (dir suffix)
"Find all the files with the given SUFFIX in the given DIR."
(split-string (shell-command-to-string
(format "find %s -iname \"*.%s\"" (->path dir) suffix)) "\n" t))
(defun el-files-in (dir)
"Return a list of elisp files in the given DIR."
(find-files dir "el"))
(defun elc-files-in (dir)
"Return a list of elisp files in the given DIR."
(find-files dir "elc"))
;; TODO: Merge this into a unified utils module with the one
;; from `fg42/utils' package
(defun path-join (&rest paths)
"Join the given PATHS."
(apply #'concat
(append
(mapcar #'file-name-as-directory (butlast paths))
(last paths))))
(provide 'fbt/utils)
;;; utils.el ends here