Commit 6cd43d07 authored by Jeff's avatar Jeff Committed by Michael Tesch
Browse files

Add cppduals::duals interface target; improve install

* Define cppduals_duals interface target which allows using
  cppduals with modern, target-based CMake.
* Export cppduals_duals to cppduals-config.cmake for use with find_package.
  Target cppduals_duals is exported as cppduals::duals
* Define a cppduals::dual alias target for use with add_subdirectory.
  Provides consistent link target regardless of how library is used.
* Update install to include headers, cmake config, and docs (if built).
* Fix bug when setting default build type
* Use local install directory if none provided
* Only configure docs if doxygen available; otherwise inform user of
  missing dependency.
parent 73c8bb6f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ cover:
pages:
  script:
  - cmake -Bbuild -H. -DCODE_COVERAGE=ON -DCPPDUALS_TESTING=ON
  - cmake --build build --target docs
  - cmake --build build --target cppduals_docs
  - cmake --build build --target cov-html
  - mv build/docs public/
  - mv build/coverage public/
+99 −45
Original line number Diff line number Diff line
#
# CMake for cppduals
#
cmake_minimum_required (VERSION 3.10)
project (cppduals C CXX)
cmake_minimum_required (VERSION 3.1)
project (cppduals
  VERSION 0.2.0
  LANGUAGES C CXX
  )
include (GNUInstallDirs)

