Unverified Commit f3e3380b authored by Peter Steinbach's avatar Peter Steinbach Committed by GitHub

Merge pull request #8 from psteinb/cmake-single-header-flow

Cmake single header flow
parents ea6a4177 8ab7ce32
# C++ project
language: cpp
dist: trusty
script:
- mkdir -p build && cd build
- cmake ..
- make
- ctest -V -j
- cd ..
\ No newline at end of file
# cmake compatibility issues
CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
CMAKE_MINIMUM_REQUIRED(VERSION 3.8)
# project name
PROJECT(compass CXX)
......@@ -25,7 +25,12 @@ SET (COMPASS_ID "${COMPASS_VENDOR_ID}.${PROJECT_NAME}")
option(WITH_CXX11_ABI "enable _GLIBCXX_USE_CXX11_ABI in GCC 5.0+" ON)
option(WITH_TESTS "enable unit tests" ON)
option(WITH_SINGLE_HEADER "produce single header file from include/" ON)
option(WITH_SINGLE_HEADER "use single header file from single-header/" OFF)
option(GENERATE_SINGLE_HEADER "run pcpp on include/ and produce single-header" OFF)
if(GENERATE_SINGLE_HEADER)
set(WITH_SINGLE_HEADER ON CACHED)
endif()
check_cxx_compiler_flag(-Wl,-Bsymbolic HAS_BSYMBOLIC_COMPILERFLAG)
check_cxx_compiler_flag("-Xclang -march=native" HAS_XCLANG_COMPILERFLAG)
......@@ -36,17 +41,80 @@ check_cxx_compiler_flag(-O3 HAS_O3_COMPILERFLAG)
check_cxx_compiler_flag(/Oi HAS_OI_COMPILERFLAG)
check_cxx_compiler_flag(-Wno-overflow HAS_WNOOVERFLOW_COMPILERFLAG)
set(COMPASS_TARGET_NAME ${PROJECT_NAME})
set(COMPASS_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}"
CACHE INTERNAL "")
set(COMPASS_INCLUDE_INSTALL_DIR "include")
set(COMPASS_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
set(COMPASS_CMAKE_CONFIG_TEMPLATE "cmake/config.cmake.in")
set(COMPASS_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}")
set(COMPASS_CMAKE_VERSION_CONFIG_FILE "${COMPASS_CMAKE_CONFIG_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(COMPASS_CMAKE_PROJECT_CONFIG_FILE "${COMPASS_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Config.cmake")
set(COMPASS_CMAKE_PROJECT_TARGETS_FILE "${COMPASS_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Targets.cmake")
if (NOT WITH_SINGLE_HEADER)
set(COMPASS_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/include")
message(STATUS "Using the multi-header code from ${COMPASS_INCLUDE_BUILD_DIR}")
else()
set(COMPASS_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/single_include")
message(STATUS "Using the single-header code from ${COMPASS_INCLUDE_BUILD_DIR}")
endif()
add_library(${COMPASS_TARGET_NAME} INTERFACE)
add_library(${PROJECT_NAME}::${COMPASS_TARGET_NAME} ALIAS ${COMPASS_TARGET_NAME})
target_include_directories(
${COMPASS_TARGET_NAME}
INTERFACE
$<BUILD_INTERFACE:${COMPASS_INCLUDE_BUILD_DIR}>
$<INSTALL_INTERFACE:include>
)
target_compile_definitions(${COMPASS_TARGET_NAME}
INTERFACE LIBRARY_HEADER_ONLY
INTERFACE cxx_std_11
)
## ============== generate single-header ================
if (${GENERATE_SINGLE_HEADER})
find_program(PCPP NAMES pcpp PATH ${PCPP_PATH} PATH_SUFFIXES bin NO_DEFAULT_PATH)
find_program(PCPP NAMES pcpp)
if(EXISTS ${PCPP})
message(STATUS "pcpp found at ${PCPP}")
if(NOT EXISTS ${COMPASS_INCLUDE_BUILD_DIR})
file(MAKE_DIRECTORY ${COMPASS_INCLUDE_BUILD_DIR})
message("created ${COMPASS_INCLUDE_BUILD_DIR}")
endif()
execute_process(COMMAND ${PCPP} -o ${COMPASS_INCLUDE_BUILD_DIR}/compass.hpp --line-directive --passthru-defines --passthru-unfound-includes --passthru-unknown-exprs ${PROJECT_SOURCE_DIR}/include/compass.hpp
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE PCPP_RESULT)
if(${PCPP_RESULT} EQUAL 0)
message(STATUS "Preprocessed ${PROJECT_SOURCE_DIR}/include/compass.hpp into ${COMPASS_INCLUDE_BUILD_DIR}/compass.hpp")
else()
message(FATAL_ERROR "Preprocessing ${PROJECT_SOURCE_DIR}/include/compass.hpp into ${COMPASS_INCLUDE_BUILD_DIR}/compass.hpp failed")
endif()
else()
message(FATAL_ERROR "pcpp not found (${PCPP_PATH} ${PCPP_FOUND}), unable to continue in single-header configuration")
endif()
endif()
#target_sources(compass INTERFACE include/compass.hpp)
IF(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "5.0")
set(WITH_CXX11_ABI ON)
endif()
if(${WITH_CXX11_ABI})
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1)
message(">> [GCC ${CMAKE_CXX_COMPILER_VERSION}] adding -D_GLIBCXX_USE_CXX11_ABI=1")
set(CXX11_ABI_VALUE 1)
else()
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
message(">> [GCC ${CMAKE_CXX_COMPILER_VERSION}] adding -D_GLIBCXX_USE_CXX11_ABI=1")
set(CXX11_ABI_VALUE 0)
endif()
target_compile_definitions(${COMPASS_TARGET_NAME} INTERFACE -D_GLIBCXX_USE_CXX11_ABI=${CXX11_ABI_VALUE})
message(">> [GCC ${CMAKE_CXX_COMPILER_VERSION}] adding -D_GLIBCXX_USE_CXX11_ABI=${CXX11_ABI_VALUE}")
endif()
IF(NOT WIN32)
......@@ -60,14 +128,26 @@ if(WITH_TESTS)
add_subdirectory(tests)
enable_testing()
include("CTestLists.txt")
endif()
################################ EXPORT/INSTALL ################################
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/"
export(
TARGETS ${COMPASS_TARGET_NAME}
NAMESPACE ${PROJECT_NAME}::
FILE ${COMPASS_CMAKE_PROJECT_TARGETS_FILE}
)
install(
TARGETS ${COMPASS_TARGET_NAME}
EXPORT ${PROJECT_NAME}Targets
INCLUDES DESTINATION ${COMPASS_INCLUDE_INSTALL_DIR}
)
install(
EXPORT ${COMPASS_TARGETS_EXPORT_NAME}
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${COMPASS_CONFIG_INSTALL_DIR}
)
install(DIRECTORY "${COMPASS_INCLUDE_BUILD_DIR}"
DESTINATION include
FILES_MATCHING
PATTERN "*.hpp"
)
)
......@@ -9,10 +9,11 @@ cmake_host_system_information(RESULT CURRENT_HOSTNAME QUERY HOSTNAME)
if(${CURRENT_HOSTNAME} MATCHES ".*(falcon2|talisker|schorle|scicomp-pc-3|recovery-station).*")
message(">> hostname (${CURRENT_HOSTNAME}): added compass test ")
add_test(NAME compass_impl COMMAND test_compass_impl)
add_test(NAME compass_sizes COMMAND test_compass_sizes)
add_test(NAME machine COMMAND test_machine)
else()
message(">> unknown host (${CURRENT_HOSTNAME}): no tests were written for your host ")
endif()
add_test(NAME compass_impl COMMAND test_compass_impl)
add_test(NAME bitview COMMAND test_bitview)
# compass
[![Build Status](https://travis-ci.org/psteinb/compass.svg?branch=master)](https://travis-ci.org/psteinb/compass)
# compass
A drop-in header-only C++ library to detect hardware capabilities at runtime and at compiletime.
......
This diff is collapsed.
......@@ -13,49 +13,53 @@ ExternalProject_Add(
)
ExternalProject_Get_Property(catch2 DOWNLOAD_DIR)
set(CATCH2_HEADER_PATH ${DOWNLOAD_DIR})
message(STATUS "catch2 header file download to ${CATCH2_HEADER_PATH}")
cmake_host_system_information(RESULT CURRENT_HOSTNAME QUERY HOSTNAME)
add_library(catcho OBJECT catch.cpp)
target_include_directories(catcho PRIVATE ${CATCH2_HEADER_PATH})
target_include_directories(catcho PUBLIC ${CATCH2_HEADER_PATH})
add_dependencies(catcho catch2)
if(${CURRENT_HOSTNAME} MATCHES ".*(falcon2|talisker|schorle|scicomp-pc-3|recovery-station).*")
add_executable(test_compass_impl test_compass_impl.cpp $<TARGET_OBJECTS:catcho>)
target_include_directories(test_compass_impl PRIVATE ${PROJECT_SOURCE_DIR}/include ${CATCH2_HEADER_PATH})
add_executable(test_compass_impl test_compass_impl.cpp $<TARGET_OBJECTS:catcho>)
target_include_directories(test_compass_impl PRIVATE ${CATCH2_HEADER_PATH} ${COMPASS_INCLUDE_BUILD_DIR})
add_executable(test_bitview test_bitview.cpp $<TARGET_OBJECTS:catcho>)
target_include_directories(test_bitview PRIVATE ${PROJECT_SOURCE_DIR}/include ${CATCH2_HEADER_PATH})
add_executable(test_compass_sizes test_compass_sizes.cpp $<TARGET_OBJECTS:catcho>)
target_include_directories(test_compass_sizes PRIVATE ${PROJECT_SOURCE_DIR}/include ${CATCH2_HEADER_PATH})
endif()
#idea for generating test fixture at cmake-invocation
#Windows 7: use `wmic cpu GET Name` to obtain clearname of CPU model
#Linux : use `lscpu` or `/proc/cpuinfo` to obtain more data about
#macOS : not sure yet what to use
add_executable(test_bitview test_bitview.cpp $<TARGET_OBJECTS:catcho>)
target_include_directories(test_bitview PRIVATE ${PROJECT_SOURCE_DIR}/include ${CATCH2_HEADER_PATH})
cmake_host_system_information(RESULT CURRENT_HOSTNAME QUERY HOSTNAME)
if(${CURRENT_HOSTNAME} MATCHES ".*(falcon2|talisker|schorle|scicomp-pc-3|recovery-station).*")
add_executable(test_machine test_machine.cpp $<TARGET_OBJECTS:catcho>)
target_include_directories(test_machine PRIVATE ${CATCH2_HEADER_PATH} ${COMPASS_INCLUDE_BUILD_DIR})
add_executable(test_compass_sizes test_compass_sizes.cpp $<TARGET_OBJECTS:catcho>)
target_include_directories(test_compass_sizes PRIVATE ${CATCH2_HEADER_PATH} ${COMPASS_INCLUDE_BUILD_DIR})
endif()
### test single header
if(WITH_SINGLE_HEADER)
find_program(PCPP NAME pcpp HINT ${PCPP_PATH})
if(PCPP_FOUND OR EXISTS ${PCPP_PATH})
add_custom_target(sh
COMMAND pcpp -o ${PROJECT_BINARY_DIR}/tests/compass-sh.hpp --line-directive --passthru-defines --passthru-unfound-includes --passthru-unknown-exprs ${PROJECT_SOURCE_DIR}/include/compass.hpp
BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/compass-sh.hpp
COMMENT "Preprocessing ${PROJECT_SOURCE_DIR}/include/compass.hpp into ${CMAKE_CURRENT_BINARY_DIR}/tests/compass-sh.hpp ..."
USES_TERMINAL)
# if(WITH_SINGLE_HEADER)
# find_program(PCPP NAME pcpp HINT ${PCPP_PATH})
# if(PCPP_FOUND OR EXISTS ${PCPP_PATH})
# add_custom_target(sh
# COMMAND pcpp -o ${PROJECT_BINARY_DIR}/tests/compass-sh.hpp --line-directive --passthru-defines --passthru-unfound-includes --passthru-unknown-exprs ${PROJECT_SOURCE_DIR}/include/compass.hpp
# BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/compass-sh.hpp
# COMMENT "Preprocessing ${PROJECT_SOURCE_DIR}/include/compass.hpp into ${CMAKE_CURRENT_BINARY_DIR}/tests/compass-sh.hpp ..."
# USES_TERMINAL)
add_executable(test_single_header test_single_header.cpp $<TARGET_OBJECTS:catcho> ${CMAKE_CURRENT_BINARY_DIR}/compass-sh.hpp)
add_dependencies(test_single_header sh)
target_include_directories(test_single_header PRIVATE ${PROJECT_BINARY_DIR}/tests ${CATCH2_HEADER_PATH})
# add_executable(test_single_header test_single_header.cpp $<TARGET_OBJECTS:catcho> ${CMAKE_CURRENT_BINARY_DIR}/compass-sh.hpp)
# add_dependencies(test_single_header sh)
# target_include_directories(test_single_header PRIVATE ${PROJECT_BINARY_DIR}/tests ${CATCH2_HEADER_PATH})
else()
message(WARNING "pcpp not found ${PCPP_PATH}")
endif()
# else()
# message(WARNING "pcpp not found ${PCPP_PATH}")
# endif()
endif()
# endif()
#include "catch.hpp"
#include "compass_fixture.hpp"
#include "compass.hpp"
......@@ -25,110 +24,20 @@ TEST_CASE( "compass_fundamentals" ){
REQUIRE(value.size()!=0u);
}
}
TEST_CASE_METHOD( host_reference, "machine_specific" ){
SECTION( "vendor_right" ){
auto value = compass::runtime::vendor();
REQUIRE(value.size()!=0u);
std::transform(value.begin(), value.end(),
value.begin(),
::tolower);
REQUIRE(value.find(expected_vendor)!=std::string::npos);
}
SECTION( "brand_right" ){
auto value = compass::runtime::brand();
REQUIRE(value.empty()!=true);
REQUIRE_THAT(value, Catch::Matchers::Contains(expected_brand) );
}
SECTION( "device_name_right" ){
auto value = compass::runtime::device_name();
REQUIRE(value.empty()!=true);
REQUIRE_THAT(value, Catch::Matchers::Contains(expected_device_name) );
}
SECTION( "ncores_right" ){
SECTION( "compass_yields_non_zero_corecount" ){
auto value = compass::runtime::threads();
REQUIRE(value>0u);
REQUIRE(value!=0);
REQUIRE(value==expected_ncores);
}
// SECTION( "physical_cores_right" ){
// auto value = compass::runtime::physical_threads();
// REQUIRE(value!=0);
// REQUIRE(value==expected_nphyscores);
// }
SECTION( "has_sse_right" ){
auto value = compass::runtime::has(compass::feature::sse());
SECTION( "compass_yields_non_zero_L1size" ){
REQUIRE(value==expected_has_sse);
}
SECTION( "has_sse2_right" ){
auto value = compass::runtime::has(compass::feature::sse2());
REQUIRE(value==expected_has_sse2);
}
SECTION( "has_sse3_right" ){
auto value = compass::runtime::has(compass::feature::sse3());
REQUIRE(value==expected_has_sse3);
}
SECTION( "has_sse4_right" ){
auto value = compass::runtime::has(compass::feature::sse4());
REQUIRE(value==expected_has_sse4);
}
SECTION( "has_avx_right" ){
auto value = compass::runtime::has(compass::feature::avx());
REQUIRE(value==expected_has_avx);
}
SECTION( "has_avx2_right" ){
auto value = compass::runtime::has(compass::feature::avx2());
REQUIRE(value==expected_has_avx2);
auto value = compass::runtime::size::cacheline::level(1);
REQUIRE(value>0u);
}
}
}
#include "catch.hpp"
#include "compass_fixture.hpp"
#include "compass.hpp"
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
TEST_CASE_METHOD( host_reference, "machine_specific" ){
SECTION( "vendor_right" ){
auto value = compass::runtime::vendor();
REQUIRE(value.size()!=0u);
std::transform(value.begin(), value.end(),
value.begin(),
::tolower);
REQUIRE(value.find(expected_vendor)!=std::string::npos);
}
SECTION( "brand_right" ){
auto value = compass::runtime::brand();
REQUIRE(value.empty()!=true);
REQUIRE_THAT(value, Catch::Matchers::Contains(expected_brand) );
}
SECTION( "device_name_right" ){
auto value = compass::runtime::device_name();
REQUIRE(value.empty()!=true);
REQUIRE_THAT(value, Catch::Matchers::Contains(expected_device_name) );
}
SECTION( "ncores_right" ){
auto value = compass::runtime::threads();
REQUIRE(value!=0);
REQUIRE(value==expected_ncores);
}
// SECTION( "physical_cores_right" ){
// auto value = compass::runtime::physical_threads();
// REQUIRE(value!=0);
// REQUIRE(value==expected_nphyscores);
// }
SECTION( "has_sse_right" ){
auto value = compass::runtime::has(compass::feature::sse());
REQUIRE(value==expected_has_sse);
}
SECTION( "has_sse2_right" ){
auto value = compass::runtime::has(compass::feature::sse2());
REQUIRE(value==expected_has_sse2);
}
SECTION( "has_sse3_right" ){
auto value = compass::runtime::has(compass::feature::sse3());
REQUIRE(value==expected_has_sse3);
}
SECTION( "has_sse4_right" ){
auto value = compass::runtime::has(compass::feature::sse4());
REQUIRE(value==expected_has_sse4);
}
SECTION( "has_avx_right" ){
auto value = compass::runtime::has(compass::feature::avx());
REQUIRE(value==expected_has_avx);
}
SECTION( "has_avx2_right" ){
auto value = compass::runtime::has(compass::feature::avx2());
REQUIRE(value==expected_has_avx2);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment