Building a header-only library — Hello World

Installing a header-only library

Directory Structure

➜ tree -I 'examples|cmake' hello
hello
├── CMakeLists.txt
├── Makefile
├── include
│ ├── hello
│ │ └── greeting.hpp
│ └── hello.hpp
└── test
└── test.cpp
➜ tree type_safe/include -I detail
type_safe/include
└── type_safe
├── arithmetic_policy.hpp
├── boolean.hpp
├── bounded_type.hpp
├── compact_optional.hpp
├── config.hpp
├── constrained_type.hpp
├── deferred_construction.hpp
├── downcast.hpp
├── flag.hpp
├── flag_set.hpp
├── floating_point.hpp
├── index.hpp
├── integer.hpp
├── narrow_cast.hpp
├── optional.hpp
├── optional_ref.hpp
├── output_parameter.hpp
├── reference.hpp
├── strong_typedef.hpp
├── tagged_union.hpp
├── types.hpp
├── variant.hpp
└── visitor.hpp
1 directory, 23 files
mkdir hello
cd hello
git init
mkdir test
mkdir -p include/hello

Just the code, Thanks

// include/hello/greeting.hpp#include <string>namespace hello {inline std::string greeting()
{
std::string response = "Hello World!!";
return response;
}
}
// include/hello.hpp#include "hello/greeting.hpp"
// test/test.cpp#include <hello.hpp>
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
TEST_CASE("test_greeting")
{
std::string value = hello::greeting();
REQUIRE(value == std::string("Hello World!!"));
}

Building

# CMakeLists.txt - Part 1# Build
cmake_minimum_required(VERSION 3.12)
project(hello VERSION 1.0.0 LANGUAGES CXX)include(GNUInstallDirs)add_library(${PROJECT_NAME} INTERFACE)target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_11)target_include_directories(
${PROJECT_NAME}
INTERFACE
$<BUILD_INTERFACE:${${PROJECT_NAME}_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
mkdir build
cd build
cmake ..
make

Testing

# CMakeLists.txt - Part 2# Test
find_package(Catch2 REQUIRED)
add_executable(hello_test test/test.cpp)
target_link_libraries(hello_test PRIVATE Catch2::Catch2)
target_include_directories(hello_test PRIVATE ${PROJECT_SOURCE_DIR}/include)
include(CTest)
include(Catch)
catch_discover_tests(hello_test)
enable_testing()
cd build
cmake ..
make
make test

Installing

# cmake/helloConfig.cmake.in@PACKAGE_INIT@include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")set_and_check(hello_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
check_required_components("@PROJECT_NAME@")
# CMakeLists.txt - Part 3# Install
install(TARGETS ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}_Targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
include(CMakePackageConfigHelpers)
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion)
if(NOT INCLUDE_INSTALL_DIR)
set(INCLUDE_INSTALL_DIR include/hello)
endif()
configure_package_config_file(
"${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake
PATH_VARS INCLUDE_INSTALL_DIR)
install(EXPORT ${PROJECT_NAME}_Targets
FILE ${PROJECT_NAME}Targets.cmake
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake)
install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake)
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME})
cd build
cmake ..
cmake --build . --config Release --target install
---
-- The CXX compiler identification is AppleClang 11.0.0.11000033
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/ryangraham/ryan/hello/build
Scanning dependencies of target hello_test
[ 50%] Building CXX object CMakeFiles/hello_test.dir/test/test.cpp.o
[100%] Linking CXX executable hello_test
[100%] Built target hello_test
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/share/hello/cmake/helloTargets.cmake
-- Installing: /usr/local/share/hello/cmake/helloConfig.cmake
-- Installing: /usr/local/share/hello/cmake/helloConfigVersion.cmake
-- Up-to-date: /usr/local/include/hello
-- Installing: /usr/local/include/hello/hello.hpp
-- Up-to-date: /usr/local/include/hello/hello
-- Installing: /usr/local/include/hello/hello/greeting.hpp

Usage

➜ tree hello/examples
hello/examples
└── cli
├── CMakeLists.txt
├── Makefile
└── src
└── main.cpp
2 directories, 3 file
// cli/src/main.cpp#include <hello.hpp>
#include <iostream>
int main()
{
using namespace hello; std::string value = greeting();
std::cout << value << std::endl;
return 0;
}
# cli/CMakeLists.txtcmake_minimum_required(VERSION 3.12)
project(cli LANGUAGES CXX)
find_package(hello CONFIG REQUIRED)
message("hello_DIR: ${hello_DIR}")
message("hello_INCLUDE_DIR: ${hello_INCLUDE_DIR}")
include_directories(${hello_INCLUDE_DIR})
add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} hello::hello)
add_custom_target(run
COMMAND cli
DEPENDS cli
WORKING_DIRECTORY ${CMAKE_PROJECT_DIR}
)
# starting in cli as pwdmkdir build
cd build
cmake ..
make
make run
---
-- The CXX compiler identification is AppleClang 11.0.0.11000033
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
hello_DIR: /usr/local/share/hello/cmake
hello_INCLUDE_DIR: /usr/local/include/hello
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/ryangraham/ryan/hello/examples/cli/build
Scanning dependencies of target cli
[ 50%] Building CXX object CMakeFiles/cli.dir/src/main.cpp.o
[100%] Linking CXX executable cli
[100%] Built target cli
[100%] Built target cli
Scanning dependencies of target run
Hello World!!
[100%] Built target run

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store