#set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set (CPPDUALS_VERSION 0.2.0)
set (CMAKE_CXX_STANDARD 11 CACHE STRING "Which C++ standard to test against.")
set (CMAKE_CXX_STANDARD_REQUIRED ON)
set (CMAKE_DISABLE_IN_SOURCE_BUILD ON)
if (NOT CMAKE_CONFIGURATION_TYPES AND
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
    message (STATUS "Configuring cppduals for standalone build")
    set (CPPDUALS_STANDALONE TRUE)
elseif ()
    message (STATUS "Configuring cppduals for subproject build")
    set (CPPDUALS_STANDALONE FALSE)
endif ()
if (CPPDUALS_STANDALONE AND
    NOT CMAKE_CONFIGURATION_TYPES AND
    NOT CMAKE_NO_BUILD_TYPE AND
    NOT CMAKE_BUILD_TYPE AND
    CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
  set (CMAKE_BUILD_TYPE RelWithDebInfo)
    NOT CMAKE_BUILD_TYPE
    )
  message (STATUS "Setting build type to 'RelWithDebInfo' since none specified")
  set_property (CACHE CMAKE_BUILD_TYPE PROPERTY VALUE RelWithDebInfo)
  set_property (CACHE CMAKE_BUILD_TYPE PROPERTY
    STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
    STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo"
    )
endif ()
if (CPPDUALS_STANDALONE AND
    CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
  set (CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install"
       CACHE PATH "cppduals installation directory"
       FORCE
       )
  message (STATUS "No install prefix specified; using '${CMAKE_INSTALL_PREFIX}'")
endif ()

set_property (CACHE CMAKE_CXX_STANDARD PROPERTY STRINGS 11 14 17 20)
@@ -51,13 +71,28 @@ if (CPPDUALS_USE_LIBCXX)
  endif ()
endif (CPPDUALS_USE_LIBCXX)

################################################################################
#
# Primary Library Target
#
add_library (cppduals_duals INTERFACE)
target_include_directories (cppduals_duals
  INTERFACE
    $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
    )
set_target_properties (cppduals_duals
  PROPERTIES
    EXPORT_NAME duals
    )
add_library (cppduals::duals ALIAS cppduals_duals)

#
# Build external dependencies for testing & benchmarking
#
if (CPPDUALS_TESTING)

  file (MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/thirdparty")
  cmake_minimum_required (VERSION 3.10) # need gtest_discover_tests
  file (MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/thirdparty")

  # generator name
  if (NOT "${CMAKE_EXTRA_GENERATOR}" STREQUAL "")
@@ -68,8 +103,15 @@ if (CPPDUALS_TESTING)

  # configure the thirdparty build dir
  execute_process (
    WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/thirdparty"
    COMMAND ${CMAKE_COMMAND} -G${GENERATOR_STRING} "-DCMAKE_CONFIGURATION_TYPES=${CMAKE_CONFIGURATION_TYPES}" -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM} -DCPPDUALS_BENCHMARK=${CPPDUALS_BENCHMARK} -DCPPDUALS_EIGEN_LATEST=${CPPDUALS_EIGEN_LATEST} -DCPPDUALS_USE_LIBCXX=${CPPDUALS_USE_LIBCXX} ${CMAKE_SOURCE_DIR}/thirdparty
    WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/thirdparty"
    COMMAND ${CMAKE_COMMAND} "-G${GENERATOR_STRING}"
                             "-DCMAKE_CONFIGURATION_TYPES=${CMAKE_CONFIGURATION_TYPES}"
                             "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
                             "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}"
                             "-DCPPDUALS_BENCHMARK=${CPPDUALS_BENCHMARK}"
                             "-DCPPDUALS_EIGEN_LATEST=${CPPDUALS_EIGEN_LATEST}"
                             "-DCPPDUALS_USE_LIBCXX=${CPPDUALS_USE_LIBCXX}"
                             "${PROJECT_SOURCE_DIR}/thirdparty"
    RESULT_VARIABLE DEPS_CONFIG_RESULT
    )
  if (DEPS_CONFIG_RESULT)
@@ -78,10 +120,10 @@ if (CPPDUALS_TESTING)

  # build the thirdparty
  message ("***************************************************************")
  message ("********** Building '${CMAKE_BINARY_DIR}/thirdparty'...")
  message ("********** Building '${PROJECT_BINARY_DIR}/thirdparty'...")
  message ("***************************************************************")
  execute_process (
    WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/thirdparty"
    WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/thirdparty"
    COMMAND "${CMAKE_COMMAND}" --build .
    RESULT_VARIABLE DEPS_BUILD_RESULT
    )
@@ -95,31 +137,26 @@ if (CPPDUALS_TESTING)

  add_subdirectory (thirdparty)

endif (CPPDUALS_TESTING)
#
# done
#
################################################################################
endif ()

#
# Code Coverage Configuration
#
add_library (coverage_config INTERFACE)

add_library (cppduals_coverage_config INTERFACE)
option (CODE_COVERAGE "Enable coverage reporting" OFF)
if (CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
  # Add required flags (GCC & LLVM/Clang)
  target_compile_options (coverage_config INTERFACE
  target_compile_options (cppduals_coverage_config INTERFACE
    -O0        # no optimization
    -g         # generate debug info
    --coverage # sets all required flags
    )
  if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.13)
    target_link_options (coverage_config INTERFACE --coverage)
    target_link_options (cppduals_coverage_config INTERFACE --coverage)
  else ()
    target_link_libraries (coverage_config INTERFACE --coverage)
    target_link_libraries (cppduals_coverage_config INTERFACE --coverage)
  endif ()
endif ()
endif (CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")

#
# Testing
@@ -133,37 +170,54 @@ endif (CPPDUALS_TESTING)
#
# Documentation
#
configure_file (${CMAKE_SOURCE_DIR}/doc/Doxyfile.in ${CMAKE_BINARY_DIR}/doc/Doxyfile)
configure_file (${CMAKE_SOURCE_DIR}/doc/DoxygenLayout.xml ${CMAKE_BINARY_DIR}/doc/DoxygenLayout.xml COPYONLY)
configure_file (${CMAKE_SOURCE_DIR}/doc/header.html ${CMAKE_BINARY_DIR}/doc/header.html COPYONLY)
configure_file (${CMAKE_SOURCE_DIR}/doc/footer.html ${CMAKE_BINARY_DIR}/doc/footer.html COPYONLY)
configure_file (${CMAKE_SOURCE_DIR}/doc/favicon.ico ${CMAKE_BINARY_DIR}/doc/favicon.ico COPYONLY)
configure_file (${CMAKE_SOURCE_DIR}/doc/customdoxygen.css ${CMAKE_BINARY_DIR}/doc/customdoxygen.css)
add_custom_target (docs
  COMMAND rm -f docs/*
  COMMAND cd doc && VERSION=1 doxygen Doxyfile
find_program (DOXYGEN doxygen)
if (DOXYGEN)
  configure_file (${PROJECT_SOURCE_DIR}/doc/Doxyfile.in       ${PROJECT_BINARY_DIR}/doc/Doxyfile)
  configure_file (${PROJECT_SOURCE_DIR}/doc/DoxygenLayout.xml ${PROJECT_BINARY_DIR}/doc/DoxygenLayout.xml COPYONLY)
  configure_file (${PROJECT_SOURCE_DIR}/doc/header.html       ${PROJECT_BINARY_DIR}/doc/header.html COPYONLY)
  configure_file (${PROJECT_SOURCE_DIR}/doc/footer.html       ${PROJECT_BINARY_DIR}/doc/footer.html COPYONLY)
  configure_file (${PROJECT_SOURCE_DIR}/doc/favicon.ico       ${PROJECT_BINARY_DIR}/doc/favicon.ico COPYONLY)
  configure_file (${PROJECT_SOURCE_DIR}/doc/customdoxygen.css ${PROJECT_BINARY_DIR}/doc/customdoxygen.css)
  add_custom_target (cppduals_docs
    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc
    COMMAND cmake -E remove_directory ${PROJECT_BINARY_DIR}/docs
    COMMAND ${DOXYGEN} Doxyfile
    )
else ()
  add_custom_target (cppduals_docs
    COMMAND echo "Please install doxygen and reconfigure to build the docs"
    )
endif ()

#
# Installation
#
install (TARGETS cppduals_duals EXPORT cppduals_export)
install (EXPORT cppduals_export
  FILE cppduals-config.cmake
  NAMESPACE cppduals::
  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cppduals
  )
install (
  DIRECTORY duals
  DESTINATION include
  DIRECTORY ${PROJECT_SOURCE_DIR}/duals
  DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
  PATTERN "*~" EXCLUDE
  )
install (
  DIRECTORY ${PROJECT_BINARY_DIR}/docs/   # Trailing slash triggers rename
  DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/cppduals
  OPTIONAL
  )

#
# etags
#
find_program (ETAGS etags)
if (ETAGS)
  add_custom_target (tags
    COMMAND etags --language=c++ ${CMAKE_SOURCE_DIR}/duals/*
    COMMAND etags --language=c++ --append ${CMAKE_SOURCE_DIR}/duals/arch/*/*
    COMMAND etags --language=c++ --append `find ${CMAKE_BINARY_DIR}/thirdparty/eigenX/src/eigenX -type f`
  add_custom_target (cppduals_etags
    COMMAND ${ETAGS} --language=c++ ${PROJECT_SOURCE_DIR}/duals/*
    COMMAND ${ETAGS} --language=c++ --append ${PROJECT_SOURCE_DIR}/duals/arch/*/*
    COMMAND ${ETAGS} --language=c++ --append `find ${PROJECT_BINARY_DIR}/thirdparty/eigenX/src/eigenX -type f`
    )
  add_custom_target (etags DEPENDS tags)
endif (ETAGS)
message ("CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
+61 −14
Original line number Diff line number Diff line
@@ -73,34 +73,81 @@ Installation
============

Copy the [duals/](./duals/) directory (or just [dual](./duals/dual) )
somewhere your `#include`\ s can find it.  Then just `#include
somewhere your `#include`s can find it.  Then just `#include
<duals/dual[_eigen]>` from your source.

Or, using cmake:
Alternatively, `cppduals` supports building with CMake. If using CMake v3.14+,
the ``FetchContent`` pattern is straightforward and enables using CMake targets
to specify library dependencies:

```sh
git clone https://gitlab.com/tesch1/cppduals.git && cd cppduals
cmake -Bbuildx -H. -DCPPDUALS_EIGEN_LATEST=OFF -DCPPDUALS_TESTING=OFF -DCPPDUALS_BENCHMARK=OFF
cmake --build buildx --target install
```cmake
  include(FetchContent)

  # Have CMake download the library
  set (CPPDUALS_TAG v0.1.2)
  set (CPPDUALS_MD5 48d9276482e5f07a768875ef692d14cd)
  FetchContent_Declare (cppduals
    URL https://gitlab.com/tesch1/cppduals/-/archive/${CPPDUALS_TAG}/cppduals-${CPPDUALS_TAG}.tar.bz2
    URL_HASH MD5=${CPPDUALS_MD5}
    )
  FetchContent_MakeAvailable (cppduals)

  # Link to cppduals
  target_link_libraries (your_target PRIVATE cppduals::duals)
```

Or, using cmake's `ExternalProject_Add()`
Older versions of CMake can achieve a similar result using the ``ExternalProject``
family of commands and modifying the global preprocessor search path:

```cmake
  include(ExternalProject)

  # Have CMake download the library
  set (CPPDUALS_VER 0.1.2)
  set (CPPDUALS_MD5 48d9276482e5f07a768875ef692d14cd)
  ExternalProject_Add (cppdualsX
    PREFIX cppdualsX
  ExternalProject_Add (cppduals
    URL https://gitlab.com/tesch1/cppduals/-/archive/v${CPPDUALS_VER}/cppduals-v${CPPDUALS_VER}.tar.bz2
    URL_HASH MD5=${CPPDUALS_MD5}
    CONFIGURE_COMMAND ""
    BUILD_COMMAND ""
    INSTALL_COMMAND ""
    )
  ExternalProject_Get_Property (cppdualsX source_dir)

  # Make include directory globally visible
  ExternalProject_Get_Property (cppduals source_dir)
  include_directories (${source_dir}/)
```

Alternatively, `cppduals` supports installation and discovery via the
`find_package` utility. First, download and install the library to a
location of your choosing:

```sh
  CPPDUALS_PREFIX=<desired_install_location>
  git clone https://gitlab.com/tesch1/cppduals.git && cd cppduals
  mkdir build && cd build
  cmake -DCMAKE_INSTALL_PREFIX="$CPPDUALS_PREFIX" ..
  cmake --build . --target install
```

Then, in your project's `CMakeLists.txt`, find and link to the library in the
standard manner:

```cmake
  find_package(cppduals REQUIRED)
  target_link_libraries(your_target PRIVATE cppduals::cppduals)
```

If you installed `cppduals` to a location that is not on `find_package`'s
default search path, you can specify the location by setting the `cppduals_DIR`
environment variable when configuring your project:

```sh
  cd your_build_dir
  cppduals_DIR="${CPPDUALS_PREFIX}" cmake ..
```


Benchmarks
==========

+11 −11
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ PROJECT_NAME = "cppduals"
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER         = ${CPPDUALS_VERSION}
PROJECT_NUMBER         = ${cppduals_VERSION}

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@@ -51,7 +51,7 @@ PROJECT_BRIEF = "Dual numbers for C++"
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.

PROJECT_LOGO           = ../../doc/Greek_Epsilon_archaic.svg
PROJECT_LOGO           = ${PROJECT_SOURCE_DIR}/doc/Greek_Epsilon_archaic.svg

# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
@@ -765,9 +765,9 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.

INPUT                  = ${CMAKE_SOURCE_DIR}/duals/dual \
                         ${CMAKE_SOURCE_DIR}/duals/dual_eigen \
                         ${CMAKE_SOURCE_DIR}/doc
INPUT                  = ${PROJECT_SOURCE_DIR}/duals/dual \
                         ${PROJECT_SOURCE_DIR}/duals/dual_eigen \
                         ${PROJECT_SOURCE_DIR}/doc

# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -860,7 +860,7 @@ EXAMPLE_RECURSIVE = NO
# that contain images that are to be included in the documentation (see the
# \image command).

IMAGE_PATH             = ${CMAKE_SOURCE_DIR}/doc
IMAGE_PATH             = ${PROJECT_SOURCE_DIR}/doc

# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@@ -908,7 +908,7 @@ FILTER_SOURCE_PATTERNS =
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.

USE_MDFILE_AS_MAINPAGE = ${CMAKE_SOURCE_DIR}/README.md
USE_MDFILE_AS_MAINPAGE = ${PROJECT_SOURCE_DIR}/README.md

#---------------------------------------------------------------------------
# Configuration options related to source browsing
@@ -1984,7 +1984,7 @@ SEARCH_INCLUDES = YES
# preprocessor.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.

INCLUDE_PATH           = ${CMAKE_SOURCE_DIR}
INCLUDE_PATH           = ${PROJECT_SOURCE_DIR}

# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
@@ -2303,7 +2303,7 @@ DOT_PATH =
# command).
# This tag requires that the tag HAVE_DOT is set to YES.

DOTFILE_DIRS           = ${CMAKE_SOURCE_DIR}/doc
DOTFILE_DIRS           = ${PROJECT_SOURCE_DIR}/doc

# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
+3 −2
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
# Public License v. 2.0. If a copy of the MPL was not distributed
# with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

# gtest_discover_tests requires 3.10
cmake_minimum_required (VERSION 3.10)

# Configure google-test as a downloadable library.
@@ -72,7 +73,7 @@ foreach (TEST_ ${ALL_TESTS})
    string (REPLACE ";" ", " L2 "${CMAKE_CXX_FLAGS}")
    target_compile_options (${TEST} PUBLIC ${PHASE_FLAGS})
    target_compile_definitions (${TEST} PRIVATE "OPT_FLAGS=${L2}")
    target_link_libraries (${TEST} gtest_main coverage_config )
    target_link_libraries (${TEST} gtest_main cppduals_coverage_config )
    #target_link_libraries (${TEST} -lasan)
    add_dependencies (${TEST} eigenX expokitX)
    gtest_discover_tests (${TEST} TEST_LIST ${TEST}_targets)
@@ -208,7 +209,7 @@ else ()
endif ()

set_target_properties (sandbox PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
target_link_libraries (sandbox PUBLIC coverage_config)
target_link_libraries (sandbox PUBLIC cppduals_coverage_config)

#
# Generate coverage reports
Loading