Add graph references
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
# Taken from https://blog.kitware.com/cmake-and-the-default-build-type/
|
||||
|
||||
# Set the default build type to "Release"
|
||||
set(default_build_type "Release")
|
||||
|
||||
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if(NOT isMultiConfig AND NOT CMAKE_BUILD_TYPE)
|
||||
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
|
||||
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
|
||||
# Set the possible values of build type for cmake-gui
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
endif()
|
||||
@@ -0,0 +1,36 @@
|
||||
include(CheckCSourceCompiles)
|
||||
include(CMakePushCheckState)
|
||||
|
||||
macro(check_tls_support VAR)
|
||||
if(NOT DEFINED "${VAR}")
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_QUIET 1)
|
||||
|
||||
check_c_source_compiles("
|
||||
__thread int tls;
|
||||
|
||||
int main(void) {
|
||||
return 0;
|
||||
}" HAVE_GCC_TLS)
|
||||
|
||||
if(HAVE_GCC_TLS)
|
||||
message(STATUS "Thread-local storage: supported (__thread)")
|
||||
set(${VAR} "__thread" CACHE INTERNAL "Thread-local storage support keyword in compiler")
|
||||
else()
|
||||
check_c_source_compiles("
|
||||
__declspec(thread) int tls;
|
||||
|
||||
int main(void) {
|
||||
return 0;
|
||||
}" HAVE_MSVC_TLS)
|
||||
if(HAVE_MSVC_TLS)
|
||||
message(STATUS "Thread-local storage: supported (__declspec(thread))")
|
||||
set(${VAR} "__declspec(thread)" CACHE INTERNAL "Thread-local storage keyword in compiler")
|
||||
else()
|
||||
message(STATUS "Thread-local storage: not supported")
|
||||
set(${VAR} "" CACHE INTERNAL "Thread-local storage keyword in compiler")
|
||||
endif()
|
||||
endif()
|
||||
cmake_pop_check_state()
|
||||
endif()
|
||||
endmacro()
|
||||
@@ -0,0 +1,750 @@
|
||||
# Copyright (c) 2012 - 2017, Lars Bilke
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# CHANGES:
|
||||
#
|
||||
# 2012-01-31, Lars Bilke
|
||||
# - Enable Code Coverage
|
||||
#
|
||||
# 2013-09-17, Joakim Söderberg
|
||||
# - Added support for Clang.
|
||||
# - Some additional usage instructions.
|
||||
#
|
||||
# 2016-02-03, Lars Bilke
|
||||
# - Refactored functions to use named parameters
|
||||
#
|
||||
# 2017-06-02, Lars Bilke
|
||||
# - Merged with modified version from github.com/ufz/ogs
|
||||
#
|
||||
# 2019-05-06, Anatolii Kurotych
|
||||
# - Remove unnecessary --coverage flag
|
||||
#
|
||||
# 2019-12-13, FeRD (Frank Dana)
|
||||
# - Deprecate COVERAGE_LCOVR_EXCLUDES and COVERAGE_GCOVR_EXCLUDES lists in favor
|
||||
# of tool-agnostic COVERAGE_EXCLUDES variable, or EXCLUDE setup arguments.
|
||||
# - CMake 3.4+: All excludes can be specified relative to BASE_DIRECTORY
|
||||
# - All setup functions: accept BASE_DIRECTORY, EXCLUDE list
|
||||
# - Set lcov basedir with -b argument
|
||||
# - Add automatic --demangle-cpp in lcovr, if 'c++filt' is available (can be
|
||||
# overridden with NO_DEMANGLE option in setup_target_for_coverage_lcovr().)
|
||||
# - Delete output dir, .info file on 'make clean'
|
||||
# - Remove Python detection, since version mismatches will break gcovr
|
||||
# - Minor cleanup (lowercase function names, update examples...)
|
||||
#
|
||||
# 2019-12-19, FeRD (Frank Dana)
|
||||
# - Rename Lcov outputs, make filtered file canonical, fix cleanup for targets
|
||||
#
|
||||
# 2020-01-19, Bob Apthorpe
|
||||
# - Added gfortran support
|
||||
#
|
||||
# 2020-02-17, FeRD (Frank Dana)
|
||||
# - Make all add_custom_target()s VERBATIM to auto-escape wildcard characters
|
||||
# in EXCLUDEs, and remove manual escaping from gcovr targets
|
||||
#
|
||||
# 2021-01-19, Robin Mueller
|
||||
# - Add CODE_COVERAGE_VERBOSE option which will allow to print out commands which are run
|
||||
# - Added the option for users to set the GCOVR_ADDITIONAL_ARGS variable to supply additional
|
||||
# flags to the gcovr command
|
||||
#
|
||||
# 2020-05-04, Mihchael Davis
|
||||
# - Add -fprofile-abs-path to make gcno files contain absolute paths
|
||||
# - Fix BASE_DIRECTORY not working when defined
|
||||
# - Change BYPRODUCT from folder to index.html to stop ninja from complaining about double defines
|
||||
#
|
||||
# 2021-05-10, Martin Stump
|
||||
# - Check if the generator is multi-config before warning about non-Debug builds
|
||||
#
|
||||
# 2022-02-22, Marko Wehle
|
||||
# - Change gcovr output from -o <filename> for --xml <filename> and --html <filename> output respectively.
|
||||
# This will allow for Multiple Output Formats at the same time by making use of GCOVR_ADDITIONAL_ARGS, e.g. GCOVR_ADDITIONAL_ARGS "--txt".
|
||||
#
|
||||
# 2022-09-28, Sebastian Mueller
|
||||
# - fix append_coverage_compiler_flags_to_target to correctly add flags
|
||||
# - replace "-fprofile-arcs -ftest-coverage" with "--coverage" (equivalent)
|
||||
#
|
||||
# USAGE:
|
||||
#
|
||||
# 1. Copy this file into your cmake modules path.
|
||||
#
|
||||
# 2. Add the following line to your CMakeLists.txt (best inside an if-condition
|
||||
# using a CMake option() to enable it just optionally):
|
||||
# include(CodeCoverage)
|
||||
#
|
||||
# 3. Append necessary compiler flags for all supported source files:
|
||||
# append_coverage_compiler_flags()
|
||||
# Or for specific target:
|
||||
# append_coverage_compiler_flags_to_target(YOUR_TARGET_NAME)
|
||||
#
|
||||
# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og
|
||||
#
|
||||
# 4. If you need to exclude additional directories from the report, specify them
|
||||
# using full paths in the COVERAGE_EXCLUDES variable before calling
|
||||
# setup_target_for_coverage_*().
|
||||
# Example:
|
||||
# set(COVERAGE_EXCLUDES
|
||||
# '${PROJECT_SOURCE_DIR}/src/dir1/*'
|
||||
# '/path/to/my/src/dir2/*')
|
||||
# Or, use the EXCLUDE argument to setup_target_for_coverage_*().
|
||||
# Example:
|
||||
# setup_target_for_coverage_lcov(
|
||||
# NAME coverage
|
||||
# EXECUTABLE testrunner
|
||||
# EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*")
|
||||
#
|
||||
# 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set
|
||||
# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR)
|
||||
# Example:
|
||||
# set(COVERAGE_EXCLUDES "dir1/*")
|
||||
# setup_target_for_coverage_gcovr_html(
|
||||
# NAME coverage
|
||||
# EXECUTABLE testrunner
|
||||
# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"
|
||||
# EXCLUDE "dir2/*")
|
||||
#
|
||||
# 5. Use the functions described below to create a custom make target which
|
||||
# runs your test executable and produces a code coverage report.
|
||||
#
|
||||
# 6. Build a Debug build:
|
||||
# cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
# make
|
||||
# make my_coverage_target
|
||||
#
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE)
|
||||
|
||||
# Check prereqs
|
||||
find_program( GCOV_PATH gcov )
|
||||
find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
|
||||
find_program( FASTCOV_PATH NAMES fastcov fastcov.py )
|
||||
find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
|
||||
find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
|
||||
find_program( CPPFILT_PATH NAMES c++filt )
|
||||
|
||||
if(NOT GCOV_PATH)
|
||||
message(FATAL_ERROR "gcov not found! Aborting...")
|
||||
endif() # NOT GCOV_PATH
|
||||
|
||||
# Check supported compiler (Clang, GNU and Flang)
|
||||
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||
foreach(LANG ${LANGUAGES})
|
||||
if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||
if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
|
||||
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
|
||||
endif()
|
||||
elseif(NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU"
|
||||
AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang")
|
||||
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(COVERAGE_COMPILER_FLAGS "-g --coverage"
|
||||
CACHE INTERNAL "")
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag(-fprofile-abs-path HAVE_cxx_fprofile_abs_path)
|
||||
if(HAVE_cxx_fprofile_abs_path)
|
||||
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
|
||||
endif()
|
||||
endif()
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||
include(CheckCCompilerFlag)
|
||||
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
|
||||
if(HAVE_c_fprofile_abs_path)
|
||||
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_Fortran_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the Fortran compiler during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the C++ compiler during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_C_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the C compiler during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used for linking binaries during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
|
||||
FORCE )
|
||||
mark_as_advanced(
|
||||
CMAKE_Fortran_FLAGS_COVERAGE
|
||||
CMAKE_CXX_FLAGS_COVERAGE
|
||||
CMAKE_C_FLAGS_COVERAGE
|
||||
CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
|
||||
|
||||
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
|
||||
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
|
||||
endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
|
||||
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
||||
link_libraries(gcov)
|
||||
endif()
|
||||
|
||||
# Defines a target for running and collection code coverage information
|
||||
# Builds dependencies, runs the given executable and outputs reports.
|
||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||
# the coverage generation will not complete.
|
||||
#
|
||||
# setup_target_for_coverage_lcov(
|
||||
# NAME testrunner_coverage # New target name
|
||||
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||
# DEPENDENCIES testrunner # Dependencies to build first
|
||||
# BASE_DIRECTORY "../" # Base directory for report
|
||||
# # (defaults to PROJECT_SOURCE_DIR)
|
||||
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
|
||||
# # to BASE_DIRECTORY, with CMake 3.4+)
|
||||
# NO_DEMANGLE # Don't demangle C++ symbols
|
||||
# # even if c++filt is found
|
||||
# )
|
||||
function(setup_target_for_coverage_lcov)
|
||||
|
||||
set(options NO_DEMANGLE SONARQUBE)
|
||||
set(oneValueArgs BASE_DIRECTORY NAME)
|
||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS)
|
||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT LCOV_PATH)
|
||||
message(FATAL_ERROR "lcov not found! Aborting...")
|
||||
endif() # NOT LCOV_PATH
|
||||
|
||||
if(NOT GENHTML_PATH)
|
||||
message(FATAL_ERROR "genhtml not found! Aborting...")
|
||||
endif() # NOT GENHTML_PATH
|
||||
|
||||
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
||||
if(DEFINED Coverage_BASE_DIRECTORY)
|
||||
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
||||
else()
|
||||
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
||||
set(LCOV_EXCLUDES "")
|
||||
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_LCOV_EXCLUDES})
|
||||
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
|
||||
endif()
|
||||
list(APPEND LCOV_EXCLUDES "${EXCLUDE}")
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES LCOV_EXCLUDES)
|
||||
|
||||
# Conditional arguments
|
||||
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
|
||||
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
|
||||
endif()
|
||||
|
||||
# Setting up commands which will be run to generate coverage data.
|
||||
# Cleanup lcov
|
||||
set(LCOV_CLEAN_CMD
|
||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory .
|
||||
-b ${BASEDIR} --zerocounters
|
||||
)
|
||||
# Create baseline to make sure untouched files show up in the report
|
||||
set(LCOV_BASELINE_CMD
|
||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -b
|
||||
${BASEDIR} -o ${Coverage_NAME}.base
|
||||
)
|
||||
# Run tests
|
||||
set(LCOV_EXEC_TESTS_CMD
|
||||
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||
)
|
||||
# Capturing lcov counters and generating report
|
||||
set(LCOV_CAPTURE_CMD
|
||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b
|
||||
${BASEDIR} --capture --output-file ${Coverage_NAME}.capture
|
||||
)
|
||||
# add baseline counters
|
||||
set(LCOV_BASELINE_COUNT_CMD
|
||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base
|
||||
-a ${Coverage_NAME}.capture --output-file ${Coverage_NAME}.total
|
||||
)
|
||||
# filter collected data to final coverage report
|
||||
set(LCOV_FILTER_CMD
|
||||
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove
|
||||
${Coverage_NAME}.total ${LCOV_EXCLUDES} --output-file ${Coverage_NAME}.info
|
||||
)
|
||||
# Generate HTML output
|
||||
set(LCOV_GEN_HTML_CMD
|
||||
${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o
|
||||
${Coverage_NAME} ${Coverage_NAME}.info
|
||||
)
|
||||
if(${Coverage_SONARQUBE})
|
||||
# Generate SonarQube output
|
||||
set(GCOVR_XML_CMD
|
||||
${GCOVR_PATH} --sonarqube ${Coverage_NAME}_sonarqube.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
|
||||
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
|
||||
)
|
||||
set(GCOVR_XML_CMD_COMMAND
|
||||
COMMAND ${GCOVR_XML_CMD}
|
||||
)
|
||||
set(GCOVR_XML_CMD_BYPRODUCTS ${Coverage_NAME}_sonarqube.xml)
|
||||
set(GCOVR_XML_CMD_COMMENT COMMENT "SonarQube code coverage info report saved in ${Coverage_NAME}_sonarqube.xml.")
|
||||
endif()
|
||||
|
||||
|
||||
if(CODE_COVERAGE_VERBOSE)
|
||||
message(STATUS "Executed command report")
|
||||
message(STATUS "Command to clean up lcov: ")
|
||||
string(REPLACE ";" " " LCOV_CLEAN_CMD_SPACED "${LCOV_CLEAN_CMD}")
|
||||
message(STATUS "${LCOV_CLEAN_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to create baseline: ")
|
||||
string(REPLACE ";" " " LCOV_BASELINE_CMD_SPACED "${LCOV_BASELINE_CMD}")
|
||||
message(STATUS "${LCOV_BASELINE_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to run the tests: ")
|
||||
string(REPLACE ";" " " LCOV_EXEC_TESTS_CMD_SPACED "${LCOV_EXEC_TESTS_CMD}")
|
||||
message(STATUS "${LCOV_EXEC_TESTS_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to capture counters and generate report: ")
|
||||
string(REPLACE ";" " " LCOV_CAPTURE_CMD_SPACED "${LCOV_CAPTURE_CMD}")
|
||||
message(STATUS "${LCOV_CAPTURE_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to add baseline counters: ")
|
||||
string(REPLACE ";" " " LCOV_BASELINE_COUNT_CMD_SPACED "${LCOV_BASELINE_COUNT_CMD}")
|
||||
message(STATUS "${LCOV_BASELINE_COUNT_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to filter collected data: ")
|
||||
string(REPLACE ";" " " LCOV_FILTER_CMD_SPACED "${LCOV_FILTER_CMD}")
|
||||
message(STATUS "${LCOV_FILTER_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to generate lcov HTML output: ")
|
||||
string(REPLACE ";" " " LCOV_GEN_HTML_CMD_SPACED "${LCOV_GEN_HTML_CMD}")
|
||||
message(STATUS "${LCOV_GEN_HTML_CMD_SPACED}")
|
||||
|
||||
if(${Coverage_SONARQUBE})
|
||||
message(STATUS "Command to generate SonarQube XML output: ")
|
||||
string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
|
||||
message(STATUS "${GCOVR_XML_CMD_SPACED}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Setup target
|
||||
add_custom_target(${Coverage_NAME}
|
||||
COMMAND ${LCOV_CLEAN_CMD}
|
||||
COMMAND ${LCOV_BASELINE_CMD}
|
||||
COMMAND ${LCOV_EXEC_TESTS_CMD}
|
||||
COMMAND ${LCOV_CAPTURE_CMD}
|
||||
COMMAND ${LCOV_BASELINE_COUNT_CMD}
|
||||
COMMAND ${LCOV_FILTER_CMD}
|
||||
COMMAND ${LCOV_GEN_HTML_CMD}
|
||||
${GCOVR_XML_CMD_COMMAND}
|
||||
|
||||
# Set output files as GENERATED (will be removed on 'make clean')
|
||||
BYPRODUCTS
|
||||
${Coverage_NAME}.base
|
||||
${Coverage_NAME}.capture
|
||||
${Coverage_NAME}.total
|
||||
${Coverage_NAME}.info
|
||||
${GCOVR_XML_CMD_BYPRODUCTS}
|
||||
${Coverage_NAME}/index.html
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
VERBATIM # Protect arguments to commands
|
||||
COMMENT "Resetting code coverage counters to zero. Processing code coverage counters and generating report."
|
||||
)
|
||||
|
||||
# Show where to find the lcov info report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND true
|
||||
COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info."
|
||||
${GCOVR_XML_CMD_COMMENT}
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND true
|
||||
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
|
||||
)
|
||||
|
||||
endfunction() # setup_target_for_coverage_lcov
|
||||
|
||||
# Defines a target for running and collection code coverage information
|
||||
# Builds dependencies, runs the given executable and outputs reports.
|
||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||
# the coverage generation will not complete.
|
||||
#
|
||||
# setup_target_for_coverage_gcovr_xml(
|
||||
# NAME ctest_coverage # New target name
|
||||
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||
# DEPENDENCIES executable_target # Dependencies to build first
|
||||
# BASE_DIRECTORY "../" # Base directory for report
|
||||
# # (defaults to PROJECT_SOURCE_DIR)
|
||||
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
|
||||
# # to BASE_DIRECTORY, with CMake 3.4+)
|
||||
# )
|
||||
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
|
||||
# GCVOR command.
|
||||
function(setup_target_for_coverage_gcovr_xml)
|
||||
|
||||
set(options NONE)
|
||||
set(oneValueArgs BASE_DIRECTORY NAME)
|
||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT GCOVR_PATH)
|
||||
message(FATAL_ERROR "gcovr not found! Aborting...")
|
||||
endif() # NOT GCOVR_PATH
|
||||
|
||||
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
||||
if(DEFINED Coverage_BASE_DIRECTORY)
|
||||
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
||||
else()
|
||||
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
||||
set(GCOVR_EXCLUDES "")
|
||||
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
|
||||
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
|
||||
endif()
|
||||
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
|
||||
|
||||
# Combine excludes to several -e arguments
|
||||
set(GCOVR_EXCLUDE_ARGS "")
|
||||
foreach(EXCLUDE ${GCOVR_EXCLUDES})
|
||||
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
|
||||
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
|
||||
endforeach()
|
||||
|
||||
# Set up commands which will be run to generate coverage data
|
||||
# Run tests
|
||||
set(GCOVR_XML_EXEC_TESTS_CMD
|
||||
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||
)
|
||||
# Running gcovr
|
||||
set(GCOVR_XML_CMD
|
||||
${GCOVR_PATH} --xml ${Coverage_NAME}.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
|
||||
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
|
||||
)
|
||||
|
||||
if(CODE_COVERAGE_VERBOSE)
|
||||
message(STATUS "Executed command report")
|
||||
|
||||
message(STATUS "Command to run tests: ")
|
||||
string(REPLACE ";" " " GCOVR_XML_EXEC_TESTS_CMD_SPACED "${GCOVR_XML_EXEC_TESTS_CMD}")
|
||||
message(STATUS "${GCOVR_XML_EXEC_TESTS_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to generate gcovr XML coverage data: ")
|
||||
string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
|
||||
message(STATUS "${GCOVR_XML_CMD_SPACED}")
|
||||
endif()
|
||||
|
||||
add_custom_target(${Coverage_NAME}
|
||||
COMMAND ${GCOVR_XML_EXEC_TESTS_CMD}
|
||||
COMMAND ${GCOVR_XML_CMD}
|
||||
|
||||
BYPRODUCTS ${Coverage_NAME}.xml
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
VERBATIM # Protect arguments to commands
|
||||
COMMENT "Running gcovr to produce Cobertura code coverage report."
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND true
|
||||
COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml."
|
||||
)
|
||||
endfunction() # setup_target_for_coverage_gcovr_xml
|
||||
|
||||
# Defines a target for running and collection code coverage information
|
||||
# Builds dependencies, runs the given executable and outputs reports.
|
||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||
# the coverage generation will not complete.
|
||||
#
|
||||
# setup_target_for_coverage_gcovr_html(
|
||||
# NAME ctest_coverage # New target name
|
||||
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||
# DEPENDENCIES executable_target # Dependencies to build first
|
||||
# BASE_DIRECTORY "../" # Base directory for report
|
||||
# # (defaults to PROJECT_SOURCE_DIR)
|
||||
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
|
||||
# # to BASE_DIRECTORY, with CMake 3.4+)
|
||||
# )
|
||||
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
|
||||
# GCVOR command.
|
||||
function(setup_target_for_coverage_gcovr_html)
|
||||
|
||||
set(options NONE)
|
||||
set(oneValueArgs BASE_DIRECTORY NAME)
|
||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT GCOVR_PATH)
|
||||
message(FATAL_ERROR "gcovr not found! Aborting...")
|
||||
endif() # NOT GCOVR_PATH
|
||||
|
||||
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
||||
if(DEFINED Coverage_BASE_DIRECTORY)
|
||||
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
||||
else()
|
||||
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
||||
set(GCOVR_EXCLUDES "")
|
||||
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
|
||||
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
|
||||
endif()
|
||||
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
|
||||
|
||||
# Combine excludes to several -e arguments
|
||||
set(GCOVR_EXCLUDE_ARGS "")
|
||||
foreach(EXCLUDE ${GCOVR_EXCLUDES})
|
||||
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
|
||||
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
|
||||
endforeach()
|
||||
|
||||
# Set up commands which will be run to generate coverage data
|
||||
# Run tests
|
||||
set(GCOVR_HTML_EXEC_TESTS_CMD
|
||||
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||
)
|
||||
# Create folder
|
||||
set(GCOVR_HTML_FOLDER_CMD
|
||||
${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME}
|
||||
)
|
||||
# Running gcovr
|
||||
set(GCOVR_HTML_CMD
|
||||
${GCOVR_PATH} --html ${Coverage_NAME}/index.html --html-details -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
|
||||
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
|
||||
)
|
||||
|
||||
if(CODE_COVERAGE_VERBOSE)
|
||||
message(STATUS "Executed command report")
|
||||
|
||||
message(STATUS "Command to run tests: ")
|
||||
string(REPLACE ";" " " GCOVR_HTML_EXEC_TESTS_CMD_SPACED "${GCOVR_HTML_EXEC_TESTS_CMD}")
|
||||
message(STATUS "${GCOVR_HTML_EXEC_TESTS_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to create a folder: ")
|
||||
string(REPLACE ";" " " GCOVR_HTML_FOLDER_CMD_SPACED "${GCOVR_HTML_FOLDER_CMD}")
|
||||
message(STATUS "${GCOVR_HTML_FOLDER_CMD_SPACED}")
|
||||
|
||||
message(STATUS "Command to generate gcovr HTML coverage data: ")
|
||||
string(REPLACE ";" " " GCOVR_HTML_CMD_SPACED "${GCOVR_HTML_CMD}")
|
||||
message(STATUS "${GCOVR_HTML_CMD_SPACED}")
|
||||
endif()
|
||||
|
||||
add_custom_target(${Coverage_NAME}
|
||||
COMMAND ${GCOVR_HTML_EXEC_TESTS_CMD}
|
||||
COMMAND ${GCOVR_HTML_FOLDER_CMD}
|
||||
COMMAND ${GCOVR_HTML_CMD}
|
||||
|
||||
BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html # report directory
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
VERBATIM # Protect arguments to commands
|
||||
COMMENT "Running gcovr to produce HTML code coverage report."
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND true
|
||||
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
|
||||
)
|
||||
|
||||
endfunction() # setup_target_for_coverage_gcovr_html
|
||||
|
||||
# Defines a target for running and collection code coverage information
|
||||
# Builds dependencies, runs the given executable and outputs reports.
|
||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||
# the coverage generation will not complete.
|
||||
#
|
||||
# setup_target_for_coverage_fastcov(
|
||||
# NAME testrunner_coverage # New target name
|
||||
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||
# DEPENDENCIES testrunner # Dependencies to build first
|
||||
# BASE_DIRECTORY "../" # Base directory for report
|
||||
# # (defaults to PROJECT_SOURCE_DIR)
|
||||
# EXCLUDE "src/dir1/" "src/dir2/" # Patterns to exclude.
|
||||
# NO_DEMANGLE # Don't demangle C++ symbols
|
||||
# # even if c++filt is found
|
||||
# SKIP_HTML # Don't create html report
|
||||
# POST_CMD perl -i -pe s!${PROJECT_SOURCE_DIR}/!!g ctest_coverage.json # E.g. for stripping source dir from file paths
|
||||
# )
|
||||
function(setup_target_for_coverage_fastcov)
|
||||
|
||||
set(options NO_DEMANGLE SKIP_HTML)
|
||||
set(oneValueArgs BASE_DIRECTORY NAME)
|
||||
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES FASTCOV_ARGS GENHTML_ARGS POST_CMD)
|
||||
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT FASTCOV_PATH)
|
||||
message(FATAL_ERROR "fastcov not found! Aborting...")
|
||||
endif()
|
||||
|
||||
if(NOT Coverage_SKIP_HTML AND NOT GENHTML_PATH)
|
||||
message(FATAL_ERROR "genhtml not found! Aborting...")
|
||||
endif()
|
||||
|
||||
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
||||
if(Coverage_BASE_DIRECTORY)
|
||||
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
||||
else()
|
||||
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
# Collect excludes (Patterns, not paths, for fastcov)
|
||||
set(FASTCOV_EXCLUDES "")
|
||||
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_FASTCOV_EXCLUDES})
|
||||
list(APPEND FASTCOV_EXCLUDES "${EXCLUDE}")
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES FASTCOV_EXCLUDES)
|
||||
|
||||
# Conditional arguments
|
||||
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
|
||||
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
|
||||
endif()
|
||||
|
||||
# Set up commands which will be run to generate coverage data
|
||||
set(FASTCOV_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
|
||||
|
||||
set(FASTCOV_CAPTURE_CMD ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH}
|
||||
--search-directory ${BASEDIR}
|
||||
--process-gcno
|
||||
--output ${Coverage_NAME}.json
|
||||
--exclude ${FASTCOV_EXCLUDES}
|
||||
)
|
||||
|
||||
set(FASTCOV_CONVERT_CMD ${FASTCOV_PATH}
|
||||
-C ${Coverage_NAME}.json --lcov --output ${Coverage_NAME}.info
|
||||
)
|
||||
|
||||
if(Coverage_SKIP_HTML)
|
||||
set(FASTCOV_HTML_CMD ";")
|
||||
else()
|
||||
set(FASTCOV_HTML_CMD ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS}
|
||||
-o ${Coverage_NAME} ${Coverage_NAME}.info
|
||||
)
|
||||
endif()
|
||||
|
||||
set(FASTCOV_POST_CMD ";")
|
||||
if(Coverage_POST_CMD)
|
||||
set(FASTCOV_POST_CMD ${Coverage_POST_CMD})
|
||||
endif()
|
||||
|
||||
if(CODE_COVERAGE_VERBOSE)
|
||||
message(STATUS "Code coverage commands for target ${Coverage_NAME} (fastcov):")
|
||||
|
||||
message(" Running tests:")
|
||||
string(REPLACE ";" " " FASTCOV_EXEC_TESTS_CMD_SPACED "${FASTCOV_EXEC_TESTS_CMD}")
|
||||
message(" ${FASTCOV_EXEC_TESTS_CMD_SPACED}")
|
||||
|
||||
message(" Capturing fastcov counters and generating report:")
|
||||
string(REPLACE ";" " " FASTCOV_CAPTURE_CMD_SPACED "${FASTCOV_CAPTURE_CMD}")
|
||||
message(" ${FASTCOV_CAPTURE_CMD_SPACED}")
|
||||
|
||||
message(" Converting fastcov .json to lcov .info:")
|
||||
string(REPLACE ";" " " FASTCOV_CONVERT_CMD_SPACED "${FASTCOV_CONVERT_CMD}")
|
||||
message(" ${FASTCOV_CONVERT_CMD_SPACED}")
|
||||
|
||||
if(NOT Coverage_SKIP_HTML)
|
||||
message(" Generating HTML report: ")
|
||||
string(REPLACE ";" " " FASTCOV_HTML_CMD_SPACED "${FASTCOV_HTML_CMD}")
|
||||
message(" ${FASTCOV_HTML_CMD_SPACED}")
|
||||
endif()
|
||||
if(Coverage_POST_CMD)
|
||||
message(" Running post command: ")
|
||||
string(REPLACE ";" " " FASTCOV_POST_CMD_SPACED "${FASTCOV_POST_CMD}")
|
||||
message(" ${FASTCOV_POST_CMD_SPACED}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Setup target
|
||||
add_custom_target(${Coverage_NAME}
|
||||
|
||||
# Cleanup fastcov
|
||||
COMMAND ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH}
|
||||
--search-directory ${BASEDIR}
|
||||
--zerocounters
|
||||
|
||||
COMMAND ${FASTCOV_EXEC_TESTS_CMD}
|
||||
COMMAND ${FASTCOV_CAPTURE_CMD}
|
||||
COMMAND ${FASTCOV_CONVERT_CMD}
|
||||
COMMAND ${FASTCOV_HTML_CMD}
|
||||
COMMAND ${FASTCOV_POST_CMD}
|
||||
|
||||
# Set output files as GENERATED (will be removed on 'make clean')
|
||||
BYPRODUCTS
|
||||
${Coverage_NAME}.info
|
||||
${Coverage_NAME}.json
|
||||
${Coverage_NAME}/index.html # report directory
|
||||
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
DEPENDS ${Coverage_DEPENDENCIES}
|
||||
VERBATIM # Protect arguments to commands
|
||||
COMMENT "Resetting code coverage counters to zero. Processing code coverage counters and generating report."
|
||||
)
|
||||
|
||||
set(INFO_MSG "fastcov code coverage info report saved in ${Coverage_NAME}.info and ${Coverage_NAME}.json.")
|
||||
if(NOT Coverage_SKIP_HTML)
|
||||
string(APPEND INFO_MSG " Open ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html in your browser to view the coverage report.")
|
||||
endif()
|
||||
# Show where to find the fastcov info report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo ${INFO_MSG}
|
||||
)
|
||||
|
||||
endfunction() # setup_target_for_coverage_fastcov
|
||||
|
||||
function(append_coverage_compiler_flags)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
|
||||
endfunction() # append_coverage_compiler_flags
|
||||
|
||||
# Setup coverage for specific library
|
||||
function(append_coverage_compiler_flags_to_target name)
|
||||
separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}")
|
||||
target_compile_options(${name} PRIVATE ${_flag_list})
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
||||
target_link_libraries(${name} PRIVATE gcov)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,85 @@
|
||||
# https://raw.githubusercontent.com/dune-project/dune-istl/master/cmake/modules/FindARPACK.cmake
|
||||
#
|
||||
# This file is taken from:
|
||||
#
|
||||
# DUNE, the Distributed and Unified Numerics Environment
|
||||
# GPLv2 licensed
|
||||
#
|
||||
# .. cmake_module::
|
||||
#
|
||||
# Module that checks whether ARPACK is available and usable.
|
||||
#
|
||||
# Variables used by this module which you may want to set:
|
||||
#
|
||||
# :ref:`ARPACK_ROOT`
|
||||
# Path list to search for ARPACK.
|
||||
#
|
||||
# Sets the following variables:
|
||||
#
|
||||
# :code:`ARPACK_FOUND`
|
||||
# True if ARPACK available.
|
||||
#
|
||||
# :code:`ARPACK_LIBRARIES`
|
||||
# Link against these libraries to use ARPACK.
|
||||
#
|
||||
# .. cmake_variable:: ARPACK_ROOT
|
||||
#
|
||||
# You may set this variable to have :ref:`FindARPACK` look
|
||||
# for the ARPACK package in the given path before inspecting
|
||||
# system paths.
|
||||
#
|
||||
|
||||
# look for library, only at positions given by the user
|
||||
find_library(ARPACK_LIBRARY
|
||||
NAMES "arpack"
|
||||
PATHS ${ARPACK_PREFIX} ${ARPACK_ROOT}
|
||||
PATH_SUFFIXES "lib" "lib32" "lib64"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
# look for library files, including default paths
|
||||
find_library(ARPACK_LIBRARY
|
||||
NAMES "arpack"
|
||||
PATH_SUFFIXES "lib" "lib32" "lib64"
|
||||
)
|
||||
|
||||
# check header usability
|
||||
include(CMakePushCheckState)
|
||||
cmake_push_check_state()
|
||||
|
||||
# we need if clauses here because variable is set variable-NOTFOUND if the
|
||||
# searches above were not successful; without them CMake print errors like:
|
||||
# "CMake Error: The following variables are used in this project, but they
|
||||
# are set to NOTFOUND. Please set them or make sure they are set and tested
|
||||
# correctly in the CMake files."
|
||||
if(ARPACK_LIBRARY)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${ARPACK_LIBRARY})
|
||||
endif()
|
||||
|
||||
# end of header usability check
|
||||
cmake_pop_check_state()
|
||||
|
||||
# behave like a CMake module is supposed to behave
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(
|
||||
"ARPACK"
|
||||
DEFAULT_MSG
|
||||
ARPACK_LIBRARY
|
||||
)
|
||||
|
||||
# hide the introduced cmake cached variables in cmake GUIs
|
||||
mark_as_advanced(ARPACK_LIBRARY)
|
||||
|
||||
# if headers are found, store results
|
||||
if(ARPACK_FOUND)
|
||||
set(ARPACK_LIBRARIES ${ARPACK_LIBRARY})
|
||||
# log result
|
||||
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
|
||||
"Determing location of ARPACK succeeded:\n"
|
||||
"Libraries to link against: ${ARPACK_LIBRARIES}\n\n")
|
||||
else()
|
||||
# log errornous result
|
||||
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||
"Determing location of ARPACK failed:\n"
|
||||
"Libraries to link against: ${ARPACK_LIBRARIES}\n\n")
|
||||
endif()
|
||||
@@ -0,0 +1,81 @@
|
||||
#[=======================================================================[.rst:
|
||||
FindGLPK
|
||||
--------
|
||||
|
||||
Finds the GLPK library.
|
||||
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
This will define the following variables:
|
||||
|
||||
``GLPK_FOUND``
|
||||
True if the system has the GLPK library.
|
||||
``GLPK_VERSION``
|
||||
The version of the GLPK library which was found.
|
||||
``GLPK_INCLUDE_DIRS``
|
||||
Include directories needed to use Foo.
|
||||
``GLPK_LIBRARIES``
|
||||
Libraries needed to link to Foo.
|
||||
|
||||
Cache Variables
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The following cache variables may also be set:
|
||||
|
||||
``GLPK_INCLUDE_DIR``
|
||||
The directory containing ``glpk.h``.
|
||||
``GLPK_LIBRARY``
|
||||
The path to the GLPK library.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
find_path(GLPK_INCLUDE_DIR
|
||||
NAMES glpk.h
|
||||
)
|
||||
|
||||
find_library(GLPK_LIBRARY
|
||||
NAMES glpk
|
||||
)
|
||||
|
||||
# parse version from header
|
||||
if(GLPK_INCLUDE_DIR)
|
||||
set(GLPK_VERSION_FILE ${GLPK_INCLUDE_DIR}/glpk.h)
|
||||
file(READ ${GLPK_VERSION_FILE} GLPK_VERSION_FILE_CONTENTS)
|
||||
|
||||
string(REGEX MATCH "#define[ ]+GLP_MAJOR_VERSION[ ]+[0-9]+"
|
||||
GLPK_VERSION_MAJOR "${GLPK_VERSION_FILE_CONTENTS}")
|
||||
string(REGEX REPLACE "#define[ ]+GLP_MAJOR_VERSION[ ]+([0-9]+)" "\\1"
|
||||
GLPK_VERSION_MAJOR "${GLPK_VERSION_MAJOR}")
|
||||
|
||||
string(REGEX MATCH "#define[ ]+GLP_MINOR_VERSION[ ]+[0-9]+"
|
||||
GLPK_VERSION_MINOR "${GLPK_VERSION_FILE_CONTENTS}")
|
||||
string(REGEX REPLACE "#define[ ]+GLP_MINOR_VERSION[ ]+([0-9]+)" "\\1"
|
||||
GLPK_VERSION_MINOR "${GLPK_VERSION_MINOR}")
|
||||
|
||||
set(GLPK_VERSION "${GLPK_VERSION_MAJOR}.${GLPK_VERSION_MINOR}")
|
||||
|
||||
# compatibility variables
|
||||
set(GLPK_VERSION_STRING "${GLPK_VERSION}")
|
||||
endif()
|
||||
|
||||
# behave like a CMake module is supposed to behave
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(GLPK
|
||||
FOUND_VAR GLPK_FOUND
|
||||
REQUIRED_VARS
|
||||
GLPK_LIBRARY
|
||||
GLPK_INCLUDE_DIR
|
||||
VERSION_VAR GLPK_VERSION
|
||||
)
|
||||
|
||||
# hide the introduced cmake cached variables in cmake GUIs
|
||||
mark_as_advanced(
|
||||
GLPK_INCLUDE_DIR
|
||||
GLPK_LIBRARY
|
||||
)
|
||||
|
||||
if(GLPK_FOUND)
|
||||
set(GLPK_LIBRARIES ${GLPK_LIBRARY})
|
||||
set(GLPK_INCLUDE_DIRS ${GLPK_INCLUDE_DIR})
|
||||
endif()
|
||||
@@ -0,0 +1,36 @@
|
||||
# Inspired by http://code.google.com/p/origin/source/browse/trunk/cmake/FindGMP.cmake
|
||||
|
||||
# Copyright (c) 2008-2010 Kent State University
|
||||
# Copyright (c) 2011-2012 Texas A&M University
|
||||
#
|
||||
# This file is distributed under the MIT License. See
|
||||
# http://www.opensource.org/licenses/mit-license.php for terms and conditions.
|
||||
#
|
||||
# Some modifications made by Tamas Nepusz to ensure that the module fits better
|
||||
# with the de facto conventions of FindXXX.cmake scripts
|
||||
|
||||
find_path(GMP_INCLUDE_DIR
|
||||
NAMES gmp.h
|
||||
)
|
||||
|
||||
find_library(GMP_LIBRARY
|
||||
NAMES gmp
|
||||
)
|
||||
|
||||
# behave like a CMake module is supposed to behave
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(
|
||||
"GMP"
|
||||
DEFAULT_MSG
|
||||
GMP_LIBRARY
|
||||
GMP_INCLUDE_DIR
|
||||
)
|
||||
|
||||
# hide the introduced cmake cached variables in cmake GUIs
|
||||
mark_as_advanced(GMP_INCLUDE_DIR)
|
||||
mark_as_advanced(GMP_LIBRARY)
|
||||
|
||||
if(GMP_FOUND)
|
||||
set(GMP_LIBRARIES ${GMP_LIBRARY})
|
||||
set(GMP_INCLUDE_DIRS ${GMP_INCLUDE_DIR})
|
||||
endif()
|
||||
@@ -0,0 +1,63 @@
|
||||
# Inspired by http://code.google.com/p/origin/source/browse/trunk/cmake/FindGMP.cmake
|
||||
|
||||
# Copyright (c) 2021 Tamas Nepusz
|
||||
#
|
||||
# This file is distributed under the MIT License. See
|
||||
# http://www.opensource.org/licenses/mit-license.php for terms and conditions.
|
||||
#
|
||||
# Some modifications made by Tamas Nepusz to ensure that the module fits better
|
||||
# with the de facto conventions of FindXXX.cmake scripts
|
||||
|
||||
find_path(PLFIT_INCLUDE_DIR
|
||||
NAMES plfit.h
|
||||
PATH_SUFFIXES plfit
|
||||
)
|
||||
|
||||
find_library(PLFIT_LIBRARY
|
||||
NAMES plfit
|
||||
)
|
||||
|
||||
# parse version from header
|
||||
if(PLFIT_INCLUDE_DIR)
|
||||
set(PLFIT_VERSION_FILE ${PLFIT_INCLUDE_DIR}/plfit_version.h)
|
||||
file(READ ${PLFIT_VERSION_FILE} PLFIT_VERSION_FILE_CONTENTS)
|
||||
|
||||
string(REGEX MATCH "#define[ ]+PLFIT_VERSION_MAJOR[ ]+[0-9]+"
|
||||
PLFIT_VERSION_MAJOR "${PLFIT_VERSION_FILE_CONTENTS}")
|
||||
string(REGEX REPLACE "#define[ ]+PLFIT_VERSION_MAJOR[ ]+([0-9]+)" "\\1"
|
||||
PLFIT_VERSION_MAJOR "${PLFIT_VERSION_MAJOR}")
|
||||
|
||||
string(REGEX MATCH "#define[ ]+PLFIT_VERSION_MINOR[ ]+[0-9]+"
|
||||
PLFIT_VERSION_MINOR "${PLFIT_VERSION_FILE_CONTENTS}")
|
||||
string(REGEX REPLACE "#define[ ]+PLFIT_VERSION_MINOR[ ]+([0-9]+)" "\\1"
|
||||
PLFIT_VERSION_MINOR "${PLFIT_VERSION_MINOR}")
|
||||
|
||||
string(REGEX MATCH "#define[ ]+PLFIT_VERSION_PATCH[ ]+[0-9]+"
|
||||
PLFIT_VERSION_PATCH "${PLFIT_VERSION_FILE_CONTENTS}")
|
||||
string(REGEX REPLACE "#define[ ]+PLFIT_VERSION_PATCH[ ]+([0-9]+)" "\\1"
|
||||
PLFIT_VERSION_PATCH "${PLFIT_VERSION_PATCH}")
|
||||
|
||||
set(PLFIT_VERSION "${PLFIT_VERSION_MAJOR}.${PLFIT_VERSION_MINOR}.${PLFIT_VERSION_PATCH}")
|
||||
|
||||
# compatibility variables
|
||||
set(PLFIT_VERSION_STRING "${PLFIT_VERSION}")
|
||||
endif()
|
||||
|
||||
# behave like a CMake module is supposed to behave
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(PLFIT
|
||||
FOUND_VAR PLFIT_FOUND
|
||||
REQUIRED_VARS
|
||||
PLFIT_LIBRARY
|
||||
PLFIT_INCLUDE_DIR
|
||||
VERSION_VAR PLFIT_VERSION
|
||||
)
|
||||
|
||||
# hide the introduced cmake cached variables in cmake GUIs
|
||||
mark_as_advanced(PLFIT_INCLUDE_DIR)
|
||||
mark_as_advanced(PLFIT_LIBRARY)
|
||||
|
||||
if(PLFIT_FOUND)
|
||||
set(PLFIT_LIBRARIES ${PLFIT_LIBRARY})
|
||||
set(PLFIT_INCLUDE_DIRS ${PLFIT_INCLUDE_DIR})
|
||||
endif()
|
||||
@@ -0,0 +1,166 @@
|
||||
# - Returns a version string from Git
|
||||
#
|
||||
# These functions force a re-configure on each git commit so that you can
|
||||
# trust the values of the variables in your build system.
|
||||
#
|
||||
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the refspec and sha hash of the current head revision
|
||||
#
|
||||
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the source tree, and adjusting
|
||||
# the output so that it tests false if an error occurs.
|
||||
#
|
||||
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe --exact-match on the source tree,
|
||||
# and adjusting the output so that it tests false if there was no exact
|
||||
# matching tag.
|
||||
#
|
||||
# git_local_changes(<var>)
|
||||
#
|
||||
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
|
||||
# Uses the return code of "git diff-index --quiet HEAD --".
|
||||
# Does not regard untracked files.
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
if(__get_git_revision_description)
|
||||
return()
|
||||
endif()
|
||||
set(__get_git_revision_description YES)
|
||||
|
||||
# We must run the following at "include" time, not at function call time,
|
||||
# to find the path to this module rather than the path to a calling list file
|
||||
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
|
||||
function(get_git_head_revision _refspecvar _hashvar)
|
||||
set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
|
||||
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
|
||||
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
|
||||
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
|
||||
# We have reached the root directory, we are not in git
|
||||
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
endwhile()
|
||||
# check if this is a submodule
|
||||
if(NOT IS_DIRECTORY ${GIT_DIR})
|
||||
file(READ ${GIT_DIR} submodule)
|
||||
string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
|
||||
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
||||
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
|
||||
endif()
|
||||
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||
if(NOT EXISTS "${GIT_DATA}")
|
||||
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${GIT_DIR}/HEAD")
|
||||
return()
|
||||
endif()
|
||||
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
|
||||
|
||||
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||
"${GIT_DATA}/grabRef.cmake"
|
||||
@ONLY)
|
||||
include("${GIT_DATA}/grabRef.cmake")
|
||||
|
||||
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
|
||||
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_describe _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# TODO sanitize
|
||||
#if((${ARGN}" MATCHES "&&") OR
|
||||
# (ARGN MATCHES "||") OR
|
||||
# (ARGN MATCHES "\\;"))
|
||||
# message("Please report the following error to the project!")
|
||||
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||
#endif()
|
||||
|
||||
execute_process(COMMAND
|
||||
"${GIT_EXECUTABLE}"
|
||||
describe
|
||||
${hash}
|
||||
${ARGN}
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE
|
||||
res
|
||||
OUTPUT_VARIABLE
|
||||
out
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT res EQUAL 0)
|
||||
set(out "${out}-${res}-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(${_var} "${out}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_get_exact_tag _var)
|
||||
git_describe(out --exact-match ${ARGN})
|
||||
set(${_var} "${out}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_local_changes _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND
|
||||
"${GIT_EXECUTABLE}"
|
||||
diff-index --quiet HEAD --
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE
|
||||
res
|
||||
OUTPUT_VARIABLE
|
||||
out
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(res EQUAL 0)
|
||||
set(${_var} "CLEAN" PARENT_SCOPE)
|
||||
else()
|
||||
set(${_var} "DIRTY" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -0,0 +1,41 @@
|
||||
#
|
||||
# Internal file for GetGitRevisionDescription.cmake
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
set(HEAD_HASH)
|
||||
|
||||
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||
|
||||
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||
if(HEAD_CONTENTS MATCHES "ref")
|
||||
# named branch
|
||||
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
else()
|
||||
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
|
||||
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
|
||||
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
|
||||
set(HEAD_HASH "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
# detached HEAD
|
||||
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
endif()
|
||||
|
||||
if(NOT HEAD_HASH)
|
||||
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||
endif()
|
||||
@@ -0,0 +1,26 @@
|
||||
# This module provides function for joining paths
|
||||
# known from from most languages
|
||||
#
|
||||
# Original license:
|
||||
# SPDX-License-Identifier: (MIT OR CC0-1.0)
|
||||
# Explicit permission given to distribute this module under
|
||||
# the terms of the project as described in /LICENSE.rst.
|
||||
# Copyright 2020 Jan Tojnar
|
||||
# https://github.com/jtojnar/cmake-snips
|
||||
#
|
||||
# Modelled after Python’s os.path.join
|
||||
# https://docs.python.org/3.7/library/os.path.html#os.path.join
|
||||
# Windows not supported
|
||||
function(join_paths joined_path first_path_segment)
|
||||
set(temp_path "${first_path_segment}")
|
||||
foreach(current_segment IN LISTS ARGN)
|
||||
if(NOT ("${current_segment}" STREQUAL ""))
|
||||
if(IS_ABSOLUTE "${current_segment}")
|
||||
set(temp_path "${current_segment}")
|
||||
else()
|
||||
set(temp_path "${temp_path}/${current_segment}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
set(${joined_path} "${temp_path}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -0,0 +1,39 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Macro PAD_STRING
|
||||
#
|
||||
# This function pads a string on the left side with a specified character to
|
||||
# reach the specified length. If the string length is already long enough or
|
||||
# longer, the string will not be modified.
|
||||
#
|
||||
# PAD_STRING(OUT_VARIABLE DESIRED_LENGTH FILL_CHAR VALUE)
|
||||
#
|
||||
# OUT_VARIABLE: name of the resulting variable to create
|
||||
# DESIRED_LENGTH: desired length of the generated string
|
||||
# FILL_CHAR: character to use for padding
|
||||
# VALUE: string to pad
|
||||
#
|
||||
# Copyright (C) 2011 by Johannes Wienke <jwienke at techfak dot uni-bielefeld dot de>
|
||||
#
|
||||
# This program is free software; you can redistribute it
|
||||
# and/or modify it under the terms of the GNU General
|
||||
# Public License as published by the Free Software Foundation;
|
||||
# either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
# ------------------------------------------------------------------------------
|
||||
FUNCTION(PAD_STRING OUT_VARIABLE DESIRED_LENGTH FILL_CHAR VALUE)
|
||||
STRING(LENGTH "${VALUE}" VALUE_LENGTH)
|
||||
MATH(EXPR REQUIRED_PADS "${DESIRED_LENGTH} - ${VALUE_LENGTH}")
|
||||
SET(PAD ${VALUE})
|
||||
IF(REQUIRED_PADS GREATER 0)
|
||||
MATH(EXPR REQUIRED_MINUS_ONE "${REQUIRED_PADS} - 1")
|
||||
FOREACH(FOO RANGE ${REQUIRED_MINUS_ONE})
|
||||
SET(PAD "${FILL_CHAR}${PAD}")
|
||||
ENDFOREACH()
|
||||
ENDIF()
|
||||
SET(${OUT_VARIABLE} "${PAD}" PARENT_SCOPE)
|
||||
ENDFUNCTION()
|
||||
@@ -0,0 +1,34 @@
|
||||
# Original source of this script:
|
||||
# https://raw.githubusercontent.com/InsightSoftwareConsortium/ITK/master/CMake/PreventInSourceBuilds.cmake
|
||||
#
|
||||
# Thanks to the ITK project!
|
||||
#
|
||||
# This function will prevent in-source builds
|
||||
function(AssureOutOfSourceBuilds)
|
||||
# make sure the user doesn't play dirty with symlinks
|
||||
get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH)
|
||||
get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH)
|
||||
|
||||
# disallow in-source builds
|
||||
if("${srcdir}" STREQUAL "${bindir}")
|
||||
message("##########################################################################")
|
||||
message("# igraph should not be configured & built in the igraph source directory")
|
||||
message("# You must run cmake in a build directory.")
|
||||
message("#")
|
||||
message("# Example:")
|
||||
message("# mkdir build; cd build; cmake ..; make")
|
||||
message("#")
|
||||
message("# NOTE: Given that you already tried to make an in-source build")
|
||||
message("# CMake have already created several files & directories")
|
||||
message("# in your source tree. If you are using git, run 'git clean -dfx'")
|
||||
message("# to start from scratch. If you don't have git, remove")
|
||||
message("# CMakeCache.txt and the CMakeFiles/ folder from the top of")
|
||||
message("# the source tree.")
|
||||
message("#")
|
||||
message("##########################################################################")
|
||||
message("")
|
||||
message(FATAL_ERROR "Quitting configuration")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
AssureOutOfSourceBuilds()
|
||||
@@ -0,0 +1,7 @@
|
||||
option(USE_CCACHE "Use ccache to speed up compilation if it is installed" ON)
|
||||
if(USE_CCACHE)
|
||||
find_program(CCACHE_PROGRAM ccache)
|
||||
if(CCACHE_PROGRAM)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
# Detect if certain attributes are supported by the compiler
|
||||
# The result will be used to set macros in include/igraph_config.h
|
||||
|
||||
# GCC-style enum value deprecation
|
||||
|
||||
include(CheckCSourceCompiles)
|
||||
include(CMakePushCheckState)
|
||||
|
||||
# Only check with Clang and GCC as we assume that the -Werror option is supported
|
||||
# For other compilers, assume that the attribute is unsupported.
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
|
||||
cmake_push_check_state()
|
||||
# Require compiling with no warning:
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror")
|
||||
check_c_source_compiles(
|
||||
"enum { A __attribute__ ((deprecated)) = 0 }; int main(void) { return 0; }"
|
||||
COMPILER_HAS_DEPRECATED_ENUMVAL_ATTR
|
||||
)
|
||||
cmake_pop_check_state()
|
||||
else()
|
||||
set(COMPILER_HAS_DEPRECATED_ENUMVAL_ATTR FALSE)
|
||||
endif()
|
||||
|
||||
if(COMPILER_HAS_DEPRECATED_ENUMVAL_ATTR)
|
||||
set(IGRAPH_DEPRECATED_ENUMVAL "__attribute__ ((deprecated))")
|
||||
endif()
|
||||
@@ -0,0 +1,43 @@
|
||||
include(CMakeParseArguments)
|
||||
|
||||
function(add_benchmark NAME NAMESPACE)
|
||||
set(TARGET_NAME ${NAMESPACE}_${NAME})
|
||||
|
||||
add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL ${PROJECT_SOURCE_DIR}/tests/benchmarks/${NAME}.c)
|
||||
use_all_warnings(${TARGET_NAME})
|
||||
add_dependencies(build_benchmarks ${TARGET_NAME})
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE igraph)
|
||||
|
||||
# Some benchmarks include plfit_sampling.h from plfit. The following ensures
|
||||
# that the correct version is included, depending on whether plfit is vendored
|
||||
target_include_directories(
|
||||
${TARGET_NAME} PRIVATE
|
||||
$<$<BOOL:${PLFIT_IS_VENDORED}>:$<TARGET_PROPERTY:plfit_vendored,INCLUDE_DIRECTORIES>>
|
||||
$<$<BOOL:${PLFIT_INCLUDE_DIR}>:${PLFIT_INCLUDE_DIR}>
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
# Add MSVC-specific include path for some headers that are missing on Windows
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/msvc/include)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
TARGET benchmark
|
||||
POST_BUILD
|
||||
COMMAND ${TARGET_NAME}
|
||||
COMMENT "Running benchmark: ${NAME}"
|
||||
USES_TERMINAL
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(add_benchmarks)
|
||||
cmake_parse_arguments(
|
||||
PARSED "" "" "NAMES;LIBRARIES" ${ARGN}
|
||||
)
|
||||
foreach(NAME ${PARSED_NAMES})
|
||||
add_benchmark(${NAME} benchmark)
|
||||
if(PARSED_LIBRARIES)
|
||||
target_link_libraries(benchmark_${NAME} PRIVATE ${PARSED_LIBRARIES})
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
@@ -0,0 +1,92 @@
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(CheckTypeSize)
|
||||
|
||||
cmake_push_check_state(RESET)
|
||||
|
||||
# Check whether the compiler supports the __popcnt64() intrinsic
|
||||
check_cxx_source_compiles("
|
||||
#include <intrin.h>
|
||||
|
||||
int main(void) {
|
||||
unsigned long long a = 0xDEADBEEF;
|
||||
volatile unsigned long long b;
|
||||
b = __popcnt64(a);
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
HAVE__POPCNT64
|
||||
)
|
||||
|
||||
# Check whether the compiler supports the __popcnt() intrinsic
|
||||
check_cxx_source_compiles("
|
||||
#include <intrin.h>
|
||||
|
||||
int main(void) {
|
||||
unsigned long a = 0xDEADBEEF;
|
||||
volatile unsigned long long b;
|
||||
b = __popcnt(a);
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
HAVE__POPCNT
|
||||
)
|
||||
|
||||
# Check whether the compiler supports the _BitScanForward64() intrinsic
|
||||
check_cxx_source_compiles("
|
||||
#include <intrin.h>
|
||||
|
||||
int main(void) {
|
||||
unsigned long long a = 0xDEADBEEF;
|
||||
unsigned long b;
|
||||
volatile unsigned long c;
|
||||
c = _BitScanForward64(&b, a) ? b : 64;
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
HAVE__BITSCANFORWARD64
|
||||
)
|
||||
|
||||
# Check whether the compiler supports the _BitScanForward() intrinsic
|
||||
check_cxx_source_compiles("
|
||||
#include <intrin.h>
|
||||
|
||||
int main(void) {
|
||||
unsigned long a = 0xDEADBEEF, b;
|
||||
volatile unsigned long c;
|
||||
c = _BitScanForward(&b, a) ? b : 64;
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
HAVE__BITSCANFORWARD
|
||||
)
|
||||
|
||||
# Check whether the compiler supports the _BitScanReverse64() intrinsic
|
||||
check_cxx_source_compiles("
|
||||
#include <intrin.h>
|
||||
|
||||
int main(void) {
|
||||
unsigned long long a = 0xDEADBEEF;
|
||||
unsigned long b;
|
||||
volatile unsigned long c;
|
||||
c = _BitScanReverse64(&b, a) ? b : 64;
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
HAVE__BITSCANREVERSE64
|
||||
)
|
||||
|
||||
# Check whether the compiler supports the _BitScanReverse() intrinsic
|
||||
check_cxx_source_compiles("
|
||||
#include <intrin.h>
|
||||
|
||||
int main(void) {
|
||||
unsigned long a = 0xDEADBEEF, b;
|
||||
volatile unsigned long c;
|
||||
c = _BitScanReverse(&b, a) ? b : 64;
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
HAVE__BITSCANREVERSE
|
||||
)
|
||||
|
||||
cmake_pop_check_state()
|
||||
@@ -0,0 +1,131 @@
|
||||
include(CheckCCompilerFlag)
|
||||
|
||||
# Enable POSIX features. This needs to be set here instead of in source files so
|
||||
# that it affects CMake-based feature tests.
|
||||
#
|
||||
# See:
|
||||
# - https://pubs.opengroup.org/onlinepubs/007904875/functions/xsh_chap02_02.html
|
||||
# - https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
|
||||
add_compile_definitions(_POSIX_C_SOURCE=200809L)
|
||||
|
||||
# On some Apple systems, with some compilers, defining _POSIX_C_SOURCE causes compilation
|
||||
# failures when including C++ headers. Defining _DARWIN_C_SOURCE explicitly usually fixes
|
||||
# this. Refs: https://trac.macports.org/ticket/60655 and https://trac.macports.org/ticket/73145
|
||||
# This is claimed to be due to _POSIX_C_SOURCE disabling APIs that C++ headers rely on
|
||||
# on some systems. _DARWIN_C_SOURCE re-enables these APIs, but _GNU_SOURCE alone does not
|
||||
# necessarily do so. Using different global defined for C and C++ is problematic with CMake,
|
||||
# so instead of restricting _POSIX_C_SOURCE to C, we define _DARWIN_C_SOURCE.
|
||||
if(APPLE)
|
||||
add_compile_definitions(_DARWIN_C_SOURCE)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_compile_options(/FS)
|
||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS) # necessary to compile for UWP
|
||||
endif()
|
||||
|
||||
if(NOT MSVC)
|
||||
# Even though we will later use 'no-unknown-warning-option', we perform the test for
|
||||
# 'unknown-warning-option', without the 'no-' prefix. This is necessary because GCC
|
||||
# will accept any warning option starting with 'no-', and will not error, yet it still
|
||||
# prints a message about the unrecognized option.
|
||||
check_c_compiler_flag("-Wunknown-warning-option" COMPILER_SUPPORTS_UNKNOWN_WARNING_OPTION_FLAG)
|
||||
endif()
|
||||
|
||||
set(
|
||||
IGRAPH_WARNINGS_AS_ERRORS ON CACHE BOOL
|
||||
"Treat warnings as errors with GCC-like compilers"
|
||||
)
|
||||
|
||||
option(FORCE_COLORED_OUTPUT "Always produce ANSI-colored output (GNU/Clang only)." FALSE)
|
||||
if(FORCE_COLORED_OUTPUT)
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
add_compile_options(-fdiagnostics-color=always)
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
add_compile_options(-fcolor-diagnostics)
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
|
||||
add_compile_options(-fcolor-diagnostics)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
macro(use_all_warnings TARGET_NAME)
|
||||
if(MSVC)
|
||||
target_compile_options(${TARGET_NAME} PRIVATE
|
||||
/W4 # enable most warnings, then disable:
|
||||
/wd4244 # 'conversion' conversion from 'type1' to 'type2', possible loss of data
|
||||
/wd4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data
|
||||
/wd4996 # deprecated functions, e.g. 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead.
|
||||
/wd4456 # declaration of 'identifier' hides previous local declaration
|
||||
/wd4800 # forcing value to 'true' or 'false' (performance warning)
|
||||
/wd4204 # nonstandard extension used: non-constant aggregate initializer
|
||||
/wd4701 # potentially uninitialized local variable
|
||||
/wd4221 # nonstandard extension used: '...': cannot be initialized using address of automatic variable '...'
|
||||
/wd4127 # conditional expression is constant
|
||||
/wd4702 # unreachable code
|
||||
)
|
||||
else()
|
||||
# Notes:
|
||||
# GCC does not complain when encountering an unsupported "no"-prefixed warning option such as -Wno-foo.
|
||||
# Clang does complain, but these complaints can be silenced with -Wno-unknown-warning-option.
|
||||
# Therefore it is generally safe to use -Wno-... options that are only supported by recent GCC/Clang.
|
||||
target_compile_options(${TARGET_NAME} PRIVATE
|
||||
# GCC-style compilers:
|
||||
$<$<C_COMPILER_ID:GCC,Clang,AppleClang,Intel,IntelLLVM>:
|
||||
$<$<BOOL:${IGRAPH_WARNINGS_AS_ERRORS}>:-Werror>
|
||||
-Wall -Wextra -pedantic
|
||||
-Wstrict-prototypes
|
||||
-Wno-unused-function -Wno-unused-parameter -Wno-unused-but-set-variable -Wno-sign-compare -Wno-constant-logical-operand
|
||||
>
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_UNKNOWN_WARNING_OPTION_FLAG}>:-Wno-unknown-warning-option>
|
||||
# Intel compiler:
|
||||
$<$<C_COMPILER_ID:Intel>:
|
||||
# disable #279: controlling expression is constant; affecting assert(condition && "message")
|
||||
# disable #592: variable "var" is used before its value is set; affecting IGRAPH_UNUSED
|
||||
# disable #10148: warning option not supported, as a replacement for -Wno-unknown-warning-option
|
||||
-wd279 -wd592 -diag-disable=remark -diag-disable=10148
|
||||
>
|
||||
# Intel LLVM:
|
||||
$<$<C_COMPILER_ID:IntelLLVM>:
|
||||
-fp-model=precise # The default 'fast' mode is not compatible with igraph's extensive use of NaN/Inf
|
||||
>
|
||||
)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Helper function to add preprocesor definition of IGRAPH_FILE_BASENAME
|
||||
# to pass the filename without directory path for debugging use.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# define_file_basename_for_sources(my_target)
|
||||
#
|
||||
# Will add -DIGRAPH_FILE_BASENAME="filename" for each source file depended
|
||||
# on by my_target, where filename is the name of the file.
|
||||
#
|
||||
# Source: https://stackoverflow.com/a/27990434/156771
|
||||
function(define_file_basename_for_sources targetname)
|
||||
get_target_property(source_files "${targetname}" SOURCES)
|
||||
get_target_property(source_dir "${targetname}" SOURCE_DIR)
|
||||
foreach(sourcefile ${source_files})
|
||||
# Turn relative paths into absolute
|
||||
get_filename_component(source_full_path "${sourcefile}" ABSOLUTE BASE_DIR "${source_dir}")
|
||||
|
||||
# Figure out whether the relative path from the source or the build folder
|
||||
# is shorter
|
||||
file(RELATIVE_PATH source_rel_path "${PROJECT_SOURCE_DIR}" "${source_full_path}")
|
||||
file(RELATIVE_PATH binary_rel_path "${PROJECT_BINARY_DIR}" "${source_full_path}")
|
||||
string(LENGTH "${source_rel_path}" source_rel_path_length)
|
||||
string(LENGTH "${binary_rel_path}" binary_rel_path_length)
|
||||
if(binary_rel_path_length LESS source_rel_path_length)
|
||||
set(basename "${binary_rel_path}")
|
||||
else()
|
||||
set(basename "${source_rel_path}")
|
||||
endif()
|
||||
|
||||
# Add the IGRAPH_FILE_BASENAME=filename compile definition to the source file
|
||||
set_property(
|
||||
SOURCE "${sourcefile}" APPEND
|
||||
PROPERTY COMPILE_DEFINITIONS "IGRAPH_FILE_BASENAME=\"${basename}\""
|
||||
)
|
||||
endforeach()
|
||||
endfunction()
|
||||
@@ -0,0 +1,87 @@
|
||||
# Custom CPack install script that allows us to whitelist files to be copied
|
||||
# to the tarball from the root directory, instead of copying the entire root
|
||||
# directory recursively
|
||||
|
||||
if(CPACK_SOURCE_INSTALLED_DIRECTORIES)
|
||||
# Make sure that the parser sources are built
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
--build "${CPACK_PACKAGE_DIRECTORY}"
|
||||
--target parsersources
|
||||
RESULT_VARIABLE EXIT_CODE
|
||||
)
|
||||
if(NOT EXIT_CODE EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to build the parser sources.")
|
||||
endif()
|
||||
|
||||
# Generate a version file in the build folder if we don't have one in the
|
||||
# source folder
|
||||
if(EXISTS "${SOURCE_DIR}/IGRAPH_VERSION")
|
||||
set(IGRAPH_VERSION_FILE "${SOURCE_DIR}/IGRAPH_VERSION")
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
--build "${CPACK_PACKAGE_DIRECTORY}"
|
||||
--target versionfile
|
||||
RESULT_VARIABLE EXIT_CODE
|
||||
)
|
||||
if(NOT EXIT_CODE EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to determine the version number of igraph that is being packaged.")
|
||||
endif()
|
||||
set(IGRAPH_VERSION_FILE "${CPACK_PACKAGE_DIRECTORY}/IGRAPH_VERSION")
|
||||
endif()
|
||||
|
||||
list(GET CPACK_BUILD_SOURCE_DIRS 0 SOURCE_DIR)
|
||||
# This branch runs only if CPack generates the source package, and within
|
||||
# this branch, CMAKE_CURRENT_BINARY_DIR refers to the root of the staging
|
||||
# area where the tarball is assembled
|
||||
file(GLOB FILES_TO_COPY "${SOURCE_DIR}/*.md")
|
||||
file(
|
||||
INSTALL ${FILES_TO_COPY}
|
||||
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
file(
|
||||
INSTALL
|
||||
"${SOURCE_DIR}/AUTHORS"
|
||||
"${SOURCE_DIR}/CMakeLists.txt"
|
||||
"${SOURCE_DIR}/CONTRIBUTORS.txt"
|
||||
"${SOURCE_DIR}/COPYING"
|
||||
"${SOURCE_DIR}/ChangeLog"
|
||||
"${SOURCE_DIR}/INSTALL"
|
||||
"${SOURCE_DIR}/NEWS"
|
||||
"${SOURCE_DIR}/ONEWS"
|
||||
"${SOURCE_DIR}/igraph.pc.in"
|
||||
"${IGRAPH_VERSION_FILE}"
|
||||
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
file(
|
||||
INSTALL
|
||||
"${SOURCE_DIR}/src/config.h.in"
|
||||
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/src"
|
||||
)
|
||||
file(
|
||||
INSTALL
|
||||
"${CPACK_PACKAGE_DIRECTORY}/src/io/parsers"
|
||||
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/src/io"
|
||||
)
|
||||
file(
|
||||
INSTALL
|
||||
"${SOURCE_DIR}/tools/removeexamples.py"
|
||||
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/tools"
|
||||
)
|
||||
file(
|
||||
INSTALL
|
||||
"${SOURCE_DIR}/tools/strip_licenses_from_examples.py"
|
||||
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/tools"
|
||||
)
|
||||
file(
|
||||
INSTALL
|
||||
"${CPACK_PACKAGE_DIRECTORY}/doc/html"
|
||||
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc"
|
||||
)
|
||||
file(
|
||||
INSTALL
|
||||
"${CPACK_PACKAGE_DIRECTORY}/doc/igraph-docs.info"
|
||||
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc"
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1,8 @@
|
||||
# CMake script that generates the IGRAPH_VERSION file in the build folder
|
||||
#
|
||||
# Script variables that need to be set before calling it via "cmake -P":
|
||||
#
|
||||
# * IGRAPH_VERSION should be set to the exact version number
|
||||
# * VERSION_FILE_PATH should be set to the name of the version file
|
||||
|
||||
FILE(WRITE "${VERSION_FILE_PATH}" "${IGRAPH_VERSION}")
|
||||
@@ -0,0 +1,7 @@
|
||||
set(
|
||||
IGRAPH_VERIFY_FINALLY_STACK
|
||||
""
|
||||
CACHE
|
||||
BOOL
|
||||
"Verify that the 'finally' stack is cleaned up properly. Useful only in debugging; do not use in production."
|
||||
)
|
||||
@@ -0,0 +1,171 @@
|
||||
include(helpers)
|
||||
|
||||
include(CheckSymbolExists)
|
||||
include(CMakePushCheckState)
|
||||
|
||||
# The threading library is not needed for igraph itself, but might be needed
|
||||
# for tests
|
||||
include(FindThreads)
|
||||
|
||||
macro(find_dependencies)
|
||||
# Declare the list of dependencies that _may_ be vendored
|
||||
set(VENDORABLE_DEPENDENCIES BLAS GLPK LAPACK ARPACK GMP PLFIT INFOMAP)
|
||||
|
||||
# Declare optional dependencies associated with IGRAPH_..._SUPPORT flags
|
||||
# Note that GLPK and INFOMAP are both vendorable and optional
|
||||
set(OPTIONAL_DEPENDENCIES GLPK OpenMP INFOMAP)
|
||||
|
||||
# Declare configuration options for dependencies
|
||||
tristate(IGRAPH_USE_INTERNAL_GMP "Compile igraph with internal Mini-GMP" AUTO)
|
||||
tristate(IGRAPH_USE_INTERNAL_ARPACK "Compile igraph with internal ARPACK" AUTO)
|
||||
tristate(IGRAPH_USE_INTERNAL_BLAS "Compile igraph with internal BLAS" AUTO)
|
||||
tristate(IGRAPH_USE_INTERNAL_GLPK "Compile igraph with internal GLPK" AUTO)
|
||||
tristate(IGRAPH_USE_INTERNAL_LAPACK "Compile igraph with internal LAPACK" AUTO)
|
||||
tristate(IGRAPH_USE_INTERNAL_PLFIT "Compile igraph with internal plfit" AUTO)
|
||||
|
||||
# Infomap currently does not support being built as an external library, so will
|
||||
# only be supported through the internal vendored build
|
||||
set(IGRAPH_USE_INTERNAL_INFOMAP ON)
|
||||
|
||||
# Declare dependencies
|
||||
set(REQUIRED_DEPENDENCIES "")
|
||||
set(OPTIONAL_DEPENDENCIES FLEX BISON OpenMP)
|
||||
set(VENDORED_DEPENDENCIES "")
|
||||
|
||||
# Declare minimum supported version for some dependencies
|
||||
set(GLPK_VERSION_MIN "4.57") # 4.57 is the first version providing glp_on_error()
|
||||
set(LIBXML2_VERSION_MIN "2.7.4") # 2.7.4 is the first version providing xmlStructuredErrorContext
|
||||
set(PLFIT_VERSION_MIN "0.9.3")
|
||||
|
||||
# Extend dependencies depending on whether we will be using the vendored
|
||||
# copies or not
|
||||
foreach(DEPENDENCY ${VENDORABLE_DEPENDENCIES})
|
||||
string(TOUPPER "${DEPENDENCY}" LIBNAME_UPPER)
|
||||
|
||||
if(IGRAPH_USE_INTERNAL_${LIBNAME_UPPER} STREQUAL "AUTO")
|
||||
find_package(${DEPENDENCY} ${${DEPENDENCY}_VERSION_MIN} QUIET)
|
||||
if(${LIBNAME_UPPER}_FOUND)
|
||||
set(IGRAPH_USE_INTERNAL_${LIBNAME_UPPER} OFF)
|
||||
else()
|
||||
set(IGRAPH_USE_INTERNAL_${LIBNAME_UPPER} ON)
|
||||
endif()
|
||||
endif()
|
||||
if(IGRAPH_USE_INTERNAL_${LIBNAME_UPPER})
|
||||
list(APPEND VENDORED_DEPENDENCIES ${DEPENDENCY})
|
||||
else()
|
||||
list(APPEND REQUIRED_DEPENDENCIES ${DEPENDENCY})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# For optional dependencies, figure out whether we should attempt to
|
||||
# link to them based on the value of the IGRAPH_..._SUPPORT option
|
||||
foreach(DEPENDENCY ${OPTIONAL_DEPENDENCIES})
|
||||
string(TOUPPER "${DEPENDENCY}" LIBNAME_UPPER)
|
||||
|
||||
if(IGRAPH_${LIBNAME_UPPER}_SUPPORT STREQUAL "AUTO")
|
||||
find_package(${DEPENDENCY} ${${DEPENDENCY}_VERSION_MIN} QUIET)
|
||||
if(${LIBNAME_UPPER}_FOUND)
|
||||
set(IGRAPH_${LIBNAME_UPPER}_SUPPORT ON)
|
||||
else()
|
||||
set(IGRAPH_${LIBNAME_UPPER}_SUPPORT OFF)
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# GraphML support is treated separately because the library name is different
|
||||
if(IGRAPH_GRAPHML_SUPPORT STREQUAL "AUTO")
|
||||
find_package(LibXml2 ${LIBXML2_VERSION_MIN} QUIET)
|
||||
if(LibXml2_FOUND)
|
||||
set(IGRAPH_GRAPHML_SUPPORT ON)
|
||||
else()
|
||||
set(IGRAPH_GRAPHML_SUPPORT OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT IGRAPH_GLPK_SUPPORT)
|
||||
if(IGRAPH_USE_INTERNAL_GLPK)
|
||||
list(REMOVE_ITEM VENDORED_DEPENDENCIES GLPK)
|
||||
else()
|
||||
list(REMOVE_ITEM REQUIRED_DEPENDENCIES GLPK)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT IGRAPH_INFOMAP_SUPPORT)
|
||||
list(REMOVE_ITEM VENDORED_DEPENDENCIES INFOMAP)
|
||||
endif()
|
||||
|
||||
if(IGRAPH_GRAPHML_SUPPORT)
|
||||
list(APPEND REQUIRED_DEPENDENCIES LibXml2)
|
||||
endif()
|
||||
|
||||
# Find dependencies
|
||||
foreach(DEPENDENCY ${REQUIRED_DEPENDENCIES} ${OPTIONAL_DEPENDENCIES})
|
||||
list(FIND REQUIRED_DEPENDENCIES "${DEPENDENCY}" INDEX)
|
||||
set(NEED_THIS_DEPENDENCY NO)
|
||||
|
||||
if(INDEX GREATER_EQUAL 0)
|
||||
# This is a required dependency, search for it unconditionally. Do
|
||||
# not use REQUIRED; we will report errors in a single batch at the end
|
||||
# of the configuration process
|
||||
set(NEED_THIS_DEPENDENCY YES)
|
||||
else()
|
||||
# This is an optional dependency, search for it only if the user did not
|
||||
# turn it off explicitly
|
||||
string(TOUPPER "${DEPENDENCY}" LIBNAME_UPPER)
|
||||
if(NOT DEFINED IGRAPH_${LIBNAME_UPPER}_SUPPORT)
|
||||
set(NEED_THIS_DEPENDENCY YES)
|
||||
elseif(IGRAPH_${LIBNAME_UPPER}_SUPPORT)
|
||||
set(NEED_THIS_DEPENDENCY YES)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NEED_THIS_DEPENDENCY AND NOT DEFINED ${DEPENDENCY}_FOUND)
|
||||
find_package(${DEPENDENCY} ${${DEPENDENCY}_VERSION_MIN})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Override libraries of vendored dependencies even if they were somehow
|
||||
# detected above
|
||||
foreach(DEPENDENCY ${VENDORED_DEPENDENCIES})
|
||||
string(TOUPPER "${DEPENDENCY}" LIBNAME_UPPER)
|
||||
string(TOLOWER "${DEPENDENCY}" LIBNAME_LOWER)
|
||||
if(IGRAPH_USE_INTERNAL_${LIBNAME_UPPER})
|
||||
set(${LIBNAME_UPPER}_LIBRARIES "")
|
||||
set(${LIBNAME_UPPER}_FOUND 1)
|
||||
set(${LIBNAME_UPPER}_IS_VENDORED 1)
|
||||
set(INTERNAL_${LIBNAME_UPPER} 1)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Export some aliases that will be used in config.h
|
||||
set(HAVE_GLPK ${GLPK_FOUND})
|
||||
set(HAVE_INFOMAP ${INFOMAP_FOUND})
|
||||
set(HAVE_GMP ${GMP_FOUND})
|
||||
set(HAVE_LIBXML ${LIBXML2_FOUND})
|
||||
|
||||
# Check whether we need to link to the math library
|
||||
if(NOT DEFINED CACHE{NEED_LINKING_AGAINST_LIBM})
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_QUIET ON)
|
||||
check_symbol_exists(sinh "math.h" SINH_FUNCTION_EXISTS)
|
||||
if(NOT SINH_FUNCTION_EXISTS)
|
||||
unset(SINH_FUNCTION_EXISTS CACHE)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES m)
|
||||
check_symbol_exists(sinh "math.h" SINH_FUNCTION_EXISTS)
|
||||
if(SINH_FUNCTION_EXISTS)
|
||||
set(NEED_LINKING_AGAINST_LIBM True CACHE BOOL "" FORCE)
|
||||
else()
|
||||
message(FATAL_ERROR "Failed to figure out how to link to the math library on this platform")
|
||||
endif()
|
||||
endif()
|
||||
unset(SINH_FUNCTION_EXISTS CACHE)
|
||||
cmake_pop_check_state()
|
||||
endif()
|
||||
|
||||
if(NEED_LINKING_AGAINST_LIBM)
|
||||
find_library(MATH_LIBRARY m)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(MATH_LIBRARY)
|
||||
mark_as_advanced(NEED_LINKING_AGAINST_LIBM)
|
||||
endmacro()
|
||||
@@ -0,0 +1,26 @@
|
||||
include(helpers)
|
||||
|
||||
include(tls)
|
||||
include(lto)
|
||||
|
||||
option(IGRAPH_GLPK_SUPPORT "Compile igraph with GLPK support" ON)
|
||||
option(IGRAPH_INFOMAP_SUPPORT "Compile igraph with Infomap support" ON)
|
||||
tristate(IGRAPH_GRAPHML_SUPPORT "Compile igraph with GraphML support" AUTO)
|
||||
tristate(IGRAPH_OPENMP_SUPPORT "Use OpenMP for parallelization" AUTO)
|
||||
|
||||
set(IGRAPH_INTEGER_SIZE AUTO CACHE STRING "Set size of igraph integers")
|
||||
set_property(CACHE IGRAPH_INTEGER_SIZE PROPERTY STRINGS AUTO 32 64)
|
||||
|
||||
if(IGRAPH_INTEGER_SIZE STREQUAL AUTO)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(IGRAPH_INTEGER_SIZE 64)
|
||||
else()
|
||||
set(IGRAPH_INTEGER_SIZE 32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(FLEX_KEEP_LINE_NUMBERS "Keep references to the original line numbers in generated Flex/Bison parser files" OFF)
|
||||
mark_as_advanced(FLEX_KEEP_LINE_NUMBERS)
|
||||
|
||||
option(BUILD_FUZZING "Build fuzz targets and enable fuzzer instrumentation" OFF)
|
||||
mark_as_advanced(BUILD_FUZZING)
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
function(add_fuzzer NAME)
|
||||
set(TARGET_NAME fuzzer_${NAME})
|
||||
|
||||
add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL ${PROJECT_SOURCE_DIR}/fuzzing/${NAME}.cpp)
|
||||
|
||||
add_dependencies(build_fuzzers ${TARGET_NAME})
|
||||
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE igraph)
|
||||
|
||||
# The -fsanitize=fuzzer-no-link is already added by the top-level CMakeLists.txt
|
||||
# for general fuzzer instrumentation. Additionally, we need -fsanitize=fuzzer
|
||||
# for the fuzz targets, which do not contain a main() function, to link in the
|
||||
# fuzz driver. See https://llvm.org/docs/LibFuzzer.html
|
||||
target_link_options(${TARGET_NAME} PRIVATE -fsanitize=fuzzer)
|
||||
endfunction()
|
||||
@@ -0,0 +1,46 @@
|
||||
# Creates a ctags-compatible tags file from a set of XML files by extracting
|
||||
# the IDs found in the XML files.
|
||||
#
|
||||
# Parameters of the script:
|
||||
#
|
||||
# - INPUT_FILES: list of input files to process, with absolute pathnames
|
||||
# - OUTPUT_FILE: the output file to write the tags into
|
||||
|
||||
string(REPLACE " " ";" INPUT_FILE_LIST "${INPUT_FILES}")
|
||||
|
||||
set(EXTRACTED_IDS "")
|
||||
|
||||
foreach(INPUT_FILE ${INPUT_FILE_LIST})
|
||||
file(READ "${INPUT_FILE}" CONTENTS)
|
||||
|
||||
# Replace newlines with semicolons. This is a hack and we should escape
|
||||
# semicolons first if we wanted to do this properly; however, here we are
|
||||
# only interested in XML IDs and they don't have semicolons
|
||||
string(REPLACE "\n" ";" LINES "${CONTENTS}")
|
||||
foreach(_line ${LINES})
|
||||
string(REGEX MATCHALL "id=\"[^-\"]*\"" MATCH_RESULT "${_line}")
|
||||
if(MATCH_RESULT)
|
||||
foreach(MATCH ${MATCH_RESULT})
|
||||
string(REGEX REPLACE "id=\"(.*)\"" "\\1" EXTRACTED_ID "${MATCH}")
|
||||
list(APPEND EXTRACTED_IDS "${EXTRACTED_ID}")
|
||||
endforeach()
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
list(SORT EXTRACTED_IDS)
|
||||
string(REPLACE ";" "\t\t\n" TAGS_OUTPUT "${EXTRACTED_IDS}")
|
||||
string(APPEND TAGS_OUTPUT "\t\t\n")
|
||||
string(SHA1 TAGS_OUTPUT_HASH "${TAGS_OUTPUT}")
|
||||
|
||||
# Update the output file only if it changed; this prevents CMake from calling
|
||||
# source-highlight if there is no point in rebuilding the highlighted
|
||||
# source files
|
||||
if(EXISTS "${OUTPUT_FILE}")
|
||||
file(SHA1 "${OUTPUT_FILE}" OUTPUT_FILE_HASH)
|
||||
if(NOT "${OUTPUT_FILE_HASH}" STREQUAL "${TAGS_OUTPUT_HASH}")
|
||||
file(WRITE "${OUTPUT_FILE}" "${TAGS_OUTPUT}")
|
||||
endif()
|
||||
else()
|
||||
file(WRITE "${OUTPUT_FILE}" "${TAGS_OUTPUT}")
|
||||
endif()
|
||||
@@ -0,0 +1,6 @@
|
||||
macro(tristate OPTION_NAME DESCRIPTION DEFAULT_VALUE)
|
||||
set(${OPTION_NAME} "${DEFAULT_VALUE}" CACHE STRING "${DESCRIPTION}")
|
||||
set_property(CACHE ${OPTION_NAME} PROPERTY STRINGS AUTO ON OFF)
|
||||
endmacro()
|
||||
|
||||
include(PadString)
|
||||
@@ -0,0 +1,54 @@
|
||||
include(CheckCSourceRuns)
|
||||
|
||||
cmake_push_check_state(RESET)
|
||||
|
||||
# Check whether IEEE754 doubles are laid out in little-endian order. We do this
|
||||
# only when not cross-compiling; during cross-compilation, the host architecture
|
||||
# might have different endianness conventions than the target, and we are running
|
||||
# the test on the host here
|
||||
if(CMAKE_CROSSCOMPILING AND NOT CMAKE_CROSSCOMPILING_EMULATOR)
|
||||
# If we are cross-compiling and we have no emulator, let's just assume that
|
||||
# IEEE754 doubles use the same endianness as uint64_t
|
||||
set(IEEE754_DOUBLE_ENDIANNESS_MATCHES YES)
|
||||
message(WARNING "\
|
||||
igraph is being cross-compiled, therefore we cannot validate whether the \
|
||||
endianness of IEEE754 doubles is the same as the endianness of uint64_t. \
|
||||
Most likely it is, unless you are compiling for some esoteric platform, \
|
||||
in which case you need make sure that this is the case on your own.\
|
||||
")
|
||||
else()
|
||||
if(NOT DEFINED CACHE{IEEE754_DOUBLE_ENDIANNESS_MATCHES})
|
||||
try_run(
|
||||
IEEE754_DOUBLE_ENDIANNESS_TEST_EXIT_CODE
|
||||
IEEE754_DOUBLE_ENDIANNESS_TEST_COMPILES
|
||||
${CMAKE_BINARY_DIR}
|
||||
${PROJECT_SOURCE_DIR}/etc/cmake/ieee754_endianness_check.c
|
||||
RUN_OUTPUT_VARIABLE IEEE754_DOUBLE_ENDIANNESS_TEST_RESULT
|
||||
)
|
||||
# Strip trailing newline, which is necessary on some platforms (such as node.js)
|
||||
# to complete printing the output.
|
||||
string(STRIP "${IEEE754_DOUBLE_ENDIANNESS_TEST_RESULT}" IEEE754_DOUBLE_ENDIANNESS_TEST_RESULT)
|
||||
if(IEEE754_DOUBLE_ENDIANNESS_TEST_EXIT_CODE EQUAL 0)
|
||||
if(IEEE754_DOUBLE_ENDIANNESS_TEST_RESULT STREQUAL "OK")
|
||||
set(TEST_RESULT YES)
|
||||
else()
|
||||
set(TEST_RESULT NO)
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "IEEE754 double endianness test terminated abnormally.")
|
||||
endif()
|
||||
|
||||
set(
|
||||
IEEE754_DOUBLE_ENDIANNESS_MATCHES ${TEST_RESULT} CACHE BOOL
|
||||
"Specifies whether the endianness of IEEE754 doubles is the same as the endianness of uint64_t."
|
||||
FORCE
|
||||
)
|
||||
mark_as_advanced(IEEE754_DOUBLE_ENDIANNESS_MATCHES)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
cmake_pop_check_state()
|
||||
|
||||
if(NOT IEEE754_DOUBLE_ENDIANNESS_MATCHES)
|
||||
message(FATAL_ERROR "igraph only supports platforms where IEEE754 doubles have the same endianness as uint64_t.")
|
||||
endif()
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Checks whether the endianness of IEEE754 doubles matches the endianness of
|
||||
* uint64_t on the target system. This is needed to ensure that the trick we
|
||||
* employ in igraph_rng_get_unif01() works. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
union {
|
||||
uint64_t as_uint64_t;
|
||||
double as_double;
|
||||
} value;
|
||||
|
||||
int main(void) {
|
||||
value.as_uint64_t = 4841376218035192321ULL;
|
||||
if (value.as_double == 4510218239279617.0) {
|
||||
/* endianness of uint64_t and double match */
|
||||
printf("OK\n");
|
||||
}
|
||||
/* We always return 0, even for a negative result, this is because we
|
||||
* need to tell on the CMake side whether a compiler misconfiguration
|
||||
* aborted our program, which can then be detected from a nonzero exit
|
||||
* code. */
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# igraph-config.cmake
|
||||
#
|
||||
# igraph CMake package
|
||||
#
|
||||
# The following variables are set:
|
||||
#
|
||||
# - IGRAPH_VERSION - The igraph version string.
|
||||
# - IGRAPH_INTEGER_SIZE - The integer size igraph was configured with (32 or 64).
|
||||
# - IGRAPH_GLPK_SUPPORT - Whether igraph was compiled with GLPK support.
|
||||
# - IGRAPH_GRAPHML_SUPPORT - Whether igraph was compiled with GraphML support.
|
||||
#
|
||||
|
||||
set(IGRAPH_VERSION "@PACKAGE_VERSION_BASE@")
|
||||
set(IGRAPH_INTEGER_SIZE @IGRAPH_INTEGER_SIZE@)
|
||||
set(IGRAPH_GLPK_SUPPORT @IGRAPH_GLPK_SUPPORT@)
|
||||
set(IGRAPH_GRAPHML_SUPPORT @IGRAPH_GRAPHML_SUPPORT@)
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/igraph-targets.cmake")
|
||||
|
||||
# Check whether C++ support is enabled; this is needed to ensure that programs
|
||||
# that are dependent on igraph will get linked with the C++ linker and not the
|
||||
# "plain" C linker
|
||||
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||
if("CXX" IN_LIST LANGUAGES)
|
||||
# This is okay
|
||||
else()
|
||||
message(FATAL_ERROR "Please enable C++ support in your project if you are linking to igraph.")
|
||||
endif()
|
||||
|
||||
# Turn on CMP0012 because the following if() conditionals will use "ON" and
|
||||
# "OFF" verbatim and they must be evaluated as booleans
|
||||
cmake_policy(PUSH)
|
||||
cmake_policy(SET CMP0012 NEW)
|
||||
if(@IGRAPH_OPENMP_SUPPORT@)
|
||||
find_package(OpenMP)
|
||||
endif()
|
||||
cmake_policy(POP)
|
||||
|
||||
check_required_components(igraph)
|
||||
@@ -0,0 +1,23 @@
|
||||
include(helpers)
|
||||
|
||||
tristate(IGRAPH_ENABLE_LTO "Enable link-time optimization" OFF)
|
||||
|
||||
include(CheckIPOSupported)
|
||||
|
||||
if(IGRAPH_ENABLE_LTO)
|
||||
# this matches both ON and AUTO
|
||||
check_ipo_supported(RESULT IPO_SUPPORTED OUTPUT IPO_NOT_SUPPORTED_REASON)
|
||||
if(IGRAPH_ENABLE_LTO STREQUAL "AUTO")
|
||||
# autodetection
|
||||
set(IGRAPH_ENABLE_LTO ${IPO_SUPPORTED})
|
||||
if(IPO_SUPPORTED)
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
endif()
|
||||
elseif(IPO_SUPPORTED)
|
||||
# user wanted LTO and the compiler supports it
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
else()
|
||||
# user wanted LTO and the compiler does not support it
|
||||
message(FATAL_ERROR "Link-time optimization not supported on this compiler")
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,70 @@
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "igraph library")
|
||||
set(CPACK_PACKAGE_HOMEPAGE_URL "https://igraph.org")
|
||||
set(CPACK_PACKAGE_VENDOR "The igraph development team")
|
||||
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
|
||||
|
||||
if(TARGET html AND TARGET info)
|
||||
# Alias "dist" to "package_source"
|
||||
add_custom_target(dist
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
--build "${CMAKE_BINARY_DIR}"
|
||||
--target package_source
|
||||
VERBATIM
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
||||
# Add dependencies to "dist"
|
||||
add_dependencies(dist html info)
|
||||
else()
|
||||
add_custom_target(dist
|
||||
COMMAND "${CMAKE_COMMAND}" -E false
|
||||
COMMENT
|
||||
"Cannot build source tarball since the HTML or the Texinfo documentation was not built."
|
||||
VERBATIM
|
||||
USES_TERMINAL
|
||||
)
|
||||
endif()
|
||||
|
||||
#############################################################################
|
||||
## Configuration of the source package
|
||||
#############################################################################
|
||||
|
||||
# Set source package name and format
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "igraph-${PACKAGE_VERSION}")
|
||||
set(CPACK_SOURCE_GENERATOR "TGZ")
|
||||
|
||||
# Declare what to include in the source tarball. Unfortunately we can only
|
||||
# declare full directories here, not individual files.
|
||||
set(
|
||||
CPACK_SOURCE_INSTALLED_DIRECTORIES
|
||||
"${CMAKE_SOURCE_DIR}/doc;/doc"
|
||||
"${CMAKE_SOURCE_DIR}/etc/cmake;/etc/cmake"
|
||||
"${CMAKE_SOURCE_DIR}/examples;/examples"
|
||||
"${CMAKE_SOURCE_DIR}/include;/include"
|
||||
"${CMAKE_SOURCE_DIR}/interfaces;/interfaces"
|
||||
"${CMAKE_SOURCE_DIR}/msvc/include;/msvc/include"
|
||||
"${CMAKE_SOURCE_DIR}/src;/src"
|
||||
"${CMAKE_SOURCE_DIR}/tests;/tests"
|
||||
"${CMAKE_SOURCE_DIR}/vendor;/vendor"
|
||||
)
|
||||
|
||||
# CPack is pretty dumb as it can only copy full directories (sans the ignored
|
||||
# files) to the target tarball by default. In some cases it is easier to
|
||||
# whitelist files to be copied; we use CPACK_INSTALL_SCRIPT for that.
|
||||
set(CPACK_INSTALL_SCRIPT "${CMAKE_SOURCE_DIR}/etc/cmake/cpack_install_script.cmake")
|
||||
|
||||
# Ignore the build and all hidden folders
|
||||
set(
|
||||
CPACK_SOURCE_IGNORE_FILES
|
||||
"\\\\..*/"
|
||||
"\\\\.l$"
|
||||
"\\\\.y$"
|
||||
"${CMAKE_SOURCE_DIR}/build"
|
||||
)
|
||||
|
||||
#############################################################################
|
||||
## Now we can include CPack
|
||||
#############################################################################
|
||||
|
||||
include(CPack)
|
||||
@@ -0,0 +1,75 @@
|
||||
# Helper functions for generating a nicely formatted igraph.pc file from
|
||||
# igraph.pc.in
|
||||
|
||||
include(JoinPaths)
|
||||
include(CheckCXXSymbolExists)
|
||||
|
||||
# Converts the name of a library file (or framework on macOS) into an
|
||||
# appropriate linker flag (-lsomething or -framework something.framework).
|
||||
# Returns the input intact if its extension does not look like a shared or
|
||||
# static library extension.
|
||||
function(convert_library_file_to_flags output_variable input)
|
||||
get_filename_component(input_filename ${input} NAME_WE)
|
||||
get_filename_component(input_extension ${input} LAST_EXT)
|
||||
if(input_extension STREQUAL ${CMAKE_SHARED_LIBRARY_SUFFIX} OR input_extension STREQUAL ${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
string(REGEX REPLACE "^${CMAKE_SHARED_LIBRARY_PREFIX}" "" input_stripped ${input_filename})
|
||||
set("${output_variable}" "-l${input_stripped}" PARENT_SCOPE)
|
||||
elseif(APPLE AND input_extension STREQUAL ".framework")
|
||||
set("${output_variable}" "-framework ${input_filename}" PARENT_SCOPE)
|
||||
else()
|
||||
set("${output_variable}" "${input}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if(MATH_LIBRARY)
|
||||
set(PKGCONFIG_LIBS_PRIVATE "-lm")
|
||||
else()
|
||||
set(PKGCONFIG_LIBS_PRIVATE "")
|
||||
endif()
|
||||
set(PKGCONFIG_REQUIRES_PRIVATE "")
|
||||
|
||||
if(NOT MSVC)
|
||||
check_cxx_symbol_exists(_LIBCPP_VERSION "vector" USING_LIBCXX)
|
||||
check_cxx_symbol_exists(__GLIBCXX__ "vector" USING_LIBSTDCXX)
|
||||
if(USING_LIBCXX)
|
||||
set(PKGCONFIG_LIBS_PRIVATE "${PKGCONFIG_LIBS_PRIVATE} -lc++")
|
||||
elseif(USING_LIBSTDCXX)
|
||||
set(PKGCONFIG_LIBS_PRIVATE "${PKGCONFIG_LIBS_PRIVATE} -lstdc++")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(IGRAPH_GRAPHML_SUPPORT)
|
||||
set(PKGCONFIG_REQUIRES_PRIVATE "${PKGCONFIG_REQUIRES_PRIVATE} libxml-2.0")
|
||||
endif()
|
||||
if(NOT IGRAPH_USE_INTERNAL_GMP)
|
||||
set(PKGCONFIG_LIBS_PRIVATE "${PKGCONFIG_LIBS_PRIVATE} -lgmp")
|
||||
endif()
|
||||
if(NOT IGRAPH_USE_INTERNAL_BLAS)
|
||||
set(PKGCONFIG_LIBS_PRIVATE "${PKGCONFIG_LIBS_PRIVATE} -lblas")
|
||||
endif()
|
||||
if(IGRAPH_GLPK_SUPPORT AND NOT IGRAPH_USE_INTERNAL_GLPK)
|
||||
set(PKGCONFIG_LIBS_PRIVATE "${PKGCONFIG_LIBS_PRIVATE} -lglpk")
|
||||
endif()
|
||||
if(NOT IGRAPH_USE_INTERNAL_LAPACK)
|
||||
set(PKGCONFIG_LIBS_PRIVATE "${PKGCONFIG_LIBS_PRIVATE} -llapack")
|
||||
endif()
|
||||
if(NOT IGRAPH_USE_INTERNAL_ARPACK)
|
||||
set(PKGCONFIG_LIBS_PRIVATE "${PKGCONFIG_LIBS_PRIVATE} -larpack")
|
||||
endif()
|
||||
if(NOT IGRAPH_USE_INTERNAL_PLFIT)
|
||||
set(PKGCONFIG_LIBS_PRIVATE "${PKGCONFIG_LIBS_PRIVATE} -lplfit")
|
||||
endif()
|
||||
if(IGRAPH_OPENMP_SUPPORT AND OpenMP_FOUND)
|
||||
foreach(CURRENT_LIB ${OpenMP_C_LIB_NAMES})
|
||||
convert_library_file_to_flags(CURRENT_LIB "${OpenMP_${CURRENT_LIB}_LIBRARY}")
|
||||
set(PKGCONFIG_LIBS_PRIVATE "${PKGCONFIG_LIBS_PRIVATE} ${CURRENT_LIB}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
join_paths(PKGCONFIG_LIBDIR "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}")
|
||||
join_paths(PKGCONFIG_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
configure_file(
|
||||
${PROJECT_SOURCE_DIR}/igraph.pc.in
|
||||
${PROJECT_BINARY_DIR}/igraph.pc
|
||||
@ONLY
|
||||
)
|
||||
@@ -0,0 +1,73 @@
|
||||
# Runs a legacy autotools-based test with a file containing the expected output
|
||||
#
|
||||
# Parameters of the script:
|
||||
#
|
||||
# - TEST_EXECUTABLE: full path of the compiled test executable
|
||||
# - EXPECTED_OUTPUT_FILE: full path of the file containing the expected output
|
||||
# - OBSERVED_OUTPUT_FILE: full path of the file where the observed output
|
||||
# can be written
|
||||
# - DIFF_FILE: full path of the file where the differences between the expectd
|
||||
# and the observed output should be written
|
||||
# - DIFF_TOOL: full path to a "diff" tool on the system of the user, if present
|
||||
# - FC_TOOL: full path to a "fc" tool on the system of the user, if present
|
||||
# - IGRAPH_VERSION: version string of igraph that should be replaced in
|
||||
# expected outputs
|
||||
|
||||
get_filename_component(WORK_DIR ${EXPECTED_OUTPUT_FILE} DIRECTORY)
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CROSSCOMPILING_EMULATOR} ${TEST_EXECUTABLE}
|
||||
WORKING_DIRECTORY ${WORK_DIR}
|
||||
RESULT_VARIABLE ERROR_CODE
|
||||
OUTPUT_VARIABLE OBSERVED_OUTPUT
|
||||
)
|
||||
|
||||
if(ERROR_CODE EQUAL 77)
|
||||
message(STATUS "Test skipped")
|
||||
elseif(ERROR_CODE)
|
||||
set(MESSAGE "Test exited abnormally with error: ${ERROR_CODE}")
|
||||
file(WRITE ${OBSERVED_OUTPUT_FILE} "${MESSAGE}\n=========================================\n${OBSERVED_OUTPUT}")
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -E cat "${OBSERVED_OUTPUT_FILE}")
|
||||
file(REMOVE ${DIFF_FILE})
|
||||
message(FATAL_ERROR "Exiting test.")
|
||||
else()
|
||||
string(REPLACE ${IGRAPH_VERSION} "\@VERSION\@" OBSERVED_OUTPUT "${OBSERVED_OUTPUT}")
|
||||
file(WRITE ${OBSERVED_OUTPUT_FILE} "${OBSERVED_OUTPUT}")
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E compare_files --ignore-eol
|
||||
${EXPECTED_OUTPUT_FILE} ${OBSERVED_OUTPUT_FILE}
|
||||
RESULT_VARIABLE ARE_DIFFERENT
|
||||
)
|
||||
|
||||
if(ARE_DIFFERENT)
|
||||
if(DIFF_TOOL)
|
||||
execute_process(
|
||||
COMMAND ${DIFF_TOOL} -u ${EXPECTED_OUTPUT_FILE} ${OBSERVED_OUTPUT_FILE}
|
||||
OUTPUT_FILE ${DIFF_FILE}
|
||||
)
|
||||
elseif(FC_TOOL)
|
||||
file(TO_NATIVE_PATH "${EXPECTED_OUTPUT_FILE}" REAL_EXPECTED_OUTPUT_FILE)
|
||||
file(TO_NATIVE_PATH "${OBSERVED_OUTPUT_FILE}" REAL_OBSERVED_OUTPUT_FILE)
|
||||
execute_process(
|
||||
COMMAND ${FC_TOOL} /A ${REAL_EXPECTED_OUTPUT_FILE} ${REAL_OBSERVED_OUTPUT_FILE}
|
||||
OUTPUT_FILE ${DIFF_FILE}
|
||||
)
|
||||
endif()
|
||||
|
||||
message(STATUS "Test case output differs from the expected output")
|
||||
if(EXISTS ${DIFF_FILE})
|
||||
message(STATUS "See diff below:")
|
||||
message(STATUS "-------------------------------------------------------")
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -E cat "${DIFF_FILE}")
|
||||
message(STATUS "-------------------------------------------------------")
|
||||
else()
|
||||
message(STATUS "Diff omitted; no diff tool was installed.")
|
||||
endif()
|
||||
message(FATAL_ERROR "Exiting test.")
|
||||
else()
|
||||
file(REMOVE ${DIFF_FILE})
|
||||
endif()
|
||||
|
||||
file(REMOVE ${OBSERVED_OUTPUT_FILE})
|
||||
endif()
|
||||
@@ -0,0 +1,18 @@
|
||||
include(CheckCXXSourceCompiles)
|
||||
|
||||
# Check whether the compiler supports the __builtin_add_overflow() and __builtin_mul_overflow()
|
||||
# builtins. These are present in recent GCC-compatible compilers.
|
||||
cmake_push_check_state(RESET)
|
||||
|
||||
check_cxx_source_compiles("
|
||||
int main(void) {
|
||||
long long a=1, b=2, c;
|
||||
__builtin_add_overflow(a, b, &c);
|
||||
__builtin_mul_overflow(a, b, &c);
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
HAVE_BUILTIN_OVERFLOW
|
||||
)
|
||||
|
||||
cmake_pop_check_state()
|
||||
@@ -0,0 +1,88 @@
|
||||
#
|
||||
# Copyright (C) 2018 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.
|
||||
|
||||
set(
|
||||
USE_SANITIZER
|
||||
""
|
||||
CACHE
|
||||
STRING
|
||||
"Compile with a sanitizer. Options are: Address, Memory, MemoryWithOrigins, Undefined, Thread, Leak, 'Address;Undefined'"
|
||||
)
|
||||
|
||||
function(append value)
|
||||
foreach(variable ${ARGN})
|
||||
set(${variable} "${${variable}} ${value}" PARENT_SCOPE)
|
||||
endforeach(variable)
|
||||
endfunction()
|
||||
|
||||
if(USE_SANITIZER)
|
||||
|
||||
if(UNIX)
|
||||
|
||||
append("-fno-omit-frame-pointer" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
|
||||
if(uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
append("-Og" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
endif()
|
||||
|
||||
if(USE_SANITIZER MATCHES "([Aa]ddress);([Uu]ndefined)"
|
||||
OR USE_SANITIZER MATCHES "([Uu]ndefined);([Aa]ddress)")
|
||||
message(STATUS "Building with Address, Undefined sanitizers")
|
||||
append("-fsanitize=address,undefined" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
elseif("${USE_SANITIZER}" MATCHES "([Aa]ddress)")
|
||||
# Optional: -fno-optimize-sibling-calls -fsanitize-address-use-after-scope
|
||||
message(STATUS "Building with Address sanitizer")
|
||||
append("-fsanitize=address" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
elseif(USE_SANITIZER MATCHES "([Mm]emory([Ww]ith[Oo]rigins)?)")
|
||||
# Optional: -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2
|
||||
append("-fsanitize=memory" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
if(USE_SANITIZER MATCHES "([Mm]emory[Ww]ith[Oo]rigins)")
|
||||
message(STATUS "Building with MemoryWithOrigins sanitizer")
|
||||
append("-fsanitize-memory-track-origins" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
else()
|
||||
message(STATUS "Building with Memory sanitizer")
|
||||
endif()
|
||||
elseif(USE_SANITIZER MATCHES "([Uu]ndefined)")
|
||||
message(STATUS "Building with Undefined sanitizer")
|
||||
append("-fsanitize=undefined" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
if(EXISTS "${BLACKLIST_FILE}")
|
||||
append("-fsanitize-blacklist=${BLACKLIST_FILE}" CMAKE_C_FLAGS
|
||||
CMAKE_CXX_FLAGS)
|
||||
endif()
|
||||
elseif(USE_SANITIZER MATCHES "([Tt]hread)")
|
||||
message(STATUS "Building with Thread sanitizer")
|
||||
append("-fsanitize=thread" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
elseif(USE_SANITIZER MATCHES "([Ll]eak)")
|
||||
message(STATUS "Building with Leak sanitizer")
|
||||
append("-fsanitize=leak" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
else()
|
||||
message(
|
||||
FATAL_ERROR "Unsupported value of USE_SANITIZER: ${USE_SANITIZER}")
|
||||
endif()
|
||||
elseif(MSVC)
|
||||
if(USE_SANITIZER MATCHES "([Aa]ddress)")
|
||||
message(STATUS "Building with Address sanitizer")
|
||||
append("-fsanitize=address" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
else()
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"This sanitizer not yet supported in the MSVC environment: ${USE_SANITIZER}"
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "USE_SANITIZER is not supported on this platform.")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
@@ -0,0 +1,108 @@
|
||||
function(print_bool HEADING VAR)
|
||||
if(${VAR})
|
||||
set(LABEL "yes")
|
||||
else()
|
||||
set(LABEL "no")
|
||||
endif()
|
||||
print_str(${HEADING} ${LABEL})
|
||||
endfunction()
|
||||
|
||||
function(print_str HEADING LABEL)
|
||||
string(LENGTH "${HEADING}" HEADING_LENGTH)
|
||||
math(EXPR REMAINING_WIDTH "30 - ${HEADING_LENGTH}")
|
||||
|
||||
if("${LABEL}" STREQUAL "")
|
||||
pad_string(PADDED ${REMAINING_WIDTH} " " "${ARGN}")
|
||||
else()
|
||||
pad_string(PADDED ${REMAINING_WIDTH} " " "${LABEL}")
|
||||
endif()
|
||||
|
||||
message(STATUS "${HEADING}: ${PADDED}")
|
||||
endfunction()
|
||||
|
||||
#############################################################################
|
||||
|
||||
set(ALL_DEPENDENCIES ${REQUIRED_DEPENDENCIES} ${OPTIONAL_DEPENDENCIES} ${VENDORED_DEPENDENCIES})
|
||||
list(SORT ALL_DEPENDENCIES CASE INSENSITIVE)
|
||||
|
||||
message(STATUS " ")
|
||||
message(STATUS "-----[ Build configuration ]----")
|
||||
print_str("Version" "${PACKAGE_VERSION}")
|
||||
print_str("CMake build type" "${CMAKE_BUILD_TYPE}" "default")
|
||||
if(BUILD_SHARED_LIBS)
|
||||
message(STATUS "Library type: shared")
|
||||
else()
|
||||
message(STATUS "Library type: static")
|
||||
endif()
|
||||
if(${IGRAPH_INTEGER_SIZE} STREQUAL "AUTO")
|
||||
print_str("igraph_int_t size" "auto")
|
||||
elseif(${IGRAPH_INTEGER_SIZE} STREQUAL 64)
|
||||
print_str("igraph_int_t size" "64 bits")
|
||||
elseif(${IGRAPH_INTEGER_SIZE} STREQUAL 32)
|
||||
print_str("igraph_int_t size" "32 bits")
|
||||
else()
|
||||
print_str("igraph_int_t size" "INVALID")
|
||||
endif()
|
||||
if(USE_CCACHE)
|
||||
if(CCACHE_PROGRAM)
|
||||
message(STATUS "Compiler cache: ccache")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Compiler cache: disabled")
|
||||
endif()
|
||||
|
||||
message(STATUS " ")
|
||||
message(STATUS "----------[ Features ]----------")
|
||||
print_bool("GLPK for optimization" IGRAPH_GLPK_SUPPORT)
|
||||
print_bool("Infomap community detection" IGRAPH_INFOMAP_SUPPORT)
|
||||
print_bool("Reading GraphML files" IGRAPH_GRAPHML_SUPPORT)
|
||||
print_bool("Thread-local storage" IGRAPH_ENABLE_TLS)
|
||||
print_bool("Link-time optimization" IGRAPH_ENABLE_LTO)
|
||||
message(STATUS " ")
|
||||
|
||||
message(STATUS "--------[ Dependencies ]--------")
|
||||
foreach(DEPENDENCY ${ALL_DEPENDENCIES})
|
||||
list(FIND VENDORED_DEPENDENCIES "${DEPENDENCY}" INDEX)
|
||||
if(INDEX EQUAL -1)
|
||||
print_bool("${DEPENDENCY}" ${DEPENDENCY}_FOUND)
|
||||
# This is a hack to skip printing Infomap, until
|
||||
# support for linking to an external version is added
|
||||
elseif(NOT "${DEPENDENCY}" STREQUAL "INFOMAP")
|
||||
print_str("${DEPENDENCY}" "vendored")
|
||||
endif()
|
||||
endforeach()
|
||||
message(STATUS " ")
|
||||
|
||||
message(STATUS "-----------[ Testing ]----------")
|
||||
if(DIFF_TOOL)
|
||||
print_str("Diff tool" "diff")
|
||||
elseif(FC_TOOL)
|
||||
print_str("Diff tool" "fc")
|
||||
else()
|
||||
print_str("Diff tool" "not found")
|
||||
endif()
|
||||
print_str("Sanitizers" "${USE_SANITIZER}" "none")
|
||||
print_bool("Code coverage" IGRAPH_ENABLE_CODE_COVERAGE)
|
||||
print_bool("Verify 'finally' stack" IGRAPH_VERIFY_FINALLY_STACK)
|
||||
message(STATUS " ")
|
||||
|
||||
message(STATUS "--------[ Documentation ]-------")
|
||||
print_bool("HTML" HTML_DOC_BUILD_SUPPORTED)
|
||||
print_bool("PDF" PDF_DOC_BUILD_SUPPORTED)
|
||||
print_bool("INFO" INFO_DOC_BUILD_SUPPORTED)
|
||||
message(STATUS " ")
|
||||
|
||||
set(MISSING_DEPENDENCIES)
|
||||
foreach(DEPENDENCY ${REQUIRED_DEPENDENCIES})
|
||||
if(NOT ${DEPENDENCY}_FOUND)
|
||||
list(APPEND MISSING_DEPENDENCIES ${DEPENDENCY})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(MISSING_DEPENDENCIES)
|
||||
list(JOIN MISSING_DEPENDENCIES ", " GLUED)
|
||||
message(FATAL_ERROR "The following dependencies are missing: ${GLUED}")
|
||||
else()
|
||||
message(STATUS "igraph configured successfully.")
|
||||
message(STATUS " ")
|
||||
endif()
|
||||
@@ -0,0 +1,120 @@
|
||||
include(CMakeParseArguments)
|
||||
|
||||
find_program(DIFF_TOOL diff)
|
||||
if(NOT DIFF_TOOL)
|
||||
find_program(FC_TOOL fc)
|
||||
endif()
|
||||
|
||||
function(add_legacy_test FOLDER NAME NAMESPACE)
|
||||
set(TARGET_NAME ${NAMESPACE}_${NAME})
|
||||
set(TEST_NAME "${NAMESPACE}::${NAME}")
|
||||
|
||||
add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL ${PROJECT_SOURCE_DIR}/${FOLDER}/${NAME}.c)
|
||||
use_all_warnings(${TARGET_NAME})
|
||||
add_dependencies(build_tests ${TARGET_NAME})
|
||||
# Specify linking with test_utilities *before* linking with igraph, to avoid
|
||||
# duplicating libigraph.a. See https://github.com/igraph/igraph/issues/2394
|
||||
if (NAMESPACE STREQUAL "test")
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE test_utilities)
|
||||
endif()
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE igraph)
|
||||
|
||||
# Some tests depend on internal igraph headers so we also have to add src/
|
||||
# to the include path even though it's not part of the public API
|
||||
target_include_directories(
|
||||
${TARGET_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/src ${CMAKE_BINARY_DIR}/src
|
||||
)
|
||||
|
||||
# Some tests include cs.h from CXSparse
|
||||
target_include_directories(
|
||||
${TARGET_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/vendor/cs
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
# Add MSVC-specific include path for some headers that are missing on Windows
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/msvc/include)
|
||||
endif()
|
||||
|
||||
set(EXPECTED_OUTPUT_FILE ${CMAKE_SOURCE_DIR}/${FOLDER}/${NAME}.out)
|
||||
set(OBSERVED_OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.out)
|
||||
set(DIFF_FILE ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.diff)
|
||||
get_filename_component(WORK_DIR ${EXPECTED_OUTPUT_FILE} DIRECTORY)
|
||||
|
||||
if(EXISTS ${EXPECTED_OUTPUT_FILE})
|
||||
get_property(CROSSCOMPILING_EMULATOR TARGET ${TARGET_NAME} PROPERTY CROSSCOMPILING_EMULATOR)
|
||||
add_test(
|
||||
NAME ${TEST_NAME}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DTEST_EXECUTABLE=$<TARGET_FILE:${TARGET_NAME}>
|
||||
-DEXPECTED_OUTPUT_FILE=${EXPECTED_OUTPUT_FILE}
|
||||
-DOBSERVED_OUTPUT_FILE=${OBSERVED_OUTPUT_FILE}
|
||||
-DDIFF_FILE=${DIFF_FILE}
|
||||
-DDIFF_TOOL=${DIFF_TOOL}
|
||||
-DFC_TOOL=${FC_TOOL}
|
||||
-DIGRAPH_VERSION=${PACKAGE_VERSION}
|
||||
"-DCROSSCOMPILING_EMULATOR=${CROSSCOMPILING_EMULATOR}"
|
||||
-P ${CMAKE_SOURCE_DIR}/etc/cmake/run_legacy_test.cmake
|
||||
)
|
||||
set_property(TEST ${TEST_NAME} PROPERTY SKIP_REGULAR_EXPRESSION "Test skipped")
|
||||
else()
|
||||
add_test(
|
||||
NAME ${TEST_NAME}
|
||||
COMMAND ${TARGET_NAME}
|
||||
WORKING_DIRECTORY ${WORK_DIR}
|
||||
)
|
||||
set_property(TEST ${TEST_NAME} PROPERTY SKIP_RETURN_CODE 77)
|
||||
endif()
|
||||
if (WIN32 AND BUILD_SHARED_LIBS)
|
||||
# On Windows the built igraph.dll is not automatically found by the tests. We therefore
|
||||
# add the dir that contains the built igraph.dll to the path environment variable
|
||||
# so that igraph.dll is found when running the tests.
|
||||
SET(IGRAPH_LIBDIR $<TARGET_FILE_DIR:igraph>)
|
||||
|
||||
# The next line is necessitated by MinGW on Windows. MinGW uses forward slashes in
|
||||
# IGRAPH_LIBDIR, but we need to supply CTest with backslashes because CTest is executed
|
||||
# in a cmd.exe shell. We therefore explicitly ensure that that path is transformed to a
|
||||
# native path.
|
||||
file(TO_NATIVE_PATH "${IGRAPH_LIBDIR}" IGRAPH_LIBDIR)
|
||||
|
||||
# Semicolons are used as list separators in CMake so we need to escape them in the PATH,
|
||||
# otherwise the PATH envvar gets split by CMake before it passes the PATH on to CTest.
|
||||
# We process each path separately to ensure it is a proper path. In particular, we need
|
||||
# to ensure that a trailing backslash is not incorrectly interpreted as an escape
|
||||
# character. Presumably, with cmake 3.20, this can be changed to using TO_NATIVE_PATH_LIST.
|
||||
SET(TEST_PATHS)
|
||||
foreach (PATH $ENV{PATH})
|
||||
file(TO_NATIVE_PATH "${PATH}" CORRECT_PATH)
|
||||
# Remove trailing backslash
|
||||
STRING(REGEX REPLACE "\\$" "" CORRECT_PATH ${CORRECT_PATH})
|
||||
list(APPEND TEST_PATHS ${CORRECT_PATH})
|
||||
endforeach()
|
||||
|
||||
# Join all paths in a single string, separated by an escaped semi-colon.
|
||||
string(JOIN "\;" CORRECT_PATHS ${TEST_PATHS})
|
||||
SET_TESTS_PROPERTIES(${TEST_NAME} PROPERTIES ENVIRONMENT "PATH=${IGRAPH_LIBDIR}\;${CORRECT_PATHS}" )
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(add_legacy_tests)
|
||||
cmake_parse_arguments(
|
||||
PARSED "" "FOLDER" "NAMES;LIBRARIES" ${ARGN}
|
||||
)
|
||||
foreach(NAME ${PARSED_NAMES})
|
||||
add_legacy_test(${PARSED_FOLDER} ${NAME} test)
|
||||
if(PARSED_LIBRARIES)
|
||||
target_link_libraries(test_${NAME} PRIVATE ${PARSED_LIBRARIES})
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(add_examples)
|
||||
cmake_parse_arguments(
|
||||
PARSED "" "FOLDER" "NAMES;LIBRARIES" ${ARGN}
|
||||
)
|
||||
foreach(NAME ${PARSED_NAMES})
|
||||
add_legacy_test(${PARSED_FOLDER} ${NAME} example)
|
||||
if(PARSED_LIBRARIES)
|
||||
target_link_libraries(example_${NAME} PRIVATE ${PARSED_LIBRARIES})
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
@@ -0,0 +1,25 @@
|
||||
tristate(IGRAPH_ENABLE_TLS "Enable thread-local storage for igraph global variables" AUTO)
|
||||
|
||||
include(CheckTLSSupport)
|
||||
check_tls_support(TLS_KEYWORD)
|
||||
|
||||
if(IGRAPH_ENABLE_TLS STREQUAL "AUTO")
|
||||
if(TLS_KEYWORD)
|
||||
set(IGRAPH_ENABLE_TLS ON)
|
||||
else()
|
||||
set(IGRAPH_ENABLE_TLS OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(IGRAPH_ENABLE_TLS)
|
||||
if(NOT TLS_KEYWORD)
|
||||
message(FATAL_ERROR "Thread-local storage not supported on this compiler")
|
||||
endif()
|
||||
|
||||
# TODO: we should probably set this only if we are building igraph with
|
||||
# internal-everything
|
||||
set(IGRAPH_THREAD_SAFE YES)
|
||||
else()
|
||||
set(TLS_KEYWORD "")
|
||||
set(IGRAPH_THREAD_SAFE NO)
|
||||
endif()
|
||||
@@ -0,0 +1,43 @@
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(CheckTypeSize)
|
||||
|
||||
cmake_push_check_state(RESET)
|
||||
|
||||
# Check whether the compiler supports the _umul128() intrinsic
|
||||
check_cxx_source_compiles("
|
||||
#include <intrin.h>
|
||||
|
||||
int main(void) {
|
||||
unsigned long long a = 0, b = 0;
|
||||
unsigned long long c;
|
||||
volatile unsigned long long d;
|
||||
d = _umul128(a, b, &c);
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
HAVE__UMUL128
|
||||
)
|
||||
|
||||
# Check whether the compiler supports the __umulh() intrinsic
|
||||
check_cxx_source_compiles("
|
||||
#include <intrin.h>
|
||||
|
||||
int main(void) {
|
||||
unsigned long long a = 0, b = 0;
|
||||
volatile unsigned long long c;
|
||||
c = __umulh(a, b);
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
HAVE___UMULH
|
||||
)
|
||||
|
||||
# Check whether the compiler has __uint128_t
|
||||
check_type_size("__uint128_t" UINT128 LANGUAGE CXX)
|
||||
if(UINT128 EQUAL 16)
|
||||
set(HAVE___UINT128_T ON)
|
||||
else()
|
||||
set(HAVE___UINT128_T OFF)
|
||||
endif()
|
||||
|
||||
cmake_pop_check_state()
|
||||
@@ -0,0 +1,90 @@
|
||||
include(GetGitRevisionDescription)
|
||||
|
||||
# At this point, igraph is either the main CMake project or a subproject of
|
||||
# another project. CMAKE_SOURCE_DIR would point to the root of the main
|
||||
# project if we are a subproject so we cannot use that; we need to use
|
||||
# CMAKE_CURRENT_SOURCE_DIR to get the directory containing the CMakeLists.txt
|
||||
# file that version.cmake was included from, which is the top-level
|
||||
# CMakeLists.txt file of igraph itself
|
||||
set(VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/IGRAPH_VERSION")
|
||||
set(NEXT_VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/NEXT_VERSION")
|
||||
|
||||
if(EXISTS "${VERSION_FILE}")
|
||||
file(READ "${VERSION_FILE}" PACKAGE_VERSION)
|
||||
string(STRIP "${PACKAGE_VERSION}" PACKAGE_VERSION)
|
||||
message(STATUS "Version number: ${PACKAGE_VERSION}")
|
||||
else()
|
||||
find_package(Git QUIET)
|
||||
if(Git_FOUND)
|
||||
git_describe(PACKAGE_VERSION)
|
||||
else()
|
||||
set(PACKAGE_VERSION "NOTFOUND")
|
||||
endif()
|
||||
|
||||
if(PACKAGE_VERSION)
|
||||
if(EXISTS "${NEXT_VERSION_FILE}")
|
||||
file(READ "${NEXT_VERSION_FILE}" PACKAGE_VERSION)
|
||||
string(STRIP "${PACKAGE_VERSION}" PACKAGE_VERSION)
|
||||
get_git_head_revision(GIT_REFSPEC GIT_COMMIT_HASH)
|
||||
string(SUBSTRING "${GIT_COMMIT_HASH}" 0 8 GIT_COMMIT_HASH_SHORT)
|
||||
string(APPEND PACKAGE_VERSION "-dev+${GIT_COMMIT_HASH_SHORT}")
|
||||
endif()
|
||||
message(STATUS "Version number from Git: ${PACKAGE_VERSION}")
|
||||
elseif(EXISTS "${NEXT_VERSION_FILE}")
|
||||
file(READ "${NEXT_VERSION_FILE}" PACKAGE_VERSION)
|
||||
string(STRIP "${PACKAGE_VERSION}" PACKAGE_VERSION)
|
||||
string(APPEND PACKAGE_VERSION "-dev")
|
||||
message(STATUS "Version number: ${PACKAGE_VERSION}")
|
||||
else()
|
||||
message(STATUS "Cannot find out the version number of this package; IGRAPH_VERSION is missing.")
|
||||
message(STATUS "")
|
||||
message(STATUS "The official igraph tarballs should contain this file, therefore you are")
|
||||
message(STATUS "most likely trying to compile a development version yourself. The development")
|
||||
message(STATUS "versions need Git to be able to determine the version number of igraph.")
|
||||
message(STATUS "")
|
||||
if(Git_FOUND)
|
||||
message(STATUS "It seems like you do have Git but it failed to determine the package version number.")
|
||||
message(STATUS "")
|
||||
message(STATUS "Git was found at: ${GIT_EXECUTABLE}")
|
||||
message(STATUS "The version number detection failed with: ${PACKAGE_VERSION}")
|
||||
message(STATUS "")
|
||||
message(STATUS "Most frequently this is caused by a shallow Git checkout that contains no tags in the history.")
|
||||
else()
|
||||
message(STATUS "Please install Git, make sure it is in your path, and then try again.")
|
||||
endif()
|
||||
message(STATUS "")
|
||||
message(FATAL_ERROR "Configuration failed.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
string(REGEX MATCH "^[^-]+" PACKAGE_VERSION_BASE "${PACKAGE_VERSION}")
|
||||
string(
|
||||
REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9+])" "\\1;\\2;\\3"
|
||||
PACKAGE_VERSION_PARTS "${PACKAGE_VERSION_BASE}"
|
||||
)
|
||||
list(GET PACKAGE_VERSION_PARTS 0 PACKAGE_VERSION_MAJOR)
|
||||
list(GET PACKAGE_VERSION_PARTS 1 PACKAGE_VERSION_MINOR)
|
||||
list(GET PACKAGE_VERSION_PARTS 2 PACKAGE_VERSION_PATCH)
|
||||
|
||||
if(PACKAGE_VERSION MATCHES "^[^-]+-")
|
||||
string(
|
||||
REGEX REPLACE "^[^-]+-([^+]*)" "\\1" PACKAGE_VERSION_PRERELEASE "${PACKAGE_VERSION}"
|
||||
)
|
||||
else()
|
||||
set(PACKAGE_VERSION_PRERELEASE "cmake-experimental")
|
||||
endif()
|
||||
|
||||
# Add a target that we can use to generate an IGRAPH_VERSION file in the build
|
||||
# folder, for the sake of creating a tarball. This is needed only if igraph is
|
||||
# the main project
|
||||
if(NOT PROJECT_NAME)
|
||||
add_custom_target(
|
||||
versionfile
|
||||
BYPRODUCTS "${CMAKE_BINARY_DIR}/IGRAPH_VERSION"
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-DIGRAPH_VERSION="${PACKAGE_VERSION}"
|
||||
-DVERSION_FILE_PATH="${CMAKE_BINARY_DIR}/IGRAPH_VERSION"
|
||||
-P "${CMAKE_SOURCE_DIR}/etc/cmake/create_igraph_version_file.cmake"
|
||||
COMMENT "Generating IGRAPH_VERSION file in build folder"
|
||||
)
|
||||
endif()
|
||||
Reference in New Issue
Block a user