Merge pull request #13 from apmccartney/master

Expanded CMake Support
This commit is contained in:
mandreyel 2018-10-17 11:42:03 +02:00 committed by GitHub
commit bf0dd0158e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 304 additions and 45 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
test/**
!test/test.cpp
!test/example.cpp
!test/CMakeLists.txt
build/

View File

@ -1,36 +1,132 @@
cmake_minimum_required( VERSION 3.2.2 )
project( mio )
cmake_minimum_required(VERSION 3.8)
### Standard
set( CMAKE_CXX_STANDARD 11 )
#
# Here we check whether mio is being configured in isolation or as a component
# of a larger project. To do so, we query whether the `PROJECT_NAME` CMake
# variable has been defined. In the case it has, we can conclude mio is a
# subproject.
#
# This convention has been borrowed from the Catch C++ unit testing library.
#
if(DEFINED PROJECT_NAME)
set(subproject ON)
else()
set(subproject OFF)
endif()
project(mio VERSION 1.0.0 LANGUAGES C CXX)
include (CTest)
include (CMakeDependentOption)
# Generate 'compile_commands.json' for clang_complete
set( CMAKE_EXPORT_COMPILE_COMMANDS ON )
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
### Flags/Options
option( BUILD_TESTS "Enable the building of mio unit tests" OFF )
#
# The `mio.testing` options only appear as cmake-gui and ccmake options iff
# mio is the highest level project. In the case that mio is a subproject, these
# options are hidden from the user interface and set to `OFF`
#
# Iff mio is the highest level project, this option is defaulted to the value
# of the traditional course grain testing option `BUILD_TESTING` established by
# the CTest module
#
CMAKE_DEPENDENT_OPTION(mio.tests
"Build the mio tests and integrate with ctest"
${BUILD_TESTING} "NOT subproject" OFF)
### Library targets
add_library( mio INTERFACE)
target_include_directories( mio INTERFACE include )
install(
DIRECTORY include/
DESTINATION include
)
#
# mio has no compiled components. As such, we declare it as an `INTERFACE`
# library, which denotes a collection of target properties to be applied
# transitively to linking targets. In our case, this amounts to an include
# directory and project header files.
#
add_library(mio INTERFACE)
add_library(mio::mio ALIAS mio)
### Test targets
if( BUILD_TESTS )
## test
add_executable(
test
test/test.cpp
)
target_link_libraries( test PRIVATE mio )
## example
add_executable(
example
test/example.cpp
)
target_link_libraries( example PRIVATE mio )
#
# mio requires C++ 11 support, at a minimum. Setting the `cxx_std_11` compile
# features ensures that the corresponding C++ standard flag is populated in
# targets linking to mio
#
target_compile_features(mio INTERFACE cxx_std_11)
#
# The include directory for mio can be expected to vary between build
# and installaion. Here we use a CMake generator expression to dispatch
# on how the configuration under which this library is being consumed.
#
target_include_directories(mio INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
$<INSTALL_INTERFACE:include>)
add_subdirectory(include/mio)
if(mio.tests)
add_subdirectory(test)
endif()
#
# Non-testing header files (preserving relative paths) are installed to the
# `include` subdirectory of the `$INSTALL_DIR/${CMAKE_INSTALL_PREFIX}`
# directory. Source file permissions preserved.
#
install(DIRECTORY include/
DESTINATION include
USE_SOURCE_PERMISSIONS
FILES_MATCHING PATTERN "*.*pp")
#
# As a header-only library, there are no target components to be installed
# directly (the PUBLIC_HEADER property is not white listed for INTERFACE
# targets for some reason).
#
# However, it is worthwhile export our target description in order to later
# generate a CMake configuration file for consumption by CMake's `find_package`
# intrinsic
#
install(TARGETS mio EXPORT mioConfig)
install(EXPORT mioConfig
FILE mioConfig.cmake
NAMESPACE mio::
DESTINATION share/cmake/mio
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
include(CMakePackageConfigHelpers) # provides `write_basic_package_version_file`
write_basic_package_version_file("mioConfigVersion.cmake"
VERSION ${mio_VERSION}
COMPATIBILITY SameMajorVersion)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/mioConfigVersion.cmake"
DESTINATION share/cmake/mio
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
#
# Rudimentary CPack support.
#
# CPack provides a mechanism to generate installation packaging for a project,
# e.g., self-extracting shell scripts, compressed tarballs, Debian Package files,
# RPM Package Manager files, Windows NSIS installation wizards,
# Apple Disk Images (.dmg), etc.
#
# Any system libraries required (runtimes, threading, etc) should be bundled
# with the project for this type of installation. The
# `InstallRequiredSystemLibraries` CMake module attempts to provide this
# functionality in an automated way. Additional libraries may be specified as
#
# ```cmake
# list(APPEND CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS <library>)
# ```
#
# A packaged installation can be generated by calling
#
# ```sh
# cpack -G <packaging type> --config CPackConfig.cmake
# ```
#
# See `cpack --help` or the CPack documentation for more information.
#
include( InstallRequiredSystemLibraries )
set( CPACK_PACKAGE_VENDOR "mandreyel" )
set( CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" )
set( CMAKE_PROJECT_HOMEPAGE_URL "https://github.com/mandreyel/mio" )
include( CPack )

148
README.md
View File

@ -156,19 +156,147 @@ using mmap_sink = mio::basic_mmap_sink<std::byte>;
Though generally not needed, since mio maps users requested offsets to page boundaries, you can query the underlying system's page allocation granularity by invoking `mio::page_size()`, which is located in `mio/page.hpp`.
### Installation
mio is a header-only library, so just copy the contents in `mio/include` into your system wide include path, such as `/usr/include`, or into your project's lib folder.
## CMake
A `CMakeLists.txt` is provided to allow easy git submodule usage or installation.
As a header-only library, mio has no compiled components. Nevertheless, a [CMake](https://cmake.org/overview/) build system is provided to allow easy testing, installation, and subproject composition on many platforms and operating systems.
To use as a submodule, clone mio within your project's dependencies/externals folder and add:
### Testing
Mio is distributed with a small suite of tests and examples.
When mio is configured as the highest level CMake project, this suite of executables is built by default.
Mio's test executables are integrated with the CMake test driver program, [CTest](https://cmake.org/cmake/help/latest/manual/ctest.1.html).
CMake supports a number of backends for compilation and linking.
To use a static configuration build tool, such as GNU Make or Ninja:
```sh
cd <mio source directory>
mkdir build
cd build
# Configure the build
cmake -D CMAKE_BUILD_TYPE=<Debug | Release> \
-G <"Unix Makefiles" | "Ninja"> ..
# build the tests
< make | ninja | cmake --build . >
# run the tests
< make test | ninja test | cmake --build . --target test | ctest >
```
add_subdirectory( dependencies_folder/mio )
target_link_libraries( MyCoolProject mio )
To use a dynamic configuration build tool, such as Visual Studio or Xcode:
```sh
cd <mio source directory>
mkdir build
cd build
# Configure the build
cmake -G <"Visual Studio 14 2015 Win64" | "Xcode"> ..
# build the tests
cmake --build . --config <Debug | Release>
# run the tests via ctest...
ctest --build-config <Debug | Release>
# ... or via CMake build tool mode...
cmake --build . --config <Debug | Release> --target test
```
to your project's `CMakeLists.txt` to add mio into `MyCoolProject`'s include-space.
To install, do an out-of-source build(such as making a `build` folder and running `cmake ..` inside of it) and then run `sudo make install` to copy relevant include files to
Of course the **build** and **test** steps can also be executed via the **all** and **test** targets, respectively, from within the IDE after opening the project file generated during the configuration step.
The optional `BUILD_TESTS` option can be used to build unit tests(off by default) by instead using `cmake -DBUILD_TESTS=ON ..`
Mio's testing is also configured to operate as a client to the [CDash](https://www.cdash.org/) software quality dashboard application. Please see the [Kitware documentation](https://cmake.org/cmake/help/latest/manual/ctest.1.html#dashboard-client) for more information on this mode of operation.
### Installation
Mio's build system provides an installation target and support for downstream consumption via CMake's [`find_package`](https://cmake.org/cmake/help/v3.0/command/find_package.html) intrinsic function.
CMake allows installation to an arbitrary location, which may be specified by defining `CMAKE_INSTALL_PREFIX` at configure time.
In the absense of a user specification, CMake will install mio to conventional location based on the platform operating system.
To use a static configuration build tool, such as GNU Make or Ninja:
```sh
cd <mio source directory>
mkdir build
cd build
# Configure the build
cmake [-D CMAKE_INSTALL_PREFIX="path/to/installation"] \
[-D BUILD_TESTING=False] \
-D CMAKE_BUILD_TYPE=Release \
-G <"Unix Makefiles" | "Ninja"> ..
# install mio
<make install | ninja install | cmake --build . --target install>
```
To use a dynamic configuration build tool, such as Visual Studio or Xcode:
```sh
cd <mio source directory>
mkdir build
cd build
# Configure the project
cmake [-D CMAKE_INSTALL_PREFIX="path/to/installation"] \
[-D BUILD_TESTING=False] \
-G <"Visual Studio 14 2015 Win64" | "Xcode"> ..
# install mio
cmake --build . --config Release --target install
```
Note that the last command of the installation sequence may require administrator privileges (e.g. `sudo`) if the installation root directory lies outside your home directory.
This installation
+ copies the mio header files to the `include/mio` subdirectory of the installation root
+ generates and copies several CMake configuration files to the `share/cmake/mio` subdirectory of the installation root
This latter step allows downstream CMake projects to consume mio via `find_package`, e.g.
```cmake
find_package( mio REQUIRED )
target_link_libraries( MyTarget PUBLIC mio::mio )
```
If mio was installed to a non-conventional location, it may be necessary for downstream projects to specify the mio installation root directory via either
+ the `CMAKE_PREFIX_PATH` configuration option,
+ the `CMAKE_PREFIX_PATH` environment variable, or
+ `mio_DIR` environment variable.
Please see the [Kitware documentation](https://cmake.org/cmake/help/v3.0/command/find_package.html) for more information.
In addition, mio supports packaged relocatable installations via [CPack](https://cmake.org/cmake/help/latest/manual/cpack.1.html).
Following configuration, from the build directory, invoke cpack as follows to generate a packaged installation:
```sh
cpack -G <generator name> -C Release
```
The list of supported generators varies from platform to platform. See the output of `cpack --help` for a complete list of supported generators on your platform.
### Subproject Composition
To use mio as a subproject, copy the mio repository to your project's dependencies/externals folder.
If your project is version controlled using git, a git submodule or git subtree can be used to syncronize with the updstream repository.
The [use](https://services.github.com/on-demand/downloads/submodule-vs-subtree-cheat-sheet/) and [relative advantages](https://andrey.nering.com.br/2016/git-submodules-vs-subtrees/) of these git facilities is beyond the scope of this document, but in brief, each may be established as follows:
```sh
# via git submodule
cd <my project's dependencies directory>
git submodule add -b master https://github.com/mandreyel/mio.git
# via git subtree
cd <my project's root directory>
git subtree add --prefix <path/to/dependencies>/mio \
https://github.com/mandreyel/mio.git master --squash
```
Given a mio subdirectory in a project, simply add the following lines to your project's to add mio include directories to your target's include path.
```cmake
add_subdirectory( path/to/mio/ )
target_link_libraries( MyTarget PUBLIC <mio::mio | mio> )
```
Note that, as a subproject, mio's tests and examples will not be built and CPack integration is deferred to the host project.

View File

@ -0,0 +1,16 @@
#
# While not strictly necessary to specify header files as target sources,
# doing so populates these files in the source listing when CMake is used
# to generate XCode and Visual Studios projects
#
target_sources(mio INTERFACE
$<BUILD_INTERFACE:
${CMAKE_CURRENT_LIST_DIR}/mmap.hpp
${CMAKE_CURRENT_LIST_DIR}/page.hpp
${CMAKE_CURRENT_LIST_DIR}/shared_mmap.hpp>
$<INSTALL_INTERFACE:
include/mio/mmap.hpp
include/mio/page.hpp
include/mio/shared_mmap.hpp>)
add_subdirectory(detail)

View File

@ -0,0 +1,11 @@
#
# iff mio is the highest level project, include the implementation
# detail files in the source listing for CMake-generated IDE projects
#
if(NOT subproject)
target_sources(mio INTERFACE
$<BUILD_INTERFACE:
${CMAKE_CURRENT_LIST_DIR}/basic_mmap.hpp
${CMAKE_CURRENT_LIST_DIR}/basic_mmap.ipp
${CMAKE_CURRENT_LIST_DIR}/string_util.hpp>)
endif()

View File

@ -21,7 +21,7 @@
#ifndef MIO_BASIC_MMAP_HEADER
#define MIO_BASIC_MMAP_HEADER
#include "../page.hpp"
#include "mio/page.hpp"
#include <iterator>
#include <string>
@ -159,6 +159,6 @@ bool operator>=(const basic_mmap<ByteT>& a, const basic_mmap<ByteT>& b);
} // namespace detail
} // namespace mio
#include "basic_mmap.ipp"
#include "mio/detail/basic_mmap.ipp"
#endif // MIO_BASIC_MMAP_HEADER

View File

@ -21,9 +21,9 @@
#ifndef MIO_BASIC_MMAP_IMPL
#define MIO_BASIC_MMAP_IMPL
#include "basic_mmap.hpp"
#include "string_util.hpp"
#include "../page.hpp"
#include "mio/detail/basic_mmap.hpp"
#include "mio/detail/string_util.hpp"
#include "mio/page.hpp"
#include <algorithm>
#include <cstdint>

View File

@ -21,7 +21,7 @@
#ifndef MIO_SHARED_MMAP_HEADER
#define MIO_SHARED_MMAP_HEADER
#include "mmap.hpp"
#include "mio/mmap.hpp"
#include <system_error> // std::error_code
#include <memory> // std::shared_ptr

7
test/CMakeLists.txt Normal file
View File

@ -0,0 +1,7 @@
add_executable(mio.test test.cpp)
target_link_libraries(mio.test PRIVATE mio::mio)
add_test(NAME mio.test COMMAND mio.test)
add_executable(mio.example example.cpp)
target_link_libraries(mio.example PRIVATE mio::mio)
add_test(NAME mio.example COMMAND mio.example)