Does Asio Have a Header-Only Option? Using the Asio Library Without Compilation
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 (lines 90-94), this conditional inclusion is clearly demonstrated:
#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. 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 (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:
ASIO_HEADER_ONLY– Required. Enables the inline inclusion of.ippimplementation files.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:
#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:
#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– The main umbrella header that aggregates all public Asio components.include/asio/config.hpp– Contains the conditional logic at lines 90-94 that includesasio/impl/config.ippwhenASIO_HEADER_ONLYis defined.include/asio/detail/config.hpp– Defines core macros includingASIO_STANDALONE(lines 17-27) and platform detection logic.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– Exemplifies the internal pattern used throughout the library to conditionally include implementation details.
Summary
- Define
ASIO_HEADER_ONLYbefore including any Asio headers to enable header-only mode. - The library pulls implementation from
.ippfiles (such asasio/impl/config.ipp) instead of external compiled objects. - Use
ASIO_STANDALONEto eliminate Boost dependencies and rely solely on standard C++. - No linking against
libasiois required; only compile with-pthreadfor 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →