glcode
This module contains the interface to the Erlang code server, which deals with the loading of compiled code into a running Erlang runtime system.
The runtime system can be started in interactive or embedded mode. Which
one is decided by the command-line flag -mode
:
erl -mode interactive
The modes are as follows:
-
In interactive mode, which is default, only some code is loaded during system startup, basically the modules needed by the runtime system. Other code is dynamically loaded when first referenced. When a call to a function in a certain module is made, and the module is not loaded, the code server searches for and tries to load the module.
-
In embedded mode, modules are not auto loaded. Trying to use a module that has not been loaded results in an error. This mode is recommended when the boot script loads all modules, as it is typically done in OTP releases. (Code can still be loaded later by explicitly ordering the code server to do so).
To prevent accidentally reloading of modules affecting the Erlang runtime
system, directories kernel
, stdlib
, and compiler
are considered
sticky. This means that the system issues a warning and rejects the
request if a user tries to reload a module residing in any of them. The
feature can be disabled by using command-line flag -nostick
.
Code Path
In interactive mode, the code server maintains a search path, usually called the code path, consisting of a list of directories, which it searches sequentially when trying to load a module.
Initially, the code path consists of the current working directory and
all Erlang object code directories under library directory $OTPROOT/lib
,
where $OTPROOT
is the installation directory of Erlang/OTP, root_dir()
.
Directories can be named Name[-Vsn]
and the code
server, by default,
chooses the directory with the highest version number among those having
the same Name. Suffix -Vsn
is optional. If an ebin directory exists under
Name[-Vsn]
, this directory is added to the code path.
Environment variable ERL_LIBS
(defined in the operating system) can be
used to define more library directories to be handled in the same way as
the standard OTP library directory described above, except that directories
without an ebin directory are ignored.
All application directories found in the additional directories appear before the standard OTP applications, except for the Kernel and STDLIB applications, which are placed before any additional applications. In other words, modules found in any of the additional library directories override modules with the same name in OTP, except for modules in Kernel and STDLIB.
Environment variable ERL_LIBS
(if defined) is to contain a
colon-separated (for Unix-like systems) or semicolon-separated (for
Windows) list of additional libraries.
Example:
On a Unix-like system, ERL_LIBS
can be set to the following
/usr/local/jungerl:/home/some_user/my_erlang_lib
On Windows, use semi-colon as separator.
Current and Old Code
The code for a module can exist in two variants in a system: current code and old code. When a module is loaded into the system for the first time, the module code becomes ‘current’ and the global export table is updated with references to all functions exported from the module.
If then a new instance of the module is loaded (for example, because of error correction), the code of the previous instance becomes ‘old’, and all export entries referring to the previous instance are removed. After that, the new instance is loaded as for the first time, and becomes ‘current’.
Both old and current code for a module are valid, and can even be evaluated concurrently. The difference is that exported functions in old code are unavailable. Hence, a global call cannot be made to an exported function in old code, but old code can still be evaluated because of processes lingering in it.
If a third instance of the module is loaded, the code server removes (purges) the old code and any processes lingering in it are terminated. Then the third instance becomes ‘current’ and the previously current code becomes ‘old’.
For more information about old and current code, and how to make a process switch from old to current code, see section “Compilation and Code Loading” in the Erlang Reference Manual.
Types
pub type AddPathError {
AddPathBadDirectory
}
Constructors
-
AddPathBadDirectory
given dir is not a directory
pub type Anno {
Anno(file: String, location: Int)
AnnoNone
}
Constructors
-
Anno(file: String, location: Int)
-
AnnoNone
pub type AtomicLoadError {
AtomicLoadBadFile(module: String)
AtomicLoadDuplicated(module: String)
AtomicLoadNoFile(module: String)
AtomicLoadNotPurged(module: String)
AtomicLoadOnLoadNotAllowed(module: String)
AtomicLoadPendingOnLoad(module: String)
AtomicLoadStickyDirectory(module: String)
}
Constructors
-
AtomicLoadBadFile(module: String)
The object code has an incorrect format or the module name in the object code is not the expected module name.
-
AtomicLoadDuplicated(module: String)
A module is included more than once in Modules.
-
AtomicLoadNoFile(module: String)
No file with object code exists.
-
AtomicLoadNotPurged(module: String)
The object code cannot be loaded because an old version of the code already exists.
-
AtomicLoadOnLoadNotAllowed(module: String)
A module contains an -on_load function.
-
AtomicLoadPendingOnLoad(module: String)
A previously loaded module contains an
-on_load
function that never finished. -
AtomicLoadStickyDirectory(module: String)
The object code resides in a sticky directory.
pub type Available {
Available(module: String, filename: String, loaded: Bool)
AvailablePreloaded(module: String, loaded: Bool)
AvailableCoverCompiled(module: String, loaded: Bool)
}
Constructors
-
Available(module: String, filename: String, loaded: Bool)
filename
is normally the absolute filename, as described foris_loaded
. -
AvailablePreloaded(module: String, loaded: Bool)
-
AvailableCoverCompiled(module: String, loaded: Bool)
pub type DeletePathError {
DeletePathBadName
DeletePathNotFound
}
Constructors
-
DeletePathBadName
given dir is invalid
-
DeletePathNotFound
given dir is wasn’t found
pub type DocsV1 {
DocsV1(
anno: Anno,
beam_language: String,
format: String,
module_doc: ModuleDoc,
metadata: dict.Dict(String, MetadataValue),
docs: List(String),
)
}
Constructors
-
DocsV1( anno: Anno, beam_language: String, format: String, module_doc: ModuleDoc, metadata: dict.Dict(String, MetadataValue), docs: List(String), )
pub type EnsureLoadedError {
EnsureLoadedEmbedded
EnsureLoadedBadFile
EnsureLoadedNoFile
EnsureLoadedOnLoadFailure
}
Constructors
-
EnsureLoadedEmbedded
modules cannot be loaded in embedded mode
-
EnsureLoadedBadFile
The object code has an incorrect format or the module name in the object code is not the expected module name.
-
EnsureLoadedNoFile
No file with object code was found.
-
EnsureLoadedOnLoadFailure
The module has an
-on_load
function that failed when it was called.
pub type EnsureModulesLoadedError {
EnsureModulesLoadedBadfile(module: String)
EnsureModulesLoadedNofile(module: String)
EnsureModulesLoadedOnLoadFailure(module: String)
}
Constructors
-
EnsureModulesLoadedBadfile(module: String)
-
EnsureModulesLoadedNofile(module: String)
-
EnsureModulesLoadedOnLoadFailure(module: String)
pub type FinishLoadingError {
FinishLoadingNotPurged(module: String)
FinishLoadingStickyDirectory(module: String)
FinishLoadingPendingOnLoad(module: String)
}
Constructors
-
FinishLoadingNotPurged(module: String)
The object code cannot be loaded because an old version of the code already exists.
-
FinishLoadingStickyDirectory(module: String)
The object code resides in a sticky directory.
-
FinishLoadingPendingOnLoad(module: String)
A previously loaded module contains an
-on_load
function that never finished.
pub type GetDocError {
GetDocNonExisting
GetDocMissing
GetDocPosix(error: String)
}
Constructors
-
GetDocNonExisting
-
GetDocMissing
-
GetDocPosix(error: String)
pub type IsLoaded {
IsLoaded(filename: String)
IsPreloaded
IsCoverCompiled
}
Constructors
-
IsLoaded(filename: String)
-
IsPreloaded
-
IsCoverCompiled
pub type LibDirOfError {
LibDirOfBadName
}
Constructors
-
LibDirOfBadName
pub type LoadError {
LoadFileBadFile
LoadFileNoFile
LoadFileNotPurged
LoadFileOnLoadFailure
LoadFileStickyDirectory
LoadFileBadArg
}
Constructors
-
LoadFileBadFile
The object code has an incorrect format or the module name in the object code is not the expected module name.
-
LoadFileNoFile
No file with object code was found.
-
LoadFileNotPurged
The object code could not be loaded because an old version of the code already existed.
-
LoadFileOnLoadFailure
The module has an -on_load function that failed when it was called.
-
LoadFileStickyDirectory
The object code resides in a sticky directory.
-
LoadFileBadArg
name or dir is invalid
pub type Loaded {
Loaded(module: String, filepath: String)
LoadedPreloaded(module: String)
LoadedCoverCompiled(module: String)
}
Constructors
-
Loaded(module: String, filepath: String)
-
LoadedPreloaded(module: String)
-
LoadedCoverCompiled(module: String)
pub type MetadataValue {
OtpDocVsn(Int, Int, Int)
}
Constructors
-
OtpDocVsn(Int, Int, Int)
pub type Module {
ModuleName(String)
ModuleObject(ObjectCode)
}
Constructors
-
ModuleName(String)
-
ModuleObject(ObjectCode)
pub type ModuleDoc {
ModuleDocNone
ModuleDocHidden
ModuleDoc(dict.Dict(String, Dynamic))
}
Constructors
-
ModuleDocNone
-
ModuleDocHidden
-
ModuleDoc(dict.Dict(String, Dynamic))
pub type ModuleStatus {
ModuleStatusNotLoaded(module: String)
ModuleStatusLoaded(module: String)
ModuleStatusRemoved(module: String)
ModuleStatusModified(module: String)
}
Constructors
-
ModuleStatusNotLoaded(module: String)
If
module
is not currently loaded -
ModuleStatusLoaded(module: String)
If
module
is loaded and the object file exists and contains the same code -
ModuleStatusRemoved(module: String)
If
module
is loaded but no corresponding object file can be found in the code path -
ModuleStatusModified(module: String)
If
module
is loaded but the object file contains code with a different MD5 checksum
pub type ObjectCode {
Object(module: String, binary: BitArray, filename: String)
}
Constructors
-
Object(module: String, binary: BitArray, filename: String)
pub type PathOrName {
Path(String)
Name(String)
}
Constructors
-
Path(String)
-
Name(String)
pub type PrepareLoadingError {
PrepareLoadingBadFile(module: String)
PrepareLoadingNoFile(module: String)
PrepareLoadingOnLoadNotAllowed(module: String)
PrepareLoadingDuplicated(module: String)
}
Constructors
-
PrepareLoadingBadFile(module: String)
The object code has an incorrect format or the module name in the object code is not the expected module name.
-
PrepareLoadingNoFile(module: String)
No file with object code exists.
-
PrepareLoadingOnLoadNotAllowed(module: String)
A module contains an
-on_load
function. -
PrepareLoadingDuplicated(module: String)
A module is included more than once in
modules
.
pub type ReplacePathError {
ReplacePathBadName
ReplacePathBadDirectory
ReplacePathBadArgument(name: String, dir: String)
}
Constructors
-
ReplacePathBadName
If Name is not found
-
ReplacePathBadDirectory
If
dir
does not exist -
ReplacePathBadArgument(name: String, dir: String)
If
name
ordir
is invalid
pub type WhereIsFileError {
WhereIsFileNonExisting
}
Constructors
-
WhereIsFileNonExisting
is returned if the file cannot be found
pub type Which {
WhichPreloaded
WhichCoverCompiled
WhichFilename(filename: String)
}
Constructors
-
WhichPreloaded
-
WhichCoverCompiled
-
WhichFilename(filename: String)
pub type WhichError {
WhichNonExisting
}
Constructors
-
WhichNonExisting
Functions
pub fn all_available() -> List(Available)
Returns a list of all available modules. A module is considered to be available if it either is loaded or would be loaded if called.
pub fn append_path(dir: String) -> Result(Nil, AddPathError)
Adds dir
to the code path. The directory is added as the last directory in
the new path. If the directory already exists in the path, it is not added.
pub fn append_paths(dirs: List(String)) -> Nil
Adds the directories in dirs
to the end of the code path. If a already
directory exists, it is not added.
pub fn atomic_load(
modules: List(Module),
) -> Result(Nil, List(AtomicLoadError))
Tries to load all of the modules in the list modules
atomically. That
means that either all modules are loaded at the same time, or none of the
modules are loaded if there is a problem with any of the modules.
If it is important to minimize the time that an application is inactive
while changing code, use prepare_loading
and
finish_loading
instead of atomic_load
. Here is an
example:
let assert Ok(prepared) = glcode.prepare_loading(["module1", "module2"])
// Put the application into an inactive state or do any other
// preparation needed before changing the code.
let assert Ok(Nil) = glcode.finish_loading(Prepared)
// Resume the application.
pub fn clash() -> Nil
Searches all directories in the code path for module names with identical
names and writes a report to stdout
.
pub fn compiler_dir() -> String
Returns the compiler library directory. Equivalent to lib_dir("compiler")
.
pub fn delete(module: String) -> Bool
Removes the current code for module
, that is, the current code for
module
is made old. This means that processes can continue to execute the
code in the module, but no external function calls can be made to it.
Returns True
if successful, or False
if there is old code for module
that must be purged first, or if module
is not a (loaded) module.
pub fn delete_path(
dir: PathOrName,
) -> Result(Nil, DeletePathError)
Deletes a directory from the code path. The argument can be a Name
, in
which case the directory with the name .../Name[-Vsn][/ebin]
is deleted
from the code path. Also, the complete directory Path
can be specified
as argument.
pub fn ensure_loaded(
module: String,
) -> Result(String, EnsureLoadedError)
Tries to load a module in the same way as load_file
, unless the module is
already loaded. However, in embedded mode it does not load a module that is
not already loaded, but returns EnsureLoadedEmbedded
instead. See EnsureLoadedError
for a description of
other possible error reasons.
pub fn ensure_modules_loaded(
modules: List(String),
) -> Result(Nil, List(EnsureModulesLoadedError))
Tries to load any modules not already loaded in the list modules
in the
same way as load_file
.
pub fn finish_loading(
prepared: Prepared,
) -> Result(Nil, List(FinishLoadingError))
Tries to load code for all modules that have been previously prepared
by prepare_loading
. The loading occurs atomically,
meaning that either all modules are loaded at the same time, or none of the
modules are loaded.
pub fn get_doc(module: String) -> Result(DocsV1, GetDocError)
Searches the code path for EEP-48 style documentation and returns it if available. If no documentation can be found the function tries to generate documentation from the debug information in the module.
For more information about the documentation chunk see Documentation Storage and Format in Kernel’s User’s Guide.
For now this returns a dynamic value since coming up with a sensible Gleam type for it is crazy.
pub fn get_mode() -> Mode
Returns an atom describing the mode of the code server: interactive or
embedded. This information is useful when an external entity (for example,
an IDE) provides additional code for a running node. If the code server is
in interactive mode, it only has to add the path to the code. If the code
server is in embedded mode, the code must be loaded with
load_binary
.
pub fn get_object_code(
module: String,
) -> Result(ObjectCode, LoadError)
This function can be used to load object code on remote Erlang nodes.
Argument binary
must contain object code for module
. filename
is only
used by the code server to keep a record of from which file the object code
for module
comes. Thus, filename
is not opened and read by the code
server.
pub fn is_loaded(module: String) -> Result(IsLoaded, Nil)
Checks if module
is loaded. If it is, the loaded filename is returned,
otherwise Error(Nil)
.
Normally, IsLoaded
contains the the absolute filename
from which the code is
obtained. If the module is preloaded (see
script(4)
), then it returns IsPreloaded
. If
the module is Cover-compiled (see
cover(3)
), it returns IsCoverCompiled
.
pub fn is_sticky(module: String) -> Bool
Returns True
if module
is the name of a module that has been loaded from
a sticky directory (in other words: an attempt to reload the module will
fail), or False
if module
is not a loaded module or is not sticky.
pub fn lib_dir() -> String
Returns the library directory, $OTPROOT/lib
, where $OTPROOT
is the root
directory of Erlang/OTP.
Example:
glcode.lib_dir()
"/nix/store/gnm9kc4qnayb7wbhmnsq0w6yqgh7xgn3-erlang-25.3.2.9/lib/erlang/lib"
pub fn lib_dir_of(name: String) -> Result(String, LibDirOfError)
Returns the path for the “library directory”, the top directory, for an
application Name located under $OTPROOT/lib
or on a directory referred to
with environment variable ERL_LIBS
.
If a regular directory called name
or name-Vsn
exists in the code
path with an ebin
subdirectory, the path to this directory is returned
(not the ebin directory).
If the directory refers to a directory in an archive, the archive name is
stripped away before the path is returned. For example, if directory /usr/ local/otp/lib/mnesia-4.2.2.ez/mnesia-4.2.2/ebin
is in the path, /usr/local/ otp/lib/mnesia-4.2.2/ebin
is returned. This means that the library directory
for an application is the same, regardless if the application resides in an
archive or not.
Example:
> glcode.lib_dir("mnesia")
"/nix/store/gnm9kc4qnayb7wbhmnsq0w6yqgh7xgn3-erlang-25.3.2.9/lib/erlang/lib/mnesia-4.21.4.2"
Returns an error if name
is not the name of an application under
$OTPROOT/lib
or on a directory referred to through environment variable
ERL_LIBS
.
pub fn lib_dir_of_sub(
module: String,
dir: String,
) -> Result(String, LibDirOfError)
Returns the path to a subdirectory directly under the top directory of an application. Normally the subdirectories reside under the top directory for the application, but when applications at least partly reside in an archive, the situation is different. Some of the subdirectories can reside as regular directories while others reside in an archive file. It is not checked whether this directory exists.
Example:
> glcode.lib_dir("megaco", "priv").
"/usr/local/otp/lib/megaco-3.9.1.1/priv"
pub fn load_abs(filename: String) -> Result(String, LoadError)
Same as load_file
, but filename
is an absolute or relative filename.
The code path is not searched. It returns a value in the same way as
load_file
. Notice that Filename must not contain the extension (for
example, .beam
) because load_abs
adds the correct extension.
pub fn load_binary(
module: String,
filename: String,
binary: BitArray,
) -> Result(String, LoadError)
This function can be used to load object code on remote Erlang nodes.
Argument binary
must contain object code for module
. filename
is only
used by the code server to keep a record of from which file the object code
for module
comes. Thus, filename
is not opened and read by the code
server.
pub fn load_file(name: String) -> Result(String, LoadError)
Tries to load the Erlang module module
, using the code path. It looks for
the object code file with an extension corresponding to the Erlang machine
used, for example, module
.beam. The loading fails if the module name found
in the object code differs from the name module
. load_binary
must be
used to load object code with a module name that is different from the file
name.
pub fn modified_modules() -> List(Module)
Returns the list of all currently loaded modules for which
module_status
returns modified. See also all_loaded
.
pub fn module_status(modules: List(String)) -> List(ModuleStatus)
Preloaded modules are always reported as loaded, without inspecting the contents on disk. Cover compiled modules will always be reported as modified if an object file exists, or as removed otherwise. Modules whose load path is an empty string (which is the convention for auto-generated code) will only be reported as Loaded or NotLoaded.
pub fn objfile_extension() -> String
Returns the object code file extension corresponding to the Erlang machine
used, namely .beam
.
pub fn prepare_loading(
modules: List(Module),
) -> Result(Prepared, List(PrepareLoadingError))
Prepares to load the modules in the list modules
. Finish the loading by
calling finish_loading(prepared)
.
pub fn prepend_path(dir: String) -> Result(Nil, AddPathError)
Adds dir
to the beginning of the code path. If the directory already
exists, it is removed from the old position in the code path.
pub fn prepend_paths(dirs: List(String)) -> Nil
Traverses dirs
and adds each directory to the beginning of the code path.
This means that the order of dirs
is reversed in the resulting code path.
For example, if you add [dir1, dir2]
, the resulting path will be
[dir2, dir1, ..old_code_path]
.
If a directory already exists in the code path, it is removed from the old
position.
pub fn priv_dir(name: String) -> Result(Nil, String)
Returns the path to the priv directory in an application. Equivalent to
lib_dir(name, "priv")
.
pub fn purge(module: String) -> Bool
Purges the code for Module, that is, removes code marked as old. If some processes still linger in the old code, these processes are killed before the code is removed. Returns true if successful and any process is needed to be killed, otherwise false.
pub fn replace_path(
name: String,
dir: String,
) -> Result(Nil, ReplacePathError)
Replaces an old occurrence of a directory named .../Name[-Vsn][/ebin]
in the
code path, with dir
. If name
does not exist, it adds the new directory dir
last in the code path. The new directory must also be named
.../Name[-Vsn][/ebin]
. This function is to be used if a new version of the
directory (library) is added to a running system.
pub fn root_dir() -> String
root_dir() -> file:filename() Returns the root directory of Erlang/OTP, which is the directory where it is installed. Example:
code:root_dir(). “/usr/local/otp”
pub fn soft_purge(module: String) -> Bool
Purges the code for Module
, that is, removes code marked as old, but only
if no processes linger in it. Returns False
if the module cannot be purged
because of processes lingering in old code, otherwise True
.
pub fn unstick_dir(dir: String) -> Result(Nil, Nil)
Unsticks a directory that is marked as sticky.
pub fn where_is_file(
filename: String,
) -> Result(String, WhereIsFileError)
Searches the code path for filename
, a file of arbitrary type. If found,
the full name is returned. The function can be useful, for example, to
locate application resource files.
pub fn which(module: String) -> Result(Which, WhichError)
If the module is not loaded, this function searches the code path for
the first file containing object code for module
and returns the absolute
filename.
If the module is loaded, it returns the name of the file containing the loaded object code.
If the module is preloaded, WhichPreloaded
is returned.
If the module is Cover-compiled, WhichCoverCompiled
is returned.
If the module cannot be found, WhichNonExisting
is returned.