Subject: Fwd: bug#79188: 31.0.50; Cannot build packages installed from VC

From: Przemysław Kryger <[email-masked]>
Date: Thu, 7 Aug 2025 17:53:00 +0100

Forwarding - missed the debbugs
---------- Forwarded message ---------
From: Przemysław Kryger <[email-masked]>
Date: Thu, 7 Aug 2025 at 17:46
Subject: Re: bug#79188: 31.0.50; Cannot build packages installed from VC
To: Philip Kaludercic <[email-masked]>

Philip Kaludercic <[email-masked]> writes:

> Przemyslaw Kryger <[email-masked]> writes:
>
>> I am using package-vc to manage a few pakcages I maintain.  However, in Emacs
>> 31 I observed a couple issues.
>>
>> The first discrepancy with what used to happen on Emacs 30 is when a package is
>> installed from a custom location, no *.elc files are produced.  I don't know
>> what the expected behaviour should be here.
>>
>> In addition to that when I attempt to rebuild such a package with
>> package-vc-rebuild it signals an error, which I believe shouldn't happen,
>> should it?  In this case no *.elc files have been produced nor updated.  Such a
>> workflow used to work on Emacs 30.
>
> Both of these shouldn't happen.

Thank you for taking a look and for confirmation.

[...]
>> (add-to-list 'package-archives '(melpa . "https://melpa.org/packages/"))
>                                    ^
>                                    this should be a string!

Thanks for pointing out.  It seems to work regardless.

>> ;; Just to avoid using existing elpa
>> (setq package-user-dir (expand-file-name "tmp/elpa" (getenv "HOME")))
>
> (Unrelated, but is there a reason you aren't doing (expand-file-name
> "~/tmp/elpa")?)

No, not really.

