# How MulleObjC-startup Defines Version Using MULLE_OBJC__STARTUP_VERSION

> Understand how MulleObjC-startup defines version using MULLE_OBJC__STARTUP_VERSION. Learn how this macro encodes epoch, major, and minor components into a comparable integer.

- Repository: [mulle-objc/mulleobjc-startup](https://github.com/mulle-objc/mulleobjc-startup)
- Tags: internals
- Published: 2026-03-07

---

**The `MULLE_OBJC__STARTUP_VERSION` macro encodes the library version as a 32-bit integer using bitwise shifts to pack epoch, major, and minor components into a single comparable value.**

The mulle-objc/mulleobjc-startup repository tracks its release version through a compact preprocessor macro rather than separate string constants. This design enables both compile-time and runtime version checking through a single numeric token defined directly in the implementation source.

## Where MULLE_OBJC__STARTUP_VERSION Is Defined

The canonical definition lives in **`src/MulleObjC-startup.m`** at line 56. According to the source code, the macro appears as:

```c
#define MULLE_OBJC__STARTUP_VERSION  ((0UL << 20) | (20 << 8) | 7)

```

This single line encodes the complete version identifier for the startup library. The repository uses this central definition to ensure that all consumers reference the same version token regardless of how they integrate the library.

## Bitwise Structure of the Version Encoding

The macro packs three distinct version components into a monotonic 32-bit unsigned integer using specific bit shifts. This layout allows simple numeric comparison while preserving access to individual version fields.

The encoding scheme distributes bits as follows:

- **Epoch** (bits 20-31): Reserved for future architectural revisions, currently `0` via `0UL << 20`
- **Major** (bits 8-19): The primary release number, currently `20` via `20 << 8`
- **Minor/Patch** (bits 0-7): The incremental update number, currently `7`

Thus, `MULLE_OBJC__STARTUP_VERSION` evaluates to the integer representation of **version 0.20.7**. Because higher bits represent more significant version components, a simple integer comparison reliably determines version ordering without parsing strings.

## Practical Usage of MULLE_OBJC__STARTUP_VERSION

### Extracting Version Components at Runtime

To display the version in human-readable format, extract each component using bitwise masks. The following example demonstrates decomposition in C:

```c
#include <stdio.h>
#include "MulleObjC-startup.h"

int main(void)
{
    unsigned long version = MULLE_OBJC__STARTUP_VERSION;
    
    unsigned long epoch = (version >> 20) & 0xFFF;
    unsigned long major = (version >> 8) & 0xFFF;
    unsigned long minor = version & 0xFF;
    
    printf("MulleObjC-startup version: %lu.%lu.%lu\n", epoch, major, minor);
    return 0;
}

```

The shift operations isolate specific bit ranges: `>> 20` retrieves the epoch, `>> 8` combined with `0xFFF` masks yields the major version, and `& 0xFF` captures the minor component directly.

### Comparing Versions in Preprocessor Logic

Because `MULLE_OBJC__STARTUP_VERSION` resolves to a compile-time constant, you can perform version checks within preprocessor directives or static assertions:

```c
#define REQUIRED_VERSION ((0UL << 20) | (20 << 8) | 5)

#if MULLE_OBJC__STARTUP_VERSION < REQUIRED_VERSION
    #error "MulleObjC-startup version 0.20.5 or later is required"
#endif

/* Or for runtime fallback logic */
if (MULLE_OBJC__STARTUP_VERSION >= ((0UL << 20) | (21 << 8) | 0)) {
    /* Use API introduced in 0.21.0 */
}

```

This approach eliminates string parsing overhead and ensures that version mismatches surface during compilation rather than at runtime.

## Build System Integration

While the macro originates in **`src/MulleObjC-startup.m`**, the build system exposes this information to external consumers through **`cmake/share/MulleObjC-startup-config.h.in`**. This template generates a configuration header that downstream projects can include to access the version without manually parsing source files.

The CMake configuration processes the raw macro definition and exports it through generated headers, ensuring that installed versions of the library report consistent version tokens across different build environments.

## Summary

- **`MULLE_OBJC__STARTUP_VERSION`** is defined in `src/MulleObjC-startup.m` as a 32-bit packed integer.
- The encoding uses bit shifts to store epoch (bits 20-31), major (bits 8-19), and minor (bits 0-7) components.
- Current version **0.20.7** is represented as `((0UL << 20) | (20 << 8) | 7)`.
- Simple numeric comparison works for version checking because higher-order bits represent more significant version numbers.
- The CMake build system exports this version through generated headers in `cmake/share/MulleObjC-startup-config.h.in`.

## Frequently Asked Questions

### What format does MULLE_OBJC__STARTUP_VERSION use?

The macro uses a packed 32-bit unsigned integer format where the epoch occupies bits 20-31, the major version occupies bits 8-19, and the minor version occupies bits 0-7. This structure allows the library to represent semantic version components as a single comparable numeric value.

### How do I extract the major version number from MULLE_OBJC__STARTUP_VERSION?

Shift the value right by 8 bits and mask with `0xFFF` to isolate the major component: `(MULLE_OBJC__STARTUP_VERSION >> 8) & 0xFFF`. This operation discards the minor version bits and removes the epoch, leaving only the major release number.

### Can I compare MULLE_OBJC__STARTUP_VERSION using standard operators?

Yes. Because the version components are ordered by significance in the bit layout (epoch > major > minor), standard comparison operators like `<`, `>`, and `==` correctly determine version precedence. A larger integer always indicates a newer or equal version.

### Where is the version macro defined in the source tree?

The definition resides in **`src/MulleObjC-startup.m`** at line 56 within the mulle-objc/mulleobjc-startup repository. This location serves as the single source of truth for the library version, which the build system then propagates to generated configuration headers.