PORTMOD(7)

NAME
portmod - Portmod Concepts

These are various concepts relevant to understanding how portmod works. It is recommended that you familiarise yourself with them before using Portmod.
Keywords | Keywords indicate the stability of game engines (architectures) for a given package.
Sets | Sets are short forms for collections of packages.
Use Flags | Use flags are the primary method of configuring portmod’s packages.
Profiles | Profiles are default game configurations for portmod.
Sandbox | The portmod sandbox allows safe access to dangerous functions such as shutil.rmtree while still allowing pybuilds to be as pythonic as possible.
Configuration Protection | For certain files in the prefix, and all files outside the prefix, portmod will not blindly overwrite them when installing, and will not allow modules to overwrite them. This helps nicely handle changes to files the user has manually modified.
Modules | Modules can be used to run global updates after package installation has been completed. This is often used to update configuration files to inform game engines of the locations of the mods which have been installed,

KEYWORDS

Keywords indicate the stability of game engines (architectures) for a given package.

Most packages declare one of the following engine-specific keywords in their KEYWORDS field:

1.  Stable: arch (E.g. openmw) - This version of the mod and the pybuild are tested and not known to have any serious issues with the given platform.

2.  Testing: ~arch (E.g. ~openmw) - The version of the mod and the pybuild are believed to work and do not have any known serious bugs, but more testing should be performed before being considered stable.

3.  No keyword: If a package has no keyword for a given arch, it means it is not known whether the package will work, or that insufficient testing has occurred for ~arch.

4.  Masked: -arch (E.g. -openmw) The package version will not work on the arch. This likely means it relies on a feature not supported by the engine, or contains serious bugs that make it unusable.

    By default, only stable versions of packages are installed. For unstable versions you will need to accept the keyword.

    You can enable testing packages by default by overriding the default ACCEPT_KEYWORDS in portmod.conf with the testing keyword appropriate for your engine.

    You can accept keywords for specific packages by adding the mod version and keyword to package.accept_keywords. E.g:

    =base/patch-for-purists-3.2.1 ~openmw
    # To ignore keywords and make the package visible regardless of keywords
    >=base/patch-for-purists-3.1.3 **

  Versioned Keywords

New in version 2.6.

Keywords can also be versioned. This is an optional feature, and may not be set up for every engine, but it allows packages to be marked as stable/testing/masked on specific versions, in addition to generally.

E.g.

# Stable on 0.48 and later
KEYWORDS = "openmw{>=0.48}"
# Masked on 0.47.0, but stable on all other versions
KEYWORDS = "openmw -openmw{==0.47.0}"
# Stable on 0.47 and related patch versions, but only testing on 0.48 and newer and older versions
KEYWORDS = "~openmw openmw{0.47*}"

When versioning is set up in the profile, ACCEPT_KEYWORDS can also be versioned. Usually it will default to use the ARCH_VERSION profile variable.

E.g. in portmod.conf

ACCEPT_KEYWORDS = "openmw{==0.48.0}"
# If you want to accept packages testing on your version
# Note that when using f-strings, literal '{' has to be escaped as '{{',
# so there end up being three
ACCEPT_KEYWORDS = f"~openmw{{=={ARCH_VERSION}}}"

See Architecture Versioning in the development guide for further details.

SETS

Sets are short forms for collections of packages.

They are roughly equivalent to specifying that same list of packages on the command line, however packages within a set will not be selected if installing using a set, and the set itself will be selected.

You can refer to a set using @, followed by the set name.

E.g. portmod <prefix> merge -uDN @world, or portmod <prefix> merge @rebuild.

The builtin sets include:

•   world: Equivalent to selected + system. This is usually the only set you need to interact with. It includes all packages that you want or need, not including their dependencies.

•   system: Packages required by the profile which cannot be removed.

•   selected: Equivalent to selected-sets + selected-packages

•   selected-sets: User-selected sets (not including builtin sets).

