# Does Asio Have a Header-Only Option? Using the Asio Library Without Compilation

> Discover how to use Asio header only by defining ASIO_HEADER_ONLY. Compile Asio without separate libraries and simplify your C++ projects.

- Repository: [chriskohlhoff/asio](https://github.com/chriskohlhoff/asio)
- Tags: how-to-guide
- Published: 2026-07-16

---

**Yes, Asio supports header-only compilation by defining the `ASIO_HEADER_ONLY` macro before including any headers, which pulls in implementation code from `.ipp` files instead of requiring a separately compiled library.**

The Asio library (chriskohlhoff/asio) is the de facto standard for asynchronous networking and low-level I/O in C++. While often distributed as a compiled library, Asio provides a header-only option that simplifies integration by eliminating build system dependencies and linking requirements.

## How Asio Header-Only Mode Works

The header-only mechanism relies on conditional compilation throughout the codebase. When you define `ASIO_HEADER_ONLY`, the library includes **inline implementation files** (`.ipp` extensions) directly into your translation units rather than expecting symbols from an external object file.

In [`include/asio/config.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/config.hpp) (lines 90-94), this conditional inclusion is clearly demonstrated:

```cpp
#if defined(ASIO_HEADER_ONLY)

# include "asio/impl/config.ipp"

#endif // defined(ASIO_HEADER_ONLY)

```

This pattern repeats across internal components such as [`include/asio/detail/socket_ops.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/detail/socket_ops.hpp). The actual function bodies reside in files like `asio/impl/config.ipp`, which contain the platform-specific implementations normally compiled into a static or shared library.

### Standalone vs. Boost.Asio Modes

Asio operates in two distinct configurations. When you define **`ASIO_STANDALONE`**, the library disables all Boost dependencies and relies solely on standard C++ headers. According to [`include/asio/detail/config.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/detail/config.hpp) (lines 17-27), this macro is automatically set unless Boost headers are already present. The header-only mechanism functions identically in both standalone and Boost-compatible modes.

## Configuring Your Build for Header-Only Asio

To compile Asio without linking a separate library, define these macros before including [`asio.hpp`](https://github.com/chriskohlhoff/asio/blob/main/asio.hpp):

1. **`ASIO_HEADER_ONLY`** – Required. Enables the inline inclusion of `.ipp` implementation files.
2. **`ASIO_STANDALONE`** – Optional. Removes the Boost dependency; set this if you want pure standard C++.

No additional linker flags (such as `-lasio`) are required. You only need to ensure the `include` directory from the chriskohlhoff/asio repository is in your compiler's search path and link against the pthread library for threading support.

## Complete Header-Only Code Examples

The following examples compile without linking against `libasio`. Both require only the `-pthread` flag for threading support.

### Example 1: Async Timer (Standalone Mode)

This minimal example demonstrates a one-shot timer using standalone Asio:

```cpp
#define ASIO_STANDALONE   // optional: disables Boost dependencies
#define ASIO_HEADER_ONLY  // enable header‑only mode
#include <asio.hpp>
#include <iostream>

int main() {
  asio::io_context ctx;
  asio::steady_timer timer(ctx, std::chrono::seconds(1));

  timer.async_wait([](const asio::error_code& ec) {
    if (!ec) std::cout << "Timer fired!\n";
  });

  ctx.run();   // runs the event loop
}

```

Compile with: `g++ -std=c++17 -pthread example1.cpp`

### Example 2: TCP Echo Server

This example shows a concurrent echo server accepting connections:

```cpp
#define ASIO_HEADER_ONLY
#include <asio.hpp>
#include <iostream>

using asio::ip::tcp;

int main() {
  try {
    asio::io_context io;
    tcp::acceptor acceptor(io, tcp::endpoint(tcp::v4(), 12345));

    std::function<void()> do_accept;
    do_accept = [&]() {
      auto socket = std::make_shared<tcp::socket>(io);
      acceptor.async_accept(*socket, [&, socket](const asio::error_code& ec) {
        if (!ec) {
          asio::async_write(*socket,
                            asio::buffer("Hello from header‑only Asio!\n"),
                            [socket](auto, auto) {});
        }
        do_accept();  // accept next connection
      });
    };
    do_accept();
    io.run();
  } catch (std::exception& e) {
    std::cerr << "Error: " << e.what() << "\n";
  }
}

```

Compile with: `g++ -std=c++17 -pthread echo_server.cpp`

## Key Implementation Files in the Asio Source

Understanding these files helps when debugging or extending Asio in header-only mode:

- **[`include/asio.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio.hpp)** – The main umbrella header that aggregates all public Asio components.
- **[`include/asio/config.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/config.hpp)** – Contains the conditional logic at lines 90-94 that includes `asio/impl/config.ipp` when `ASIO_HEADER_ONLY` is defined.
- **[`include/asio/detail/config.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/detail/config.hpp)** – Defines core macros including `ASIO_STANDALONE` (lines 17-27) and platform detection logic.
- **[`include/asio/impl/config.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/impl/config.hpp)** – Declares the implementation functions used by the header-only mode.
- **`include/asio/impl/config.ipp`** – Contains the inline implementations that replace compiled library functions when in header-only mode.
- **[`include/asio/detail/socket_ops.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/detail/socket_ops.hpp)** – Exemplifies the internal pattern used throughout the library to conditionally include implementation details.

## Summary

- Define **`ASIO_HEADER_ONLY`** before including any Asio headers to enable header-only mode.
- The library pulls implementation from **`.ipp` files** (such as `asio/impl/config.ipp`) instead of external compiled objects.
- Use **`ASIO_STANDALONE`** to eliminate Boost dependencies and rely solely on standard C++.
- No linking against `libasio` is required; only compile with `-pthread` for threading support.
- This mode works identically across all platforms supported by the chriskohlhoff/asio codebase.

## Frequently Asked Questions

### Does Asio header-only mode require Boost?

No. While Asio originated as Boost.Asio, the standalone version (chriskohlhoff/asio) operates independently. Define `ASIO_STANDALONE` to ensure no Boost headers are included. The header-only mechanism works equally well in both configurations, though standalone mode is typically preferred for modern C++ projects.

### What is the difference between ASIO_HEADER_ONLY and ASIO_STANDALONE?

**`ASIO_HEADER_ONLY`** controls how the library is compiled, determining whether implementation code comes from `.ipp` files or a pre-compiled library. **`ASIO_STANDALONE`** controls dependencies, switching between Boost libraries and standard C++ equivalents. You can use either macro independently, though they are commonly defined together for drop-in header-only usage.

### Is there a performance penalty for using Asio header-only?

There is no inherent runtime performance penalty. The same machine code executes in both modes; the only difference is whether functions are inlined into your translation units or linked from a compiled library. Modern link-time optimization often eliminates any binary size differences between the two approaches.

### Can I mix header-only and compiled Asio in the same project?

No. You must choose one mode consistently across your entire project. Mixing translation units compiled with `ASIO_HEADER_ONLY` and others expecting a compiled library (such as `-lboost_asio` or `-lasio`) will result in duplicate symbol definitions or missing references at link time.