elisp: Declaring Functions
12.15 Telling the Compiler that a Function is Defined
=====================================================
Byte-compiling a file often produces warnings about functions that the
compiler doesn’t know about (Compiler Errors). Sometimes this
indicates a real problem, but usually the functions in question are
defined in other files which would be loaded if that code is run. For
example, byte-compiling ‘fortran.el’ used to warn:
In end of data:
fortran.el:2152:1:Warning: the function ‘gud-find-c-expr’ is not
known to be defined.
In fact, ‘gud-find-c-expr’ is only used in the function that Fortran
mode uses for the local value of ‘gud-find-expr-function’, which is a
callback from GUD; if it is called, the GUD functions will be loaded.
When you know that such a warning does not indicate a real problem, it
is good to suppress the warning. That makes new warnings which might
mean real problems more visible. You do that with ‘declare-function’.
All you need to do is add a ‘declare-function’ statement before the
first use of the function in question:
(declare-function gud-find-c-expr "gud.el" nil)
This says that ‘gud-find-c-expr’ is defined in ‘gud.el’ (the ‘.el’
can be omitted). The compiler takes for granted that that file really
defines the function, and does not check.
The optional third argument specifies the argument list of
‘gud-find-c-expr’. In this case, it takes no arguments (‘nil’ is
different from not specifying a value). In other cases, this might be
something like ‘(file &optional overwrite)’. You don’t have to specify
the argument list, but if you do the byte compiler can check that the
calls match the declaration.
-- Macro: declare-function function file &optional arglist fileonly
Tell the byte compiler to assume that FUNCTION is defined, with
arguments ARGLIST, and that the definition should come from the
file FILE. FILEONLY non-‘nil’ means only check that FILE exists,
not that it actually defines FUNCTION.
To verify that these functions really are declared where
‘declare-function’ says they are, use ‘check-declare-file’ to check all
‘declare-function’ calls in one source file, or use
‘check-declare-directory’ check all the files in and under a certain
directory.
These commands find the file that ought to contain a function’s
definition using ‘locate-library’; if that finds no file, they expand
the definition file name relative to the directory of the file that
contains the ‘declare-function’ call.
You can also say that a function is a primitive by specifying a file
name ending in ‘.c’ or ‘.m’. This is useful only when you call a
primitive that is defined only on certain systems. Most primitives are
always defined, so they will never give you a warning.
Sometimes a file will optionally use functions from an external
package. If you prefix the filename in the ‘declare-function’ statement
with ‘ext:’, then it will be checked if it is found, otherwise skipped
without error.
There are some function definitions that ‘check-declare’ does not
understand (e.g., ‘defstruct’ and some other macros). In such cases,
you can pass a non-‘nil’ FILEONLY argument to ‘declare-function’,
meaning to only check that the file exists, not that it actually defines
the function. Note that to do this without having to specify an
argument list, you should set the ARGLIST argument to ‘t’ (because ‘nil’
means an empty argument list, as opposed to an unspecified one).