•   selected-packages: The user-selected list of packages. This includes any package you have explicitly installed (i.e. installed without the --oneshot/-1 option). It does not include dependencies which were installed implicitly.

•   installed: All currently installed packages.

•   rebuild: Packages are added to this set automatically for certain unusual packages when they are determined to need to be rebuilt. A warning message will be displayed when you need to use this set.

    Deprecated since version 2.4: The rebuild set is from a deprecated feature and will no longer be a built-in set in Portmod 3.0. However, there is a module which replaces this functionality.

    You can also create custom User Sets

  Module Sets

New in version 2.4.

Sets created in the var/sets directory within the prefix will be used first when looking up sets. This allows Modules to create and manage their own sets. Module-created sets always have priority over User Sets.

USE FLAGS

Use flags are the primary method of configuring portmod’s packages.

  Global Flags

Global use flags are enabled by default for all packages (unless explicitly disabled for a specific package). You can enable or disable a use flag by including it in the USE variable in portmod.conf. If prefixed by a -, the flag will be considered disabled, otherwise it will be considered enabled.

E.g. portmod.conf

USE = "tribunal -bloodmoon"

You can also enable a global use flag using portmod <prefix> use -E <flag>, and explicitly disable a flag using portmod <prefix> use -D <flag>.

You should note that explicitly disabling a flag is not the same as unsetting the flag. When explicitly disabled (e.g. -tribunal), all packages using the flag will disable it. You can unset a use flag using portmod <prefix> use -R <flag>, which will remove the flag from the USE variable in portmod.conf if it’s been either enabled or disabled, and will make packages revert to their default behaviour for that flag (individual packages declare whether a flag is enabled or disabled by default).

  Local Flags

Local flags are similar to global flags, but only apply to a specific package. Local flags are declared in the file package.use in the CONFIG_DIR.

Each line in this file should begin with a package specifier, and end with a (space separated) list of flags.

E.g. package.use

base/morrowind tribunal -bloodmoon
>=landmasses/tamriel-rebuilt-19.12 travels music -preview

You can also enable or disable local flags using the -m argument to the use subcommand, with the atom for the package you want to disable. E.g. portmod <prefix> use -E <flag> -m <atom>.

  Temporary use flags

You can temporarily set flags using the USE environment variable.

E.g. in bash

USE=-tribunal portmod <prefix> merge -uDN @world

  After changing use flags

After making changes to your use flag configuration, you should always run an update ( portmod <prefix> merge -uD @world) to make sure that any packages are rebuilt if they need to be. Just changing a use flag will not modify your installed mod packages.

  Further Reading

•   Developer Guide: Use Flag Guide

PROFILES

Profiles are default game configurations for portmod.

They are used to set default values for various settings. Certain user-relevant settings can be viewed with the portmod <prefix> info subcommand.

They also specify the mandatory packages in the system set (see Sets), and can provide other metadata such as default Use Flags and masked packages (in the same manner as package.mask).

SANDBOX

The portmod sandbox allows safe access to dangerous functions such as shutil.rmtree while still allowing pybuilds to be as pythonic as possible.

This is achieved through the use of RestrictedPython for loading package metadata in an environment without access to file i/o or any dangerous commands. During package installation and removal where file i/o is necessary, package functions are run through the use of a sandbox program such as bubblewrap on Linux and sandbox-exec on OSX.

In general, the following is restricted:

•   File I/O in the global scope. All file I/O must be within functions in the Package class.

•   Use of imports in the global scope, other than imports from the common or pybuild modules (the imports themselves can be in the global scope, however they will be ignored during package loading and using imported functions will cause an exception). - File I/O outside the build directory in src_unpack and can_update_live.

•   Network access outside src_unpack and can_update_live

•   File writes outside the build directory in all scopes

    The idea is that this prevents:

1.  Poorly written code from accidentally performing dangerous actions such as deleting your files.

2.  Malicious actors from creating a seemingly benign third-party repository (or sneaking packages into a repository which is otherwise trustworthy) and causing either deliberate damage to your system or stealing your personal information when you try to install or update packages from that repository.

  Python Sandbox

Note that for compatibility reasons, packages should be written to target the minimum version of python portmod supports (this is currently Python 3.8). Using features introduced in later versions of python will break the packages on systems which are using an older version of python.

Additionally, the following restrictions apply to the pybuild code:

•   Prior to Portmod 2.4, you could only access the following modules:

•   pybuild

•   pybuild.info

•   pybuild.winreg

•   filecmp

•   glob

•   os

•   os.path

•   sys

•   shutil

•   stat

•   fnmatch

•   re

•   csv

•   json

•   typing

•   collections

•   common submodules (noting that common modules are subject to the same restrictions as pybuilds).

    Since Portmod 2.4 all module imports are allowed. Modules outside the standard library and pybuild/common must be installed within the prefix and the package must depend on them.

•   Use of the str.format function is banned. This is known to be unsafe and is disabled by RestrictedPython by default. It is encouraged to used f-strings instead.

•   Access to attributes that begin with underscores is banned. The convention in python is that these attributes are considered hidden, and represent internal functions and variables which could change at any time. By blocking the use of them pybuilds are forced to use the more stable public module APIs.

•   Use of the super function is allowed, however note that super().__init__(self) cannot be invoked manually due to underscored functions being banned. As such, it is automatically called in any Package class that overrides __init__.

•   Use of builtins that allow arbitrary code execution is banned. This includes exec, compile, eval, etc.

•   Prior to Portmod 2.4: The dir function was not implemented. The implementation omits private underscored fields, which are inaccessible anyway.

  Executable Sandbox

All external executable calls are sandboxed using a platform-specific sandbox command. This prevents filesystem write access outside the build directory and prevents filesystem read access until all potentially-unsafe network access has been completed (i.e. prevents a malicious pybuild from scanning your system and uploading data to a remote server).

  Temporary Directories

Writable temporary directories are always available in the Sandbox. On Windows and Linux, the TMP environment variable will provide the path to a writable temporary directory, and the TMPDIR environment variable will on macOS.

  Windows

Portmod uses Sandboxie on Windows. Please note that there are known issues with Sandboxie (see #102), however in general it appears to be working. If you encounter issues, please report them, as portmod's primary developers do not work regularly with Windows and is usually only regularly tested via CI.

CONFIGURATION PROTECTION

For certain files in the prefix, and all files outside the prefix, portmod will not blindly overwrite them when installing, and will not allow modules to overwrite them. This helps nicely handle changes to files the user has manually modified.

Instead, these writes will be diverted to a different file, and the changes will be displayed to the user when they run portmod <prefix> cfg-update.

Portmod has a simple builtin tool to accept or reject the changes, and you can get it to launch a custom merge tool by setting the MERGE_TOOL configuration variable in portmod.conf.

Changed in version 2.6: Portmod no longer runs cfg-update automatically after merges, to avoid covering up important information which may be displayed after a merge.

MODULES

Modules can be used to run global updates after package installation has been completed. This is often used to update configuration files to inform game engines of the locations of the mods which have been installed,

Module updates can be triggered manually with the portmod <prefix> module-update subcommand.

Changed in version 2.6: Module updates are no longer run as part of the cfg-update subcommand

For implementing modules, see the Modules chapter in the Developer Guide.

AUTHOR
Benjamin Winger, Roma Tentser, PopeRigby, Hristos N. Triantafillou, lumbo7332, Pope_Rigby, marius david, marius851000, Basile Thullen, Joel, Nords Morrow, Anonymous, Paul Infield-Harm, Qazaaq, Tenchi, Weblate, gbtb, louisabraham, ultramink

COPYRIGHT
2019-2025, Portmod Authors