0

I have a relatively large elisp file which starts becoming hard to maintain and I am going to split it into smaller files.

However, for my use case, it would be still convenient to have a single byte-compiled file (because I use it on other systems and it is simpler to copy a single file).

Of course, I could concatenate all source files into a single foo.el file and compile the latter.
Before going this way, I would like to know if there is already a function along the lines of:

(byte-compile-directory foo-dir foo)

generating a single foo.elc from sources in foo-dir.

antonio
  • 1,762
  • 12
  • 24
  • 1
    Why do you want to have a single byte-compiled file? If it's because you only want to require one thing, I think there are better ways of doing that. – Qudit Mar 03 '18 at 21:58
  • @Qudit: Well, for a proper package, you update it on a public repo and you install it on the targets. If you update it, you re-upload and reinstall it on the targets. But, for 2/3 boxes, a single file elc is much more convenient. You can put it on a USB pen and execute `emacs --batch -l ...`. And you can generate a single el file to copy along the elc, better than nx2 files. I find this more practical than zipping/unizipping, but it might be a matter of taste. – antonio Mar 03 '18 at 22:34

2 Answers2

1

There is byte-recompile-directory, but it does not produce a single .elc.

Consider putting the files in the same, dedicated directory; using byte-recompile-directory (after compiling each file once); and zipping the directory into a .zip archive or similar.

One command to byte-compile everything, one command to zip it all up, and one to unzip it at the destination. (And you can combine the first two commands into one.)

Drew
  • 75,699
  • 9
  • 109
  • 225
0

Another possibility below.

se-load-chunks loads all the source files set by the variable chunks.
se-make-single creates the unique source file single.el.
se-compile both makes a single.el and compiles it.

;; compile-help.el

(defvar chunks (list "chunk1"
                     "chunk2"))

(defun se-load-chunks ()
  (mapc (lambda (file) (load (se-make-path file))) chunks))

(defun se-make-single ()
  (let ((dst (se-make-path "single")))
    (if (file-exists-p dst) (delete-file dst))
    (mapc (lambda (chunk)
            (se-append-file dst (se-make-path chunk)))
          chunks)))

(defun se-compile ()
  (interactive)
  (se-make-single)
  (byte-compile-file (se-make-path "single")))

(defun se-append-file (destination source)      
  (with-temp-buffer (insert-file-contents source)
        (append-to-file (point-min) (point-max) destination)))

(defun se-make-path (file)
  "Make path"
  (expand-file-name (concat file ".el")))

Update Implemented @Basil suggestions.
Replace the se- namespace with something better.

antonio
  • 1,762
  • 12
  • 24
  • Some nits: 1) `cd` and `compile` are existing core commands; it is bad to recommend overriding them. Please consider using a namespace prefix as suggested in [`(elisp) Coding Conventions`](https://www.gnu.org/software/emacs/manual/html_node/elisp/Coding-Conventions.html). 2) You should call `(expand-file-name (concat file ".el"))` instead of `concat`ing path components. 3) You can simplify `append-file` by using the built-in `append-to-file`. 4) Please fix the indentation - tabs don't have the same width on SE as they do in Emacs. – Basil Mar 03 '18 at 13:05
  • @Basil: Thanks for your valuable feedback. Everything has been implemented – antonio Mar 03 '18 at 21:41
  • Thanks. You can probably still make `se-append-file` more performant via `(with-temp-buffer (insert-file-contents source) (append-to-file (point-min) (point-max) destination))`; buffer positions are always quicker than building strings. How is `se-load-chunks` relevant? – Basil Mar 03 '18 at 21:49
  • @Basil: Fixing that too. As regards, `se-load`, the idea is that `se-compile` comes into play only when you are finished and you want to execute the elc file elsewhere or want to keep a single el for archiving or sharing. However, when developing and modifying constituent el files, instead of opening and using `eval-buffer` for each file, you use `se-load`. If there is a unique entry point for the package, say `(main)`, that should be called by `se-load` too. – antonio Mar 03 '18 at 22:04