[...]
>> (let ((pkg-dir (expand-file-name "tmp/helm-projectile" (getenv "HOME"))))
>>   (eval
>>    `(use-package helm-projectile
>>       :vc t
>>       :load-path ,pkg-dir)))
>
> For posterity, this expands to
>
[...]
> which in turn would invoke
>
> (package-vc-install-from-checkout "/tmp/helm-projectile/" "helm-projectile")

I think I reached very similar same conclusion.  When I changed the
installation bit to:

(package-vc-install-from-checkout (expand-file-name "~/tmp/helm-projectile")
                                  "helm-projectile")

both issues still reproduce.  That is after installation there are no
*.elc files to be found and an attempt to rebuild the package with
`package-vc-rebuild' yielded the same stack.

[...]

>> Which yields the following:
>>
>> Debugger entered--Lisp error: (wrong-type-argument stringp nil)
>>   expand-file-name(nil)
>>   vc-file-getprop(nil vc-working-revision)
>>   vc-working-revision(nil)
>>   package-vc--unpack-1(#s(package-desc :name helm-projectile :version (1 3 1)
>> :summary "Helm integration for Projectile" :reqs nil :kind vc :archive nil
>> :dir "/Users/pkryger/tmp/elpa/helm-projectile/" :extras ((:commit
>> . "2ecd3d85b7077f39bb2fefe2227cc46931d4b92b")) :signed nil)
>> "/Users/pkryger/tmp/elpa/helm-projectile/")
>>   package-vc-rebuild(#s(package-desc :name helm-projectile :version (1 3 1) :summary "Helm integration for Projectile" :reqs nil :kind vc :archive nil :dir "/Users/pkryger/tmp/elpa/helm-projectile/" :extras ((:commit . "2ecd3d85b7077f39bb2fefe2227cc46931d4b92b")) :signed nil))
>>   funcall-interactively(package-vc-rebuild #s(package-desc :name helm-projectile :version (1 3 1) :summary "Helm integration for Projectile" :reqs nil :kind vc :archive nil :dir "/Users/pkryger/tmp/elpa/helm-projectile/" :extras ((:commit . "2ecd3d85b7077f39bb2fefe2227cc46931d4b92b")) :signed nil))
>>   call-interactively(package-vc-rebuild record nil)
>>   command-execute(package-vc-rebuild record)
>>   execute-extended-command(nil "package-vc-rebuild" "pack-v-re")
>>   funcall-interactively(execute-extended-command nil "package-vc-rebuild" "pack-v-re")
>>   call-interactively(execute-extended-command nil nil)
>>   command-execute(execute-extended-command)
>
> I couldn't reproduce this stack trace :/  It seems like
> `package-vc--main-file' returned nil.  Can you check what the function
> returns, perhaps using edebug?

I run `package-vc-rebuild' and indeed the `package-vc--main-file' yields
is nil in Edebug instrumented `package-vc--unpack-file-1'.

>> Could these be introduced by  4226eb2b20408ba49787195bbc59bb0066c9c9e4?
>
> That seems reasonable, but in that case we should be able to reproduce
> the issue with a more simple example (especially one that doesn't involve
> use-package, MELPA and missing dependencies).  I tried it out with a
> local package I had lying around and I also noticed that we don't
> byte-compile files anymore!
>
> This should fix the first issue, but it probably won't change anything
> about the latter:
>
> diff --git a/lisp/package/package-vc.el b/lisp/package/package-vc.el
> index db12c76133e..f2c7c460f6d 100644
> --- a/lisp/package/package-vc.el
> +++ b/lisp/package/package-vc.el
> @@ -549,7 +549,14 @@ package-vc--unpack-1
>          ;; FIXME: Compilation should be done as a separate, optional, step.
>          ;; E.g. for multi-package installs, we should first install all packages
>          ;; and then compile them.
> -        (package--compile new-desc)
> +        (package--compile
> +         (if lisp-dir
> +             ;; In case we are installing a package from a local
> +             ;; checkout, we want to compile the checkout, not the
> +             ;; redirection!
> +             (package-desc-create :dir lisp-dir)
> +          new-desc))
> +
>          (when package-native-compile
>            (package--native-compile-async new-desc))
>          ;; After compilation, load again any files loaded by
>

I don't have lisp/pakcage/package-vc.el, but I changed the file name to
lisp/emacs-lisp/packgage-vc.el and the patch applied cleanly.

Below I will use:
- "package source directory" to denote where package
   resides (i.e., ${HOME}/tmp/helm-projectile)
- "package install directory" to denote where package is installed,
  i.e. a result of:

(expand-file-name "helm-projectile" package-user-dir)

After I repeated the experiment the package installed with just
`package-vc-install-from-checkout' (as described above) and
helm-projectile.elc file has been produced into package source
directory.

Not sure if it is important but at this point my `load-path' has only
the package source directory and no package install directory.  I wonder
how the helm-projectile-autoloads.el that has been produced into the
package install directory is going to take part further (in the same and
in a future Emacs session).  Will both directories eventually end up in
the `load-path'?

I removed the compiled helm-projectile.elc from package source directory
and executed:

M-x package-vc-rebuild RET helm-projectile RET

which yield familiar stack trace.

The funny thing is that this time around, the package source directory
had no *.elc files created.  However, the package install directory
contained helm-projectile-autoloads.elc [sic!].

I run the patched `package-vc--unpack-1' and this time `lisp-dir' was nil
(in l.550, where patch has been applied) and 'package-desc--main-file'
yielded nil again.

A question: shouldn't the newly generated *.elc files be put in package
install directory, just like the (non compiled) autoloads file is?  In
my - very naïve - view this would not only remove burden of doubling
`load-path' entries (will that happen) but would also allow for a
complete separation of compiled files between multiple Emacs versions
coexisting on the same machine and reusing the same package source
directories.

Last but not least.  When stepping through `package-vc--unpack-1' under
Edebug for `package-vc-rebuild' I noticed that when it scans for
dependencies it examines files in package install directory.  However,
these files (i.e., helm-projectile-pkg.el and
helm-projectile-autoloads.el) define no dependencies.  Shouldn't the
scan happen for files in the package source directory? I think this was
what Emacs 30 did, due to symlink.