vimpunk / mio

Cross-platform C++11 header-only library for memory mapped file IO
MIT License
1.71k stars 157 forks source link

Allow consumers of mio to control the imported surface area of the Windows API #21

Closed gmbeard closed 5 years ago

gmbeard commented 6 years ago

Because the Windows version of mio uses the WinAPI, it would be useful to allow consumers to control how much of the WinAPI is pulled into their own applications. Being header only, #defines such as WIN32_LEAN_AND_MEAN will leak into upstream downstream code. This may cause an inconvenience if any upstream downstream code needs to use APIs such as Windows Cryptography, GDI, etc. This SO answer provides a nice list of what WIN32_LEAN_AND_MEAN disables.

Of course, consumers can still include the individual WIndows headers they need explicitly, and this could well be a suitable solution, instead of addressing this in mio.

My initial suggestion (on Reddit) was to expose a CMake option (such as MIO_MINIMAL_WIN_API) to allow consumers to control this. On reflection, this maybe not ideal; As I understand, this option would only be controllable at the point mio is configured, not once it's installed. A better solution would be to expose multiple CMake targets, instead. For example, mio::mio would default to a fully stripped down WinAPI, while mio::mio_full_winapi wouldn't set any WinAPI definitions. This way, the consumer can choose whichever suits their project.

All existing #defines for WIN32_LEAN_AND_MEAN, etc. would need to be removed from the header files for this to work.

This could be implemented with somthing similar to...

if(WIN32)
    add_library(mio_full_winapi INTERFACE)
    add_library(mio::mio_full_winapi ALIAS mio_full_winapi)

    # [ All the target configuration for the original mio
    # target should be applied to mio_full_winapi here ]

    add_library(mio INTERFACE) # This target will just extend mio_full_winapi to
                               # add defintions needed to strip down the imported 
                               # WinAPI
    add_library(mio::mio ALIAS mio)

    target_compile_definitions(mio
        INTERFACE WIN32_LEAN_AND_MEAN NOMINMAX # and any others (STRICT, etc)
    )

    target_link_libraries(mio
        INTERFACE mio_full_winapi
    )

    install(
        TARGETS
            mio
            mio_full_winapi
        EXPORT
            mioConfig
    )
else()
    # [ The normal mio target config for non-Windows here ]
endif()

It could probably be structured better (with include()s, etc) but you get the idea. I'm happy to attempt a PR for this, if needed.

vimpunk commented 6 years ago

@gmbeard I never even considered this, but it's a valid point. Thank you for bringing it to my attention.

I think your proposed solution is fine, so I'd gladly accept a PR! If you decide to do this, could you please include relevant documentation in the README?

gmbeard commented 6 years ago

@mandreyel Sure, I will update the docs. No problem. I'm pretty close to sending a PR but I only have access to Windows and a FreeBSD host for compiling. Are you able to test compilation on any other OSes?

vimpunk commented 6 years ago

@gmbeard Awesome! I only have access to Linux, but we could create an issue asking for help in testing on other platforms, although I think coverage is pretty high already.