Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Show who is requiring

88 views
Skip to first unread message

Sebastien Vauban

unread,
Nov 16, 2012, 6:08:43 PM11/16/12
to
Hello,

I'd like to advice `require' in order to show which package is making the call
to require another one.

I tried using (current-buffer) to get the name of the "source" package (i.e.,
the one which makes the `require' request), but that's wrong. Any idea how to
get the name of the "caller" package?

Best regards,
Seb

--
Sebastien Vauban

Eli Zaretskii

unread,
Nov 17, 2012, 2:53:00 AM11/17/12
to help-gn...@gnu.org
> From: "Sebastien Vauban" <wxhgmq...@spammotel.com>
> Date: Sat, 17 Nov 2012 00:08:43 +0100
> I'd like to advice `require' in order to show which package is making the call
> to require another one.
>
> I tried using (current-buffer) to get the name of the "source" package (i.e.,
> the one which makes the `require' request), but that's wrong. Any idea how to
> get the name of the "caller" package?

Doesn't "C-h f require RET" give you that information?

Bastien

unread,
Nov 17, 2012, 3:29:01 AM11/17/12
to Sebastien Vauban, public-help-gnu-...@plane.gmane.org


Hi Sébastien,

"Sebastien Vauban"
<wxhgmqzgwmuf-geNe...@public.gmane.org> writes:

> I tried using (current-buffer) to get the name of the "source" package (i.e.,
> the one which makes the `require' request), but that's wrong. Any idea how to
> get the name of the "caller" package?

Check this out:

C-h f find-lisp-object-file-name RET

HTH,

--
Bastien


Sebastien Vauban

unread,
Nov 17, 2012, 4:41:29 AM11/17/12
to
Hi Eli and Bastien,

Bastien wrote:
> Sebastien Vauban writes:
>
>> I tried using (current-buffer) to get the name of the "source" package
>> (i.e., the one which makes the `require' request), but that's wrong. Any
>> idea how to get the name of the "caller" package?
>
> Check this out:
>
> C-h f find-lisp-object-file-name RET

I wasn't clear enough: what I'd like is that if, for example, helm-m-x.el contains
a require of helm.el, then (with my advice'd require), when requiring
helm-m-x, I'd see in the Messages:

helm-m-x.el is now requiring helm.el

So, I'm interested in the name of the package which contains require's of
other packages (and executes them).

That could be done statically on the file system, but I'd like to see the view
of "who called who" for my Emacs session.

Am I clearer in what I'm searching for?

Oleksandr Gavenko

unread,
Nov 17, 2012, 4:43:57 AM11/17/12
to help-gn...@gnu.org
On 2012-11-17, Bastien wrote:

>> I tried using (current-buffer) to get the name of the "source" package
>> (i.e., the one which makes the `require' request), but that's wrong. Any
>> idea how to get the name of the "caller" package?
>
> Check this out:
>
> C-h f find-lisp-object-file-name RET

Why instead of:

(symbol-file 'c-mode)

use:

(find-lisp-object-file-name 'c-mode (symbol-function 'c-mode))

??

--
Best regards!


Bastien

unread,
Nov 17, 2012, 5:05:56 AM11/17/12
to Oleksandr Gavenko, help-gn...@gnu.org
Oleksandr Gavenko <gave...@gmail.com> writes:

> Why instead of:
>
> (symbol-file 'c-mode)
>
> use:
>
> (find-lisp-object-file-name 'c-mode (symbol-function 'c-mode))

Indeed.

> ??

You don't need the double "??" in all your emails.

--
Bastien

Eli Zaretskii

unread,
Nov 17, 2012, 5:11:09 AM11/17/12
to help-gn...@gnu.org
> From: "Sebastien Vauban" <wxhgmq...@spammotel.com>
> Date: Sat, 17 Nov 2012 10:41:29 +0100
>
> I wasn't clear enough: what I'd like is that if, for example, helm-m-x.el contains
> a require of helm.el, then (with my advice'd require), when requiring
> helm-m-x, I'd see in the Messages:
>
> helm-m-x.el is now requiring helm.el
>
> So, I'm interested in the name of the package which contains require's of
> other packages (and executes them).

And I will repeat what I asked: doesn't "C-h f require" gives you that
information?

Let me put here what it shows, with suitably emphasized portions that
should tell you what to do:

(require FEATURE &optional FILENAME NOERROR)

If feature FEATURE is not loaded, load it from FILENAME.
If FEATURE is not a member of the list `features', then the feature
is not loaded; so load the file FILENAME.
^^^^^^^^^^^^^^^^^^^^^^
If FILENAME is omitted, the printname of FEATURE is used as the file name,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
and `load' will try to load this name appended with the suffix `.elc' or
`.el', in that order. The name without appended suffix will not be used.
See `get-load-suffixes' for the complete list of suffixes.
If the optional third argument NOERROR is non-nil,
then return nil if the file is not found instead of signaling an error.
Normally the return value is FEATURE.
The normal messages at start and end of loading FILENAME are suppressed.

Since your defadvice has access to all the arguments of the call to
'require, you should be trivially able to see if FILENAME is
specified, and if not, use something like (symbol-name FEATURE) to
retrieve the file name.

Am I missing something?

Thien-Thi Nguyen

unread,
Nov 17, 2012, 5:38:37 AM11/17/12
to Eli Zaretskii, help-gn...@gnu.org
() Eli Zaretskii <el...@gnu.org>
() Sat, 17 Nov 2012 12:11:09 +0200

Am I missing something?

Yes, the OP seeks a way to find "a" when a.el says ‘(require 'b)’.
That is, both vertices of the edge.

Probably ‘load-history’ is fine to walk for after-the-fact, and
‘current-buffer’ to chase for at-the-moment.

--
Thien-Thi Nguyen ..................................... GPG key: 4C807502
. NB: ttn at glug dot org is not me .
. (and has not been since 2007 or so) .
. ACCEPT NO SUBSTITUTES .
........... please send technical questions to mailing lists ...........

Eli Zaretskii

unread,
Nov 17, 2012, 6:02:47 AM11/17/12
to help-gn...@gnu.org
> From: Thien-Thi Nguyen <t...@gnuvola.org>
> Cc: help-gn...@gnu.org
> Date: Sat, 17 Nov 2012 11:38:37 +0100
>
> Am I missing something?
>
> Yes, the OP seeks a way to find "a" when a.el says ‘(require 'b)’.
> That is, both vertices of the edge.
>
> Probably ‘load-history’ is fine to walk for after-the-fact, and
> ‘current-buffer’ to chase for at-the-moment.

Sorry, I just couldn't imagine that someone will not know about
buffer-file-name and current-buffer.


Thien-Thi Nguyen

unread,
Nov 17, 2012, 7:00:34 AM11/17/12
to Eli Zaretskii, help-gn...@gnu.org
() Eli Zaretskii <el...@gnu.org>
() Sat, 17 Nov 2012 13:02:47 +0200

Sorry, I just couldn't imagine that someone will not know about
buffer-file-name and current-buffer.

To be fair, guessing those requires knowing something about how ‘load’
works. Emacs is buffer-centric so it ‘load’s by first populating a
buffer then ‘read’ing from it. Guile, as a counter-example, implements
‘load’ by ‘read’ing from a "port". Other systems might mmap(2) or talk
to a daemon or whatever.

I see that (info "(emacs) Lisp Libraries")
says only:

To "load" an Emacs Lisp file, type `M-x load-file'. This command reads
a file name using the minibuffer, and executes the contents of that
file as Emacs Lisp code. It is not necessary to visit the file first;
this command reads the file directly from disk, not from an existing
Emacs buffer.

In (info "(elisp) How Programs Do Loading")
there is a bit more:

Whatever the name under which the file is eventually found, and the
directory where Emacs found it, Emacs sets the value of the variable
`load-file-name' to that file's name.

[...]

When loading a source file (not compiled), `load' performs
character set translation just as Emacs would do when visiting the
file. *Note Coding Systems::.

but again, how ‘load’ actually does its job is never detailed. To my
ears, this is a just omission, and thus OP's question has some merit.

Drew Adams

unread,
Nov 17, 2012, 11:17:41 AM11/17/12
to Sebastien Vauban, help-gn...@gnu.org
Seb - I understand that you want runtime info. I think, in any case, that this
is a good place to start:

http://emacswiki.org/emacs/LibraryDependencies

In particular, take a look at the code in these libraries:
http://www.emacswiki.org/emacs-en/download/lib-requires.el
http://www.emacswiki.org/emacs/download/elisp-depend.el

HTH.


Stefan Monnier

unread,
Nov 19, 2012, 9:59:11 AM11/19/12
to
> I tried using (current-buffer) to get the name of the "source" package
> (i.e., the one which makes the `require' request), but that's
> wrong. Any idea how to get the name of the "caller" package?

IIUC you want load-file-name.


Stefan

Ludwig, Mark

unread,
Nov 19, 2012, 10:18:17 AM11/19/12
to Stefan Monnier, help-gn...@gnu.org
> From: Stefan Monnier
> Sent: Monday, November 19, 2012 8:59 AM
> To: help-gn...@gnu.org
> Subject: Re: Show who is requiring
How does this report the names of files that require another package?

Perhaps you assume the OP's scenario is that he has already loaded the packages that require?
My understanding of the request is the inverse: for some package PKG, he wants to find where it is used.
The OP wants a list of other packages that require PKG.

For example, from the 23.1 Lisp source, we have (grep -n):

fringe.el:162: :require 'fringe
fringe.el:262:(provide 'fringe)
menu-bar.el:874: (require 'fringe)
menu-bar.el:886: (require 'fringe)
menu-bar.el:898: (require 'fringe)
ruler-mode.el:114:(require 'fringe)

If the OP is interested in the fringe package, he is looking for a way to be told definitively that menu-bar.el and ruler-mode.el depend on it.

Cheers,
Mark


Kevin Rodgers

unread,
Nov 19, 2012, 10:54:28 AM11/19/12
to help-gn...@gnu.org
On 11/16/12 4:08 PM, Sebastien Vauban wrote:
> Hello,
>
> I'd like to advice `require' in order to show which package is making the call
> to require another one.
>
> I tried using (current-buffer) to get the name of the "source" package (i.e.,
> the one which makes the `require' request), but that's wrong. Any idea how to
> get the name of the "caller" package?

I think the `load-file-name' variable has that information.

--
Kevin Rodgers
Denver, Colorado, USA


Stefan Monnier

unread,
Nov 19, 2012, 11:03:59 AM11/19/12
to
>> > I tried using (current-buffer) to get the name of the "source" package
>> > (i.e., the one which makes the `require' request), but that's
>> > wrong. Any idea how to get the name of the "caller" package?
>> IIUC you want load-file-name.
> How does this report the names of files that require another package?

IIUC he has put an advice on `require', so in this advice,
`load-file-name' should contain the name of the code that's calling the
`require'.


Stefan

Sebastien Vauban

unread,
Nov 19, 2012, 11:13:31 AM11/19/12
to
Hello Stefan and all,
From your description, that's exactly what I'm after. I'll test and report.

My ultimate goal is to generate a Dotty graph of "who required who" among the
different packages I'm directly, or indirectly, requiring.

So, I need to output relations such as:

a.el -> b.el
b.el -> c.el
b.el -> d.el
...

Thanks to Drew and to Thien-Thi to point me to `load-history' as well... Quite
complex to read, and not exactly the same, but clearly useful.

Sebastien Vauban

unread,
Dec 7, 2012, 4:57:02 PM12/7/12
to
Hello Stefan and all,

"Sebastien Vauban" wrote:
> Stefan Monnier wrote:
>>>>> I tried using (current-buffer) to get the name of the "source" package
>>>>> (i.e., the one which makes the `require' request), but that's wrong. Any
>>>>> idea how to get the name of the "caller" package?
>>>>
>>>> IIUC you want load-file-name.
>>>
>>> How does this report the names of files that require another package?
>>
>> IIUC he has put an advice on `require', so in this advice, `load-file-name'
>> should contain the name of the code that's calling the `require'.
>
> From your description, that's exactly what I'm after. I'll test and report.

For some unknown reason (I mean: to me), `load-file-name' is sometimes nil,
like if the requires came out of nowhere:

--8<---------------cut here---------------start------------->8---
Loading Minimal Emacs...
.emacs-minimal -> help-fns... Done [3 times]
Loading Minimal Emacs... Done
org -> calendar...
calendar -> cal-menu...
cal-menu -> calendar... Done
calendar -> cal-menu... Done
org -> calendar... Done
org -> find-func... Done
org -> format-spec... Done
org -> ob-emacs-lisp...
ob-emacs-lisp -> ob...
ob -> ob-eval... Done
ob -> org-macs... Done
ob -> org-compat...
org-compat -> org-macs... Done
ob -> org-compat... Done
ob-emacs-lisp -> ob... Done
org -> ob-emacs-lisp... Done
org -> org-compat... Done
org -> outline... Done
org -> noutline... Done
org -> time-date... Done
org -> easymenu... Done
org -> overlay... Done
org -> org-macs... Done
org -> org-entities...
org-entities -> org-macs... Done
org -> org-entities... Done
org -> org-faces...
org-faces -> org-macs... Done
org-faces -> org-compat... Done
org -> org-faces... Done
org -> org-list...
org-list -> org-macs... Done
org-list -> org-compat... Done
org -> org-list... Done
org -> org-pcomplete...
org-pcomplete -> org-macs... Done
org-pcomplete -> org-compat... Done
org-pcomplete -> pcomplete...
pcomplete -> comint...
comint -> ring... Done
comint -> ansi-color... Done
comint -> regexp-opt... Done
pcomplete -> comint... Done
org-pcomplete -> pcomplete... Done
org -> org-pcomplete... Done
org -> org-src...
org-src -> org-macs... Done
org-src -> org-compat... Done
org-src -> ob-keys...
ob-keys -> ob... Done
org-src -> ob-keys... Done
org-src -> ob-comint...
ob-comint -> ob... Done
ob-comint -> org-compat... Done
ob-comint -> comint... Done
org-src -> ob-comint... Done
org -> org-src... Done
org -> org-footnote...
org-footnote -> org-macs... Done
org-footnote -> org-compat... Done
org -> org-footnote... Done
org -> ob... Done
org -> ob-table...
ob-table -> ob... Done
org -> ob-table... Done
org -> ob-lob...
ob-lob -> ob... Done
ob-lob -> ob-table... Done
org -> ob-lob... Done
org -> ob-ref...
ob-ref -> ob... Done
org -> ob-ref... Done
org -> ob-tangle...
ob-tangle -> ob... Done
ob-tangle -> org-src... Done
org -> ob-tangle... Done
org -> ob-comint... Done
org -> ob-keys... Done
org -> font-lock... Done
org -> help-fns... Done [2 times]
org -> bytecomp...
bytecomp -> backquote... Done
bytecomp -> macroexp... Done
bytecomp -> cconv... Done
org -> bytecomp... Done
org -> warnings... Done
byte-opt -> bytecomp... Done
byte-opt -> macroexp... Done
org -> help-fns... Done [3 times]
nil? -> org-bbdb...
org-bbdb -> org... Done
nil? -> org-bbdb... Done
nil? -> org-bibtex...
org-bibtex -> org... Done
org-bibtex -> bibtex...
bibtex -> button... Done
org-bibtex -> bibtex... Done
org-bibtex -> org-compat... Done
nil? -> org-bibtex... Done
nil? -> org-docview...
org-docview -> org... Done
nil? -> org-docview... Done
nil? -> org-gnus...
org-gnus -> org... Done
org-gnus -> gnus-util...
gnus-util -> time-date... Done
org-gnus -> gnus-util... Done
nil? -> org-gnus... Done
nil? -> org-info...
org-info -> org... Done
nil? -> org-info... Done
nil? -> org-jsinfo...
org-jsinfo -> org-exp...
org-exp -> org... Done
org-exp -> org-macs... Done
org-exp -> org-agenda...
org-agenda -> org... Done
org-agenda -> org-macs... Done
org-exp -> org-agenda... Done
org-exp -> org-exp-blocks...
org-exp-blocks -> find-func... Done
org-exp-blocks -> org-compat... Done
org-exp -> org-exp-blocks... Done
org-exp -> ob-exp...
ob-exp -> ob... Done
ob-exp -> org-exp-blocks... Done
org-exp -> ob-exp... Done
org-exp -> org-src... Done
org-jsinfo -> org-exp... Done
org-jsinfo -> org-html...
org-html -> org-exp... Done
org-html -> format-spec... Done
org-jsinfo -> org-html... Done
nil? -> org-jsinfo... Done
nil? -> org-irc...
org-irc -> org... Done
nil? -> org-irc... Done
nil? -> org-mew...
org-mew -> org... Done
nil? -> org-mew... Done
nil? -> org-mhe...
org-mhe -> org... Done
nil? -> org-mhe... Done
nil? -> org-rmail...
org-rmail -> org... Done
nil? -> org-rmail... Done
nil? -> org-vm...
org-vm -> org... Done
nil? -> org-vm... Done
nil? -> org-w3m...
org-w3m -> org... Done
nil? -> org-w3m... Done
nil? -> org-wl...
org-wl -> org... Done
nil? -> org-wl... Done
OVERVIEW
Loading vc-svn...done
nil? -> vc-svn... Done
--8<---------------cut here---------------end--------------->8---

The above trace is obtained with the following minimal Emacs file:

--8<---------------cut here---------------start------------->8---
(message "Loading Minimal Emacs...")

(defadvice require (around require-around)
"Leave a trace of packages being loaded."
(let* ((feature (ad-get-arg 0))
(require-depth (or (and (boundp 'require-depth) require-depth)
0))
(prefix (concat (make-string (* 2 require-depth) ? ) "")))
(cond ((featurep feature)
(message "%s%s -> %s... Done" ;; already loaded
prefix
(if load-file-name
(file-name-base load-file-name)
"nil?")
feature)
(setq ad-return-value feature))
(t
(let ((lvn/time-start))
(message "%s%s -> %s..."
prefix
(if load-file-name
(file-name-base load-file-name)
"nil?")
feature)
(setq lvn/time-start (float-time))
(let ((require-depth (1+ require-depth)))
ad-do-it)
(message "%s%s -> %s... Done"
prefix
(if load-file-name
(file-name-base load-file-name)
"nil?")
feature))))))

(ad-activate 'require)

(message "Loading Minimal Emacs... Done")
--8<---------------cut here---------------end--------------->8---

launched with the command `emacs -q -l .emacs-minimal.el'.

In the above session, I just opened a random `.org' file...

Any idea on (how to get) who is requiring packages such as:

- org-bbdb,
- org-bibtex,
- org-docview,
- org-gnus,
- org-info,
- org-jsinfo,
- org-irc,
- org-mew,
- org-mhe,
- org-rmail,
- org-vm,
- org-w3m,
- org-wl, and
- vc-svn?

Writing it down, I just realize that all the `org-*' packages here are the
ones in `org-modules'. In fact, that's `org.el' who's requiring them:

--8<---------------cut here---------------start------------->8---
(defun org-load-modules-maybe (&optional force)
"Load all extensions listed in `org-modules'."
(when (or force (not org-modules-loaded))
(mapc (lambda (ext)
(condition-case nil (require ext)
(error (message "Problems while trying to load feature `%s'" ext))))
org-modules)
(setq org-modules-loaded t)))
--8<---------------cut here---------------end--------------->8---

Why isn't `load-file-name' set to `org.el' in this case, then?

No idea, neither, for `vc-svn'... Who required it? Who's hidden under the
alias nil, here?

Sebastien Vauban

unread,
Dec 7, 2012, 5:31:37 PM12/7/12
to
Hello,

"Sebastien Vauban" wrote:
> I tried using (current-buffer) to get the name of the "source" package
> (i.e., the one which makes the `require' request), but that's wrong. Any
> idea how to get the name of the "caller" package?

You could be interested by the first version of my "package tree":

http://tinypic.com/r/10hr9c7/6

2 observations for which I don't know if it's normal or not:

- calendar requires cal-menu, and vice versa
- dired+ requires itself

Sebastien Vauban

unread,
Dec 7, 2012, 5:54:56 PM12/7/12
to
Hello,

"Sebastien Vauban" wrote:
> "Sebastien Vauban" wrote:
>> I tried using (current-buffer) to get the name of the "source" package
>> (i.e., the one which makes the `require' request), but that's wrong. Any
>> idea how to get the name of the "caller" package?
>
> You could be interested by the first version of my "package tree":
>
> http://tinypic.com/r/10hr9c7/6

You can download it in PDF format from
http://issuu.com/svauban/docs/package_tree.

Stefan Monnier

unread,
Dec 10, 2012, 8:57:43 PM12/10/12
to help-gn...@gnu.org
> For some unknown reason (I mean: to me), `load-file-name' is sometimes nil,
> like if the requires came out of nowhere:

A require can happen when load-file-name is nil if that require is not
at some top-level in a file, but is instead inside a function.

> - vc-svn?

For this one it's vc-find-backend-function in vc-hooks.el which loads VC
backends on-demand.

> Why isn't `load-file-name' set to `org.el' in this case, then?

Because org.el has finished loading before org-load-modules-maybe is run.

> - calendar requires cal-menu, and vice versa
> - dired+ requires itself

"Recursive" requires are not very common but do happen every once in
a while. It's usually better to restructure your code to avoid them,
but some authors don't want to bother (and the result is not always
really better because the resulting structure is a result of details of
implementation).

At other times it's because some functions defined are used during
compilation of the same file (e.g. they're used during
macro-expansion). You can sometimes avoid self-requiring by using
eval-and-compile instead (as does eieio.el, which uses eval-and-compile
on a very large part of itself).


Stefan


0 new messages