From e2533d7ae61e55727b443b8493a6938dd2ba2598 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 22 Sep 2023 16:25:37 -0400 Subject: [PATCH 01/29] initial commit --- README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..70653ec5 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# random number generators From fadbcd7b54bd689d4bd31026a51c956ea781044c Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sat, 23 Sep 2023 13:07:45 -0400 Subject: [PATCH 02/29] + xoshiro256ss (copied from kalman project) --- CMakeLists.txt | 73 +++ README.md | 15 + cmake/code-coverage.cmake | 678 +++++++++++++++++++++++++++ cmake/cxx.cmake | 40 ++ example/CMakeLists.txt | 2 + example/ex1/CMakeLists.txt | 2 + example/ex1/ex1.cpp | 26 + example/ex2/CMakeLists.txt | 3 + example/ex2/ex2.cpp | 16 + include/randomgen/engine_concept.hpp | 36 ++ include/randomgen/random_seed.hpp | 70 +++ include/randomgen/xoshiro256.hpp | 169 +++++++ 12 files changed, 1130 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 cmake/code-coverage.cmake create mode 100644 cmake/cxx.cmake create mode 100644 example/CMakeLists.txt create mode 100644 example/ex1/CMakeLists.txt create mode 100644 example/ex1/ex1.cpp create mode 100644 example/ex2/CMakeLists.txt create mode 100644 example/ex2/ex2.cpp create mode 100644 include/randomgen/engine_concept.hpp create mode 100644 include/randomgen/random_seed.hpp create mode 100644 include/randomgen/xoshiro256.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..533fe8e5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,73 @@ +# using indentlog/CMakeLists.txt as model + +cmake_minimum_required(VERSION 3.10) + +project(randomgen VERSION 0.1) +enable_language(CXX) + +include(cmake/cxx.cmake) +include(cmake/code-coverage.cmake) + +# ---------------------------------------------------------------- +# unit test setup + +enable_testing() + + +# activate code coverage for all executables + libraries (when configured with -DCODE_COVERAGE=ON) +add_code_coverage() +# 1. assuming that /nix/store/ prefixes .hpp files belonging to gcc, catch2 etc. +# we're not interested in code coverage for these sources. +# 2. exclude the utest/ subdir, we don't need coverage on the unit tests themselves; +# rather, want coverage on the code that the unit tests exercise. +# +add_code_coverage_all_targets(EXCLUDE /nix/store/* utest/*) + +# ---------------------------------------------------------------- +# c++ settings + +set(PROJECT_CXX_FLAGS "-fconcepts-diagnostics-depth=2") + +add_definitions(${PROJECT_CXX_FLAGS}) + +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 20) +endif() + +set(CMAKE_CXX_STANDARD_REQUIRED True) + +# always write compile_commands.json +set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") + +# ---------------------------------------------------------------- +# default install + +if(NOT USER) + set(USER $ENV{USER}) +endif() + +if(NOT CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX /home/${USER}/local CACHE STRING "install directory") +endif() +if(NOT CMAKE_INSTALL_RPATH) + set(CMAKE_INSTALL_RPATH /home/${USER}/local/lib CACHE STRING "runpath in installed libraries/executables") +endif() + +# ---------------------------------------------------------------- +# external dependencies +# +# set CMAKE_INSTALL_PREFIX to analog of /usr +# to use .cmake assistants from /usr/lib/cmake/indentlog +# +find_package(indentlog REQUIRED) + +# ---------------------------------------------------------------- + +add_subdirectory(example) +#add_subdirectory(utest) + +# ---------------------------------------------------------------- + +install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ DESTINATION include) + +install(TARGETS ex1 DESTINATION bin/randomgen/example) diff --git a/README.md b/README.md index 70653ec5..18300542 100644 --- a/README.md +++ b/README.md @@ -1 +1,16 @@ # random number generators + +# to build + install locally + +``` +$ cd randomgen +$ mkdir build +$ cd build +$ cmake -DCMAKE_PREFIX_PATH=$(HOME)/local .. +$ make +$ make install +``` + +# to build + install to /usr/local (deprecated) + +same as above, but set `CMAKE_PREFIX_PATH` to `/usr/local` diff --git a/cmake/code-coverage.cmake b/cmake/code-coverage.cmake new file mode 100644 index 00000000..b6b36064 --- /dev/null +++ b/cmake/code-coverage.cmake @@ -0,0 +1,678 @@ +# +# Copyright (C) 2018-2020 by George Cave - gcave@stablecoder.ca +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +# USAGE: To enable any code coverage instrumentation/targets, the single CMake +# option of `CODE_COVERAGE` needs to be set to 'ON', either by GUI, ccmake, or +# on the command line. +# +# From this point, there are two primary methods for adding instrumentation to +# targets: +# +# 1 - A blanket instrumentation by calling `add_code_coverage()`, where +# all targets in that directory and all subdirectories are automatically +# instrumented. +# +# 2 - Per-target instrumentation by calling +# `target_code_coverage()`, where the target is given and thus only +# that target is instrumented. This applies to both libraries and executables. +# +# To add coverage targets, such as calling `make ccov` to generate the actual +# coverage information for perusal or consumption, call +# `target_code_coverage()` on an *executable* target. +# +# Example 1: All targets instrumented +# +# In this case, the coverage information reported will will be that of the +# `theLib` library target and `theExe` executable. +# +# 1a: Via global command +# +# ~~~ +# add_code_coverage() # Adds instrumentation to all targets +# +# add_library(theLib lib.cpp) +# +# add_executable(theExe main.cpp) +# target_link_libraries(theExe PRIVATE theLib) +# target_code_coverage(theExe) # As an executable target, adds the 'ccov-theExe' target +# # (instrumentation already added via global anyways) +# # for generating code coverage reports. +# ~~~ +# +# 1b: Via target commands +# +# ~~~ +# add_library(theLib lib.cpp) +# target_code_coverage(theLib) # As a library target, adds coverage instrumentation but no targets. +# +# add_executable(theExe main.cpp) +# target_link_libraries(theExe PRIVATE theLib) +# target_code_coverage(theExe) # As an executable target, adds the 'ccov-theExe' target and instrumentation for generating code coverage reports. +# ~~~ +# +# Example 2: Target instrumented, but with regex pattern of files to be excluded +# from report +# +# ~~~ +# add_executable(theExe main.cpp non_covered.cpp) +# target_code_coverage(theExe EXCLUDE non_covered.cpp test/*) # As an executable target, the reports will exclude the non-covered.cpp file, and any files in a test/ folder. +# ~~~ +# +# Example 3: Target added to the 'ccov' and 'ccov-all' targets +# +# ~~~ +# add_code_coverage_all_targets(EXCLUDE test/*) # Adds the 'ccov-all' target set and sets it to exclude all files in test/ folders. +# +# add_executable(theExe main.cpp non_covered.cpp) +# target_code_coverage(theExe AUTO ALL EXCLUDE non_covered.cpp test/*) # As an executable target, adds to the 'ccov' and ccov-all' targets, and the reports will exclude the non-covered.cpp file, and any files in a test/ folder. +# ~~~ + +# Options +option( + CODE_COVERAGE + "Builds targets with code coverage instrumentation. (Requires GCC or Clang)" + OFF) + +# Programs +find_program(LLVM_COV_PATH llvm-cov) +find_program(LLVM_PROFDATA_PATH llvm-profdata) +find_program(LCOV_PATH lcov) +find_program(GENHTML_PATH genhtml) +# Hide behind the 'advanced' mode flag for GUI/ccmake +mark_as_advanced(FORCE LLVM_COV_PATH LLVM_PROFDATA_PATH LCOV_PATH GENHTML_PATH) + +# Variables +set(CMAKE_COVERAGE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/ccov) +set_property(GLOBAL PROPERTY JOB_POOLS ccov_serial_pool=1) + +# Common initialization/checks +if(CODE_COVERAGE AND NOT CODE_COVERAGE_ADDED) + set(CODE_COVERAGE_ADDED ON) + + # Common Targets + add_custom_target( + ccov-preprocessing + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY} + DEPENDS ccov-clean) + + if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" + OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") + # Messages + message(STATUS "Building with llvm Code Coverage Tools") + + if(NOT LLVM_COV_PATH) + message(FATAL_ERROR "llvm-cov not found! Aborting.") + else() + # Version number checking for 'EXCLUDE' compatibility + execute_process(COMMAND ${LLVM_COV_PATH} --version + OUTPUT_VARIABLE LLVM_COV_VERSION_CALL_OUTPUT) + string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" LLVM_COV_VERSION + ${LLVM_COV_VERSION_CALL_OUTPUT}) + + if(LLVM_COV_VERSION VERSION_LESS "7.0.0") + message( + WARNING + "target_code_coverage()/add_code_coverage_all_targets() 'EXCLUDE' option only available on llvm-cov >= 7.0.0" + ) + endif() + endif() + + # Targets + if(${CMAKE_VERSION} VERSION_LESS "3.17.0") + add_custom_target( + ccov-clean + COMMAND ${CMAKE_COMMAND} -E remove -f + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list + COMMAND ${CMAKE_COMMAND} -E remove -f + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list) + else() + add_custom_target( + ccov-clean + COMMAND ${CMAKE_COMMAND} -E rm -f + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list + COMMAND ${CMAKE_COMMAND} -E rm -f + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list) + endif() + + # Used to get the shared object file list before doing the main all- + # processing + add_custom_target( + ccov-libs + COMMAND ; + COMMENT "libs ready for coverage report.") + + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES + "GNU") + # Messages + message(STATUS "Building with lcov Code Coverage Tools") + + if(CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} upper_build_type) + if(NOT ${upper_build_type} STREQUAL "DEBUG") + message( + WARNING + "Code coverage results with an optimized (non-Debug) build may be misleading" + ) + endif() + else() + message( + WARNING + "Code coverage results with an optimized (non-Debug) build may be misleading" + ) + endif() + if(NOT LCOV_PATH) + message(FATAL_ERROR "lcov not found! Aborting...") + endif() + if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Aborting...") + endif() + + # Targets + add_custom_target(ccov-clean COMMAND ${LCOV_PATH} --directory + ${CMAKE_BINARY_DIR} --zerocounters) + + else() + message(FATAL_ERROR "Code coverage requires Clang or GCC. Aborting.") + endif() +endif() + +# Adds code coverage instrumentation to a library, or instrumentation/targets +# for an executable target. +# ~~~ +# EXECUTABLE ADDED TARGETS: +# GCOV/LCOV: +# ccov : Generates HTML code coverage report for every target added with 'AUTO' parameter. +# ccov-${TARGET_NAME} : Generates HTML code coverage report for the associated named target. +# ccov-all : Generates HTML code coverage report, merging every target added with 'ALL' parameter into a single detailed report. +# +# LLVM-COV: +# ccov : Generates HTML code coverage report for every target added with 'AUTO' parameter. +# ccov-report : Generates HTML code coverage report for every target added with 'AUTO' parameter. +# ccov-${TARGET_NAME} : Generates HTML code coverage report. +# ccov-report-${TARGET_NAME} : Prints to command line summary per-file coverage information. +# ccov-export-${TARGET_NAME} : Exports the coverage report to a JSON file. +# ccov-show-${TARGET_NAME} : Prints to command line detailed per-line coverage information. +# ccov-all : Generates HTML code coverage report, merging every target added with 'ALL' parameter into a single detailed report. +# ccov-all-report : Prints summary per-file coverage information for every target added with ALL' parameter to the command line. +# ccov-all-export : Exports the coverage report to a JSON file. +# +# Required: +# TARGET_NAME - Name of the target to generate code coverage for. +# Optional: +# PUBLIC - Sets the visibility for added compile options to targets to PUBLIC instead of the default of PRIVATE. +# INTERFACE - Sets the visibility for added compile options to targets to INTERFACE instead of the default of PRIVATE. +# PLAIN - Do not set any target visibility (backward compatibility with old cmake projects) +# AUTO - Adds the target to the 'ccov' target so that it can be run in a batch with others easily. Effective on executable targets. +# ALL - Adds the target to the 'ccov-all' and 'ccov-all-report' targets, which merge several executable targets coverage data to a single report. Effective on executable targets. +# EXTERNAL - For GCC's lcov, allows the profiling of 'external' files from the processing directory +# COVERAGE_TARGET_NAME - For executables ONLY, changes the outgoing target name so instead of `ccov-${TARGET_NAME}` it becomes `ccov-${COVERAGE_TARGET_NAME}`. +# EXCLUDE - Excludes files of the patterns provided from coverage. Note that GCC/lcov excludes by glob pattern, and clang/LLVM excludes via regex! **These do not copy to the 'all' targets.** +# OBJECTS - For executables ONLY, if the provided targets are shared libraries, adds coverage information to the output +# ARGS - For executables ONLY, appends the given arguments to the associated ccov-* executable call +# ~~~ +function(target_code_coverage TARGET_NAME) + # Argument parsing + set(options AUTO ALL EXTERNAL PUBLIC INTERFACE PLAIN) + set(single_value_keywords COVERAGE_TARGET_NAME) + set(multi_value_keywords EXCLUDE OBJECTS ARGS) + cmake_parse_arguments( + target_code_coverage "${options}" "${single_value_keywords}" + "${multi_value_keywords}" ${ARGN}) + + # Set the visibility of target functions to PUBLIC, INTERFACE or default to + # PRIVATE. + if(target_code_coverage_PUBLIC) + set(TARGET_VISIBILITY PUBLIC) + set(TARGET_LINK_VISIBILITY PUBLIC) + elseif(target_code_coverage_INTERFACE) + set(TARGET_VISIBILITY INTERFACE) + set(TARGET_LINK_VISIBILITY INTERFACE) + elseif(target_code_coverage_PLAIN) + set(TARGET_VISIBILITY PUBLIC) + set(TARGET_LINK_VISIBILITY) + else() + set(TARGET_VISIBILITY PRIVATE) + set(TARGET_LINK_VISIBILITY PRIVATE) + endif() + + if(NOT target_code_coverage_COVERAGE_TARGET_NAME) + # If a specific name was given, use that instead. + set(target_code_coverage_COVERAGE_TARGET_NAME ${TARGET_NAME}) + endif() + + if(CODE_COVERAGE) + + # Add code coverage instrumentation to the target's linker command + if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" + OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") + target_compile_options(${TARGET_NAME} ${TARGET_VISIBILITY} + -fprofile-instr-generate -fcoverage-mapping) + target_link_options(${TARGET_NAME} ${TARGET_VISIBILITY} + -fprofile-instr-generate -fcoverage-mapping) + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES + "GNU") + target_compile_options(${TARGET_NAME} ${TARGET_VISIBILITY} -fprofile-arcs + -ftest-coverage) + target_link_libraries(${TARGET_NAME} ${TARGET_LINK_VISIBILITY} gcov) + endif() + + # Targets + get_target_property(target_type ${TARGET_NAME} TYPE) + + # Add shared library to processing for 'all' targets + if(target_type STREQUAL "SHARED_LIBRARY" AND target_code_coverage_ALL) + if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" + OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") + add_custom_target( + ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${CMAKE_COMMAND} -E echo "-object=$" >> + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list + DEPENDS ccov-preprocessing ${TARGET_NAME}) + + if(NOT TARGET ccov-libs) + message( + FATAL_ERROR + "Calling target_code_coverage with 'ALL' must be after a call to 'add_code_coverage_all_targets'." + ) + endif() + + add_dependencies(ccov-libs + ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME}) + endif() + endif() + + # For executables add targets to run and produce output + if(target_type STREQUAL "EXECUTABLE") + if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" + OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") + + # If there are shared objects to also work with, generate the string to + # add them here + foreach(SO_TARGET ${target_code_coverage_OBJECTS}) + # Check to see if the target is a shared object + if(TARGET ${SO_TARGET}) + get_target_property(SO_TARGET_TYPE ${SO_TARGET} TYPE) + if(${SO_TARGET_TYPE} STREQUAL "SHARED_LIBRARY") + set(SO_OBJECTS ${SO_OBJECTS} -object=$) + endif() + endif() + endforeach() + + # Run the executable, generating raw profile data Make the run data + # available for further processing. Separated to allow Windows to run + # this target serially. + add_custom_target( + ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${CMAKE_COMMAND} -E env + LLVM_PROFILE_FILE=${target_code_coverage_COVERAGE_TARGET_NAME}.profraw + $ ${target_code_coverage_ARGS} + COMMAND + ${CMAKE_COMMAND} -E echo "-object=$" + ${SO_OBJECTS} >> ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list + COMMAND + ${CMAKE_COMMAND} -E echo + "${CMAKE_CURRENT_BINARY_DIR}/${target_code_coverage_COVERAGE_TARGET_NAME}.profraw" + >> ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list + JOB_POOL ccov_serial_pool + DEPENDS ccov-preprocessing ccov-libs ${TARGET_NAME}) + + # Merge the generated profile data so llvm-cov can process it + add_custom_target( + ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${LLVM_PROFDATA_PATH} merge -sparse + ${target_code_coverage_COVERAGE_TARGET_NAME}.profraw -o + ${target_code_coverage_COVERAGE_TARGET_NAME}.profdata + DEPENDS ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME}) + + # Ignore regex only works on LLVM >= 7 + if(LLVM_COV_VERSION VERSION_GREATER_EQUAL "7.0.0") + foreach(EXCLUDE_ITEM ${target_code_coverage_EXCLUDE}) + set(EXCLUDE_REGEX ${EXCLUDE_REGEX} + -ignore-filename-regex='${EXCLUDE_ITEM}') + endforeach() + endif() + + # Print out details of the coverage information to the command line + add_custom_target( + ccov-show-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${LLVM_COV_PATH} show $ ${SO_OBJECTS} + -instr-profile=${target_code_coverage_COVERAGE_TARGET_NAME}.profdata + -show-line-counts-or-regions ${EXCLUDE_REGEX} + DEPENDS ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME}) + + # Print out a summary of the coverage information to the command line + add_custom_target( + ccov-report-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${LLVM_COV_PATH} report $ ${SO_OBJECTS} + -instr-profile=${target_code_coverage_COVERAGE_TARGET_NAME}.profdata + ${EXCLUDE_REGEX} + DEPENDS ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME}) + + # Export coverage information so continuous integration tools (e.g. + # Jenkins) can consume it + add_custom_target( + ccov-export-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${LLVM_COV_PATH} export $ ${SO_OBJECTS} + -instr-profile=${target_code_coverage_COVERAGE_TARGET_NAME}.profdata + -format="text" ${EXCLUDE_REGEX} > + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME}.json + DEPENDS ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME}) + + # Generates HTML output of the coverage information for perusal + add_custom_target( + ccov-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${LLVM_COV_PATH} show $ ${SO_OBJECTS} + -instr-profile=${target_code_coverage_COVERAGE_TARGET_NAME}.profdata + -show-line-counts-or-regions + -output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME} + -format="html" ${EXCLUDE_REGEX} + DEPENDS ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME}) + + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES + "GNU") + set(COVERAGE_INFO + "${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME}.info" + ) + + # Run the executable, generating coverage information + add_custom_target( + ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND $ ${target_code_coverage_ARGS} + DEPENDS ccov-preprocessing ${TARGET_NAME}) + + # Generate exclusion string for use + foreach(EXCLUDE_ITEM ${target_code_coverage_EXCLUDE}) + set(EXCLUDE_REGEX ${EXCLUDE_REGEX} --remove ${COVERAGE_INFO} + '${EXCLUDE_ITEM}') + endforeach() + + if(EXCLUDE_REGEX) + set(EXCLUDE_COMMAND ${LCOV_PATH} ${EXCLUDE_REGEX} --output-file + ${COVERAGE_INFO}) + else() + set(EXCLUDE_COMMAND ;) + endif() + + if(NOT ${target_code_coverage_EXTERNAL}) + set(EXTERNAL_OPTION --no-external) + endif() + + # Capture coverage data + if(${CMAKE_VERSION} VERSION_LESS "3.17.0") + add_custom_target( + ccov-capture-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND ${CMAKE_COMMAND} -E remove -f ${COVERAGE_INFO} + COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --zerocounters + COMMAND $ ${target_code_coverage_ARGS} + COMMAND + ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --base-directory + ${CMAKE_SOURCE_DIR} --capture ${EXTERNAL_OPTION} --output-file + ${COVERAGE_INFO} + COMMAND ${EXCLUDE_COMMAND} + DEPENDS ccov-preprocessing ${TARGET_NAME}) + else() + add_custom_target( + ccov-capture-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND ${CMAKE_COMMAND} -E rm -f ${COVERAGE_INFO} + COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --zerocounters + COMMAND $ ${target_code_coverage_ARGS} + COMMAND + ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --base-directory + ${CMAKE_SOURCE_DIR} --capture ${EXTERNAL_OPTION} --output-file + ${COVERAGE_INFO} + COMMAND ${EXCLUDE_COMMAND} + DEPENDS ccov-preprocessing ${TARGET_NAME}) + endif() + + # Generates HTML output of the coverage information for perusal + add_custom_target( + ccov-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${GENHTML_PATH} -o + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME} + ${COVERAGE_INFO} + DEPENDS ccov-capture-${target_code_coverage_COVERAGE_TARGET_NAME}) + endif() + + add_custom_command( + TARGET ccov-${target_code_coverage_COVERAGE_TARGET_NAME} + POST_BUILD + COMMAND ; + COMMENT + "Open ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME}/index.html in your browser to view the coverage report." + ) + + # AUTO + if(target_code_coverage_AUTO) + if(NOT TARGET ccov) + add_custom_target(ccov) + endif() + add_dependencies(ccov ccov-${target_code_coverage_COVERAGE_TARGET_NAME}) + + if(NOT CMAKE_C_COMPILER_ID MATCHES "GNU" AND NOT CMAKE_CXX_COMPILER_ID + MATCHES "GNU") + if(NOT TARGET ccov-report) + add_custom_target(ccov-report) + endif() + add_dependencies( + ccov-report + ccov-report-${target_code_coverage_COVERAGE_TARGET_NAME}) + endif() + endif() + + # ALL + if(target_code_coverage_ALL) + if(NOT TARGET ccov-all-processing) + message( + FATAL_ERROR + "Calling target_code_coverage with 'ALL' must be after a call to 'add_code_coverage_all_targets'." + ) + endif() + + add_dependencies(ccov-all-processing + ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME}) + endif() + endif() + endif() +endfunction() + +# Adds code coverage instrumentation to all targets in the current directory and +# any subdirectories. To add coverage instrumentation to only specific targets, +# use `target_code_coverage`. +function(add_code_coverage) + if(CODE_COVERAGE) + if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" + OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") + add_compile_options(-fprofile-instr-generate -fcoverage-mapping) + add_link_options(-fprofile-instr-generate -fcoverage-mapping) + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES + "GNU") + add_compile_options(-fprofile-arcs -ftest-coverage) + link_libraries(gcov) + endif() + endif() +endfunction() + +# Adds the 'ccov-all' type targets that calls all targets added via +# `target_code_coverage` with the `ALL` parameter, but merges all the coverage +# data from them into a single large report instead of the numerous smaller +# reports. Also adds the ccov-all-capture Generates an all-merged.info file, for +# use with coverage dashboards (e.g. codecov.io, coveralls). +# ~~~ +# Optional: +# EXCLUDE - Excludes files of the patterns provided from coverage. Note that GCC/lcov excludes by glob pattern, and clang/LLVM excludes via regex! +# ~~~ +function(add_code_coverage_all_targets) + # Argument parsing + set(multi_value_keywords EXCLUDE) + cmake_parse_arguments(add_code_coverage_all_targets "" "" + "${multi_value_keywords}" ${ARGN}) + + if(CODE_COVERAGE) + if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" + OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") + + # Merge the profile data for all of the run executables + if(WIN32) + add_custom_target( + ccov-all-processing + COMMAND + powershell -Command $$FILELIST = Get-Content + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list\; llvm-profdata.exe + merge -o ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + -sparse $$FILELIST) + else() + add_custom_target( + ccov-all-processing + COMMAND + ${LLVM_PROFDATA_PATH} merge -o + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata -sparse `cat + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list`) + endif() + + # Regex exclude only available for LLVM >= 7 + if(LLVM_COV_VERSION VERSION_GREATER_EQUAL "7.0.0") + foreach(EXCLUDE_ITEM ${add_code_coverage_all_targets_EXCLUDE}) + set(EXCLUDE_REGEX ${EXCLUDE_REGEX} + -ignore-filename-regex='${EXCLUDE_ITEM}') + endforeach() + endif() + + # Print summary of the code coverage information to the command line + if(WIN32) + add_custom_target( + ccov-all-report + COMMAND + powershell -Command $$FILELIST = Get-Content + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list\; llvm-cov.exe + report $$FILELIST + -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + ${EXCLUDE_REGEX} + DEPENDS ccov-all-processing) + else() + add_custom_target( + ccov-all-report + COMMAND + ${LLVM_COV_PATH} report `cat + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list` + -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + ${EXCLUDE_REGEX} + DEPENDS ccov-all-processing) + endif() + + # Export coverage information so continuous integration tools (e.g. + # Jenkins) can consume it + add_custom_target( + ccov-all-export + COMMAND + ${LLVM_COV_PATH} export `cat + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list` + -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + -format="text" ${EXCLUDE_REGEX} > + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/coverage.json + DEPENDS ccov-all-processing) + + # Generate HTML output of all added targets for perusal + if(WIN32) + add_custom_target( + ccov-all + COMMAND + powershell -Command $$FILELIST = Get-Content + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list\; llvm-cov.exe show + $$FILELIST + -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + -show-line-counts-or-regions + -output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged + -format="html" ${EXCLUDE_REGEX} + DEPENDS ccov-all-processing) + else() + add_custom_target( + ccov-all + COMMAND + ${LLVM_COV_PATH} show `cat + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list` + -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + -show-line-counts-or-regions + -output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged + -format="html" ${EXCLUDE_REGEX} + DEPENDS ccov-all-processing) + endif() + + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES + "GNU") + set(COVERAGE_INFO "${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.info") + + # Nothing required for gcov + add_custom_target(ccov-all-processing COMMAND ;) + + # Exclusion regex string creation + set(EXCLUDE_REGEX) + foreach(EXCLUDE_ITEM ${add_code_coverage_all_targets_EXCLUDE}) + set(EXCLUDE_REGEX ${EXCLUDE_REGEX} --remove ${COVERAGE_INFO} + '${EXCLUDE_ITEM}') + endforeach() + + if(EXCLUDE_REGEX) + set(EXCLUDE_COMMAND ${LCOV_PATH} ${EXCLUDE_REGEX} --output-file + ${COVERAGE_INFO}) + else() + set(EXCLUDE_COMMAND ;) + endif() + + # Capture coverage data + if(${CMAKE_VERSION} VERSION_LESS "3.17.0") + add_custom_target( + ccov-all-capture + COMMAND ${CMAKE_COMMAND} -E remove -f ${COVERAGE_INFO} + COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --capture + --output-file ${COVERAGE_INFO} + COMMAND ${EXCLUDE_COMMAND} + DEPENDS ccov-preprocessing ccov-all-processing) + else() + add_custom_target( + ccov-all-capture + COMMAND ${CMAKE_COMMAND} -E rm -f ${COVERAGE_INFO} + COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --capture + --output-file ${COVERAGE_INFO} + COMMAND ${EXCLUDE_COMMAND} + DEPENDS ccov-preprocessing ccov-all-processing) + endif() + + # Generates HTML output of all targets for perusal + add_custom_target( + ccov-all + COMMAND ${GENHTML_PATH} -o ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged + ${COVERAGE_INFO} -p ${CMAKE_SOURCE_DIR} + DEPENDS ccov-all-capture) + + endif() + + add_custom_command( + TARGET ccov-all + POST_BUILD + COMMAND ; + COMMENT + "Open ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged/index.html in your browser to view the coverage report." + ) + endif() +endfunction() diff --git a/cmake/cxx.cmake b/cmake/cxx.cmake new file mode 100644 index 00000000..e01e6801 --- /dev/null +++ b/cmake/cxx.cmake @@ -0,0 +1,40 @@ +# ---------------------------------------------------------------- +# use this in subdirs that compile c++ code +# +macro(xo_include_options target) + # ---------------------------------------------------------------- + # PROJECT_SOURCE_DIR: + # so we can for example write + # #include "ordinaltree/foo.hpp" + # from anywhere in the project + # PROJECT_BINARY_DIR: + # since generated version file will be in build directory, + # need that build directory to also appear in + # compiler's include path + # + target_include_directories( + ${target} PUBLIC + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_BINARY_DIR} + ) + + # ---------------------------------------------------------------- + # make standard directories for std:: includes explicit + # so that + # (1) they appear in compile_commands.json. + # (2) clangd (run from emacs lsp-mode) can find them + # + if(CMAKE_EXPORT_COMPILE_COMMANDS) + set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) + endif() +endmacro() + +# ---------------------------------------------------------------- +# use this when relying on indentlog [[https://github.com/rconybea/indentlog]] headers +# +macro(xo_indentlog_dependency target) + find_package(indentlog REQUIRED) + #add_dependencies(${target} indentlog) + target_link_libraries(${target} PUBLIC indentlog) + #target_include_directories(${target} PUBLIC ${indentlog_DIR}/../../../include) +endmacro() diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt new file mode 100644 index 00000000..ac5b07f6 --- /dev/null +++ b/example/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(ex1) +add_subdirectory(ex2) diff --git a/example/ex1/CMakeLists.txt b/example/ex1/CMakeLists.txt new file mode 100644 index 00000000..6af29d79 --- /dev/null +++ b/example/ex1/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(ex1 ex1.cpp) +xo_include_options(ex1) diff --git a/example/ex1/ex1.cpp b/example/ex1/ex1.cpp new file mode 100644 index 00000000..8c908fa5 --- /dev/null +++ b/example/ex1/ex1.cpp @@ -0,0 +1,26 @@ +/* @file ex1.cpp */ + +#include "randomgen/xoshiro256.hpp" +#include +#include +//#include +//#include + +using namespace xo; +using namespace xo::rng; + +int +main(int argc, char ** argv) { + xoshiro256ss rng{123456789}; + + std::array v; + + std::generate(v.begin(), v.end(), rng); + + for (std::uint64_t i=0; i seed; + + xoshiro256ss eng(seed); +} /*main*/ + +/* end ex2.cpp */ diff --git a/include/randomgen/engine_concept.hpp b/include/randomgen/engine_concept.hpp new file mode 100644 index 00000000..42557b0e --- /dev/null +++ b/include/randomgen/engine_concept.hpp @@ -0,0 +1,36 @@ +/* @file engine_concept.hpp */ + +#pragma once + +#include +#include + +namespace xo { + namespace rng { + /* an engine generates psuedo-random bits. + * given + * RngEngine eng = ...; + * + * RngEngine::result_type x = eng(); + * + * puts random bits into x. + */ + template + concept engine_concept = requires(RngEngine engine, typename RngEngine::result_type r) { + /* note: the first 4 requirements characterize UniformRandomBitGenerator */ + typename RngEngine::result_type; + { RngEngine(r) }; + { engine.min() } -> std::same_as; + { engine.max() } -> std::same_as; + /* must return value in closed interval [.min(), .max()] */ + { engine() } -> std::same_as; + + { engine.seed() }; + { engine.seed(r) }; + { engine == engine }; + { engine != engine }; + } && std::copyable && std::uniform_random_bit_generator; + } /*namespace rng*/ +} /*namespace xo*/ + +/* end engine_concept.hpp */ diff --git a/include/randomgen/random_seed.hpp b/include/randomgen/random_seed.hpp new file mode 100644 index 00000000..5273ddeb --- /dev/null +++ b/include/randomgen/random_seed.hpp @@ -0,0 +1,70 @@ +/* @file random_seed.hpp */ + +#include "indentlog/print/array.hpp" +#include +#include +#include + +namespace xo { + namespace rng { + /* generate a 64-bit random seed using /dev/urandom or similar source. + * This is relatively expensive; at least cost of a system call + * + may block if host has rebooted recently + * + * Require: + * - T is null-constructible. + * + * return value will contain a T-instance in which representation + * has been populated with random bits. Expecting T to be something + * like int32_t, or std::array + */ + template + void random_seed(T * p_seed) { + /* NOTE: arc4random_buf() works on darwin/nix; + * probably need to do something else on intel linux + */ + arc4random_buf(p_seed, sizeof(*p_seed)); + } /*random_seed*/ + + template + T random_seed() { + T retval; + random_seed(&retval); + + return retval; + } /*random_seed*/ + + /* RAII-style random-number seed + * + * Usage: + * + * Seed seed; + * + * auto eng = xoshiro256ss(seed); + * or + * auto rng = UnitIntervalGen::make(seed); + */ + template + struct Seed { + using seed_type = typename Engine::seed_type; + + Seed() { random_seed(&seed_); } + + operator seed_type const & () const { return seed_; } + + seed_type seed_; + }; /*Seed*/ + + template + inline std::ostream & + operator<<(std::ostream & os, + Seed const & x) + { + os << x.seed_; + return os; + } /*operator<<*/ + + } /*namespace rng*/ +} /*namespace xo*/ + +/* end random_seed.hpp */ diff --git a/include/randomgen/xoshiro256.hpp b/include/randomgen/xoshiro256.hpp new file mode 100644 index 00000000..b202650a --- /dev/null +++ b/include/randomgen/xoshiro256.hpp @@ -0,0 +1,169 @@ +/* @file xoshiro256.hpp */ + +#pragma once + +#include "engine_concept.hpp" +#include +#include +#include +#include + +namespace xo { + namespace rng { + + /* engine for producing 64-bit random numbers + * + * see https:/en.wikipedia.org/wiki/Xorshift#xoshiro256** + * + * - satisfies c++ UniformRandomBitGenerator + * - satisfies c++ + * + * Note: zero seed --> constant output sequence {0, 0, 0, ...} + */ + class xoshiro256ss { + public: + using result_type = std::uint64_t; + using seed_type = std::array; + + public: + /* null state -- generates constant stream of 0 bits */ + xoshiro256ss() : xoshiro256ss(0) {} + /* copy ctor */ + xoshiro256ss(xoshiro256ss const & x) = default; + xoshiro256ss(seed_type const & seed) : s_(seed) {} + + /* fallback version -- deprecated */ + xoshiro256ss(std::uint64_t seed) + { + this->s_[0] = 0; + this->s_[1] = seed; + this->s_[2] = 0; + this->s_[3] = 0; + + generate(); + } + + static constexpr std::uint64_t min() { return 0; } + static constexpr std::uint64_t max() { return std::numeric_limits::max(); } + + static std::uint64_t rol64(std::uint64_t x, std::int64_t k) + { + return (x << k) | (x >> (64 - k)); + } + + static bool equal(xoshiro256ss const & x, xoshiro256ss const & y) { + return ((x.s_[0] == y.s_[0]) + && (x.s_[1] == y.s_[1]) + && (x.s_[2] == y.s_[2]) + && (x.s_[3] == y.s_[3])); + } + + /* puts generator into null state */ + void seed() { *this = xoshiro256ss(); } + void seed(std::uint64_t s) { *this = xoshiro256ss{s}; } + /* e.g. used with std::seed_seq<> */ + template + void seed(SeedSeq & sseq) { + sseq.generate(s_.begin(), s_.end()); + } + + std::uint64_t generate() { + std::array & s = (this->s_); + std::uint64_t const result = rol64(s[1] * 5, 7) * 9; + std::uint64_t const t = s[1] << 17; + + s[2] ^= s[0]; + s[3] ^= s[1]; + s[1] ^= s[2]; + s[0] ^= s[3]; + + s[2] ^= t; + s[3] = rol64(s[3], 45); + + return result; + } /*generate*/ + + /* advance to same state as obtained from z calls to .generate(). O(z) ! + * usually better to use jump(). + * + * providing .discard() to satisfy c++ named requirement _RandomNumberEngine_ + */ + void discard(std::uint64_t z) { + for (std::uint64_t i=0; igenerate(); + } + + /* equivalent to .discard(2^128), but uses O(1) time + * + * (may use in multithreaded program to get determinsitic non-overlapping random sequences) + */ + void jump() { + std::array const s_jump_v + = {{0x180ec6d33cfd0aba, + 0xd5a61266f0c9392c, + 0xa9582618e03fc9aa, + 0x39abdc4529b1661c}}; + + std::array & s = (this->s_); + + std::uint64_t s0 = 0; + std::uint64_t s1 = 0; + std::uint64_t s2 = 0; + std::uint64_t s3 = 0; + for (std::uint32_t i = 0; i < s_jump_v.size(); ++i) { + for (std::uint32_t bit = 0; bit < 64; ++bit) { + if (s_jump_v[i] & 1UL << bit) { + s0 ^= s[0]; + s1 ^= s[1]; + s2 ^= s[2]; + s3 ^= s[3]; + } + this->generate(); + } + } + + s[0] = s0; + s[1] = s1; + s[2] = s2; + s[3] = s3; + } /*jump*/ + + /* inverse of .load() */ + void print(std::ostream & os) const { + os << ""; + } + + /* inverse of .print() */ + void load(std::istream & is) { + std::string header, trailer; + std::array sv; + + is >> header >> sv[0] >> sv[1] >> sv[2] >> sv[3] >> trailer; + + if ((header != ""); + + this->s_ = sv; + } /*load*/ + + std::uint64_t operator()() { return generate(); } + + private: + /* state */ + std::array s_; + }; /*xoshiro256ss*/ + + inline bool operator==(xoshiro256ss const & x, xoshiro256ss const & y) { + return xoshiro256ss::equal(x, y); + } + + inline bool operator!=(xoshiro256ss const & x, xoshiro256ss const & y) { + return !xoshiro256ss::equal(x, y); + } + + static_assert(engine_concept); + + } /*namespace rng*/ +} /*namespace xo*/ + +/* end xoshiro256.hpp */ From 1db6cd4d4a267320502f64f6e941a5990d221ede Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sat, 23 Sep 2023 13:14:50 -0400 Subject: [PATCH 03/29] build: fix CMAKE_INSTALL_RPATH --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 533fe8e5..f53843ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,7 @@ if(NOT CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX /home/${USER}/local CACHE STRING "install directory") endif() if(NOT CMAKE_INSTALL_RPATH) - set(CMAKE_INSTALL_RPATH /home/${USER}/local/lib CACHE STRING "runpath in installed libraries/executables") + set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib CACHE STRING "runpath in installed libraries/executables") endif() # ---------------------------------------------------------------- From aac74e276325b0e6497b80f2125a1b174ac0ef0c Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 27 Sep 2023 10:29:15 -0400 Subject: [PATCH 04/29] build: adopt xo_cmake dependency --- CMakeLists.txt | 1 + README.md | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f53843ac..16cb2202 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ cmake_minimum_required(VERSION 3.10) project(randomgen VERSION 0.1) enable_language(CXX) +include(xo_macros/xo_cxx) include(cmake/cxx.cmake) include(cmake/code-coverage.cmake) diff --git a/README.md b/README.md index 18300542..905f267e 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,7 @@ $ cd randomgen $ mkdir build $ cd build -$ cmake -DCMAKE_PREFIX_PATH=$(HOME)/local .. +$ cmake -DCMAKE_MODULE_PATH=${INSTALL_PREFIX}/share/cmake -DCMAKE_PREFIX_PATH=$(INSTALL_PREFIX) .. $ make $ make install ``` - -# to build + install to /usr/local (deprecated) - -same as above, but set `CMAKE_PREFIX_PATH` to `/usr/local` From 748c7d86e42af77b56436fae6607f98384c26945 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 27 Sep 2023 10:29:59 -0400 Subject: [PATCH 05/29] + .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..69e11d47 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# clangd (run via lsp) keeps state here +.cache +# typical build directory +build From fb5bb1b03a1f2a6b9250dab078f0810c019ba527 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 27 Sep 2023 17:57:54 -0400 Subject: [PATCH 06/29] randomgen: build streamlining using xo-cmake macros --- CMakeLists.txt | 15 ++++++--------- example/ex1/CMakeLists.txt | 2 +- example/ex2/CMakeLists.txt | 4 ++-- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 16cb2202..e27486bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,15 +6,13 @@ project(randomgen VERSION 0.1) enable_language(CXX) include(xo_macros/xo_cxx) -include(cmake/cxx.cmake) -include(cmake/code-coverage.cmake) +include(xo_macros/code-coverage) +#include(cmake/cxx.cmake) # ---------------------------------------------------------------- # unit test setup enable_testing() - - # activate code coverage for all executables + libraries (when configured with -DCODE_COVERAGE=ON) add_code_coverage() # 1. assuming that /nix/store/ prefixes .hpp files belonging to gcc, catch2 etc. @@ -50,9 +48,8 @@ endif() if(NOT CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX /home/${USER}/local CACHE STRING "install directory") endif() -if(NOT CMAKE_INSTALL_RPATH) - set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib CACHE STRING "runpath in installed libraries/executables") -endif() + +xo_toplevel_compile_options() # ---------------------------------------------------------------- # external dependencies @@ -60,7 +57,7 @@ endif() # set CMAKE_INSTALL_PREFIX to analog of /usr # to use .cmake assistants from /usr/lib/cmake/indentlog # -find_package(indentlog REQUIRED) +#find_package(indentlog REQUIRED) # ---------------------------------------------------------------- @@ -69,6 +66,6 @@ add_subdirectory(example) # ---------------------------------------------------------------- -install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ DESTINATION include) +xo_install_include_tree() install(TARGETS ex1 DESTINATION bin/randomgen/example) diff --git a/example/ex1/CMakeLists.txt b/example/ex1/CMakeLists.txt index 6af29d79..a9d1b27d 100644 --- a/example/ex1/CMakeLists.txt +++ b/example/ex1/CMakeLists.txt @@ -1,2 +1,2 @@ add_executable(ex1 ex1.cpp) -xo_include_options(ex1) +xo_include_options2(ex1) diff --git a/example/ex2/CMakeLists.txt b/example/ex2/CMakeLists.txt index bab03164..ee6687f2 100644 --- a/example/ex2/CMakeLists.txt +++ b/example/ex2/CMakeLists.txt @@ -1,3 +1,3 @@ add_executable(ex2 ex2.cpp) -xo_include_options(ex2) -xo_indentlog_dependency(ex2) +xo_include_options2(ex2) +xo_internal_dependency(ex2 indentlog) From cf4a928783ed0595d131ea721da435eab1263686 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 27 Sep 2023 18:14:37 -0400 Subject: [PATCH 07/29] randomgen: consolidate CMAKE_CXX_STANDARD setting --- CMakeLists.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e27486bb..83076439 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,12 +29,6 @@ set(PROJECT_CXX_FLAGS "-fconcepts-diagnostics-depth=2") add_definitions(${PROJECT_CXX_FLAGS}) -if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 20) -endif() - -set(CMAKE_CXX_STANDARD_REQUIRED True) - # always write compile_commands.json set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") From 11092bc4fd0ce795e62f058a632ab0fe4d947c8a Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 27 Sep 2023 18:22:08 -0400 Subject: [PATCH 08/29] randomgen: consolidate CMAKE_EXPORT_COMPILE_COMMANDS + tidy --- CMakeLists.txt | 11 - cmake/code-coverage.cmake | 678 -------------------------------------- cmake/cxx.cmake | 40 --- 3 files changed, 729 deletions(-) delete mode 100644 cmake/code-coverage.cmake delete mode 100644 cmake/cxx.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 83076439..5653ec33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,20 +29,9 @@ set(PROJECT_CXX_FLAGS "-fconcepts-diagnostics-depth=2") add_definitions(${PROJECT_CXX_FLAGS}) -# always write compile_commands.json -set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") - # ---------------------------------------------------------------- # default install -if(NOT USER) - set(USER $ENV{USER}) -endif() - -if(NOT CMAKE_INSTALL_PREFIX) - set(CMAKE_INSTALL_PREFIX /home/${USER}/local CACHE STRING "install directory") -endif() - xo_toplevel_compile_options() # ---------------------------------------------------------------- diff --git a/cmake/code-coverage.cmake b/cmake/code-coverage.cmake deleted file mode 100644 index b6b36064..00000000 --- a/cmake/code-coverage.cmake +++ /dev/null @@ -1,678 +0,0 @@ -# -# Copyright (C) 2018-2020 by George Cave - gcave@stablecoder.ca -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not -# use this file except in compliance with the License. You may obtain a copy of -# the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations under -# the License. - -# USAGE: To enable any code coverage instrumentation/targets, the single CMake -# option of `CODE_COVERAGE` needs to be set to 'ON', either by GUI, ccmake, or -# on the command line. -# -# From this point, there are two primary methods for adding instrumentation to -# targets: -# -# 1 - A blanket instrumentation by calling `add_code_coverage()`, where -# all targets in that directory and all subdirectories are automatically -# instrumented. -# -# 2 - Per-target instrumentation by calling -# `target_code_coverage()`, where the target is given and thus only -# that target is instrumented. This applies to both libraries and executables. -# -# To add coverage targets, such as calling `make ccov` to generate the actual -# coverage information for perusal or consumption, call -# `target_code_coverage()` on an *executable* target. -# -# Example 1: All targets instrumented -# -# In this case, the coverage information reported will will be that of the -# `theLib` library target and `theExe` executable. -# -# 1a: Via global command -# -# ~~~ -# add_code_coverage() # Adds instrumentation to all targets -# -# add_library(theLib lib.cpp) -# -# add_executable(theExe main.cpp) -# target_link_libraries(theExe PRIVATE theLib) -# target_code_coverage(theExe) # As an executable target, adds the 'ccov-theExe' target -# # (instrumentation already added via global anyways) -# # for generating code coverage reports. -# ~~~ -# -# 1b: Via target commands -# -# ~~~ -# add_library(theLib lib.cpp) -# target_code_coverage(theLib) # As a library target, adds coverage instrumentation but no targets. -# -# add_executable(theExe main.cpp) -# target_link_libraries(theExe PRIVATE theLib) -# target_code_coverage(theExe) # As an executable target, adds the 'ccov-theExe' target and instrumentation for generating code coverage reports. -# ~~~ -# -# Example 2: Target instrumented, but with regex pattern of files to be excluded -# from report -# -# ~~~ -# add_executable(theExe main.cpp non_covered.cpp) -# target_code_coverage(theExe EXCLUDE non_covered.cpp test/*) # As an executable target, the reports will exclude the non-covered.cpp file, and any files in a test/ folder. -# ~~~ -# -# Example 3: Target added to the 'ccov' and 'ccov-all' targets -# -# ~~~ -# add_code_coverage_all_targets(EXCLUDE test/*) # Adds the 'ccov-all' target set and sets it to exclude all files in test/ folders. -# -# add_executable(theExe main.cpp non_covered.cpp) -# target_code_coverage(theExe AUTO ALL EXCLUDE non_covered.cpp test/*) # As an executable target, adds to the 'ccov' and ccov-all' targets, and the reports will exclude the non-covered.cpp file, and any files in a test/ folder. -# ~~~ - -# Options -option( - CODE_COVERAGE - "Builds targets with code coverage instrumentation. (Requires GCC or Clang)" - OFF) - -# Programs -find_program(LLVM_COV_PATH llvm-cov) -find_program(LLVM_PROFDATA_PATH llvm-profdata) -find_program(LCOV_PATH lcov) -find_program(GENHTML_PATH genhtml) -# Hide behind the 'advanced' mode flag for GUI/ccmake -mark_as_advanced(FORCE LLVM_COV_PATH LLVM_PROFDATA_PATH LCOV_PATH GENHTML_PATH) - -# Variables -set(CMAKE_COVERAGE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/ccov) -set_property(GLOBAL PROPERTY JOB_POOLS ccov_serial_pool=1) - -# Common initialization/checks -if(CODE_COVERAGE AND NOT CODE_COVERAGE_ADDED) - set(CODE_COVERAGE_ADDED ON) - - # Common Targets - add_custom_target( - ccov-preprocessing - COMMAND ${CMAKE_COMMAND} -E make_directory - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY} - DEPENDS ccov-clean) - - if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" - OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") - # Messages - message(STATUS "Building with llvm Code Coverage Tools") - - if(NOT LLVM_COV_PATH) - message(FATAL_ERROR "llvm-cov not found! Aborting.") - else() - # Version number checking for 'EXCLUDE' compatibility - execute_process(COMMAND ${LLVM_COV_PATH} --version - OUTPUT_VARIABLE LLVM_COV_VERSION_CALL_OUTPUT) - string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" LLVM_COV_VERSION - ${LLVM_COV_VERSION_CALL_OUTPUT}) - - if(LLVM_COV_VERSION VERSION_LESS "7.0.0") - message( - WARNING - "target_code_coverage()/add_code_coverage_all_targets() 'EXCLUDE' option only available on llvm-cov >= 7.0.0" - ) - endif() - endif() - - # Targets - if(${CMAKE_VERSION} VERSION_LESS "3.17.0") - add_custom_target( - ccov-clean - COMMAND ${CMAKE_COMMAND} -E remove -f - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list - COMMAND ${CMAKE_COMMAND} -E remove -f - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list) - else() - add_custom_target( - ccov-clean - COMMAND ${CMAKE_COMMAND} -E rm -f - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list - COMMAND ${CMAKE_COMMAND} -E rm -f - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list) - endif() - - # Used to get the shared object file list before doing the main all- - # processing - add_custom_target( - ccov-libs - COMMAND ; - COMMENT "libs ready for coverage report.") - - elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES - "GNU") - # Messages - message(STATUS "Building with lcov Code Coverage Tools") - - if(CMAKE_BUILD_TYPE) - string(TOUPPER ${CMAKE_BUILD_TYPE} upper_build_type) - if(NOT ${upper_build_type} STREQUAL "DEBUG") - message( - WARNING - "Code coverage results with an optimized (non-Debug) build may be misleading" - ) - endif() - else() - message( - WARNING - "Code coverage results with an optimized (non-Debug) build may be misleading" - ) - endif() - if(NOT LCOV_PATH) - message(FATAL_ERROR "lcov not found! Aborting...") - endif() - if(NOT GENHTML_PATH) - message(FATAL_ERROR "genhtml not found! Aborting...") - endif() - - # Targets - add_custom_target(ccov-clean COMMAND ${LCOV_PATH} --directory - ${CMAKE_BINARY_DIR} --zerocounters) - - else() - message(FATAL_ERROR "Code coverage requires Clang or GCC. Aborting.") - endif() -endif() - -# Adds code coverage instrumentation to a library, or instrumentation/targets -# for an executable target. -# ~~~ -# EXECUTABLE ADDED TARGETS: -# GCOV/LCOV: -# ccov : Generates HTML code coverage report for every target added with 'AUTO' parameter. -# ccov-${TARGET_NAME} : Generates HTML code coverage report for the associated named target. -# ccov-all : Generates HTML code coverage report, merging every target added with 'ALL' parameter into a single detailed report. -# -# LLVM-COV: -# ccov : Generates HTML code coverage report for every target added with 'AUTO' parameter. -# ccov-report : Generates HTML code coverage report for every target added with 'AUTO' parameter. -# ccov-${TARGET_NAME} : Generates HTML code coverage report. -# ccov-report-${TARGET_NAME} : Prints to command line summary per-file coverage information. -# ccov-export-${TARGET_NAME} : Exports the coverage report to a JSON file. -# ccov-show-${TARGET_NAME} : Prints to command line detailed per-line coverage information. -# ccov-all : Generates HTML code coverage report, merging every target added with 'ALL' parameter into a single detailed report. -# ccov-all-report : Prints summary per-file coverage information for every target added with ALL' parameter to the command line. -# ccov-all-export : Exports the coverage report to a JSON file. -# -# Required: -# TARGET_NAME - Name of the target to generate code coverage for. -# Optional: -# PUBLIC - Sets the visibility for added compile options to targets to PUBLIC instead of the default of PRIVATE. -# INTERFACE - Sets the visibility for added compile options to targets to INTERFACE instead of the default of PRIVATE. -# PLAIN - Do not set any target visibility (backward compatibility with old cmake projects) -# AUTO - Adds the target to the 'ccov' target so that it can be run in a batch with others easily. Effective on executable targets. -# ALL - Adds the target to the 'ccov-all' and 'ccov-all-report' targets, which merge several executable targets coverage data to a single report. Effective on executable targets. -# EXTERNAL - For GCC's lcov, allows the profiling of 'external' files from the processing directory -# COVERAGE_TARGET_NAME - For executables ONLY, changes the outgoing target name so instead of `ccov-${TARGET_NAME}` it becomes `ccov-${COVERAGE_TARGET_NAME}`. -# EXCLUDE - Excludes files of the patterns provided from coverage. Note that GCC/lcov excludes by glob pattern, and clang/LLVM excludes via regex! **These do not copy to the 'all' targets.** -# OBJECTS - For executables ONLY, if the provided targets are shared libraries, adds coverage information to the output -# ARGS - For executables ONLY, appends the given arguments to the associated ccov-* executable call -# ~~~ -function(target_code_coverage TARGET_NAME) - # Argument parsing - set(options AUTO ALL EXTERNAL PUBLIC INTERFACE PLAIN) - set(single_value_keywords COVERAGE_TARGET_NAME) - set(multi_value_keywords EXCLUDE OBJECTS ARGS) - cmake_parse_arguments( - target_code_coverage "${options}" "${single_value_keywords}" - "${multi_value_keywords}" ${ARGN}) - - # Set the visibility of target functions to PUBLIC, INTERFACE or default to - # PRIVATE. - if(target_code_coverage_PUBLIC) - set(TARGET_VISIBILITY PUBLIC) - set(TARGET_LINK_VISIBILITY PUBLIC) - elseif(target_code_coverage_INTERFACE) - set(TARGET_VISIBILITY INTERFACE) - set(TARGET_LINK_VISIBILITY INTERFACE) - elseif(target_code_coverage_PLAIN) - set(TARGET_VISIBILITY PUBLIC) - set(TARGET_LINK_VISIBILITY) - else() - set(TARGET_VISIBILITY PRIVATE) - set(TARGET_LINK_VISIBILITY PRIVATE) - endif() - - if(NOT target_code_coverage_COVERAGE_TARGET_NAME) - # If a specific name was given, use that instead. - set(target_code_coverage_COVERAGE_TARGET_NAME ${TARGET_NAME}) - endif() - - if(CODE_COVERAGE) - - # Add code coverage instrumentation to the target's linker command - if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" - OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") - target_compile_options(${TARGET_NAME} ${TARGET_VISIBILITY} - -fprofile-instr-generate -fcoverage-mapping) - target_link_options(${TARGET_NAME} ${TARGET_VISIBILITY} - -fprofile-instr-generate -fcoverage-mapping) - elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES - "GNU") - target_compile_options(${TARGET_NAME} ${TARGET_VISIBILITY} -fprofile-arcs - -ftest-coverage) - target_link_libraries(${TARGET_NAME} ${TARGET_LINK_VISIBILITY} gcov) - endif() - - # Targets - get_target_property(target_type ${TARGET_NAME} TYPE) - - # Add shared library to processing for 'all' targets - if(target_type STREQUAL "SHARED_LIBRARY" AND target_code_coverage_ALL) - if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" - OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") - add_custom_target( - ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME} - COMMAND - ${CMAKE_COMMAND} -E echo "-object=$" >> - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list - DEPENDS ccov-preprocessing ${TARGET_NAME}) - - if(NOT TARGET ccov-libs) - message( - FATAL_ERROR - "Calling target_code_coverage with 'ALL' must be after a call to 'add_code_coverage_all_targets'." - ) - endif() - - add_dependencies(ccov-libs - ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME}) - endif() - endif() - - # For executables add targets to run and produce output - if(target_type STREQUAL "EXECUTABLE") - if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" - OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") - - # If there are shared objects to also work with, generate the string to - # add them here - foreach(SO_TARGET ${target_code_coverage_OBJECTS}) - # Check to see if the target is a shared object - if(TARGET ${SO_TARGET}) - get_target_property(SO_TARGET_TYPE ${SO_TARGET} TYPE) - if(${SO_TARGET_TYPE} STREQUAL "SHARED_LIBRARY") - set(SO_OBJECTS ${SO_OBJECTS} -object=$) - endif() - endif() - endforeach() - - # Run the executable, generating raw profile data Make the run data - # available for further processing. Separated to allow Windows to run - # this target serially. - add_custom_target( - ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME} - COMMAND - ${CMAKE_COMMAND} -E env - LLVM_PROFILE_FILE=${target_code_coverage_COVERAGE_TARGET_NAME}.profraw - $ ${target_code_coverage_ARGS} - COMMAND - ${CMAKE_COMMAND} -E echo "-object=$" - ${SO_OBJECTS} >> ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list - COMMAND - ${CMAKE_COMMAND} -E echo - "${CMAKE_CURRENT_BINARY_DIR}/${target_code_coverage_COVERAGE_TARGET_NAME}.profraw" - >> ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list - JOB_POOL ccov_serial_pool - DEPENDS ccov-preprocessing ccov-libs ${TARGET_NAME}) - - # Merge the generated profile data so llvm-cov can process it - add_custom_target( - ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME} - COMMAND - ${LLVM_PROFDATA_PATH} merge -sparse - ${target_code_coverage_COVERAGE_TARGET_NAME}.profraw -o - ${target_code_coverage_COVERAGE_TARGET_NAME}.profdata - DEPENDS ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME}) - - # Ignore regex only works on LLVM >= 7 - if(LLVM_COV_VERSION VERSION_GREATER_EQUAL "7.0.0") - foreach(EXCLUDE_ITEM ${target_code_coverage_EXCLUDE}) - set(EXCLUDE_REGEX ${EXCLUDE_REGEX} - -ignore-filename-regex='${EXCLUDE_ITEM}') - endforeach() - endif() - - # Print out details of the coverage information to the command line - add_custom_target( - ccov-show-${target_code_coverage_COVERAGE_TARGET_NAME} - COMMAND - ${LLVM_COV_PATH} show $ ${SO_OBJECTS} - -instr-profile=${target_code_coverage_COVERAGE_TARGET_NAME}.profdata - -show-line-counts-or-regions ${EXCLUDE_REGEX} - DEPENDS ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME}) - - # Print out a summary of the coverage information to the command line - add_custom_target( - ccov-report-${target_code_coverage_COVERAGE_TARGET_NAME} - COMMAND - ${LLVM_COV_PATH} report $ ${SO_OBJECTS} - -instr-profile=${target_code_coverage_COVERAGE_TARGET_NAME}.profdata - ${EXCLUDE_REGEX} - DEPENDS ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME}) - - # Export coverage information so continuous integration tools (e.g. - # Jenkins) can consume it - add_custom_target( - ccov-export-${target_code_coverage_COVERAGE_TARGET_NAME} - COMMAND - ${LLVM_COV_PATH} export $ ${SO_OBJECTS} - -instr-profile=${target_code_coverage_COVERAGE_TARGET_NAME}.profdata - -format="text" ${EXCLUDE_REGEX} > - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME}.json - DEPENDS ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME}) - - # Generates HTML output of the coverage information for perusal - add_custom_target( - ccov-${target_code_coverage_COVERAGE_TARGET_NAME} - COMMAND - ${LLVM_COV_PATH} show $ ${SO_OBJECTS} - -instr-profile=${target_code_coverage_COVERAGE_TARGET_NAME}.profdata - -show-line-counts-or-regions - -output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME} - -format="html" ${EXCLUDE_REGEX} - DEPENDS ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME}) - - elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES - "GNU") - set(COVERAGE_INFO - "${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME}.info" - ) - - # Run the executable, generating coverage information - add_custom_target( - ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME} - COMMAND $ ${target_code_coverage_ARGS} - DEPENDS ccov-preprocessing ${TARGET_NAME}) - - # Generate exclusion string for use - foreach(EXCLUDE_ITEM ${target_code_coverage_EXCLUDE}) - set(EXCLUDE_REGEX ${EXCLUDE_REGEX} --remove ${COVERAGE_INFO} - '${EXCLUDE_ITEM}') - endforeach() - - if(EXCLUDE_REGEX) - set(EXCLUDE_COMMAND ${LCOV_PATH} ${EXCLUDE_REGEX} --output-file - ${COVERAGE_INFO}) - else() - set(EXCLUDE_COMMAND ;) - endif() - - if(NOT ${target_code_coverage_EXTERNAL}) - set(EXTERNAL_OPTION --no-external) - endif() - - # Capture coverage data - if(${CMAKE_VERSION} VERSION_LESS "3.17.0") - add_custom_target( - ccov-capture-${target_code_coverage_COVERAGE_TARGET_NAME} - COMMAND ${CMAKE_COMMAND} -E remove -f ${COVERAGE_INFO} - COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --zerocounters - COMMAND $ ${target_code_coverage_ARGS} - COMMAND - ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --base-directory - ${CMAKE_SOURCE_DIR} --capture ${EXTERNAL_OPTION} --output-file - ${COVERAGE_INFO} - COMMAND ${EXCLUDE_COMMAND} - DEPENDS ccov-preprocessing ${TARGET_NAME}) - else() - add_custom_target( - ccov-capture-${target_code_coverage_COVERAGE_TARGET_NAME} - COMMAND ${CMAKE_COMMAND} -E rm -f ${COVERAGE_INFO} - COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --zerocounters - COMMAND $ ${target_code_coverage_ARGS} - COMMAND - ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --base-directory - ${CMAKE_SOURCE_DIR} --capture ${EXTERNAL_OPTION} --output-file - ${COVERAGE_INFO} - COMMAND ${EXCLUDE_COMMAND} - DEPENDS ccov-preprocessing ${TARGET_NAME}) - endif() - - # Generates HTML output of the coverage information for perusal - add_custom_target( - ccov-${target_code_coverage_COVERAGE_TARGET_NAME} - COMMAND - ${GENHTML_PATH} -o - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME} - ${COVERAGE_INFO} - DEPENDS ccov-capture-${target_code_coverage_COVERAGE_TARGET_NAME}) - endif() - - add_custom_command( - TARGET ccov-${target_code_coverage_COVERAGE_TARGET_NAME} - POST_BUILD - COMMAND ; - COMMENT - "Open ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME}/index.html in your browser to view the coverage report." - ) - - # AUTO - if(target_code_coverage_AUTO) - if(NOT TARGET ccov) - add_custom_target(ccov) - endif() - add_dependencies(ccov ccov-${target_code_coverage_COVERAGE_TARGET_NAME}) - - if(NOT CMAKE_C_COMPILER_ID MATCHES "GNU" AND NOT CMAKE_CXX_COMPILER_ID - MATCHES "GNU") - if(NOT TARGET ccov-report) - add_custom_target(ccov-report) - endif() - add_dependencies( - ccov-report - ccov-report-${target_code_coverage_COVERAGE_TARGET_NAME}) - endif() - endif() - - # ALL - if(target_code_coverage_ALL) - if(NOT TARGET ccov-all-processing) - message( - FATAL_ERROR - "Calling target_code_coverage with 'ALL' must be after a call to 'add_code_coverage_all_targets'." - ) - endif() - - add_dependencies(ccov-all-processing - ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME}) - endif() - endif() - endif() -endfunction() - -# Adds code coverage instrumentation to all targets in the current directory and -# any subdirectories. To add coverage instrumentation to only specific targets, -# use `target_code_coverage`. -function(add_code_coverage) - if(CODE_COVERAGE) - if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" - OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") - add_compile_options(-fprofile-instr-generate -fcoverage-mapping) - add_link_options(-fprofile-instr-generate -fcoverage-mapping) - elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES - "GNU") - add_compile_options(-fprofile-arcs -ftest-coverage) - link_libraries(gcov) - endif() - endif() -endfunction() - -# Adds the 'ccov-all' type targets that calls all targets added via -# `target_code_coverage` with the `ALL` parameter, but merges all the coverage -# data from them into a single large report instead of the numerous smaller -# reports. Also adds the ccov-all-capture Generates an all-merged.info file, for -# use with coverage dashboards (e.g. codecov.io, coveralls). -# ~~~ -# Optional: -# EXCLUDE - Excludes files of the patterns provided from coverage. Note that GCC/lcov excludes by glob pattern, and clang/LLVM excludes via regex! -# ~~~ -function(add_code_coverage_all_targets) - # Argument parsing - set(multi_value_keywords EXCLUDE) - cmake_parse_arguments(add_code_coverage_all_targets "" "" - "${multi_value_keywords}" ${ARGN}) - - if(CODE_COVERAGE) - if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" - OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") - - # Merge the profile data for all of the run executables - if(WIN32) - add_custom_target( - ccov-all-processing - COMMAND - powershell -Command $$FILELIST = Get-Content - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list\; llvm-profdata.exe - merge -o ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata - -sparse $$FILELIST) - else() - add_custom_target( - ccov-all-processing - COMMAND - ${LLVM_PROFDATA_PATH} merge -o - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata -sparse `cat - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list`) - endif() - - # Regex exclude only available for LLVM >= 7 - if(LLVM_COV_VERSION VERSION_GREATER_EQUAL "7.0.0") - foreach(EXCLUDE_ITEM ${add_code_coverage_all_targets_EXCLUDE}) - set(EXCLUDE_REGEX ${EXCLUDE_REGEX} - -ignore-filename-regex='${EXCLUDE_ITEM}') - endforeach() - endif() - - # Print summary of the code coverage information to the command line - if(WIN32) - add_custom_target( - ccov-all-report - COMMAND - powershell -Command $$FILELIST = Get-Content - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list\; llvm-cov.exe - report $$FILELIST - -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata - ${EXCLUDE_REGEX} - DEPENDS ccov-all-processing) - else() - add_custom_target( - ccov-all-report - COMMAND - ${LLVM_COV_PATH} report `cat - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list` - -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata - ${EXCLUDE_REGEX} - DEPENDS ccov-all-processing) - endif() - - # Export coverage information so continuous integration tools (e.g. - # Jenkins) can consume it - add_custom_target( - ccov-all-export - COMMAND - ${LLVM_COV_PATH} export `cat - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list` - -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata - -format="text" ${EXCLUDE_REGEX} > - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/coverage.json - DEPENDS ccov-all-processing) - - # Generate HTML output of all added targets for perusal - if(WIN32) - add_custom_target( - ccov-all - COMMAND - powershell -Command $$FILELIST = Get-Content - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list\; llvm-cov.exe show - $$FILELIST - -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata - -show-line-counts-or-regions - -output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged - -format="html" ${EXCLUDE_REGEX} - DEPENDS ccov-all-processing) - else() - add_custom_target( - ccov-all - COMMAND - ${LLVM_COV_PATH} show `cat - ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list` - -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata - -show-line-counts-or-regions - -output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged - -format="html" ${EXCLUDE_REGEX} - DEPENDS ccov-all-processing) - endif() - - elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES - "GNU") - set(COVERAGE_INFO "${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.info") - - # Nothing required for gcov - add_custom_target(ccov-all-processing COMMAND ;) - - # Exclusion regex string creation - set(EXCLUDE_REGEX) - foreach(EXCLUDE_ITEM ${add_code_coverage_all_targets_EXCLUDE}) - set(EXCLUDE_REGEX ${EXCLUDE_REGEX} --remove ${COVERAGE_INFO} - '${EXCLUDE_ITEM}') - endforeach() - - if(EXCLUDE_REGEX) - set(EXCLUDE_COMMAND ${LCOV_PATH} ${EXCLUDE_REGEX} --output-file - ${COVERAGE_INFO}) - else() - set(EXCLUDE_COMMAND ;) - endif() - - # Capture coverage data - if(${CMAKE_VERSION} VERSION_LESS "3.17.0") - add_custom_target( - ccov-all-capture - COMMAND ${CMAKE_COMMAND} -E remove -f ${COVERAGE_INFO} - COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --capture - --output-file ${COVERAGE_INFO} - COMMAND ${EXCLUDE_COMMAND} - DEPENDS ccov-preprocessing ccov-all-processing) - else() - add_custom_target( - ccov-all-capture - COMMAND ${CMAKE_COMMAND} -E rm -f ${COVERAGE_INFO} - COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --capture - --output-file ${COVERAGE_INFO} - COMMAND ${EXCLUDE_COMMAND} - DEPENDS ccov-preprocessing ccov-all-processing) - endif() - - # Generates HTML output of all targets for perusal - add_custom_target( - ccov-all - COMMAND ${GENHTML_PATH} -o ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged - ${COVERAGE_INFO} -p ${CMAKE_SOURCE_DIR} - DEPENDS ccov-all-capture) - - endif() - - add_custom_command( - TARGET ccov-all - POST_BUILD - COMMAND ; - COMMENT - "Open ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged/index.html in your browser to view the coverage report." - ) - endif() -endfunction() diff --git a/cmake/cxx.cmake b/cmake/cxx.cmake deleted file mode 100644 index e01e6801..00000000 --- a/cmake/cxx.cmake +++ /dev/null @@ -1,40 +0,0 @@ -# ---------------------------------------------------------------- -# use this in subdirs that compile c++ code -# -macro(xo_include_options target) - # ---------------------------------------------------------------- - # PROJECT_SOURCE_DIR: - # so we can for example write - # #include "ordinaltree/foo.hpp" - # from anywhere in the project - # PROJECT_BINARY_DIR: - # since generated version file will be in build directory, - # need that build directory to also appear in - # compiler's include path - # - target_include_directories( - ${target} PUBLIC - ${PROJECT_SOURCE_DIR}/include - ${PROJECT_BINARY_DIR} - ) - - # ---------------------------------------------------------------- - # make standard directories for std:: includes explicit - # so that - # (1) they appear in compile_commands.json. - # (2) clangd (run from emacs lsp-mode) can find them - # - if(CMAKE_EXPORT_COMPILE_COMMANDS) - set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) - endif() -endmacro() - -# ---------------------------------------------------------------- -# use this when relying on indentlog [[https://github.com/rconybea/indentlog]] headers -# -macro(xo_indentlog_dependency target) - find_package(indentlog REQUIRED) - #add_dependencies(${target} indentlog) - target_link_libraries(${target} PUBLIC indentlog) - #target_include_directories(${target} PUBLIC ${indentlog_DIR}/../../../include) -endmacro() From 90dcd600c07068fc4162e1068941fae983f38d87 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 4 Oct 2023 00:02:38 -0400 Subject: [PATCH 09/29] build: + cmake find_package() support --- CMakeLists.txt | 25 +++++++++++++++++++------ README.md | 3 ++- cmake/randomgenConfig.cmake.in | 4 ++++ 3 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 cmake/randomgenConfig.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 5653ec33..87383904 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# using indentlog/CMakeLists.txt as model +# randomgen/CMakeLists.txt cmake_minimum_required(VERSION 3.10) @@ -23,14 +23,14 @@ add_code_coverage() add_code_coverage_all_targets(EXCLUDE /nix/store/* utest/*) # ---------------------------------------------------------------- -# c++ settings - -set(PROJECT_CXX_FLAGS "-fconcepts-diagnostics-depth=2") +# bespoke (usually temporary) c++ settings +set(PROJECT_CXX_FLAGS "") +#set(PROJECT_CXX_FLAGS "-fconcepts-diagnostics-depth=2") add_definitions(${PROJECT_CXX_FLAGS}) # ---------------------------------------------------------------- -# default install +# common include paths etc. xo_toplevel_compile_options() @@ -40,7 +40,7 @@ xo_toplevel_compile_options() # set CMAKE_INSTALL_PREFIX to analog of /usr # to use .cmake assistants from /usr/lib/cmake/indentlog # -#find_package(indentlog REQUIRED) +# xo_internal_dependency(..) # ---------------------------------------------------------------- @@ -48,7 +48,20 @@ add_subdirectory(example) #add_subdirectory(utest) # ---------------------------------------------------------------- +# output targets +set(SELF_LIB randomgen) +add_library(${SELF_LIB} INTERFACE) +xo_include_headeronly_options2(${SELF_LIB}) + +# ---------------------------------------------------------------- +# standard install + provide find_package() support + +xo_install_library2(${SELF_LIB}) xo_install_include_tree() +xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets) + +# ---------------------------------------------------------------- +# install additional components install(TARGETS ex1 DESTINATION bin/randomgen/example) diff --git a/README.md b/README.md index 905f267e..73f13f1b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ $ cd randomgen $ mkdir build $ cd build -$ cmake -DCMAKE_MODULE_PATH=${INSTALL_PREFIX}/share/cmake -DCMAKE_PREFIX_PATH=$(INSTALL_PREFIX) .. +$ PREFIX=/usr/local # for example +$ cmake -DCMAKE_MODULE_PATH=${PREFIX}/share/cmake -DCMAKE_PREFIX_PATH=$(PREFIX) -DCMAKE_INSTALL_PREFIX=${PREFIX} .. $ make $ make install ``` diff --git a/cmake/randomgenConfig.cmake.in b/cmake/randomgenConfig.cmake.in new file mode 100644 index 00000000..e66430b0 --- /dev/null +++ b/cmake/randomgenConfig.cmake.in @@ -0,0 +1,4 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/randomgenTargets.cmake") +check_required_components("@PROJECT_NAME@") From a26a6e4656e2ed45be533a7a70c866647a8793d7 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 4 Oct 2023 15:50:40 -0400 Subject: [PATCH 10/29] random: use get_random() instead of arc4random_buf() for non-bsd builds --- include/randomgen/random_seed.hpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/include/randomgen/random_seed.hpp b/include/randomgen/random_seed.hpp index 5273ddeb..016f612f 100644 --- a/include/randomgen/random_seed.hpp +++ b/include/randomgen/random_seed.hpp @@ -1,9 +1,14 @@ /* @file random_seed.hpp */ -#include "indentlog/print/array.hpp" +//#include "indentlog/print/array.hpp" #include #include #include +#ifdef _BSD_SOURCE +# include +#else +# include +#endif namespace xo { namespace rng { @@ -20,10 +25,22 @@ namespace xo { */ template void random_seed(T * p_seed) { +# ifdef _BSD_SOURCE /* NOTE: arc4random_buf() works on darwin/nix; * probably need to do something else on intel linux */ - arc4random_buf(p_seed, sizeof(*p_seed)); + ::arc4random_buf(p_seed, sizeof(*p_seed)); +# else + /* avail flags: GRND_RANDOM | GRND_NONBLOCK */ + while (::getrandom(p_seed, sizeof(*p_seed), 0) == -1) { + if (errno == EINTR) { + /* interrupted by signal, try again */ + continue; + } else { + break; + } + } +# endif } /*random_seed*/ template From 9a2fc0605be5b736efc6ab3d545487eae84110c0 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 4 Oct 2023 16:01:48 -0400 Subject: [PATCH 11/29] randomgen: + print.hpp --- include/randomgen/print.hpp | 7 +++++++ include/randomgen/random_seed.hpp | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 include/randomgen/print.hpp diff --git a/include/randomgen/print.hpp b/include/randomgen/print.hpp new file mode 100644 index 00000000..e9860ab0 --- /dev/null +++ b/include/randomgen/print.hpp @@ -0,0 +1,7 @@ +/* @file print.hpp */ + +#pragma once + +#include "indentlog/print/array.hpp" + +/* end print.hpp */ diff --git a/include/randomgen/random_seed.hpp b/include/randomgen/random_seed.hpp index 016f612f..67246c01 100644 --- a/include/randomgen/random_seed.hpp +++ b/include/randomgen/random_seed.hpp @@ -1,6 +1,5 @@ /* @file random_seed.hpp */ -//#include "indentlog/print/array.hpp" #include #include #include From 00fae469e02e42ed9c9e3f9b5aa1f4527d789cf2 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 6 Oct 2023 18:41:45 -0400 Subject: [PATCH 12/29] randomgen: fixing include paths for xo/ insertion --- example/ex1/ex1.cpp | 4 +--- example/ex2/ex2.cpp | 4 ++-- include/{ => xo}/randomgen/engine_concept.hpp | 0 include/{ => xo}/randomgen/print.hpp | 0 include/{ => xo}/randomgen/random_seed.hpp | 0 include/{ => xo}/randomgen/xoshiro256.hpp | 0 6 files changed, 3 insertions(+), 5 deletions(-) rename include/{ => xo}/randomgen/engine_concept.hpp (100%) rename include/{ => xo}/randomgen/print.hpp (100%) rename include/{ => xo}/randomgen/random_seed.hpp (100%) rename include/{ => xo}/randomgen/xoshiro256.hpp (100%) diff --git a/example/ex1/ex1.cpp b/example/ex1/ex1.cpp index 8c908fa5..0db92be4 100644 --- a/example/ex1/ex1.cpp +++ b/example/ex1/ex1.cpp @@ -1,10 +1,8 @@ /* @file ex1.cpp */ -#include "randomgen/xoshiro256.hpp" +#include "xo/randomgen/xoshiro256.hpp" #include #include -//#include -//#include using namespace xo; using namespace xo::rng; diff --git a/example/ex2/ex2.cpp b/example/ex2/ex2.cpp index c77e06ff..949b65dc 100644 --- a/example/ex2/ex2.cpp +++ b/example/ex2/ex2.cpp @@ -1,7 +1,7 @@ /* @file ex2.cpp */ -#include "randomgen/xoshiro256.hpp" -#include "randomgen/random_seed.hpp" +#include "xo/randomgen/xoshiro256.hpp" +#include "xo/randomgen/random_seed.hpp" using namespace xo; using namespace xo::rng; diff --git a/include/randomgen/engine_concept.hpp b/include/xo/randomgen/engine_concept.hpp similarity index 100% rename from include/randomgen/engine_concept.hpp rename to include/xo/randomgen/engine_concept.hpp diff --git a/include/randomgen/print.hpp b/include/xo/randomgen/print.hpp similarity index 100% rename from include/randomgen/print.hpp rename to include/xo/randomgen/print.hpp diff --git a/include/randomgen/random_seed.hpp b/include/xo/randomgen/random_seed.hpp similarity index 100% rename from include/randomgen/random_seed.hpp rename to include/xo/randomgen/random_seed.hpp diff --git a/include/randomgen/xoshiro256.hpp b/include/xo/randomgen/xoshiro256.hpp similarity index 100% rename from include/randomgen/xoshiro256.hpp rename to include/xo/randomgen/xoshiro256.hpp From 5b558ce086ccbb4861e914a676dc8212cb3042f0 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 6 Oct 2023 18:42:32 -0400 Subject: [PATCH 13/29] .gitignore: + compile_commands.json --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 69e11d47..e90fd723 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ .cache # typical build directory build +# compile_commands.json: symlink to build directory, should be created manually +compile_commands.json From b3d4a1276efcfa9b555161b38dc7db44747e05f6 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 6 Oct 2023 19:27:24 -0400 Subject: [PATCH 14/29] build: fix include path to insert xo/ dir --- include/xo/randomgen/print.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/xo/randomgen/print.hpp b/include/xo/randomgen/print.hpp index e9860ab0..d5b0a992 100644 --- a/include/xo/randomgen/print.hpp +++ b/include/xo/randomgen/print.hpp @@ -2,6 +2,6 @@ #pragma once -#include "indentlog/print/array.hpp" +#include "xo/indentlog/print/array.hpp" /* end print.hpp */ From 5019c9402474883a71f77740df6fc979d057c397 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 8 Oct 2023 13:51:39 -0400 Subject: [PATCH 15/29] build nit: xo_internal_dependency() -> xo_dependency() --- CMakeLists.txt | 2 +- example/ex2/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 87383904..c5413d7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,7 @@ xo_toplevel_compile_options() # set CMAKE_INSTALL_PREFIX to analog of /usr # to use .cmake assistants from /usr/lib/cmake/indentlog # -# xo_internal_dependency(..) +# xo_dependency(..) # ---------------------------------------------------------------- diff --git a/example/ex2/CMakeLists.txt b/example/ex2/CMakeLists.txt index ee6687f2..78016d45 100644 --- a/example/ex2/CMakeLists.txt +++ b/example/ex2/CMakeLists.txt @@ -1,3 +1,3 @@ add_executable(ex2 ex2.cpp) xo_include_options2(ex2) -xo_internal_dependency(ex2 indentlog) +xo_dependency(ex2 indentlog) From f05068a45b2e15be7b438b44921caf47fe04873d Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 8 Oct 2023 13:52:02 -0400 Subject: [PATCH 16/29] bugfix: xo/ in include path --- include/xo/randomgen/print.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/xo/randomgen/print.hpp b/include/xo/randomgen/print.hpp index e9860ab0..d5b0a992 100644 --- a/include/xo/randomgen/print.hpp +++ b/include/xo/randomgen/print.hpp @@ -2,6 +2,6 @@ #pragma once -#include "indentlog/print/array.hpp" +#include "xo/indentlog/print/array.hpp" /* end print.hpp */ From f0208ec71aab7c3bd45b179700b1b0aab76babd5 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Tue, 17 Oct 2023 00:20:00 -0400 Subject: [PATCH 17/29] randomgen: compile fixes for OSX (clang 11) --- include/xo/randomgen/engine_concept.hpp | 39 ++++++++++++++++++++++++- include/xo/randomgen/random_seed.hpp | 2 +- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/include/xo/randomgen/engine_concept.hpp b/include/xo/randomgen/engine_concept.hpp index 42557b0e..38b65cd7 100644 --- a/include/xo/randomgen/engine_concept.hpp +++ b/include/xo/randomgen/engine_concept.hpp @@ -5,6 +5,37 @@ #include #include +namespace std { +#ifdef __clang__ + template < class T > + concept integral = std::is_integral_v; + + template < class T > + concept signed_integral = std::integral && std::is_signed_v; + + template < class T > + concept unsigned_integral + = std::integral && !std::signed_integral; + + template< class F, class... Args > + concept invocable + = requires(F&& f, Args&&... args) { + std::invoke(std::forward(f), std::forward(args)...); + /* not required to be equality-preserving */ + }; + + template< typename G > + concept uniform_random_bit_generator + = std::invocable + && std::unsigned_integral> + && requires { { G::min() } -> std::same_as>; + { G::max() } -> std::same_as>; + requires std::bool_constant<(G::min() < G::max())>::value; }; +#else + /* uniform_random_bit_generator provided by gcc 12.3.2 */ +#endif +} /*namespace std*/ + namespace xo { namespace rng { /* an engine generates psuedo-random bits. @@ -29,7 +60,13 @@ namespace xo { { engine.seed(r) }; { engine == engine }; { engine != engine }; - } && std::copyable && std::uniform_random_bit_generator; + } +#ifdef __clang__ + // std::copyable apparently not available in clang11 ? +#else + && std::copyable +#endif + && std::uniform_random_bit_generator; } /*namespace rng*/ } /*namespace xo*/ diff --git a/include/xo/randomgen/random_seed.hpp b/include/xo/randomgen/random_seed.hpp index 67246c01..92447b3c 100644 --- a/include/xo/randomgen/random_seed.hpp +++ b/include/xo/randomgen/random_seed.hpp @@ -24,7 +24,7 @@ namespace xo { */ template void random_seed(T * p_seed) { -# ifdef _BSD_SOURCE +# ifdef __clang__ /* NOTE: arc4random_buf() works on darwin/nix; * probably need to do something else on intel linux */ From a4c264d8db2f02e7d7bc433e22f571b65450aba1 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Tue, 17 Oct 2023 14:54:27 -0400 Subject: [PATCH 18/29] randomgen: distribution + related concepts --- include/xo/randomgen/distribution_concept.hpp | 35 +++++++++++++ include/xo/randomgen/generator.hpp | 49 +++++++++++++++++++ include/xo/randomgen/normalgen.hpp | 14 ++++++ 3 files changed, 98 insertions(+) create mode 100644 include/xo/randomgen/distribution_concept.hpp create mode 100644 include/xo/randomgen/generator.hpp create mode 100644 include/xo/randomgen/normalgen.hpp diff --git a/include/xo/randomgen/distribution_concept.hpp b/include/xo/randomgen/distribution_concept.hpp new file mode 100644 index 00000000..61c764e0 --- /dev/null +++ b/include/xo/randomgen/distribution_concept.hpp @@ -0,0 +1,35 @@ +/* @file distribution_concept.hpp */ + +#pragma once + +#include + +namespace xo { + namespace rng { + template + concept distribution_concept = requires(Distribution dist, typename Distribution::param_type p) { + typename Distribution::result_type; + typename Distribution::param_type; + { Distribution() }; + { Distribution(p) }; + { dist.reset() }; + { dist.param() }; + { dist.param(p) }; + // { dist(g) }; // generator g satisfying engine_concept + // { dist(g, p) }; + { dist.min() }; + { dist.max() }; + { dist == dist }; + { dist != dist }; + // os << dist + // is >> dist + + } && std::copyable + && std::copyable + && std::equality_comparable; + } /*namespace rng*/ + +} /*namespace xo*/ + + +/* end distribution_concept.hpp */ diff --git a/include/xo/randomgen/generator.hpp b/include/xo/randomgen/generator.hpp new file mode 100644 index 00000000..f35c0994 --- /dev/null +++ b/include/xo/randomgen/generator.hpp @@ -0,0 +1,49 @@ +/* @file generator.hpp */ + +#pragma once + +#include "engine_concept.hpp" +#include "distribution_concept.hpp" +#include + +namespace xo { + namespace rng { + /* Engine: uniform integer random number generator, e.g. xoshiro256ss + * Distribution: random number distribution, e.g. std::normal_distribution + */ + template requires engine_concept && distribution_concept + class generator { + public: + using result_type = typename Distribution::result_type; + using engine_type = Engine; + + public: + generator(Engine & e, Distribution const & d) + : engine_{e}, + distribution_{d} {} + generator(Engine && e, Distribution && d) + : engine_{std::move(e)}, + distribution_{std::move(d)} {} + + static generator make(Engine e, Distribution d) { + return generator(e, d); + } + + result_type operator()() { return this->distribution_(this->engine_); } + + private: + /* random number generator; generates uniformly-distributed integers */ + Engine engine_; + /* distribution object */ + Distribution distribution_; + }; /*generator*/ + + template + generator make_generator(Engine e, Distribution d) { + return generator::make(std::move(e), + std::move(d)); + } /*make_generator*/ + } /*namespace rng*/ +} /*namespace xo*/ + +/* end generator.hpp */ diff --git a/include/xo/randomgen/normalgen.hpp b/include/xo/randomgen/normalgen.hpp new file mode 100644 index 00000000..dad04328 --- /dev/null +++ b/include/xo/randomgen/normalgen.hpp @@ -0,0 +1,14 @@ +/* @file normalgen.hpp */ + +#pragma once + +#include "generator.hpp" +#include + +namespace xo { + namespace rng { + /* Engine: e.g. xo::rng::xoshiro256 or std::mt19937 */ + template + using normalgen = generator>; + } /*namespace rng*/ +} /*namespace xo*/ From 0068f6c0fda6b270c9e7481a17a7d0556be15f60 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 19 Oct 2023 00:00:41 -0400 Subject: [PATCH 19/29] build: concept carveout for clang + std::copyable --- include/xo/randomgen/distribution_concept.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/xo/randomgen/distribution_concept.hpp b/include/xo/randomgen/distribution_concept.hpp index 61c764e0..979a64d5 100644 --- a/include/xo/randomgen/distribution_concept.hpp +++ b/include/xo/randomgen/distribution_concept.hpp @@ -24,12 +24,16 @@ namespace xo { // os << dist // is >> dist - } && std::copyable + } +#ifdef __clang__ + // std::copyable apparently not available in clang11 ? +#else + && std::copyable && std::copyable +#endif && std::equality_comparable; } /*namespace rng*/ } /*namespace xo*/ - /* end distribution_concept.hpp */ From a6d0252dd46c19772370fab8e752c15497f0ca64 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 19 Oct 2023 12:15:18 -0400 Subject: [PATCH 20/29] build: clang16 fixes (c++20 concept headers available) --- include/xo/randomgen/distribution_concept.hpp | 3 ++- include/xo/randomgen/engine_concept.hpp | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/xo/randomgen/distribution_concept.hpp b/include/xo/randomgen/distribution_concept.hpp index 979a64d5..c2343255 100644 --- a/include/xo/randomgen/distribution_concept.hpp +++ b/include/xo/randomgen/distribution_concept.hpp @@ -30,8 +30,9 @@ namespace xo { #else && std::copyable && std::copyable + && std::equality_comparable #endif - && std::equality_comparable; + ; } /*namespace rng*/ } /*namespace xo*/ diff --git a/include/xo/randomgen/engine_concept.hpp b/include/xo/randomgen/engine_concept.hpp index 38b65cd7..2b3a2e53 100644 --- a/include/xo/randomgen/engine_concept.hpp +++ b/include/xo/randomgen/engine_concept.hpp @@ -7,6 +7,8 @@ namespace std { #ifdef __clang__ + +# if __clang_major__ <= 11 template < class T > concept integral = std::is_integral_v; @@ -31,8 +33,11 @@ namespace std { && requires { { G::min() } -> std::same_as>; { G::max() } -> std::same_as>; requires std::bool_constant<(G::min() < G::max())>::value; }; +# endif + #else /* uniform_random_bit_generator provided by gcc 12.3.2 */ + /* uniform_random_bit_generator provided by clang 16 */ #endif } /*namespace std*/ From 36a6edc51f217ca1f89ce24dd3776f3f6d9877f9 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 19 Oct 2023 16:34:28 -0400 Subject: [PATCH 21/29] build: allow symlink-preferred install --- CMakeLists.txt | 9 +++++---- README.md | 7 ++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c5413d7a..3f68effb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,14 +51,15 @@ add_subdirectory(example) # output targets set(SELF_LIB randomgen) -add_library(${SELF_LIB} INTERFACE) -xo_include_headeronly_options2(${SELF_LIB}) +xo_add_headeronly_library(${SELF_LIB}) +#add_library(${SELF_LIB} INTERFACE) +#xo_include_headeronly_options2(${SELF_LIB}) # ---------------------------------------------------------------- # standard install + provide find_package() support -xo_install_library2(${SELF_LIB}) -xo_install_include_tree() +xo_install_library4(${SELF_LIB} ${PROJECT_NAME}Targets) +#xo_install_include_tree() xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets) # ---------------------------------------------------------------- diff --git a/README.md b/README.md index 73f13f1b..414a8218 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,12 @@ # random number generators -# to build + install locally +## Getting Started +### build + install dependencies + +- see [github/Rconybea/cmake](https://github.com/Rconybea/xo-cmake) -- cmake modules + +### to build + install locally ``` $ cd randomgen $ mkdir build From fa5e4216a8c5f1bb7ea14a91ef1b10d8cfa085fe Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 22 Oct 2023 14:49:21 -0400 Subject: [PATCH 22/29] globally-unique cmake target names for submodule build --- CMakeLists.txt | 2 +- example/ex1/CMakeLists.txt | 4 ++-- example/ex2/CMakeLists.txt | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f68effb..8506e5b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,4 +65,4 @@ xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets # ---------------------------------------------------------------- # install additional components -install(TARGETS ex1 DESTINATION bin/randomgen/example) +install(TARGETS randomgen_ex1 DESTINATION bin/randomgen/example) diff --git a/example/ex1/CMakeLists.txt b/example/ex1/CMakeLists.txt index a9d1b27d..0c809818 100644 --- a/example/ex1/CMakeLists.txt +++ b/example/ex1/CMakeLists.txt @@ -1,2 +1,2 @@ -add_executable(ex1 ex1.cpp) -xo_include_options2(ex1) +add_executable(randomgen_ex1 ex1.cpp) +xo_include_options2(randomgen_ex1) diff --git a/example/ex2/CMakeLists.txt b/example/ex2/CMakeLists.txt index 78016d45..877fae36 100644 --- a/example/ex2/CMakeLists.txt +++ b/example/ex2/CMakeLists.txt @@ -1,3 +1,3 @@ -add_executable(ex2 ex2.cpp) -xo_include_options2(ex2) -xo_dependency(ex2 indentlog) +add_executable(randomgen_ex2 ex2.cpp) +xo_include_options2(randomgen_ex2) +xo_dependency(randomgen_ex2 indentlog) From e3743cc01feb9daa8b9c0481f1d6939a0a5829df Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 23 Oct 2023 20:18:45 -0400 Subject: [PATCH 23/29] + bernoulli/exponential/uniform/guussianpair --- include/xo/randomgen/bernoulligen.hpp | 29 ++++++ include/xo/randomgen/exponentialgen.hpp | 21 +++++ include/xo/randomgen/gaussianpairgen.hpp | 108 +++++++++++++++++++++++ include/xo/randomgen/uniformgen.hpp | 25 ++++++ 4 files changed, 183 insertions(+) create mode 100644 include/xo/randomgen/bernoulligen.hpp create mode 100644 include/xo/randomgen/exponentialgen.hpp create mode 100644 include/xo/randomgen/gaussianpairgen.hpp create mode 100644 include/xo/randomgen/uniformgen.hpp diff --git a/include/xo/randomgen/bernoulligen.hpp b/include/xo/randomgen/bernoulligen.hpp new file mode 100644 index 00000000..9de59300 --- /dev/null +++ b/include/xo/randomgen/bernoulligen.hpp @@ -0,0 +1,29 @@ +/* @file bernoulligen.hpp */ + +#pragma once + +#include "generator.hpp" +#include + +namespace xo { + namespace rng { + /* Engine: e.g. xo::rng::xoshiro256ss or std::mt19937 */ + template + class bernoulligen : public generator> { + public: + using generator_type = generator>; + + template + static generator_type make(Engine engine, double prob) { + return generator_type::make(std::move(engine), + std::bernoulli_distribution(prob)); + } + + template + static generator_type conflip(Engine engine) { + return generator_type::make(std::move(engine), + std::bernoulli_distribution(0.5)); + } + }; + } /*namespace rng*/ + } /*namespace xo*/ diff --git a/include/xo/randomgen/exponentialgen.hpp b/include/xo/randomgen/exponentialgen.hpp new file mode 100644 index 00000000..35945f5b --- /dev/null +++ b/include/xo/randomgen/exponentialgen.hpp @@ -0,0 +1,21 @@ +/* @file exponentialgen.hpp */ + +#pragma once + +#include "generator.hpp" +#include + +namespace xo { + namespace rng { + template + class exponentialgen : public generator> { + public: + using generator_type = generator>; + + template + static generator_type make(Engine eng, double lambda) { + return make_generator(std::move(eng), std::exponential_distribution(lambda)); + } + }; + } /*namespace rng*/ +} /*namespace xo*/ diff --git a/include/xo/randomgen/gaussianpairgen.hpp b/include/xo/randomgen/gaussianpairgen.hpp new file mode 100644 index 00000000..d5cc4699 --- /dev/null +++ b/include/xo/randomgen/gaussianpairgen.hpp @@ -0,0 +1,108 @@ +/* @file gaussianpairgen.hpp */ + +#pragma once + +#include "generator.hpp" +#include +#include + +namespace xo { + namespace random { + /* editor bait: 2d normal, normal xy + * + * if + * N1 ~ N(0,1) + * N2 ~ N(0,1) + * are two indepenent, normally-distributed r.v's with + * mean 0 and variance 1, then + * let + * A = | 1 0 | X = | N1 | + * | r q | | N2 | + * + * with r^2 + q^2 = 1 + * + * and consider + * A.X = | N1 | := | Y1 | + * | r.N1 + q.N2 | | Y2 | + * + * Y1, Y2 both have mean 0, + * since both are linear combination of 0-mean N(0,1) variables + * + * Var(Y1) = 1 + * Var(Y2) = r^2.Var(N1) + q^2.Var(N2) + * = r^2 + q^2 + * = 1 + * + * (since N1,N2 indept, and Var(N1)=Var(N2)=1) + * + * Cov(Y1,Y2) = r.Cov(N1,N1) + q.Cov(N1,N2) + * = r.Var(N1) + * = r + * + * (since Cov(N1,N2)=0) + * + * we have correlation coefficient for Y1,Y2: + * + * Cov(Y1,Y2) + * p(Y1,Y2) = -------------------- + * sqrt(Var(Y1).Var(Y2)) + * + * = r + */ + template + class gaussianpair_dist { + public: + using result_type = std::array; + + public: + /* generate pairs of gaussian N(0,1) random numbers, + * with correlation coefficient rho + * + * Require: + * - rho in the interval [-1, +1] + */ + explicit gaussianpair_dist(FloatType rho) + : r_(rho), q_(std::sqrt(1.0 - rho*rho)) {} + + template + result_type operator()(Engine & engine) { + FloatType n1 = this->ndist_(engine); + FloatType n2 = this->ndist_(engine); + + FloatType y1 = n1; + FloatType y2 = this->r_ * n1 + this->q_ * n2; + + return {y1, y2}; + } /*operator()*/ + + private: + /* correlation coefficient r + * 2nd random variable Y2 in each pair will be constructed by + * r.N1 + sqrt(1-r^2).N2 + */ + FloatType r_; + /* q := sqrt(1-r^2) */ + FloatType q_; + + /* state for generating indept normally-distributed r.v's */ + std::normal_distribution ndist_; + }; /*gaussianpair_dist*/ + + /* generate pairs of correlated gaussian random variables */ + template + class gaussianpairgen { + public: + using engine_type = Engine; + using generator_type = generator>; + + template + static generator_type make(Engine eng, + double rho) { + return generator_type::make(std::move(eng), + gaussianpair_dist(rho)); + } + }; /*GaussianPairGen*/ + } /*namespace random*/ +} /*namespace xo*/ + +/* end gaussianpairgen.hpp */ diff --git a/include/xo/randomgen/uniformgen.hpp b/include/xo/randomgen/uniformgen.hpp new file mode 100644 index 00000000..d1c4d62b --- /dev/null +++ b/include/xo/randomgen/uniformgen.hpp @@ -0,0 +1,25 @@ +/* @file uniformgen.hpp */ + +#pragma once + +#include "generator.hpp" +#include + +namespace xo { + namespace rng { + template + class uniformgen : public generator> { + public: + using generator_type = generator>; + + template + static generator_type unit(Engine eng) { + return make_generator(std::move(eng), + std::uniform_real_distribution(0.0, 1.0)); + } + }; + } /*namespace rng*/ +} /*namespace xo*/ + + +/* end uniformgen.hpp */ From c0ff16e3acca3b0e5c22360b3bd5d5edc5cbba57 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 15 Mar 2024 19:27:50 -0400 Subject: [PATCH 24/29] build: streamline CMAKE_MODULE_PATH interaction --- .gitignore | 2 +- CMakeLists.txt | 4 +--- cmake/xo-bootstrap-macros.cmake | 12 ++++++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 cmake/xo-bootstrap-macros.cmake diff --git a/.gitignore b/.gitignore index e90fd723..b0029e6b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # clangd (run via lsp) keeps state here .cache # typical build directory -build +.build # compile_commands.json: symlink to build directory, should be created manually compile_commands.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 8506e5b6..52606f5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,9 +5,7 @@ cmake_minimum_required(VERSION 3.10) project(randomgen VERSION 0.1) enable_language(CXX) -include(xo_macros/xo_cxx) -include(xo_macros/code-coverage) -#include(cmake/cxx.cmake) +include(cmake/xo-bootstrap-macros.cmake) # ---------------------------------------------------------------- # unit test setup diff --git a/cmake/xo-bootstrap-macros.cmake b/cmake/xo-bootstrap-macros.cmake new file mode 100644 index 00000000..16644435 --- /dev/null +++ b/cmake/xo-bootstrap-macros.cmake @@ -0,0 +1,12 @@ +if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL "prefix")) + # default to typical install location for xo-project-macros + set(CMAKE_MODULE_PATH ${CMAKE_INSTALL_PREFIX}/share/cmake) +endif() + +message("-- CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}") +message("-- CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}") + +# needs to have been installed somewhere on CMAKE_MODULE_PATH, +# (e.g. from xo-cmake with the same value for CMAKE_INSTALL_PREFIX) +# +include(xo_macros/xo-project-macros) From fdefb286b0b7222687192d505ec50706ffb5582a Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 29 Mar 2024 14:33:41 -0400 Subject: [PATCH 25/29] build: suppress bootstrap message in submodule build --- cmake/xo-bootstrap-macros.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/xo-bootstrap-macros.cmake b/cmake/xo-bootstrap-macros.cmake index 16644435..96592216 100644 --- a/cmake/xo-bootstrap-macros.cmake +++ b/cmake/xo-bootstrap-macros.cmake @@ -3,8 +3,10 @@ if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL "pr set(CMAKE_MODULE_PATH ${CMAKE_INSTALL_PREFIX}/share/cmake) endif() -message("-- CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}") -message("-- CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}") +if (NOT XO_SUBMODULE_BUILD) + message("-- CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}") + message("-- CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}") +endif() # needs to have been installed somewhere on CMAKE_MODULE_PATH, # (e.g. from xo-cmake with the same value for CMAKE_INSTALL_PREFIX) From a449316999d2724f26f5711c5dfd6350c43d221f Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 29 Mar 2024 14:43:50 -0400 Subject: [PATCH 26/29] uniformgen: + interval() method --- include/xo/randomgen/uniformgen.hpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/include/xo/randomgen/uniformgen.hpp b/include/xo/randomgen/uniformgen.hpp index d1c4d62b..28e311ca 100644 --- a/include/xo/randomgen/uniformgen.hpp +++ b/include/xo/randomgen/uniformgen.hpp @@ -12,11 +12,19 @@ namespace xo { public: using generator_type = generator>; - template - static generator_type unit(Engine eng) { + /* named ctor idiom */ + template + static generator_type unit(Eng eng) { return make_generator(std::move(eng), std::uniform_real_distribution(0.0, 1.0)); } + + /* named ctor idiom */ + template + static generator_type interval(Eng eng, double lo, double hi) { + return make_generator(std::move(eng), + std::uniform_real_distribution(lo, hi)); + } }; } /*namespace rng*/ } /*namespace xo*/ From be5a3261f5783bf297c912610b0421c36f14d79b Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 29 Mar 2024 14:44:15 -0400 Subject: [PATCH 27/29] minor comment --- include/xo/randomgen/random_seed.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/xo/randomgen/random_seed.hpp b/include/xo/randomgen/random_seed.hpp index 92447b3c..d68fc10c 100644 --- a/include/xo/randomgen/random_seed.hpp +++ b/include/xo/randomgen/random_seed.hpp @@ -76,6 +76,7 @@ namespace xo { operator<<(std::ostream & os, Seed const & x) { + /* NOTE: if compile error here, may want caller to #include [indentlog/print/vector.hpp] */ os << x.seed_; return os; } /*operator<<*/ From 45cc28b4f8187ff105e1fa8331bc4586ba11bdfb Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 29 Apr 2024 23:17:36 -0500 Subject: [PATCH 28/29] xo-randomgen: streamline build using improved xo-cmake macros --- CMakeLists.txt | 41 ++++++++------------------------- cmake/xo-bootstrap-macros.cmake | 33 +++++++++++++++++++++----- 2 files changed, 36 insertions(+), 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 52606f5a..49871c13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,22 +3,19 @@ cmake_minimum_required(VERSION 3.10) project(randomgen VERSION 0.1) -enable_language(CXX) +include(GNUInstallDirs) include(cmake/xo-bootstrap-macros.cmake) -# ---------------------------------------------------------------- -# unit test setup +xo_cxx_toplevel_options2() -enable_testing() -# activate code coverage for all executables + libraries (when configured with -DCODE_COVERAGE=ON) -add_code_coverage() -# 1. assuming that /nix/store/ prefixes .hpp files belonging to gcc, catch2 etc. -# we're not interested in code coverage for these sources. -# 2. exclude the utest/ subdir, we don't need coverage on the unit tests themselves; -# rather, want coverage on the code that the unit tests exercise. -# -add_code_coverage_all_targets(EXCLUDE /nix/store/* utest/*) +# ---------------------------------------------------------------- +# cmake -DCMAKE_BUILD_TYPE=debug +xo_toplevel_debug_config2() + +# ---------------------------------------------------------------- +# cmake -DCMAKE_BUILD_TYPE=coverage +xo_toplevel_coverage_config2() # ---------------------------------------------------------------- # bespoke (usually temporary) c++ settings @@ -27,19 +24,6 @@ set(PROJECT_CXX_FLAGS "") #set(PROJECT_CXX_FLAGS "-fconcepts-diagnostics-depth=2") add_definitions(${PROJECT_CXX_FLAGS}) -# ---------------------------------------------------------------- -# common include paths etc. - -xo_toplevel_compile_options() - -# ---------------------------------------------------------------- -# external dependencies -# -# set CMAKE_INSTALL_PREFIX to analog of /usr -# to use .cmake assistants from /usr/lib/cmake/indentlog -# -# xo_dependency(..) - # ---------------------------------------------------------------- add_subdirectory(example) @@ -50,14 +34,7 @@ add_subdirectory(example) set(SELF_LIB randomgen) xo_add_headeronly_library(${SELF_LIB}) -#add_library(${SELF_LIB} INTERFACE) -#xo_include_headeronly_options2(${SELF_LIB}) - -# ---------------------------------------------------------------- -# standard install + provide find_package() support - xo_install_library4(${SELF_LIB} ${PROJECT_NAME}Targets) -#xo_install_include_tree() xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets) # ---------------------------------------------------------------- diff --git a/cmake/xo-bootstrap-macros.cmake b/cmake/xo-bootstrap-macros.cmake index 96592216..3cbc8f79 100644 --- a/cmake/xo-bootstrap-macros.cmake +++ b/cmake/xo-bootstrap-macros.cmake @@ -1,14 +1,35 @@ -if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL "prefix")) - # default to typical install location for xo-project-macros - set(CMAKE_MODULE_PATH ${CMAKE_INSTALL_PREFIX}/share/cmake) +# ---------------------------------------------------------------- +# for example: +# $ PREFIX=/usr/local +# $ cmake -DCMAKE_MODULE_PATH=prefix -DCMAKE_INSTALL_PREFIX=$PREFIX -B .build +# +# will get +# CMAKE_MODULE_PATH +# from xo-cmake-config --cmake-module-path +# +# and expect .cmake macros in +# CMAKE_MODULE_PATH/xo_macros/xo_cxx.cmake +# ---------------------------------------------------------------- + +find_program(XO_CMAKE_CONFIG_EXECUTABLE NAMES xo-cmake-config REQUIRED) + +if ("${XO_CMAKE_CONFIG_EXECUTABLE}" STREQUAL "XO_CMAKE_CONFIG_EXECUTABLE-NOT_FOUND") + message(FATAL "could not find xo-cmake-config executable") endif() +message(STATUS "XO_CMAKE_CONFIG_EXECUTABLE=${XO_CMAKE_CONFIG_EXECUTABLE}") + if (NOT XO_SUBMODULE_BUILD) - message("-- CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}") - message("-- CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}") + if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL prefix)) + # default to typical install location for xo-project-macros + execute_process(COMMAND ${XO_CMAKE_CONFIG_EXECUTABLE} --cmake-module-path OUTPUT_VARIABLE CMAKE_MODULE_PATH) + message(STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}") + endif() endif() # needs to have been installed somewhere on CMAKE_MODULE_PATH, # (e.g. from xo-cmake with the same value for CMAKE_INSTALL_PREFIX) # -include(xo_macros/xo-project-macros) +include(xo_macros/xo_cxx) + +xo_cxx_bootstrap_message() From 44a31724ec8e91c2a2cb2995bcef55780277e8a4 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 29 Apr 2024 23:17:58 -0500 Subject: [PATCH 29/29] xo-randomgen: bugfix: test with __APPLE__ instead of __clang__ --- include/xo/randomgen/random_seed.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/xo/randomgen/random_seed.hpp b/include/xo/randomgen/random_seed.hpp index d68fc10c..b8d89630 100644 --- a/include/xo/randomgen/random_seed.hpp +++ b/include/xo/randomgen/random_seed.hpp @@ -24,7 +24,7 @@ namespace xo { */ template void random_seed(T * p_seed) { -# ifdef __clang__ +# ifdef __APPLE__ /* NOTE: arc4random_buf() works on darwin/nix; * probably need to do something else on intel linux */