# How to Create Executables that Use MulleObjC: A Complete Guide

> Learn to create MulleObjC executables by linking to the MulleObjC-startup library. Initialize the runtime without a full Foundation stack for efficient C-based Objective-C development.

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

---

**Link your executable against the MulleObjC-startup static library to automatically register the `__register_mulle_objc_universe` function and initialize the runtime without pulling in the full Foundation stack.**

The [mulle-objc/mulleobjc-startup](https://github.com/mulle-objc/mulleobjc-startup) repository provides a lightweight bootstrap mechanism for building standalone executables that leverage the Mulle Objective-C runtime. By including this static library in your build, you obtain the minimal runtime initialization code required to boot the MulleObjC universe, along with automatic handling of `mulle-atinit` and `mulle-atexit` helpers.

## What Is MulleObjC-startup?

MulleObjC-startup is a static library that supplies the mandatory `__register_mulle_objc_universe` function referenced by the MulleObjC runtime. When linked into an executable, this library ensures the Objective-C universe is properly initialized before your `main()` function executes. The core implementation resides in **`src/MulleObjC-startup.m`**, where the private registration symbol is defined and the `bang` routine invokes `MulleObjCBang` to perform the actual universe setup.

Unlike the full Foundation framework, this library provides only the essential startup mechanics, making it ideal for lightweight command-line tools and embedded applications.

## Prerequisites and Project Setup

The recommended workflow uses the `mulle-sde` command-line tool to scaffold a CMake-based project preconfigured for MulleObjC development.

Initialize a new executable project:

```bash
mulle-sde init -d my-project -m mulle-objc/objc-developer executable
cd my-project

```

Enable colorful build output (optional):

```bash
mulle-sde vibecoding on

```

Add the startup library dependency:

```bash
mulle-sde add github:mulle-objc/MulleObjC-startup

```

If you require the complete Foundation stack later, you can additionally add `github:mulle-objc/MulleFoundation-startup`, though the basic MulleObjC-startup is sufficient for runtime-only executables.

## Writing Your Executable Code

Include the public header in your source files to ensure proper registration:

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

```

A minimal executable looks like this:

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

int main( int argc, const char * argv[] )
{
   // The universe is automatically registered by the library's constructor
   printf( "Hello from MulleObjC!\n");
   return 0;
}

```

The runtime registration happens automatically through library constructors, so you do not need to manually invoke initialization functions in your `main()` routine.

## CMake Configuration and Linker Flags

When using `mulle-sde`, the build system automatically configures the necessary linker flags through the templates in **`cmake/share/ExecutableObjC.cmake`** and **`cmake/share/InstallExecutable.cmake`**.

The generated [`CMakeLists.txt`](https://github.com/mulle-objc/mulleobjc-startup/blob/main/CMakeLists.txt) links your executable against the startup library:

```cmake
cmake_minimum_required(VERSION 3.13)

project(my_project C)

add_executable( my_exe src/main.c )
target_link_libraries( my_exe PUBLIC MulleObjC-startup)

```

The CMake scripts automatically inject platform-specific linker directives:
- **Linux**: `--export-dynamic` to expose symbols for runtime registration
- **macOS**: `-exported_symbol,__register_mulle_objc_universe` to explicitly export the required registration symbol

These flags ensure the `__register_mulle_objc_universe` symbol remains visible to the dynamic linker during universe initialization.

## Build and Run

Compile and link your executable using the standard mulle-sde workflow:

```bash
mulle-sde run

```

Alternatively, invoke CMake directly:

```bash
cmake --build . && ./my_exe

```

During the build process, the system:
1. Pulls in the MulleObjC-startup static library from your dependencies
2. Applies the linker flags defined in `ExecutableObjC.cmake`
3. Produces an executable with the runtime pre-registered and ready for Objective-C code

## Summary

- **MulleObjC-startup** is a static library providing the `__register_mulle_objc_universe` symbol required to boot the MulleObjC runtime
- Use **`mulle-sde init`** to scaffold projects with proper CMake configuration already in place
- Include **[`MulleObjC-startup/MulleObjC-startup.h`](https://github.com/mulle-objc/mulleobjc-startup/blob/main/MulleObjC-startup/MulleObjC-startup.h)** to access the runtime registration interface
- The **`cmake/share/ExecutableObjC.cmake`** template automatically handles platform-specific linker flags for symbol export
- The initialization sequence in **`src/MulleObjC-startup.m`** invokes `MulleObjCBang` to configure the universe before `main()` executes

## Frequently Asked Questions

### Do I need to call any initialization functions in my main() function?

No. The MulleObjC-startup library uses constructor attributes to automatically register the universe during dynamic library loading. By including the header and linking the library, the `__register_mulle_objc_universe` function defined in `src/MulleObjC-startup.m` executes before your `main()` function, ensuring the runtime is ready when your code begins executing.

### Why does my executable need special linker flags?

The MulleObjC runtime dynamically discovers and registers universes through the `__register_mulle_objc_universe` symbol. On Linux, `--export-dynamic` ensures this symbol is visible to the dynamic linker, while macOS requires `-exported_symbol,__register_mulle_objc_universe` to prevent symbol stripping. The `ExecutableObjC.cmake` file in the repository provides these flags automatically when using the recommended build system.

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

Yes, though you must manually configure your build system to link against the static library and include the appropriate linker flags. Clone the repository, build the library using the provided [`CMakeLists.txt`](https://github.com/mulle-objc/mulleobjc-startup/blob/main/CMakeLists.txt), then add the library path to your executable's link step. You must also manually apply the platform-specific export flags found in `cmake/share/ExecutableObjC.cmake` to ensure proper symbol visibility.

### What is the difference between MulleObjC-startup and MulleFoundation-startup?

**MulleObjC-startup** provides only the minimal runtime bootstrap code—the universe registration and basic initialization hooks. **MulleFoundation-startup** extends this with the full Foundation framework initialization, including standard library classes and utilities. For command-line tools that only need the Objective-C runtime without Foundation classes, MulleObjC-startup is the lighter and faster option.