# MulleObjC-startup Dependencies: Understanding mulle-atinit and mulle-atexit

> Discover mulle-atinit and mulle-atexit dependencies for MulleObjC-startup. Learn how they ensure deterministic initialization before main and orderly cleanup after, for predictable Objective-C runtime behavior.

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

---

**MulleObjC-startup requires `mulle-atinit` for deterministic initialization before `main()` and `mulle-atexit` for orderly cleanup after `main()`, providing a predictable startup and shutdown sequence for the Objective-C runtime.**

MulleObjC-startup is a thin static library from the mulle-objc ecosystem that supplies the essential `__register_mulle_objc_universe` symbol. To achieve deterministic behavior without boilerplate code, it depends on two specific helper libraries from the mulle-core suite that handle automatic constructor and destructor execution.

## Core Dependencies of MulleObjC-startup

The library relies on two non-optional helper libraries to manage the Objective-C universe lifecycle. These dependencies are declared in the repository's [`README.md`](https://github.com/mulle-objc/mulleobjc-startup/blob/main/README.md) and enforced through CMake build checks.

### mulle-atinit: Deterministic Initialization

**mulle-atinit** provides a deterministic initialization order by registering functions that execute automatically before `main()` via the GNU `constructor` attribute. MulleObjC-startup leverages this mechanism to invoke `__register_mulle_objc_universe` and the optional `bang()` hook without requiring explicit user initialization code.

According to the source documentation in `cola/description.md.bud`, this library ensures the Objective-C universe is fully registered and ready before any application code runs.

### mulle-atexit: Orderly Termination

**mulle-atexit** provides deterministic termination order using the GNU `destructor` attribute to register cleanup functions that execute after `main()` finishes. MulleObjC-startup uses this to safely destroy the Objective-C universe and execute any registered atexit callbacks, preventing resource leaks and ensuring proper teardown sequence.

As noted in the repository's [`README.md`](https://github.com/mulle-objc/mulleobjc-startup/blob/main/README.md) (line 10), this dependency is mandatory for proper shutdown behavior.

## Build System Integration and Enforcement

The dependencies are not merely optional recommendations; the build system actively enforces their presence. In `cmake/share/Executable.cmake` (lines 161-168), the CMake configuration contains a fatal error check:

```cmake
if( STARTUP_ALL_LOAD_DEPENDENCY_LIBRARIES)
   message( FATAL_ERROR "STARTUP_ALL_LOAD_DEPENDENCY_LIBRARIES \
   \"${STARTUP_ALL_LOAD_DEPENDENCY_LIBRARIES}\" are not linked to ${EXECUTABLE_NAME}. \
   STARTUP_ALL_LOAD_DEPENDENCY_LIBRARIES is a mulle-c/c-developer feature, but this \
   project is seemingly not setup for it.")
endif()

```

This guard ensures that both `mulle-atinit` and `mulle-atexit` are properly linked to any executable using MulleObjC-startup. If these libraries are missing, the build fails immediately with the `STARTUP_ALL_LOAD_DEPENDENCY_LIBRARIES` error message.

## Implementation Details

The core implementation resides in `src/MulleObjC-startup.m`, which contains the universe registration logic and the optional startup hook mechanism. The library works by:

1. **Automatic Registration**: Using `mulle-atinit` to call `__register_mulle_objc_universe` before program entry
2. **Lifecycle Management**: Maintaining the Objective-C universe throughout program execution
3. **Cleanup Execution**: Utilizing `mulle-atexit` to destroy the universe after `main()` returns

This architecture provides a deterministic, order-preserving startup/shutdown model that functions correctly even when the executable links against numerous other static libraries.

## Practical Usage Examples

### Automatic Initialization (Standard Usage)

When linking against MulleObjC-startup, you do not need to write initialization boilerplate. The `mulle-atinit` library automatically registers the universe before your code runs:

```c
#include <MulleObjC/MulleObjC.h>
#include <MulleObjC-startup/MulleObjC-startup.h>

int main(void)
{
    // Universe already initialized by mulle-atinit
    printf("MulleObjC version: %s\n", mulle_objc_get_version());
    return 0;
}

```

Compile with the required libraries:

```bash
clang -o demo demo.c -lMulleObjC-startup -lMulleObjC -lmulle-atinit -lmulle-atexit

```

When the binary executes, `mulle-atinit` invokes `__register_mulle_objc_universe` before entering `main()`. After `main()` returns, `mulle-atexit` automatically destroys the universe.

### Manual Invocation (Advanced Scenarios)

For custom build systems or specialized use cases, you can bypass the automatic constructor and call the initialization function explicitly:

```c
extern void __register_mulle_objc_universe(void);

int main(void)
{
    __register_mulle_objc_universe();   // Explicit initialization
    // Application code here
    return 0;
}

```

You must still link against both helper libraries, but this approach provides explicit control over initialization timing in exotic build configurations.

## Summary

- **MulleObjC-startup** is a static library that provides essential runtime registration symbols for the mulle-objc ecosystem.
- **mulle-atinit** is a mandatory dependency that provides pre-main initialization using GNU constructor attributes to register the Objective-C universe.
- **mulle-atexit** is a mandatory dependency that provides post-main cleanup using GNU destructor attributes to destroy the universe.
- The build system enforces these dependencies through `STARTUP_ALL_LOAD_DEPENDENCY_LIBRARIES` checks in `cmake/share/Executable.cmake`.
- Standard usage requires no boilerplate code; initialization and cleanup occur automatically through the helper libraries.

## Frequently Asked Questions

### What happens if I don't link mulle-atinit and mulle-atexit?

The build will fail with a fatal CMake error referencing `STARTUP_ALL_LOAD_DEPENDENCY_LIBRARIES`. If you somehow bypass the build check, the executable will fail to link due to missing symbols required by `src/MulleObjC-startup.m`, specifically the constructor/destructor mechanisms needed for universe registration and cleanup.

### Can I use MulleObjC without MulleObjC-startup?

Technically yes, but you would need to manually call `__register_mulle_objc_universe()` before using any Objective-C objects and ensure proper cleanup afterward. MulleObjC-startup exists specifically to eliminate this boilerplate using `mulle-atinit` and `mulle-atexit` for deterministic, automatic lifecycle management.

### How does mulle-atinit differ from C++ global constructors?

While both use similar underlying mechanisms (GNU constructor attributes), **mulle-atinit** provides deterministic ordering guarantees specifically designed for C library initialization. Unlike C++ global constructors which can suffer from initialization order fiasco across translation units, `mulle-atinit` implements a controlled registration system that ensures consistent startup behavior regardless of link order.

### Is the initialization order deterministic across all platforms?

The deterministic ordering relies on the GNU `constructor` and `destructor` attributes, which are supported on ELF-based systems (Linux, BSD) and modern macOS. The `mulle-atinit` and `mulle-atexit` libraries abstract these platform specifics, but you should verify platform support in [`assets/dox/TOC.md`](https://github.com/mulle-objc/mulleobjc-startup/blob/main/assets/dox/TOC.md) when targeting non-ELF binary formats.