diff --git a/CMakeLists.txt b/CMakeLists.txt index 71825273..92061c0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,45 +5,15 @@ cmake_minimum_required(VERSION 3.10) project(xo_ratio VERSION 1.0) enable_language(CXX) -# common XO cmake macros (see proj/xo-cmake) include(GNUInstallDirs) include(cmake/xo-bootstrap-macros.cmake) -# ---------------------------------------------------------------- -# unit test setup - -enable_testing() +xo_cxx_toplevel_options2() # ---------------------------------------------------------------- # cmake -DCMAKE_BUILD_TYPE=coverage - -if (NOT DEFINED PROJECT_CXX_FLAGS_COVERAGE) - # note: for clang would use -fprofile-instr-generate -fcoverage-mapping here instead and also at link time - set(PROJECT_CXX_FLAGS_COVERAGE ${PROJECT_CXX_FLAGS} -ggdb -Og -fprofile-arcs -ftest-coverage - CACHE STRING "coverage c++ compiler flags") -endif() -message("-- PROJECT_CXX_FLAGS_COVERAGE: coverage c++ flags are [${PROJECT_CXX_FLAGS_COVERAGE}]") - -add_compile_options("$<$:${PROJECT_CXX_FLAGS_COVERAGE}>") -# when -DCMAKE_BUILD_TYPE=coverage, link executables with gcov -link_libraries("$<$:gcov>") - -find_program(LCOV_EXECUTABLE NAMES lcov) -find_program(GENHTML_EXECUTABLE NAMES genhtml) - -# with coverage build: -# 1. invoke instrumented executables for which you want coverage: -# (cd path/to/build && ctest) -# 2. post-process low-level coverage data -# (path/to/build/gen-ccov) -# 3. point browser to generated html data -# file:///path/to/build/ccov/html/index.html # -configure_file( - ${PROJECT_SOURCE_DIR}/cmake/gen-ccov.in - ${PROJECT_BINARY_DIR}/gen-ccov) - -file(CHMOD ${PROJECT_BINARY_DIR}/gen-ccov PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +xo_toplevel_coverage_config2() # ---------------------------------------------------------------- # c++ settings @@ -53,13 +23,10 @@ set(PROJECT_CXX_FLAGS "") #set(PROJECT_CXX_FLAGS "-fconcepts-diagnostics-depth=2") add_definitions(${PROJECT_CXX_FLAGS}) -xo_toplevel_compile_options() - # ---------------------------------------------------------------- add_subdirectory(example) add_subdirectory(utest) -add_subdirectory(docs) # ---------------------------------------------------------------- # provide find_package() support for projects using this library @@ -69,6 +36,11 @@ xo_add_headeronly_library(${SELF_LIB}) xo_install_library4(${SELF_LIB} ${PROJECT_NAME}Targets) xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets) +# ---------------------------------------------------------------- +# docs targets depend on all the other library/utest targets +# +add_subdirectory(docs) + # ---------------------------------------------------------------- # dependencies diff --git a/README.md b/README.md index 8572d0cc..d4104014 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ $ git clone https://github.com/Rconybea/xo-ratio $ cd xo-ratio $ PREFIX=/usr/local # for example $ BUILDDIR=.build # for example -$ make ${BUILDDIR} +$ mkdir ${BUILDDIR} $ cmake --build .build $ cmake --install .build ``` diff --git a/cmake/gen-ccov.in b/cmake/gen-ccov.in deleted file mode 100644 index e335aed4..00000000 --- a/cmake/gen-ccov.in +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash - -srcdir=@PROJECT_SOURCE_DIR@ -builddir=@PROJECT_BINARY_DIR@ -lcov=@LCOV_EXECUTABLE@ -genhtml=@GENHTML_EXECUTABLE@ - -if [[ $lcov == "LCOV_EXECUTABLE-NOTFOUND" ]]; then - echo "gen-ccov: lcov executable not found" - exit 1 -fi - -if [[ $genhtml == "GENHTML_EXECUTABLE-NOTFOUND" ]]; then - echo "gen-ccov: genhtml executable not found" - exit 1 -fi - -mkdir $builddir/ccov - -$srcdir/cmake/lcov-harness $srcdir $builddir $builddir/ccov/out $lcov $genhtml diff --git a/cmake/lcov-harness b/cmake/lcov-harness deleted file mode 100755 index 27ac8be9..00000000 --- a/cmake/lcov-harness +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env bash - -srcdir=$1 -builddir=$2 -outputstem=$3 -lcov=$4 -genhtml=$5 - -if [[ -z "${srcdir}" ]]; then - echo "lcov-harness: expected non-empty srcdir" - exit 1 -fi - -if [[ -z ${builddir} ]]; then - echo "lcov-harness: expected non-empty builddir" - exit 1 -fi - -if [[ -z ${outputstem} ]]; then - echo "lcov-harness: expected non-empty outputstem" - exit 1 -fi - -if [[ -z ${lcov} ]]; then - echo "lcov-harness: exepcted non-empty lcov" - exit 1 -fi - -if [[ -z ${genhtml} ]]; then - echo "lcov-harness: expected non-empty genhtml" - exit 1 -fi - -# directory stems for location of {.gcda, gcno} coverage information, -# -# if we have source tree: -# -# ${srcdir} -# +- foo -# | \- foo.cpp -# \- bar -# \- quux -# +- quux.cpp -# \- quux_main.cpp -# -# then we expect build tree: -# -# ${builddir} -# +- foo -# | \- CMakeFiles -# | \- foo_target.dir -# | +- foo.cpp.gcda -# | \- foo.cpp.gcno -# +- bar -# \- quux -# \- CMakeFiles -# \- target4quux.dir -# +- quux.cpp.gcda -# +- quux.cpp.gcno -# +- quux_main.cpp.gcda -# \- quux_main.cpp.gcno -# -# in which case will have cmd_body: -# -# ${primarydirs} -# ./foo/CMakeFiles/foo_target.dir -# ./bar/quux/CMakeFiles/target4quux.dir -# -# here foo_target, quux_target are whatever build is using for corresponding cmake target names. -# -# We want to invoke lcov like: -# -# lcov --capture \ -# --output ${builddir}/ccov \ -# --exclude /utest/ \ -# --base-directory ${srcdir}/foo --directory ${builddir}/foo/CMakeFiles/foo_target.dir \ -# --base-directory ${srcdir}/bar/quux --directory ${builddir}/bar/quux/CMakeFiles/target4quux.dir -# -primarydirs=$(cd ${builddir} && find -name '*.gcno' \ - | xargs --replace=xx dirname xx \ - | uniq \ - | sed -e 's:^\./::') - -#echo "primarydirs=${primarydirs}" - -cmd="${lcov} --output ${outputstem}.info --capture --ignore-errors source" - -for bdir in ${primarydirs}; do - sdir=$(dirname $(dirname ${bdir})) - - cmd="${cmd} --base-directory ${srcdir}/${sdir} --directory ${builddir}/${bdir}" -done - -#echo cmd=${cmd} - -set -x - -# capture -${cmd} - -# keep only files with paths under source tree -# (don't want coverage for external libraries such as libstdc++ etc) -${lcov} --extract ${outputstem}.info "${srcdir}/*" --output ${outputstem}2.info - -# remove unit test dirs -# (we're interested in coverage of our installed code, not of the unit tests that exercise it) -${lcov} --remove ${outputstem}2.info '*/utest/*' --output ${outputstem}3.info - -# generate .html tree -mkdir -p ${builddir}/ccov/html -${genhtml} --ignore-errors source --show-details --prefix ${srcdir} --output-directory ${builddir}/ccov/html ${outputstem}3.info - -# also send report to stdout -${lcov} --list ${outputstem}3.info diff --git a/cmake/xo-bootstrap-macros.cmake b/cmake/xo-bootstrap-macros.cmake index e0902f26..2cf387e5 100644 --- a/cmake/xo-bootstrap-macros.cmake +++ b/cmake/xo-bootstrap-macros.cmake @@ -1,15 +1,33 @@ +# ---------------------------------------------------------------- +# for example: +# $ PREFIX=/usr/local # for example +# $ 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 (("${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) + message(FATAL "could not find xo-cmake-config executable") endif() if (NOT XO_SUBMODULE_BUILD) - message("-- GUESSED_CMAKE_CMD=cmake -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH} -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_DOCDIR=${CMAKE_INSTALL_DOCDIR} -B ${CMAKE_BINARY_DIR}") - 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() diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 57a99c20..4d64b102 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -1,118 +1,5 @@ -# xo-ratio/docs/CMakeLists.txt +# xo-flatstring/docs/CMakeLists.txt -if (XO_SUBMODULE_BUILD) - # in submodule build, rely on toplevel docs/CMakeLists.txt file instead -else() - # build docs starting from here only in standalone build. - # otherwise use top-level doxygen setup instead. - - set(ALL_LIBRARY_TARGETS xo_ratio) # todo: automate this from xo-cmake macros - set(ALL_UTEST_TARGETS utest.ratio xo_ratio_ex1 ) # todo: automate this from xo-cmake macros - - # look for doxygen executable - find_program(DOXYGEN_EXECUTABLE NAMES doxygen REQUIRED) - message("-- DOXYGEN_EXECUTABLE=${DOXYGEN_EXECUTABLE}") - - # look for sphinx-build executable - find_program(SPHINX_EXECUTABLE NAMES sphinx-build REQUIRED) - message("-- SPHINX_EXECUTABLE=${SPHINX_EXECUTABLE}") - - set(DOX_CONFIG_FILE ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) - - set(DOX_INPUT_DIR ${PROJECT_SOURCE_DIR}) - set(DOX_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/dox) - - set(DOX_INDEX_FILE ${DOX_OUTPUT_DIR}/html/index.html) - - # .hpp files reachable from xo-ratio/include - # - # REMINDER: for reliability will need to re-run cmake when the set of .hpp files changes - # - file(GLOB_RECURSE DOX_HPP_FILES_GLOB ${PROJECT_SOURCE_DIR}/include *.hpp) - - set(SPHINX_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/sphinx/html) - set(SPHINX_INDEX_FILE ${SPHINX_OUTPUT_DIR}/index.html) - # - # sphinx .rst files reachable from cmake-examples/docs - # - # REMINDER: for reliability will need to re-run cmake when the set of .rst files changes - # - file(GLOB_RECURSE SPHINX_RST_FILES_GLOB ${CMAKE_CURRENT_SOURCE_DIR} *.rst) - - set(SPHINX_RST_FILES index.rst - #install.rst - #lessons.rst - #flatstring-reference.rst - #flatstring-class.rst - ) - - # TODO: - # 1. move Doxyfile.in to xo-cmake project - # 2. replace this command section with xo-cmake macro - # - configure_file( - Doxyfile.in ${DOX_CONFIG_FILE} - FILE_PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE - @ONLY) - - set(DOX_DEPS ${ALL_LIBRARY_TARGETS} ${ALL_UTEST_TARGETS} ${DOX_HPP_FILES_GLOB}) - - file(MAKE_DIRECTORY ${DOX_OUTPUT_DIR}) - add_custom_command( - OUTPUT ${DOX_INDEX_FILE} - DEPENDS ${DOX_DEPS} - COMMAND "${DOXYGEN_EXECUTABLE}" ${DOX_CONFIG_FILE} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - MAIN_DEPENDENCY ${DOX_CONFIG_FILE} - COMMENT "Generating docs (doxygen)") - - # To build this target - # $ cmake --build .build -j -- doxygen - # or - # $ cd .build - # $ make doxygen - # - add_custom_target( - doxygen - DEPENDS ${DOX_INDEX_FILE} ${DOX_DEPS} - ) - - # root of sphinx doc tree - set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}) - set(SPHINX_DEPS doxygen conf.py ${SPHINX_RST_FILES} ${SPHINX_RST_FILES_GLOB} ${DOX_DEPS}) - - add_custom_command( - OUTPUT ${SPHINX_INDEX_FILE} - DEPENDS ${SPHINX_DEPS} - COMMAND ${SPHINX_EXECUTABLE} - -b html -Dbreathe_projects.xodoxxml=${CMAKE_CURRENT_BINARY_DIR}/dox/xml - ${SPHINX_SOURCE} ${SPHINX_OUTPUT_DIR} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Generating docs (sphinx) -> [${SPHINX_OUTPUT_DIR}]") - - # make sphinx --> generate sphinx documentation - # - add_custom_target( - sphinx - DEPENDS ${SPHINX_INDEX_FILE}) - - # - html docs generated in build/docs/sphinx - # - copy the doc tree to share/doc/xo_unit/html - # - # DESTINATION: CMAKE_INSTALL_DOCDIR - # => DATAROOTDIR/doc/PROJECT_NAME - # => CMAKE_INSTALL_PREFIX/share/doc/xo_flatstring - # OPTIONAL: install directory tree if it exists, - # but don't complain if it's missing - install( - DIRECTORY ${SPHINX_OUTPUT_DIR} - FILE_PERMISSIONS OWNER_READ GROUP_READ WORLD_READ - DESTINATION ${CMAKE_INSTALL_DOCDIR} - COMPONENT Documentation - OPTIONAL) - - # make docs --> generate sphinx documentation - add_custom_target( - docs - DEPENDS sphinx) -endif() +xo_doxygen_collect_deps() +xo_docdir_doxygen_config() +xo_docdir_sphinx_config(index.rst install.rst ratio-reference.rst ratio-class.rst ratio-functions.rst) diff --git a/utest/CMakeLists.txt b/utest/CMakeLists.txt index 2da04264..a0cdc40e 100644 --- a/utest/CMakeLists.txt +++ b/utest/CMakeLists.txt @@ -5,9 +5,7 @@ set(SELF_SRCS ratio_utest_main.cpp ratio.test.cpp) -add_executable(${SELF_EXE} ${SELF_SRCS}) -xo_include_options2(${SELF_EXE}) -add_test(NAME ${SELF_EXE} COMMAND ${SELF_EXE}) +xo_add_utest_executable(${SELF_EXE} ${SELF_SRCS}) # ---------------------------------------------------------------- # in coverage build, target to build+install coverage report @@ -55,3 +53,5 @@ xo_self_headeronly_dependency(${SELF_EXE} xo_ratio) xo_dependency(${SELF_EXE} randomgen) xo_dependency(${SELF_EXE} indentlog) xo_external_target_dependency(${SELF_EXE} Catch2 Catch2::Catch2) + +# end CMakeLists.txt