I forgot about this, and now that you mention it I will have to study my new libraries (Http.Io and Websocket.Io) to figure out how much can be compiled separately. The answer to your question is simple though: any code whose compilation would be affected by Asio's configuration macros must remain in headers. This means that the amount of code that is compiled into the static or shared library is going to be small. My approach for tackling this is to break up my libraries into two parts. A "protocol" library (also called "sans-io": https://sans-io.readthedocs.io/how-to-sans-io.html) which is fully compiled and an "i/o" library which uses Asio and the protocol library. The io library is still compiled but there is more header-only material. I strive to minimize the amount of I/O-specific code. This is process is more disciplined by having the protocol library be physically separated.
Actually, MySQL did this some months ago. There is no physical separation of libraries, and the sansio part is internal, but I'm a disciplined author, and the change was one of the best things I did. Yet, you need to measure. What takes time to build is instantiating ssl::stream async methods. While keeping the protocol in source helps, you won't get real benefits until you tackle this problem. MySQL is migrating away from the fully-templated connection to a type-erased model (I've measured and efficiency isn't really affected - the best way to optimize is to provide things like pipelines and batch inserts). MySQL now uses any_completion_handler for this, and manages to cut times pretty well. It will all be cleaner when the new type-erased connections become the default.
Okay well it sounds like your library is already not "header-only" in practice... LOL. If you require linking to OpenSSL then you are paying all the costs of header-only development without getting the full benefits. Let me make this clear:
It's not. As I said, I've been wanting to get rid of header-onlyness for a lot of time. But, there's Boost.Asio :)
* We (C++ library authors collectively) MUST make OpenSSL easy to install, with NO friction for users
My experience with this was: - If you're using CMake, find_package(OpenSSL REQUIRED) is good, and (most) users will do it without a problem. - If you're doing the equivalent from b2, things work in Linux but not in Windows, where additional configuration on the user side is required. As I mentioned, this has no relevance if the Asio point doesn't have a solution, as you seem to imply.