Populate options field select values dynamically using a function

Drupal's core options module provides fields to create a select list (existing of integers, floats or strings). From the user interface, these options seem to be static (i.e., are stored directly in configuration), but when looking at the exported configuration field.storage.<entity_type>.<field_name>.yml file there is an allowed_values_function setting. So, instead of writing an hook_form_alter(), you can add a function that will be invoked when the options select list is created (hence allowing for dynamic values).

field_name: <field_name>
entity_type: node
type: list_string
  allowed_values: {  }
  allowed_values_function: example_allowed_values()
module: options

The example code below illustrates how to create the options of the select list dynamically. Note that in the documentation of options_allowed_values() the returned keys and values should be sanitized using the fieldFilterXss() function from the AllowedTagsXssTrait trait (of course only necessary when values are used that can be provided/changed by a user). Since, the options_allowed_values implementation often is placed in a .module file, we can simply invoke FieldFilteredMarkup::create() directly to create escaped keys and values.

use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Field\FieldFilteredMarkup;
use Drupal\field\Entity\FieldStorageConfig;

 * Provides key-value options for an select list.
 * @param \Drupal\field\Entity\FieldStorageConfig $definition
 *   The field definition.
 * @param \Drupal\Core\Entity\ContentEntityInterface|null $entity
 *   The entity being created, if applicable.
 * @param bool $cacheable
 *   Boolean indicating if the results are cache-able.
 * @return array
 *   An array of possible key and value options.
 * @see options_allowed_values()
function example_allowed_values(FieldStorageConfig $definition, ContentEntityInterface $entity = NULL, $cacheable) {
  $options = [];

  // Usually, the options list is constructed using a loop.
  $options['example_key'] = FieldFilteredMarkup::create('Example description, e.g., retrieved from configuration');

  // Note: the key of the options list is stored in the database, not the value.
  return $options;

Don't forget to import the configuration after setting the allowed_values_function and rebuild Drupal's caches in order for the function to be found.