diff --git a/.gitignore b/.gitignore index 1cc71e473..27effcf0c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,9 +4,10 @@ bin/* # build directories for cmake -build/ -build_*/ -build-*/ +build*/ +cmake-build*/ +cmake-install*/ +CMakeUserPresets.json # LLVM project llvm-project/* @@ -26,6 +27,7 @@ doc/* # log/ directory log/* +**/*/logs/ # CMake build dir build/* @@ -118,22 +120,3 @@ TAGS # config files compiler_info.txt standard_header_paths.conf - -# CMake temporary files -CMakeFiles -CMakeCache.txt -!cmake/*.cmake -cmake-build-debug/* -*.pc -Makefile -!test/*/Makefile - -# Unit test output -Testing/ -unittests/DB/DBConnTest -unittests/PhasarLLVM/ControlFlow/LLVMBasedCFGTest -unittests/PhasarLLVM/ifdside/Problems/IFDSConstAnalysisTest -unittests/PhasarLLVM/ifdside/Problems/IFDSTaintAnalysisTest -unittests/PhasarLLVM/Pointer/LLVMTypeHierarchyTest -unittests/Utils/LLVMShorthandsTest -unittests/Utils/PAMMTest diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 70653bf9e..000000000 --- a/.gitmodules +++ /dev/null @@ -1,11 +0,0 @@ -[submodule "lib/json"] - path = external/json - url = https://github.com/nlohmann/json.git - ignore = dirty -[submodule "lib/googletest"] - path = external/googletest - url = https://github.com/google/googletest.git - branch = master -[submodule "external/json-schema-validator"] - path = external/json-schema-validator - url = https://github.com/pboettch/json-schema-validator.git diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index a984a6a78..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -# Improvements and API changes - -Please see [*PhASAR's Releases*](https://github.com/secure-software-engineering/phasar/wiki/PhASAR's-Releases) diff --git a/CMakeLists.txt b/CMakeLists.txt index cec3c6243..54c268c49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,494 +1,50 @@ -cmake_minimum_required (VERSION 3.9) +cmake_minimum_required (VERSION 3.21) +project(phasar + VERSION 1.0.0 + HOMEPAGE_URL "https://github.com/secure-software-engineering/phasar" + LANGUAGES C CXX) -# Avoid IPO/LTO Warnings: -cmake_policy(SET CMP0069 NEW) -set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) - -# Check if we build within the llvm source tree -if (DEFINED LLVM_MAIN_SRC_DIR) - set(PHASAR_IN_TREE 1) -endif() - -if (NOT PHASAR_IN_TREE) - project (phasar) - set(CMAKE_PROJECT_NAME "phasar") -endif () - -option(PHASAR_EXPERIMENTAL_CXX20 "Build phasar in C++20 mode. This is an experimental feature" OFF) - -set(CMAKE_EXPORT_COMPILE_COMMANDS YES) -if(PHASAR_EXPERIMENTAL_CXX20) - message(STATUS "Selected experimental C++ build") - set(CMAKE_CXX_STANDARD 20) -else() - set(CMAKE_CXX_STANDARD 17) -endif() -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) - -include(GNUInstallDirs) +include(cmake/options.cmake) +include(cmake/just-simple.cmake) +# disable target completion output in terminal set_property(GLOBAL PROPERTY TARGET_MESSAGES OFF) -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build mode ('DebugSan' or 'Debug' or 'Release', default is 'Debug')" FORCE) -endif () - -if(CMAKE_BUILD_TYPE STREQUAL "DebugSan") - message(STATUS "Selected Debug Build with sanitizers") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -MP -fvisibility-inlines-hidden -fstack-protector-strong -ffunction-sections -fdata-sections -pipe -g -fno-omit-frame-pointer -fsanitize=address,undefined") -elseif(CMAKE_BUILD_TYPE STREQUAL "Debug") - message(STATUS "Selected Debug Build") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -MP -fvisibility-inlines-hidden -fstack-protector-strong -ffunction-sections -fdata-sections -pipe -g") -else() - message(STATUS "Selected Release Build") - - include(CheckIPOSupported) - check_ipo_supported(RESULT LTO_SUPPORTED OUTPUT LTO_SUPPORT_ERROR) - - - if(LTO_SUPPORTED) - message(STATUS "IPO/LTO enabled") - set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) # LTO - else() - message(STATUS "IPO/LTO not supported: ${LTO_SUPPORT_ERROR}") - endif() - - - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -MP -fvisibility-inlines-hidden -fstack-protector-strong -ffunction-sections -fdata-sections -pipe") - -endif() - -# Enable testing -enable_testing() - -# TODO: allow Phasar to be build as a llvm drop-in as well -# if (NOT DEFINED LLVM_MAIN_SRC_DIR) -# message(FATAL_ERROR "Phasar is not a llvm drop-in, abort!") -# endif() - -set(PHASAR_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PHASAR_SRC_DIR}/cmake") - -file(STRINGS ${PHASAR_SRC_DIR}/include/phasar/Config/Version.h VERSION_NUMBER_FILE) -string(REPLACE " " ";" VERSION_NUMBER_FILE ${VERSION_NUMBER_FILE}) -list(GET VERSION_NUMBER_FILE 2 VERSION_NUMBER_PHASAR) - -include("phasar_macros") - -option(PHASAR_BUILD_UNITTESTS "Build all tests (default is ON)" ON) - -option(BUILD_SWIFT_TESTS "Builds the Swift tests (Swift compiler has to be installed manually beforehand!)" OFF) -if (BUILD_SWIFT_TESTS) - set(CMAKE_Swift_FLAGS_RELEASE "-g") - set(CMAKE_Swift_FLAGS_RELWITHDEBINFO "-g") - enable_language(Swift) -endif(BUILD_SWIFT_TESTS) - -option(PHASAR_BUILD_OPENSSL_TS_UNITTESTS "Build OPENSSL typestate tests (require OpenSSL, default is OFF)" OFF) - -option(PHASAR_BUILD_IR "Build IR test code (default is ON)" ON) - -option(PHASAR_ENABLE_CLANG_TIDY_DURING_BUILD "Run clang-tidy during build (default is OFF)" OFF) - -option(PHASAR_BUILD_DOC "Build documentation" OFF) - -option(PHASAR_DEBUG_LIBDEPS "Debug internal library dependencies (private linkage)" OFF) - -#option(BUILD_SHARED_LIBS "Build shared libraries (default is ON)" ON) -option(PHASAR_BUILD_DYNLIB "Build one fat shared library. Requires BUILD_SHARED_LIBS to be turned OFF (default is OFF)" OFF) - -if(PHASAR_BUILD_DYNLIB AND BUILD_SHARED_LIBS) - message(FATAL_ERROR "PHASAR_BUILD_DYNLIB is incompatible with BUILD_SHARED_LIBS") -endif() - -option(PHASAR_ENABLE_WARNINGS "Enable warnings" ON) -if (PHASAR_ENABLE_WARNINGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-return-type-c-linkage ") -endif (PHASAR_ENABLE_WARNINGS) - -option(PHASAR_ENABLE_PIC "Build Position-Independed Code" ON) -if (PHASAR_ENABLE_PIC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") -endif (PHASAR_ENABLE_PIC) - -if (NOT PHASAR_ENABLE_PAMM) - set(PHASAR_ENABLE_PAMM "Off" CACHE STRING "Enable the performance measurement mechanism ('Off', 'Core' or 'Full', default is 'Off')" FORCE) - set_property(CACHE PHASAR_ENABLE_PAMM PROPERTY STRINGS "Off" "Core" "Full") -endif() -if(PHASAR_ENABLE_PAMM STREQUAL "Core" AND NOT PHASAR_BUILD_UNITTESTS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPAMM_CORE") - message("PAMM metric severity level: Core") -elseif(PHASAR_ENABLE_PAMM STREQUAL "Full" AND NOT PHASAR_BUILD_UNITTESTS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPAMM_FULL") - message("PAMM metric severity level: Full") -elseif(PHASAR_BUILD_UNITTESTS) - message("PAMM metric severity level: Off (due to unittests)") -else() - message("PAMM metric severity level: Off") -endif() - -option(PHASAR_ENABLE_DYNAMIC_LOG "Makes it possible to switch the logger on and off at runtime (default is ON)" ON) - -if (PHASAR_ENABLE_DYNAMIC_LOG) - message(STATUS "Dynamic log enabled") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDYNAMIC_LOG") +# handle LTO +include(CheckIPOSupported) +check_ipo_supported(RESULT LTO_SUPPORTED OUTPUT LTO_SUPPORT_ERROR) +if(LTO_SUPPORTED) + message(STATUS "IPO/LTO enabled") + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) else() - message(STATUS "Dynamic log disabled") + message(STATUS "IPO/LTO not supported: ${LTO_SUPPORT_ERROR}") endif() +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -MP -fvisibility-inlines-hidden -fstack-protector-strong -ffunction-sections -fdata-sections -pipe") -configure_file(config.h.in config.h @ONLY) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -include_directories( - ${PHASAR_SRC_DIR}/include -) - -if (NOT PHASAR_IN_TREE) - set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) - - if (NOT "${CMAKE_INSTALL_LIBDIR}" STREQUAL "lib") - message(STATUS "Detected CMAKE_INSTALL_LIBDIR that deviates from 'lib': ${CMAKE_INSTALL_LIBDIR}. Add ${CMAKE_INSTALL_PREFIX}/lib to the RPATH as json-schema-validator needs it") - list(APPEND CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib) - endif() - - set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -endif() - -if (LLVM_ENABLE_LIBCXX) - set(PHASAR_STD_FILESYSTEM c++fs) -else() - set(PHASAR_STD_FILESYSTEM stdc++fs) -endif() - -set(PHASAR_CUSTOM_CONFIG_INSTALL_DIR "" CACHE STRING "If set, customizes the directory, where configuration files for PhASAR are installed (default is /usr/local/.phasar-config)") -if ("${PHASAR_CUSTOM_CONFIG_INSTALL_DIR}" STREQUAL "") - set(PHASAR_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/.phasar-config/") -else() +# TODO: really cache? +set(PHASAR_CUSTOM_CONFIG_INSTALL_DIR "" CACHE STRING "If set, customizes the directory, where configuration files for PhASAR are installed (default is ${CMAKE_INSTALL_PREFIX}/.phasar-config)") +if (PHASAR_CUSTOM_CONFIG_INSTALL_DIR) set(PHASAR_CONFIG_INSTALL_DIR "${PHASAR_CUSTOM_CONFIG_INSTALL_DIR}") endif() - add_compile_definitions(PHASAR_CONFIG_DIR="${PHASAR_CONFIG_INSTALL_DIR}") -add_compile_definitions(PHASAR_DIR="${PHASAR_SRC_DIR}") - - -### Adding external libraries -# Threads -find_package(Threads) - -# Boost -find_package(Boost 1.65.1 COMPONENTS graph ${BOOST_THREAD} REQUIRED) -#find_package(Boost 1.72.0 COMPONENTS graph ${BOOST_THREAD} REQUIRED) -include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) - -# Disable clang-tidy for the external projects -set(CMAKE_CXX_CLANG_TIDY "") - -# Nlohmann JSON - -set(JSON_BuildTests OFF) -set(JSON_Install ON) -add_subdirectory(external/json) -include_directories(SYSTEM external/json/include/) - -# We need to work around the behavior of nlohmann_json_schema_validator and nlohmann_json here -# The validator needs the json part, but if you include it, the library of nlohmann_json_schema_validator -# is not installed, leading to linker error. But just including nlohmann_json is not sufficient, as -# in the installed state the nlohmann_json_schema_validator needs the nlohmann_json package which needs -# to be installed. -# The following workaround may collapse or become unnecessary once the issue is -# changed or fixed in nlohmann_json_schema_validator. - -#Override option of nlohmann_json_schema_validator to not build its tests -set(BUILD_TESTS OFF CACHE BOOL "Build json-schema-validator-tests") - -if (PHASAR_IN_TREE) - set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS nlohmann_json_schema_validator) -endif() - -# Json Schema Validator -set(JSON_VALIDATOR_INSTALL ON) -add_subdirectory(external/json-schema-validator) -include_directories(SYSTEM external/json-schema-validator/src/) - -# Googletest -if (NOT PHASAR_IN_TREE) - add_subdirectory(external/googletest EXCLUDE_FROM_ALL) - include_directories(SYSTEM external/googletest/googletest/include) - include_directories(SYSTEM external/googletest/googlemock/include) -else() - # Set llvm distributed includes for gtest header - include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include) - include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googlemock/include) -endif() - -# SQL -find_path(SQLITE3_INCLUDE_DIR NAMES sqlite3.h) -find_library(SQLITE3_LIBRARY NAMES sqlite3) -include_directories(SYSTEM ${SQLITE3_INCLUDE_DIR}) - -# LLVM -if (NOT PHASAR_IN_TREE) - # Only search for LLVM if we build out of tree - find_package(LLVM 14 REQUIRED CONFIG) - include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) - link_directories(${LLVM_LIB_PATH} ${LLVM_LIBRARY_DIRS}) -endif() - -add_definitions(${LLVM_DEFINITIONS}) - -if (NOT PHASAR_IN_TREE) - find_library(LLVM_LIBRARY NAMES LLVM PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) - if(NOT ${LLVM_LIBRARY} STREQUAL "LLVM_LIBRARY-NOTFOUND") - message(STATUS "Found consolidated shared LLVM lib " ${LLVM_LIBRARY} " that will be linked against.") - set(USE_LLVM_FAT_LIB on) - endif() -endif() - -# Clang -# The clang-cpp shared library is now the preferred way to link dynamically against libclang if we build out of tree. -if(NOT PHASAR_IN_TREE) - find_library(CLANG_LIBRARY NAMES clang-cpp libclang-cpp REQUIRED HINTS ${LLVM_LIBRARY_DIRS}) - if(${CLANG_LIBRARY} STREQUAL "CLANG_LIBRARY-NOTFOUND") - set(NEED_LIBCLANG_COMPONENT_LIBS on) - endif() -endif() -# As fallback, look for the small clang libraries -if(PHASAR_IN_TREE OR NEED_LIBCLANG_COMPONENT_LIBS) - set(CLANG_LIBRARY - clangTooling - clangFrontendTool - clangFrontend - clangDriver - clangSerialization - clangCodeGen - clangParse - clangSema - clangStaticAnalyzerFrontend - clangStaticAnalyzerCheckers - clangStaticAnalyzerCore - clangAnalysis - clangARCMigrate - clangRewrite - clangRewriteFrontend - clangEdit - clangAST - clangASTMatchers - clangLex - clangBasic - LLVMFrontendOpenMP) -endif() -if (NOT PHASAR_IN_TREE) - # Only search for clang if we build out of tree - link_directories(${CLANG_LIB_PATH}) -endif() - -if (PHASAR_IN_TREE) - # Phasar needs clang headers, specificaly some that are generated by clangs table-gen - include_directories(SYSTEM - ${CLANG_INCLUDE_DIR} - ${PHASAR_SRC_DIR}/../clang/include - ${PROJECT_BINARY_DIR}/tools/clang/include - ) -endif() - -# Set up clang-tidy to run during PhASAR's compilation to indicate code smells -if (PHASAR_ENABLE_CLANG_TIDY_DURING_BUILD) - message(STATUS "Enabled clang-tidy during build") - set(CMAKE_CXX_CLANG_TIDY - clang-tidy; - -header-filter=include/phasar.*h$; - # -warnings-as-errors=*; - ) -endif () - -# Add PhASAR's subdirectories -add_subdirectory(include) -add_subdirectory(lib) - -set(LLVM_LINK_COMPONENTS - coverage - coroutines - demangle - libdriver - lto - support - analysis - bitwriter - core - ipo - irreader - instcombine - instrumentation - linker - objcarcopts - scalaropts - transformutils - codegen - vectorize -) - -llvm_map_components_to_libnames(llvm_libs - ${LLVM_LINK_COMPONENTS} -) - -# phasar-based binaries -add_subdirectory(tools) - -# Add Phasar unittests and build all IR test code -if (PHASAR_BUILD_UNITTESTS) - message("Phasar unittests") - add_subdirectory(unittests) - set(PHASAR_BUILD_IR ON) -endif() - -# Build all IR test code -if (PHASAR_BUILD_IR) - message("Building IR test code") - add_subdirectory(test) -endif() - -set(INCLUDE_INSTALL_DIR include/ CACHE PATH "Install dir of headers") - -# Install targets of phasar-cli, other executables, and libraries are to be -# found in the individual subdirectories of tools/ - -# Install Phasar include directory -install(DIRECTORY include/ - DESTINATION include - FILES_MATCHING - PATTERN "*.def" - PATTERN "*.h" -) -# Install the header only json container -install(DIRECTORY external/json/single_include/ - DESTINATION include - FILES_MATCHING PATTERN "*.hpp" -) - -# Install the gtest header files (TODO this installation dependency should be eliminated) -install(DIRECTORY external/googletest/googletest/include/gtest/ - DESTINATION include/gtest -) - -# Install Phasar utils helper scripts -install(DIRECTORY utils/ - DESTINATION bin - FILES_MATCHING - PATTERN "CodeGen" EXCLUDE # CodeGen does not contain files to install - PATTERN "phasar-*" - PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ - GROUP_EXECUTE GROUP_READ - WORLD_EXECUTE WORLD_READ -) - -# Install the Phasar config files into CMAKE_INSTALL_PREFIX/.phasar-config/ -install(DIRECTORY config/ - DESTINATION ${PHASAR_CONFIG_INSTALL_DIR} - PATTERN "config/*" - PERMISSIONS OWNER_WRITE OWNER_READ - GROUP_WRITE GROUP_READ - WORLD_READ -) - -include(CMakePackageConfigHelpers) -configure_package_config_file( - Config.cmake.in - phasarConfig.cmake - INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/phasar - PATH_VARS INCLUDE_INSTALL_DIR - ) - -write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/phasarConfigVersion.cmake - VERSION 1.0.0 - COMPATIBILITY SameMajorVersion - ) - -### Install Config and ConfigVersion files -install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/phasarConfig.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/phasarConfigVersion.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/phasar" - ) - -# If the Phasar shared object libraries are not installed into a system folder -# the so libs must be added manually to the linker search path and the linker -# config must be updated as follows: -# -# $ export LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:/home/philipp/Schreibtisch/tmp/lib -# $ sudo ldconfig -# -# Or even better: just link statically when trying to package Phasar <- this is no longer possible - -# Settings for building various packages using Cpack -# How to pack using the following settings? -# $ mkdir build -# $ cd build -# $ cmake -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=/usr/local .. -# $ cpack .. -# $ dpkg -i ./.deb or better: apt-get install ./.deb -set(MAJOR_VERSION 1) -set(MINOR_VERSION 0) -set(PATCH_VERSION 0) -if (NOT PHASAR_IN_TREE) -IF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") -INCLUDE(InstallRequiredSystemLibraries) -set(CPACK_SET_DESTDIR "on") -set(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -#set(CPACK_GENERATOR "DEB") -set(CPACK_GENERATOR "RPM") -set(CPACK_PACKAGE_DESCRIPTION "Phasar") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Phasar a LLVM-based static analysis framework") -set(CPACK_PACKAGE_VENDOR "Phasar Team - Philipp Schubert and others") -set(CPACK_PACKAGE_CONTACT "philipp.schubert@upb.de") -set(CPACK_PACKAGE_VERSION_MAJOR "${MAJOR_VERSION}") -set(CPACK_PACKAGE_VERSION_MINOR "${MINOR_VERSION}") -set(CPACK_PACKAGE_VERSION_PATCH "${PATCH_VERSION}") -set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${MAJOR_VERSION}.${MINOR_VERSION}.${CPACK_PACKAGE_VERSION_PATCH}") -set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${MAJOR_VERSION}.${MINOR_VERSION}.${CPACK_PACKAGE_VERSION_PATCH}") -# package dependencies can be set-up here -# better use autogenerated dependency information -set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) -# set(CPACK_DEBIAN_PACKAGE_DEPENDS "libboost_program_options (>= 1.66.0), -# libboost_graph (>= 1.66.0), -# libboost_thread (>= 1.66.0), -# libsqlite3 (>= 4.5.0), -# libpthread (>= 4.5.0), -# libdl (>= 4.5.0), -# librt (>= 4.5.0), -# libtinfo (>= 4.5.0), -# libz (>= 4.5.0), -# libm (>= 4.5.0), -# libstdc++ (>= 4.5.0), -# libgcc_s (>= 4.5.0), -# libc (>= 4.5.0), -# ld-linux-x86-64 (>= 4.5.0)") -set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") -set(CPACK_DEBIAN_PACKAGE_SECTION "kde") -set(CPACK_DEBIAN_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) -set(CPACK_COMPONENTS_ALL Libraries ApplicationData) -INCLUDE(CPack) -ENDIF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") -endif() +set(PHASAR_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +add_compile_definitions(PHASAR_DIR="${PHASAR_SRC_DIR}") -# Setup the doxygen code documentation -if(PHASAR_BUILD_DOC) - find_package(Doxygen) - if (DOXYGEN_FOUND) - set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in) - set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) - configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY) - message("Doxygen build started") - add_custom_target(doc_doxygen ALL - COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Generating API documentation with Doxygen" - VERBATIM - ) - else(DOXYGEN_FOUND) - message(FATAL_ERROR "Doxygen need to be installed to generate the doxygen documentation.") - endif() -endif() +just_limit_jobs(COMPILE 1200 LINK 1200) +add_subdirectory(phasar/clang) +add_subdirectory(phasar/config) +add_subdirectory(phasar/controller) +add_subdirectory(phasar/db) +add_subdirectory(phasar/example-tool) +add_subdirectory(phasar/llvm) +add_subdirectory(phasar/utils) +add_subdirectory(phasar/test-utils) +add_subdirectory(phasar/analysisstrategy) +add_subdirectory(phasar/controlflow) +add_subdirectory(phasar/dataflow) +add_subdirectory(phasar/domain) +add_subdirectory(phasar/pointer) +add_subdirectory(phasar/typehierarchy) +add_subdirectory(phasar/cli) +add_subdirectory(phasar/all) diff --git a/CMakeLists.txt.old b/CMakeLists.txt.old new file mode 100644 index 000000000..73000661e --- /dev/null +++ b/CMakeLists.txt.old @@ -0,0 +1,447 @@ +cmake_minimum_required (VERSION 3.0) + +# Check if we build within the llvm source tree +if (DEFINED LLVM_MAIN_SRC_DIR) + set(PHASAR_IN_TREE 1) +endif() + +if (NOT PHASAR_IN_TREE) + project (phasar) + set(CMAKE_PROJECT_NAME "phasar") +endif () + +set(CMAKE_EXPORT_COMPILE_COMMANDS YES) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +include(GNUInstallDirs) + +set_property(GLOBAL PROPERTY TARGET_MESSAGES OFF) + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build mode ('DebugSan' or 'Debug' or 'Release', default is 'Debug')" FORCE) +endif () + +if(CMAKE_BUILD_TYPE STREQUAL "DebugSan") + message(STATUS "Selected Debug Build with sanitizers") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -MP -fvisibility-inlines-hidden -fstack-protector-strong -ffunction-sections -fdata-sections -pipe -g -fno-omit-frame-pointer -fsanitize=address,undefined") +elseif(CMAKE_BUILD_TYPE STREQUAL "Debug") + message(STATUS "Selected Debug Build") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -MP -fvisibility-inlines-hidden -fstack-protector-strong -ffunction-sections -fdata-sections -pipe -g") +else() + message(STATUS "Selected Release Build") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -MP -fvisibility-inlines-hidden -fstack-protector-strong -ffunction-sections -fdata-sections -pipe -march=native") +endif() + +# Enable testing +enable_testing() + +# TODO: allow Phasar to be build as a llvm drop-in as well +# if (NOT DEFINED LLVM_MAIN_SRC_DIR) +# message(FATAL_ERROR "Phasar is not a llvm drop-in, abort!") +# endif() + +set(PHASAR_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PHASAR_SRC_DIR}/cmake") + +file(STRINGS ${PHASAR_SRC_DIR}/include/phasar/Config/Version.h VERSION_NUMBER_FILE) +string(REPLACE " " ";" VERSION_NUMBER_FILE ${VERSION_NUMBER_FILE}) +list(GET VERSION_NUMBER_FILE 2 VERSION_NUMBER_PHASAR) + +include("phasar_macros") + +option(PHASAR_BUILD_UNITTESTS "Build all tests (default is ON)" ON) + +option(PHASAR_BUILD_OPENSSL_TS_UNITTESTS "Build OPENSSL typestate tests (require OpenSSL, default is OFF)" OFF) + +option(PHASAR_BUILD_IR "Build IR test code (default is ON)" ON) + +option(PHASAR_ENABLE_CLANG_TIDY_DURING_BUILD "Run clang-tidy during build (default is OFF)" OFF) + +option(PHASAR_BUILD_DOC "Build documentation" OFF) + +option(PHASAR_DEBUG_LIBDEPS "Debug internal library dependencies (private linkage)" OFF) + +option(BUILD_SHARED_LIBS "Build shared libraries (default is ON)" ON) + +option(PHASAR_ENABLE_WARNINGS "Enable warnings" ON) +if (PHASAR_ENABLE_WARNINGS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-return-type-c-linkage ") +endif (PHASAR_ENABLE_WARNINGS) + +option(PHASAR_ENABLE_PIC "Build Position-Independed Code" ON) +if (PHASAR_ENABLE_PIC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") +endif (PHASAR_ENABLE_PIC) + +if (NOT PHASAR_ENABLE_PAMM) + set(PHASAR_ENABLE_PAMM "Off" CACHE STRING "Enable the performance measurement mechanism ('Off', 'Core' or 'Full', default is 'Off')" FORCE) + set_property(CACHE PHASAR_ENABLE_PAMM PROPERTY STRINGS "Off" "Core" "Full") +endif() +if(PHASAR_ENABLE_PAMM STREQUAL "Core" AND NOT PHASAR_BUILD_UNITTESTS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPAMM_CORE") + message("PAMM metric severity level: Core") +elseif(PHASAR_ENABLE_PAMM STREQUAL "Full" AND NOT PHASAR_BUILD_UNITTESTS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPAMM_FULL") + message("PAMM metric severity level: Full") +elseif(PHASAR_BUILD_UNITTESTS) + message("PAMM metric severity level: Off (due to unittests)") +else() + message("PAMM metric severity level: Off") +endif() + +option(PHASAR_ENABLE_DYNAMIC_LOG "Makes it possible to switch the logger on and off at runtime (default is ON)" ON) + +if (PHASAR_ENABLE_DYNAMIC_LOG) + message(STATUS "Dynamic log enabled") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDYNAMIC_LOG") +else() + message(STATUS "Dynamic log disabled") +endif() + +configure_file(config.h.in config.h @ONLY) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +include_directories( + ${PHASAR_SRC_DIR}/include +) + +set(PHASAR_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}/phasar) + +if (NOT PHASAR_IN_TREE) + set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${PHASAR_INSTALL_LIBDIR}) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +endif() + +if (LLVM_ENABLE_LIBCXX) + set(PHASAR_STD_FILESYSTEM c++fs) +else() + set(PHASAR_STD_FILESYSTEM stdc++fs) +endif() + +### Adding external libraries +# Threads +find_package(Threads) + +# Boost +find_package(Boost 1.65.1 COMPONENTS graph program_options ${BOOST_THREAD} REQUIRED) +#find_package(Boost 1.72.0 COMPONENTS graph program_options ${BOOST_THREAD} REQUIRED) +include_directories(${Boost_INCLUDE_DIRS}) + +# Disable clang-tidy for the external projects +set(CMAKE_CXX_CLANG_TIDY "") + +# We need to work around the behavior of nlohmann_json_schema_validator and nlohmann_json here +# The validator needs the json part, but if you include it, the library of nlohmann_json_schema_validator +# is not installed, leading to linker error. But just including nlohmann_json is not sufficient, as +# in the installed state the nlohmann_json_schema_validator needs the nlohmann_json package which needs +# to be installed. +# The following workaround may collapse or become unnecessary once the issue is +# changed or fixed in nlohmann_json_schema_validator. + +#Override option of nlohmann_json_schema_validator to not build its tests +set(BUILD_TESTS OFF CACHE BOOL "Build json-schema-validator-tests") + +# Make nlohmann_json_schema_validator happy by telling it how to find the single include of nlohmann_json +include_directories(external/json/single_include/) + +if (PHASAR_IN_TREE) + set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS nlohmann_json_schema_validator) +endif() + +set(nlohmann_json_DIR ${PHASAR_SRC_DIR}/external/json/single_include/) + +# Json Schema Validator +set(JSON_VALIDATOR_INSTALL ON) +add_subdirectory(external/json-schema-validator) +include_directories(external/json-schema-validator/src/) + +# now we finally add the subdirectory +set(JSON_BuildTests OFF) +set(JSON_Install ON) +add_subdirectory(external/json) + +# Googletest +if (NOT PHASAR_IN_TREE) + add_subdirectory(external/googletest EXCLUDE_FROM_ALL) + include_directories(external/googletest/googletest/include) + include_directories(external/googletest/googlemock/include) +else() + # Set llvm distributed includes for gtest header + include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include) + include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googlemock/include) +endif() + +# SQL +find_path(SQLITE3_INCLUDE_DIR NAMES sqlite3.h) +find_library(SQLITE3_LIBRARY NAMES sqlite3) +include_directories(${SQLITE3_INCLUDE_DIR}) + +# LLVM +if (NOT PHASAR_IN_TREE) + # Only search for LLVM if we build out of tree + find_package(LLVM 14 REQUIRED CONFIG) + include_directories(${LLVM_INCLUDE_DIRS}) + link_directories(${LLVM_LIB_PATH} ${LLVM_LIBRARY_DIRS}) +endif() + +add_definitions(${LLVM_DEFINITIONS}) + +if (NOT PHASAR_IN_TREE) + find_library(LLVM_LIBRARY NAMES LLVM PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + if(NOT ${LLVM_LIBRARY} STREQUAL "LLVM_LIBRARY-NOTFOUND") + message(STATUS "Found consolidated shared LLVM lib " ${LLVM_LIBRARY} " that will be linked against.") + set(USE_LLVM_FAT_LIB on) + endif() +endif() + +# Clang +# The clang-cpp shared library is now the preferred way to link dynamically against libclang if we build out of tree. +if(NOT PHASAR_IN_TREE) + find_library(CLANG_LIBRARY NAMES clang-cpp libclang-cpp REQUIRED HINTS ${LLVM_LIBRARY_DIRS}) + if(${CLANG_LIBRARY} STREQUAL "CLANG_LIBRARY-NOTFOUND") + set(NEED_LIBCLANG_COMPONENT_LIBS on) + endif() +endif() +# As fallback, look for the small clang libraries +if(PHASAR_IN_TREE OR NEED_LIBCLANG_COMPONENT_LIBS) + set(CLANG_LIBRARY + clangTooling + clangFrontendTool + clangFrontend + clangDriver + clangSerialization + clangCodeGen + clangParse + clangSema + clangStaticAnalyzerFrontend + clangStaticAnalyzerCheckers + clangStaticAnalyzerCore + clangAnalysis + clangARCMigrate + clangRewrite + clangRewriteFrontend + clangEdit + clangAST + clangASTMatchers + clangLex + clangBasic + LLVMFrontendOpenMP) +endif() +if (NOT PHASAR_IN_TREE) + # Only search for clang if we build out of tree + link_directories(${CLANG_LIB_PATH}) +endif() + +if (PHASAR_IN_TREE) + # Phasar needs clang headers, specificaly some that are generated by clangs table-gen + include_directories( + ${CLANG_INCLUDE_DIR} + ${PHASAR_SRC_DIR}/../clang/include + ${PROJECT_BINARY_DIR}/tools/clang/include + ) +endif() + +# WALi-OpenNWA +add_subdirectory(external/WALi-OpenNWA) +include_directories(external/WALi-OpenNWA/Source/wali/include) + +# Set up clang-tidy to run during PhASAR's compilation to indicate code smells +if (PHASAR_ENABLE_CLANG_TIDY_DURING_BUILD) + message(STATUS "Enabled clang-tidy during build") + set(CMAKE_CXX_CLANG_TIDY + clang-tidy; + -header-filter=include/phasar.*h$; + # -warnings-as-errors=*; + ) +endif () + +# Add PhASAR's subdirectories +add_subdirectory(include) +add_subdirectory(lib) + +set(LLVM_LINK_COMPONENTS + coverage + coroutines + demangle + libdriver + lto + support + analysis + bitwriter + core + ipo + irreader + instcombine + instrumentation + linker + objcarcopts + scalaropts + transformutils + codegen + vectorize +) + +llvm_map_components_to_libnames(llvm_libs + ${LLVM_LINK_COMPONENTS} +) + +# phasar-based binaries +add_subdirectory(tools) + +# Add Phasar unittests and build all IR test code +if (PHASAR_BUILD_UNITTESTS) + message("Phasar unittests") + add_subdirectory(unittests) + set(PHASAR_BUILD_IR ON) +endif() + +# Build all IR test code +if (PHASAR_BUILD_IR) + message("Building IR test code") + add_subdirectory(test) +endif() + +set(INCLUDE_INSTALL_DIR include/ CACHE PATH "Install dir of headers") + +# Install targets of phasar-llvm, other executables, and libraries are to be +# found in the individual subdirectories of tools/ + +# Install Phasar include directory +install(DIRECTORY include/ + DESTINATION include + FILES_MATCHING + PATTERN "*.def" + PATTERN "*.h" +) + +# Install the header only json container +install(DIRECTORY external/json/single_include/ + DESTINATION include + FILES_MATCHING PATTERN "*.hpp" +) + +# Install the gtest header files (TODO this installation dependency should be eliminated) +install(DIRECTORY external/googletest/googletest/include/gtest/ + DESTINATION include/gtest +) + +# Install Phasar utils helper scripts +install(DIRECTORY utils/ + DESTINATION bin + FILES_MATCHING PATTERN "phasar-*" + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ + GROUP_EXECUTE GROUP_READ + WORLD_EXECUTE WORLD_READ +) + +# Install the Phasar config files into ~/.config/phasar/ +install(DIRECTORY config/ + DESTINATION $ENV{HOME}/.config/phasar + PATTERN "config/*" + PERMISSIONS OWNER_WRITE OWNER_READ + GROUP_WRITE GROUP_READ + WORLD_READ +) + +include(CMakePackageConfigHelpers) +configure_package_config_file( + Config.cmake.in + phasarConfig.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/phasar + PATH_VARS INCLUDE_INSTALL_DIR + ) + +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/phasarConfigVersion.cmake + VERSION 1.0.0 + COMPATIBILITY SameMajorVersion + ) + +### Install Config and ConfigVersion files +install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/phasarConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/phasarConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/phasar" + ) + +# If the Phasar shared object libraries are not installed into a system folder +# the so libs must be added manually to the linker search path and the linker +# config must be updated as follows: +# +# $ export LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:/home/philipp/Schreibtisch/tmp/lib +# $ sudo ldconfig +# +# Or even better: just link statically when trying to package Phasar <- this is no longer possible + +# Settings for building various packages using Cpack +# How to pack using the following settings? +# $ mkdir build +# $ cd build +# $ cmake -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=/usr/local .. +# $ cpack .. +# $ dpkg -i ./.deb or better: apt-get install ./.deb +set(MAJOR_VERSION 1) +set(MINOR_VERSION 0) +set(PATCH_VERSION 0) +if (NOT PHASAR_IN_TREE) +IF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") +INCLUDE(InstallRequiredSystemLibraries) +set(CPACK_SET_DESTDIR "on") +set(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +#set(CPACK_GENERATOR "DEB") +set(CPACK_GENERATOR "RPM") +set(CPACK_PACKAGE_DESCRIPTION "Phasar") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Phasar a LLVM-based static analysis framework") +set(CPACK_PACKAGE_VENDOR "Phasar Team - Philipp Schubert and others") +set(CPACK_PACKAGE_CONTACT "philipp.schubert@upb.de") +set(CPACK_PACKAGE_VERSION_MAJOR "${MAJOR_VERSION}") +set(CPACK_PACKAGE_VERSION_MINOR "${MINOR_VERSION}") +set(CPACK_PACKAGE_VERSION_PATCH "${PATCH_VERSION}") +set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${MAJOR_VERSION}.${MINOR_VERSION}.${CPACK_PACKAGE_VERSION_PATCH}") +set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${MAJOR_VERSION}.${MINOR_VERSION}.${CPACK_PACKAGE_VERSION_PATCH}") +# package dependencies can be set-up here +# better use autogenerated dependency information +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) +# set(CPACK_DEBIAN_PACKAGE_DEPENDS "libboost_program_options (>= 1.66.0), +# libboost_graph (>= 1.66.0), +# libboost_thread (>= 1.66.0), +# libsqlite3 (>= 4.5.0), +# libpthread (>= 4.5.0), +# libdl (>= 4.5.0), +# librt (>= 4.5.0), +# libtinfo (>= 4.5.0), +# libz (>= 4.5.0), +# libm (>= 4.5.0), +# libstdc++ (>= 4.5.0), +# libgcc_s (>= 4.5.0), +# libc (>= 4.5.0), +# ld-linux-x86-64 (>= 4.5.0)") +set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") +set(CPACK_DEBIAN_PACKAGE_SECTION "kde") +set(CPACK_DEBIAN_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) +set(CPACK_COMPONENTS_ALL Libraries ApplicationData) +INCLUDE(CPack) +ENDIF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") +endif() + +# Setup the doxygen code documentation +if(PHASAR_BUILD_DOC) + find_package(Doxygen) + if (DOXYGEN_FOUND) + set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in) + set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY) + message("Doxygen build started") + add_custom_target(doc_doxygen ALL + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" + VERBATIM + ) + else(DOXYGEN_FOUND) + message(FATAL_ERROR "Doxygen need to be installed to generate the doxygen documentation.") + endif() +endif() diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 000000000..71c441572 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,129 @@ +{ + "version": 2, + "configurePresets": [ + { + "name": "default", + "displayName": "Debug Static", + "description": "Sets Ninja generator, build and install directory", + "generator": "Ninja", + "binaryDir": "${sourceDir}/cmake-build/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/cmake-install/${presetName}", + "PHASAR_BUILD_UNITTESTS": "ON", + "BUILD_SHARED_LIBS": "OFF", + "CODE_COVERAGE": "ON", + "USE_CLANG_ADDRESS_SANITIZER": "ON" + } + }, + { + "inherits": [ + "default" + ], + "name": "debug", + "displayName": "Debug Static" + }, + { + "inherits": [ + "default" + ], + "name": "release", + "displayName": "Release Static", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "CODE_COVERAGE": "OFF", + "USE_CLANG_ADDRESS_SANITIZER": "OFF" + } + }, + { + "inherits": [ + "default" + ], + "name": "debug-shared", + "displayName": "Debug Shared", + "cacheVariables": { + "BUILD_SHARED_LIBS": "ON" + } + }, + { + "inherits": [ + "default" + ], + "name": "release-shared", + "displayName": "Release Shared", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "BUILD_SHARED_LIBS": "ON", + "CODE_COVERAGE": "OFF", + "USE_CLANG_ADDRESS_SANITIZER": "OFF" + } + } + ], + "buildPresets": [ + { + "name": "debug", + "configurePreset": "debug", + "targets": [ + "all" + ] + }, + { + "name": "release", + "configurePreset": "release", + "targets": [ + "all" + ] + }, + { + "name": "debug-shared", + "configurePreset": "debug-shared", + "targets": [ + "all" + ] + }, + { + "name": "release-shared", + "configurePreset": "release-shared", + "targets": [ + "all" + ] + } + ], + "testPresets": [ + { + "name": "debug", + "displayName": "Debug Static", + "configurePreset": "debug", + "output": { + "outputOnFailure": true + }, + "execution": { + "jobs": 20 + } + }, + { + "inherits": [ + "debug" + ], + "name": "release", + "displayName": "Release Static", + "configurePreset": "release" + }, + { + "inherits": [ + "debug" + ], + "name": "debug-shared", + "displayName": "Debug Shared", + "configurePreset": "debug-shared" + }, + { + "inherits": [ + "debug" + ], + "name": "release-shared", + "displayName": "Release Shared", + "configurePreset": "release-shared" + } + ] +} \ No newline at end of file diff --git a/cmake/code-coverage.cmake b/cmake/code-coverage.cmake new file mode 100644 index 000000000..d19d83d3a --- /dev/null +++ b/cmake/code-coverage.cmake @@ -0,0 +1,672 @@ +# +# Copyright (C) 2018-2020 by George Cave - gcave@stablecoder.ca +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +# USAGE: To enable any code coverage instrumentation/targets, the single CMake +# option of `CODE_COVERAGE` needs to be set to 'ON', either by GUI, ccmake, or +# on the command line. +# +# From this point, there are two primary methods for adding instrumentation to +# targets: 1 - A blanket instrumentation by calling `add_code_coverage()`, where +# all targets in that directory and all subdirectories are automatically +# instrumented. 2 - Per-target instrumentation by calling +# `target_code_coverage()`, where the target is given and thus only +# that target is instrumented. This applies to both libraries and executables. +# +# To add coverage targets, such as calling `make ccov` to generate the actual +# coverage information for perusal or consumption, call +# `target_code_coverage()` on an *executable* target. +# +# Example 1: All targets instrumented +# +# In this case, the coverage information reported will will be that of the +# `theLib` library target and `theExe` executable. +# +# 1a: Via global command +# +# ~~~ +# add_code_coverage() # Adds instrumentation to all targets +# +# add_library(theLib lib.cpp) +# +# add_executable(theExe main.cpp) +# target_link_libraries(theExe PRIVATE theLib) +# target_code_coverage(theExe) # As an executable target, adds the 'ccov-theExe' target (instrumentation already added via global anyways) for generating code coverage reports. +# ~~~ +# +# 1b: Via target commands +# +# ~~~ +# add_library(theLib lib.cpp) +# target_code_coverage(theLib) # As a library target, adds coverage instrumentation but no targets. +# +# add_executable(theExe main.cpp) +# target_link_libraries(theExe PRIVATE theLib) +# target_code_coverage(theExe) # As an executable target, adds the 'ccov-theExe' target and instrumentation for generating code coverage reports. +# ~~~ +# +# Example 2: Target instrumented, but with regex pattern of files to be excluded +# from report +# +# ~~~ +# add_executable(theExe main.cpp non_covered.cpp) +# target_code_coverage(theExe EXCLUDE non_covered.cpp test/*) # As an executable target, the reports will exclude the non-covered.cpp file, and any files in a test/ folder. +# ~~~ +# +# Example 3: Target added to the 'ccov' and 'ccov-all' targets +# +# ~~~ +# add_code_coverage_all_targets(EXCLUDE test/*) # Adds the 'ccov-all' target set and sets it to exclude all files in test/ folders. +# +# add_executable(theExe main.cpp non_covered.cpp) +# target_code_coverage(theExe AUTO ALL EXCLUDE non_covered.cpp test/*) # As an executable target, adds to the 'ccov' and ccov-all' targets, and the reports will exclude the non-covered.cpp file, and any files in a test/ folder. +# ~~~ + +# Options +option( + CODE_COVERAGE + "Builds targets with code coverage instrumentation. (Requires GCC or Clang)" + OFF) + +# Programs +find_program(LLVM_COV_PATH llvm-cov) +find_program(LLVM_PROFDATA_PATH llvm-profdata) +find_program(LCOV_PATH lcov) +find_program(GENHTML_PATH genhtml) +# Hide behind the 'advanced' mode flag for GUI/ccmake +mark_as_advanced(FORCE LLVM_COV_PATH LLVM_PROFDATA_PATH LCOV_PATH GENHTML_PATH) + +# Variables +set(CMAKE_COVERAGE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/ccov) +set_property(GLOBAL PROPERTY JOB_POOLS ccov_serial_pool=1) + +# Common initialization/checks +if(CODE_COVERAGE AND NOT CODE_COVERAGE_ADDED) + set(CODE_COVERAGE_ADDED ON) + + # Common Targets + add_custom_target( + ccov-preprocessing + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY} + DEPENDS ccov-clean) + + if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" + OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") + # Messages + message(STATUS "Building with llvm Code Coverage Tools") + + if(NOT LLVM_COV_PATH) + message(FATAL_ERROR "llvm-cov not found! Aborting.") + else() + # Version number checking for 'EXCLUDE' compatibility + execute_process(COMMAND ${LLVM_COV_PATH} --version + OUTPUT_VARIABLE LLVM_COV_VERSION_CALL_OUTPUT) + string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" LLVM_COV_VERSION + ${LLVM_COV_VERSION_CALL_OUTPUT}) + + if(LLVM_COV_VERSION VERSION_LESS "7.0.0") + message( + WARNING + "target_code_coverage()/add_code_coverage_all_targets() 'EXCLUDE' option only available on llvm-cov >= 7.0.0" + ) + endif() + endif() + + # Targets + if(${CMAKE_VERSION} VERSION_LESS "3.17.0") + add_custom_target( + ccov-clean + COMMAND ${CMAKE_COMMAND} -E remove -f + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list + COMMAND ${CMAKE_COMMAND} -E remove -f + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list) + else() + add_custom_target( + ccov-clean + COMMAND ${CMAKE_COMMAND} -E rm -f + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list + COMMAND ${CMAKE_COMMAND} -E rm -f + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list) + endif() + + # Used to get the shared object file list before doing the main all- + # processing + add_custom_target( + ccov-libs + COMMAND ; + COMMENT "libs ready for coverage report.") + + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES + "GNU") + # Messages + message(STATUS "Building with lcov Code Coverage Tools") + + if(CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} upper_build_type) + if(NOT ${upper_build_type} STREQUAL "DEBUG") + message( + WARNING + "Code coverage results with an optimized (non-Debug) build may be misleading" + ) + endif() + else() + message( + WARNING + "Code coverage results with an optimized (non-Debug) build may be misleading" + ) + endif() + if(NOT LCOV_PATH) + message(FATAL_ERROR "lcov not found! Aborting...") + endif() + if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Aborting...") + endif() + + # Targets + add_custom_target(ccov-clean COMMAND ${LCOV_PATH} --directory + ${CMAKE_BINARY_DIR} --zerocounters) + + else() + message(FATAL_ERROR "Code coverage requires Clang or GCC. Aborting.") + endif() +endif() + +# Adds code coverage instrumentation to a library, or instrumentation/targets +# for an executable target. +# ~~~ +# EXECUTABLE ADDED TARGETS: +# GCOV/LCOV: +# ccov : Generates HTML code coverage report for every target added with 'AUTO' parameter. +# ccov-${TARGET_NAME} : Generates HTML code coverage report for the associated named target. +# ccov-all : Generates HTML code coverage report, merging every target added with 'ALL' parameter into a single detailed report. +# +# LLVM-COV: +# ccov : Generates HTML code coverage report for every target added with 'AUTO' parameter. +# ccov-report : Generates HTML code coverage report for every target added with 'AUTO' parameter. +# ccov-${TARGET_NAME} : Generates HTML code coverage report. +# ccov-report-${TARGET_NAME} : Prints to command line summary per-file coverage information. +# ccov-export-${TARGET_NAME} : Exports the coverage report to a JSON file. +# ccov-show-${TARGET_NAME} : Prints to command line detailed per-line coverage information. +# ccov-all : Generates HTML code coverage report, merging every target added with 'ALL' parameter into a single detailed report. +# ccov-all-report : Prints summary per-file coverage information for every target added with ALL' parameter to the command line. +# ccov-all-export : Exports the coverage report to a JSON file. +# +# Required: +# TARGET_NAME - Name of the target to generate code coverage for. +# Optional: +# PUBLIC - Sets the visibility for added compile options to targets to PUBLIC instead of the default of PRIVATE. +# INTERFACE - Sets the visibility for added compile options to targets to INTERFACE instead of the default of PRIVATE. +# PLAIN - Do not set any target visibility (backward compatibility with old cmake projects) +# AUTO - Adds the target to the 'ccov' target so that it can be run in a batch with others easily. Effective on executable targets. +# ALL - Adds the target to the 'ccov-all' and 'ccov-all-report' targets, which merge several executable targets coverage data to a single report. Effective on executable targets. +# EXTERNAL - For GCC's lcov, allows the profiling of 'external' files from the processing directory +# COVERAGE_TARGET_NAME - For executables ONLY, changes the outgoing target name so instead of `ccov-${TARGET_NAME}` it becomes `ccov-${COVERAGE_TARGET_NAME}`. +# EXCLUDE - Excludes files of the patterns provided from coverage. Note that GCC/lcov excludes by glob pattern, and clang/LLVM excludes via regex! **These do not copy to the 'all' targets.** +# OBJECTS - For executables ONLY, if the provided targets are shared libraries, adds coverage information to the output +# ARGS - For executables ONLY, appends the given arguments to the associated ccov-* executable call +# ~~~ +function(target_code_coverage TARGET_NAME) + # Argument parsing + set(options AUTO ALL EXTERNAL PUBLIC INTERFACE PLAIN) + set(single_value_keywords COVERAGE_TARGET_NAME) + set(multi_value_keywords EXCLUDE OBJECTS ARGS) + cmake_parse_arguments( + target_code_coverage "${options}" "${single_value_keywords}" + "${multi_value_keywords}" ${ARGN}) + + # Set the visibility of target functions to PUBLIC, INTERFACE or default to + # PRIVATE. + if(target_code_coverage_PUBLIC) + set(TARGET_VISIBILITY PUBLIC) + set(TARGET_LINK_VISIBILITY PUBLIC) + elseif(target_code_coverage_INTERFACE) + set(TARGET_VISIBILITY INTERFACE) + set(TARGET_LINK_VISIBILITY INTERFACE) + elseif(target_code_coverage_PLAIN) + set(TARGET_VISIBILITY PUBLIC) + set(TARGET_LINK_VISIBILITY) + else() + set(TARGET_VISIBILITY PRIVATE) + set(TARGET_LINK_VISIBILITY PRIVATE) + endif() + + if(NOT target_code_coverage_COVERAGE_TARGET_NAME) + # If a specific name was given, use that instead. + set(target_code_coverage_COVERAGE_TARGET_NAME ${TARGET_NAME}) + endif() + + if(CODE_COVERAGE) + + # Add code coverage instrumentation to the target's linker command + if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" + OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") + target_compile_options(${TARGET_NAME} ${TARGET_VISIBILITY} + -fprofile-instr-generate -fcoverage-mapping) + target_link_options(${TARGET_NAME} ${TARGET_VISIBILITY} + -fprofile-instr-generate -fcoverage-mapping) + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES + "GNU") + target_compile_options(${TARGET_NAME} ${TARGET_VISIBILITY} -fprofile-arcs + -ftest-coverage) + target_link_libraries(${TARGET_NAME} ${TARGET_LINK_VISIBILITY} gcov) + endif() + + # Targets + get_target_property(target_type ${TARGET_NAME} TYPE) + + # Add shared library to processing for 'all' targets + if(target_type STREQUAL "SHARED_LIBRARY" AND target_code_coverage_ALL) + if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" + OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") + add_custom_target( + ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${CMAKE_COMMAND} -E echo "-object=$" >> + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list + DEPENDS ccov-preprocessing ${TARGET_NAME}) + + if(NOT TARGET ccov-libs) + message( + FATAL_ERROR + "Calling target_code_coverage with 'ALL' must be after a call to 'add_code_coverage_all_targets'." + ) + endif() + + add_dependencies(ccov-libs + ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME}) + endif() + endif() + + # For executables add targets to run and produce output + if(target_type STREQUAL "EXECUTABLE") + if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" + OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") + + # If there are shared objects to also work with, generate the string to + # add them here + foreach(SO_TARGET ${target_code_coverage_OBJECTS}) + # Check to see if the target is a shared object + if(TARGET ${SO_TARGET}) + get_target_property(SO_TARGET_TYPE ${SO_TARGET} TYPE) + if(${SO_TARGET_TYPE} STREQUAL "SHARED_LIBRARY") + set(SO_OBJECTS ${SO_OBJECTS} -object=$) + endif() + endif() + endforeach() + + # Run the executable, generating raw profile data Make the run data + # available for further processing. Separated to allow Windows to run + # this target serially. + add_custom_target( + ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${CMAKE_COMMAND} -E env + LLVM_PROFILE_FILE=${target_code_coverage_COVERAGE_TARGET_NAME}.profraw + $ ${target_code_coverage_ARGS} + COMMAND + ${CMAKE_COMMAND} -E echo "-object=$" + ${SO_OBJECTS} >> ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list + COMMAND + ${CMAKE_COMMAND} -E echo + "${CMAKE_CURRENT_BINARY_DIR}/${target_code_coverage_COVERAGE_TARGET_NAME}.profraw" + >> ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list + JOB_POOL ccov_serial_pool + DEPENDS ccov-preprocessing ccov-libs ${TARGET_NAME}) + + # Merge the generated profile data so llvm-cov can process it + add_custom_target( + ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${LLVM_PROFDATA_PATH} merge -sparse + ${target_code_coverage_COVERAGE_TARGET_NAME}.profraw -o + ${target_code_coverage_COVERAGE_TARGET_NAME}.profdata + DEPENDS ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME}) + + # Ignore regex only works on LLVM >= 7 + if(LLVM_COV_VERSION VERSION_GREATER_EQUAL "7.0.0") + foreach(EXCLUDE_ITEM ${target_code_coverage_EXCLUDE}) + set(EXCLUDE_REGEX ${EXCLUDE_REGEX} + -ignore-filename-regex='${EXCLUDE_ITEM}') + endforeach() + endif() + + # Print out details of the coverage information to the command line + add_custom_target( + ccov-show-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${LLVM_COV_PATH} show $ ${SO_OBJECTS} + -instr-profile=${target_code_coverage_COVERAGE_TARGET_NAME}.profdata + -show-line-counts-or-regions ${EXCLUDE_REGEX} + DEPENDS ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME}) + + # Print out a summary of the coverage information to the command line + add_custom_target( + ccov-report-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${LLVM_COV_PATH} report $ ${SO_OBJECTS} + -instr-profile=${target_code_coverage_COVERAGE_TARGET_NAME}.profdata + ${EXCLUDE_REGEX} + DEPENDS ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME}) + + # Export coverage information so continuous integration tools (e.g. + # Jenkins) can consume it + add_custom_target( + ccov-export-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${LLVM_COV_PATH} export $ ${SO_OBJECTS} + -instr-profile=${target_code_coverage_COVERAGE_TARGET_NAME}.profdata + -format="text" ${EXCLUDE_REGEX} > + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME}.json + DEPENDS ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME}) + + # Generates HTML output of the coverage information for perusal + add_custom_target( + ccov-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${LLVM_COV_PATH} show $ ${SO_OBJECTS} + -instr-profile=${target_code_coverage_COVERAGE_TARGET_NAME}.profdata + -show-line-counts-or-regions + -output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME} + -format="html" ${EXCLUDE_REGEX} + DEPENDS ccov-processing-${target_code_coverage_COVERAGE_TARGET_NAME}) + + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES + "GNU") + set(COVERAGE_INFO + "${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME}.info" + ) + + # Run the executable, generating coverage information + add_custom_target( + ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND $ ${target_code_coverage_ARGS} + DEPENDS ccov-preprocessing ${TARGET_NAME}) + + # Generate exclusion string for use + foreach(EXCLUDE_ITEM ${target_code_coverage_EXCLUDE}) + set(EXCLUDE_REGEX ${EXCLUDE_REGEX} --remove ${COVERAGE_INFO} + '${EXCLUDE_ITEM}') + endforeach() + + if(EXCLUDE_REGEX) + set(EXCLUDE_COMMAND ${LCOV_PATH} ${EXCLUDE_REGEX} --output-file + ${COVERAGE_INFO}) + else() + set(EXCLUDE_COMMAND ;) + endif() + + if(NOT ${target_code_coverage_EXTERNAL}) + set(EXTERNAL_OPTION --no-external) + endif() + + # Capture coverage data + if(${CMAKE_VERSION} VERSION_LESS "3.17.0") + add_custom_target( + ccov-capture-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND ${CMAKE_COMMAND} -E remove -f ${COVERAGE_INFO} + COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --zerocounters + COMMAND $ ${target_code_coverage_ARGS} + COMMAND + ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --base-directory + ${CMAKE_SOURCE_DIR} --capture ${EXTERNAL_OPTION} --output-file + ${COVERAGE_INFO} + COMMAND ${EXCLUDE_COMMAND} + DEPENDS ccov-preprocessing ${TARGET_NAME}) + else() + add_custom_target( + ccov-capture-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND ${CMAKE_COMMAND} -E rm -f ${COVERAGE_INFO} + COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --zerocounters + COMMAND $ ${target_code_coverage_ARGS} + COMMAND + ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --base-directory + ${CMAKE_SOURCE_DIR} --capture ${EXTERNAL_OPTION} --output-file + ${COVERAGE_INFO} + COMMAND ${EXCLUDE_COMMAND} + DEPENDS ccov-preprocessing ${TARGET_NAME}) + endif() + + # Generates HTML output of the coverage information for perusal + add_custom_target( + ccov-${target_code_coverage_COVERAGE_TARGET_NAME} + COMMAND + ${GENHTML_PATH} -o + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME} + ${COVERAGE_INFO} + DEPENDS ccov-capture-${target_code_coverage_COVERAGE_TARGET_NAME}) + endif() + + add_custom_command( + TARGET ccov-${target_code_coverage_COVERAGE_TARGET_NAME} + POST_BUILD + COMMAND ; + COMMENT + "Open ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${target_code_coverage_COVERAGE_TARGET_NAME}/index.html in your browser to view the coverage report." + ) + + # AUTO + if(target_code_coverage_AUTO) + if(NOT TARGET ccov) + add_custom_target(ccov) + endif() + add_dependencies(ccov ccov-${target_code_coverage_COVERAGE_TARGET_NAME}) + + if(NOT CMAKE_C_COMPILER_ID MATCHES "GNU" AND NOT CMAKE_CXX_COMPILER_ID + MATCHES "GNU") + if(NOT TARGET ccov-report) + add_custom_target(ccov-report) + endif() + add_dependencies( + ccov-report + ccov-report-${target_code_coverage_COVERAGE_TARGET_NAME}) + endif() + endif() + + # ALL + if(target_code_coverage_ALL) + if(NOT TARGET ccov-all-processing) + message( + FATAL_ERROR + "Calling target_code_coverage with 'ALL' must be after a call to 'add_code_coverage_all_targets'." + ) + endif() + + add_dependencies(ccov-all-processing + ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME}) + endif() + endif() + endif() +endfunction() + +# Adds code coverage instrumentation to all targets in the current directory and +# any subdirectories. To add coverage instrumentation to only specific targets, +# use `target_code_coverage`. +function(add_code_coverage) + if(CODE_COVERAGE) + if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" + OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") + add_compile_options(-fprofile-instr-generate -fcoverage-mapping) + add_link_options(-fprofile-instr-generate -fcoverage-mapping) + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES + "GNU") + add_compile_options(-fprofile-arcs -ftest-coverage) + link_libraries(gcov) + endif() + endif() +endfunction() + +# Adds the 'ccov-all' type targets that calls all targets added via +# `target_code_coverage` with the `ALL` parameter, but merges all the coverage +# data from them into a single large report instead of the numerous smaller +# reports. Also adds the ccov-all-capture Generates an all-merged.info file, for +# use with coverage dashboards (e.g. codecov.io, coveralls). +# ~~~ +# Optional: +# EXCLUDE - Excludes files of the patterns provided from coverage. Note that GCC/lcov excludes by glob pattern, and clang/LLVM excludes via regex! +# ~~~ +function(add_code_coverage_all_targets) + # Argument parsing + set(multi_value_keywords EXCLUDE) + cmake_parse_arguments(add_code_coverage_all_targets "" "" + "${multi_value_keywords}" ${ARGN}) + + if(CODE_COVERAGE) + if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang" + OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang") + + # Merge the profile data for all of the run executables + if(WIN32) + add_custom_target( + ccov-all-processing + COMMAND + powershell -Command $$FILELIST = Get-Content + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list\; llvm-profdata.exe + merge -o ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + -sparse $$FILELIST) + else() + add_custom_target( + ccov-all-processing + COMMAND + ${LLVM_PROFDATA_PATH} merge -o + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata -sparse `cat + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list`) + endif() + + # Regex exclude only available for LLVM >= 7 + if(LLVM_COV_VERSION VERSION_GREATER_EQUAL "7.0.0") + foreach(EXCLUDE_ITEM ${add_code_coverage_all_targets_EXCLUDE}) + set(EXCLUDE_REGEX ${EXCLUDE_REGEX} + -ignore-filename-regex='${EXCLUDE_ITEM}') + endforeach() + endif() + + # Print summary of the code coverage information to the command line + if(WIN32) + add_custom_target( + ccov-all-report + COMMAND + powershell -Command $$FILELIST = Get-Content + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list\; llvm-cov.exe + report $$FILELIST + -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + ${EXCLUDE_REGEX} + DEPENDS ccov-all-processing) + else() + add_custom_target( + ccov-all-report + COMMAND + ${LLVM_COV_PATH} report `cat + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list` + -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + ${EXCLUDE_REGEX} + DEPENDS ccov-all-processing) + endif() + + # Export coverage information so continuous integration tools (e.g. + # Jenkins) can consume it + add_custom_target( + ccov-all-export + COMMAND + ${LLVM_COV_PATH} export `cat + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list` + -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + -format="text" ${EXCLUDE_REGEX} > + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/coverage.json + DEPENDS ccov-all-processing) + + # Generate HTML output of all added targets for perusal + if(WIN32) + add_custom_target( + ccov-all + COMMAND + powershell -Command $$FILELIST = Get-Content + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list\; llvm-cov.exe show + $$FILELIST + -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + -show-line-counts-or-regions + -output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged + -format="html" ${EXCLUDE_REGEX} + DEPENDS ccov-all-processing) + else() + add_custom_target( + ccov-all + COMMAND + ${LLVM_COV_PATH} show `cat + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list` + -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + -show-line-counts-or-regions + -output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged + -format="html" ${EXCLUDE_REGEX} + DEPENDS ccov-all-processing) + endif() + + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES + "GNU") + set(COVERAGE_INFO "${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.info") + + # Nothing required for gcov + add_custom_target(ccov-all-processing COMMAND ;) + + # Exclusion regex string creation + set(EXCLUDE_REGEX) + foreach(EXCLUDE_ITEM ${add_code_coverage_all_targets_EXCLUDE}) + set(EXCLUDE_REGEX ${EXCLUDE_REGEX} --remove ${COVERAGE_INFO} + '${EXCLUDE_ITEM}') + endforeach() + + if(EXCLUDE_REGEX) + set(EXCLUDE_COMMAND ${LCOV_PATH} ${EXCLUDE_REGEX} --output-file + ${COVERAGE_INFO}) + else() + set(EXCLUDE_COMMAND ;) + endif() + + # Capture coverage data + if(${CMAKE_VERSION} VERSION_LESS "3.17.0") + add_custom_target( + ccov-all-capture + COMMAND ${CMAKE_COMMAND} -E remove -f ${COVERAGE_INFO} + COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --capture + --output-file ${COVERAGE_INFO} + COMMAND ${EXCLUDE_COMMAND} + DEPENDS ccov-preprocessing ccov-all-processing) + else() + add_custom_target( + ccov-all-capture + COMMAND ${CMAKE_COMMAND} -E rm -f ${COVERAGE_INFO} + COMMAND ${LCOV_PATH} --directory ${CMAKE_BINARY_DIR} --capture + --output-file ${COVERAGE_INFO} + COMMAND ${EXCLUDE_COMMAND} + DEPENDS ccov-preprocessing ccov-all-processing) + endif() + + # Generates HTML output of all targets for perusal + add_custom_target( + ccov-all + COMMAND ${GENHTML_PATH} -o ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged + ${COVERAGE_INFO} -p ${CMAKE_SOURCE_DIR} + DEPENDS ccov-all-capture) + + endif() + + add_custom_command( + TARGET ccov-all + POST_BUILD + COMMAND ; + COMMENT + "Open ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged/index.html in your browser to view the coverage report." + ) + endif() +endfunction() diff --git a/cmake/conan.cmake b/cmake/conan.cmake new file mode 100644 index 000000000..4f5f67e74 --- /dev/null +++ b/cmake/conan.cmake @@ -0,0 +1,1026 @@ +# The MIT License (MIT) + +# Copyright (c) 2018 JFrog + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + + +# This file comes from: https://github.com/conan-io/cmake-conan. Please refer +# to this repository for issues and documentation. + +# Its purpose is to wrap and launch Conan C/C++ Package Manager when cmake is called. +# It will take CMake current settings (os, compiler, compiler version, architecture) +# and translate them to conan settings for installing and retrieving dependencies. + +# It is intended to facilitate developers building projects that have conan dependencies, +# but it is only necessary on the end-user side. It is not necessary to create conan +# packages, in fact it shouldn't be use for that. Check the project documentation. + +# version: 0.18.1 + +include(CMakeParseArguments) + +function(_get_msvc_ide_version result) + set(${result} "" PARENT_SCOPE) + if(NOT MSVC_VERSION VERSION_LESS 1400 AND MSVC_VERSION VERSION_LESS 1500) + set(${result} 8 PARENT_SCOPE) + elseif(NOT MSVC_VERSION VERSION_LESS 1500 AND MSVC_VERSION VERSION_LESS 1600) + set(${result} 9 PARENT_SCOPE) + elseif(NOT MSVC_VERSION VERSION_LESS 1600 AND MSVC_VERSION VERSION_LESS 1700) + set(${result} 10 PARENT_SCOPE) + elseif(NOT MSVC_VERSION VERSION_LESS 1700 AND MSVC_VERSION VERSION_LESS 1800) + set(${result} 11 PARENT_SCOPE) + elseif(NOT MSVC_VERSION VERSION_LESS 1800 AND MSVC_VERSION VERSION_LESS 1900) + set(${result} 12 PARENT_SCOPE) + elseif(NOT MSVC_VERSION VERSION_LESS 1900 AND MSVC_VERSION VERSION_LESS 1910) + set(${result} 14 PARENT_SCOPE) + elseif(NOT MSVC_VERSION VERSION_LESS 1910 AND MSVC_VERSION VERSION_LESS 1920) + set(${result} 15 PARENT_SCOPE) + elseif(NOT MSVC_VERSION VERSION_LESS 1920 AND MSVC_VERSION VERSION_LESS 1930) + set(${result} 16 PARENT_SCOPE) + elseif(NOT MSVC_VERSION VERSION_LESS 1930 AND MSVC_VERSION VERSION_LESS 1940) + set(${result} 17 PARENT_SCOPE) + else() + message(FATAL_ERROR "Conan: Unknown MSVC compiler version [${MSVC_VERSION}]") + endif() +endfunction() + +macro(_conan_detect_build_type) + conan_parse_arguments(${ARGV}) + + if(ARGUMENTS_BUILD_TYPE) + set(_CONAN_SETTING_BUILD_TYPE ${ARGUMENTS_BUILD_TYPE}) + elseif(CMAKE_BUILD_TYPE) + set(_CONAN_SETTING_BUILD_TYPE ${CMAKE_BUILD_TYPE}) + else() + message(FATAL_ERROR "Please specify in command line CMAKE_BUILD_TYPE (-DCMAKE_BUILD_TYPE=Release)") + endif() + + string(TOUPPER ${_CONAN_SETTING_BUILD_TYPE} _CONAN_SETTING_BUILD_TYPE_UPPER) + if (_CONAN_SETTING_BUILD_TYPE_UPPER STREQUAL "DEBUG") + set(_CONAN_SETTING_BUILD_TYPE "Debug") + elseif(_CONAN_SETTING_BUILD_TYPE_UPPER STREQUAL "RELEASE") + set(_CONAN_SETTING_BUILD_TYPE "Release") + elseif(_CONAN_SETTING_BUILD_TYPE_UPPER STREQUAL "RELWITHDEBINFO") + set(_CONAN_SETTING_BUILD_TYPE "RelWithDebInfo") + elseif(_CONAN_SETTING_BUILD_TYPE_UPPER STREQUAL "MINSIZEREL") + set(_CONAN_SETTING_BUILD_TYPE "MinSizeRel") + endif() +endmacro() + +macro(_conan_check_system_name) + #handle -s os setting + if(CMAKE_SYSTEM_NAME AND NOT CMAKE_SYSTEM_NAME STREQUAL "Generic") + #use default conan os setting if CMAKE_SYSTEM_NAME is not defined + set(CONAN_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}) + if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") + set(CONAN_SYSTEM_NAME Macos) + endif() + if(${CMAKE_SYSTEM_NAME} STREQUAL "QNX") + set(CONAN_SYSTEM_NAME Neutrino) + endif() + set(CONAN_SUPPORTED_PLATFORMS Windows Linux Macos Android iOS FreeBSD WindowsStore WindowsCE watchOS tvOS FreeBSD SunOS AIX Arduino Emscripten Neutrino) + list (FIND CONAN_SUPPORTED_PLATFORMS "${CONAN_SYSTEM_NAME}" _index) + if (${_index} GREATER -1) + #check if the cmake system is a conan supported one + set(_CONAN_SETTING_OS ${CONAN_SYSTEM_NAME}) + else() + message(FATAL_ERROR "cmake system ${CONAN_SYSTEM_NAME} is not supported by conan. Use one of ${CONAN_SUPPORTED_PLATFORMS}") + endif() + endif() +endmacro() + +macro(_conan_check_language) + get_property(_languages GLOBAL PROPERTY ENABLED_LANGUAGES) + if (";${_languages};" MATCHES ";CXX;") + set(LANGUAGE CXX) + set(USING_CXX 1) + elseif (";${_languages};" MATCHES ";C;") + set(LANGUAGE C) + set(USING_CXX 0) + else () + message(FATAL_ERROR "Conan: Neither C or C++ was detected as a language for the project. Unabled to detect compiler version.") + endif() +endmacro() + +macro(_conan_detect_compiler) + + conan_parse_arguments(${ARGV}) + + if(ARGUMENTS_ARCH) + set(_CONAN_SETTING_ARCH ${ARGUMENTS_ARCH}) + endif() + + if(USING_CXX) + set(_CONAN_SETTING_COMPILER_CPPSTD ${CMAKE_CXX_STANDARD}) + endif() + + if (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL GNU) + # using GCC + # TODO: Handle other params + string(REPLACE "." ";" VERSION_LIST ${CMAKE_${LANGUAGE}_COMPILER_VERSION}) + list(GET VERSION_LIST 0 MAJOR) + list(GET VERSION_LIST 1 MINOR) + set(COMPILER_VERSION ${MAJOR}.${MINOR}) + if(${MAJOR} GREATER 4) + set(COMPILER_VERSION ${MAJOR}) + endif() + set(_CONAN_SETTING_COMPILER gcc) + set(_CONAN_SETTING_COMPILER_VERSION ${COMPILER_VERSION}) + if (USING_CXX) + conan_cmake_detect_unix_libcxx(_LIBCXX) + set(_CONAN_SETTING_COMPILER_LIBCXX ${_LIBCXX}) + endif () + elseif (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL Intel) + string(REPLACE "." ";" VERSION_LIST ${CMAKE_${LANGUAGE}_COMPILER_VERSION}) + list(GET VERSION_LIST 0 MAJOR) + list(GET VERSION_LIST 1 MINOR) + set(COMPILER_VERSION ${MAJOR}.${MINOR}) + set(_CONAN_SETTING_COMPILER intel) + set(_CONAN_SETTING_COMPILER_VERSION ${COMPILER_VERSION}) + if (USING_CXX) + conan_cmake_detect_unix_libcxx(_LIBCXX) + set(_CONAN_SETTING_COMPILER_LIBCXX ${_LIBCXX}) + endif () + elseif (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL AppleClang) + # using AppleClang + string(REPLACE "." ";" VERSION_LIST ${CMAKE_${LANGUAGE}_COMPILER_VERSION}) + list(GET VERSION_LIST 0 MAJOR) + list(GET VERSION_LIST 1 MINOR) + set(_CONAN_SETTING_COMPILER apple-clang) + set(_CONAN_SETTING_COMPILER_VERSION ${MAJOR}.${MINOR}) + if (USING_CXX) + conan_cmake_detect_unix_libcxx(_LIBCXX) + set(_CONAN_SETTING_COMPILER_LIBCXX ${_LIBCXX}) + endif () + elseif (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL Clang + AND NOT "${CMAKE_${LANGUAGE}_COMPILER_FRONTEND_VARIANT}" STREQUAL "MSVC" + AND NOT "${CMAKE_${LANGUAGE}_SIMULATE_ID}" STREQUAL "MSVC") + + string(REPLACE "." ";" VERSION_LIST ${CMAKE_${LANGUAGE}_COMPILER_VERSION}) + list(GET VERSION_LIST 0 MAJOR) + list(GET VERSION_LIST 1 MINOR) + set(_CONAN_SETTING_COMPILER clang) + set(_CONAN_SETTING_COMPILER_VERSION ${MAJOR}.${MINOR}) + if(APPLE) + cmake_policy(GET CMP0025 APPLE_CLANG_POLICY) + if(NOT APPLE_CLANG_POLICY STREQUAL NEW) + message(STATUS "Conan: APPLE and Clang detected. Assuming apple-clang compiler. Set CMP0025 to avoid it") + set(_CONAN_SETTING_COMPILER apple-clang) + endif() + endif() + if(${_CONAN_SETTING_COMPILER} STREQUAL clang AND ${MAJOR} GREATER 7) + set(_CONAN_SETTING_COMPILER_VERSION ${MAJOR}) + endif() + if (USING_CXX) + conan_cmake_detect_unix_libcxx(_LIBCXX) + set(_CONAN_SETTING_COMPILER_LIBCXX ${_LIBCXX}) + endif () + elseif(${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL MSVC + OR (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL Clang + AND "${CMAKE_${LANGUAGE}_COMPILER_FRONTEND_VARIANT}" STREQUAL "MSVC" + AND "${CMAKE_${LANGUAGE}_SIMULATE_ID}" STREQUAL "MSVC")) + + set(_VISUAL "Visual Studio") + _get_msvc_ide_version(_VISUAL_VERSION) + if("${_VISUAL_VERSION}" STREQUAL "") + message(FATAL_ERROR "Conan: Visual Studio not recognized") + else() + set(_CONAN_SETTING_COMPILER ${_VISUAL}) + set(_CONAN_SETTING_COMPILER_VERSION ${_VISUAL_VERSION}) + endif() + + if(NOT _CONAN_SETTING_ARCH) + if (MSVC_${LANGUAGE}_ARCHITECTURE_ID MATCHES "64") + set(_CONAN_SETTING_ARCH x86_64) + elseif (MSVC_${LANGUAGE}_ARCHITECTURE_ID MATCHES "^ARM") + message(STATUS "Conan: Using default ARM architecture from MSVC") + set(_CONAN_SETTING_ARCH armv6) + elseif (MSVC_${LANGUAGE}_ARCHITECTURE_ID MATCHES "86") + set(_CONAN_SETTING_ARCH x86) + else () + message(FATAL_ERROR "Conan: Unknown MSVC architecture [${MSVC_${LANGUAGE}_ARCHITECTURE_ID}]") + endif() + endif() + + conan_cmake_detect_vs_runtime(_vs_runtime ${ARGV}) + message(STATUS "Conan: Detected VS runtime: ${_vs_runtime}") + set(_CONAN_SETTING_COMPILER_RUNTIME ${_vs_runtime}) + + if (CMAKE_GENERATOR_TOOLSET) + set(_CONAN_SETTING_COMPILER_TOOLSET ${CMAKE_VS_PLATFORM_TOOLSET}) + elseif(CMAKE_VS_PLATFORM_TOOLSET AND (CMAKE_GENERATOR STREQUAL "Ninja")) + set(_CONAN_SETTING_COMPILER_TOOLSET ${CMAKE_VS_PLATFORM_TOOLSET}) + endif() + else() + message(FATAL_ERROR "Conan: compiler setup not recognized") + endif() + +endmacro() + +function(conan_cmake_settings result) + #message(STATUS "COMPILER " ${CMAKE_CXX_COMPILER}) + #message(STATUS "COMPILER " ${CMAKE_CXX_COMPILER_ID}) + #message(STATUS "VERSION " ${CMAKE_CXX_COMPILER_VERSION}) + #message(STATUS "FLAGS " ${CMAKE_LANG_FLAGS}) + #message(STATUS "LIB ARCH " ${CMAKE_CXX_LIBRARY_ARCHITECTURE}) + #message(STATUS "BUILD TYPE " ${CMAKE_BUILD_TYPE}) + #message(STATUS "GENERATOR " ${CMAKE_GENERATOR}) + #message(STATUS "GENERATOR WIN64 " ${CMAKE_CL_64}) + + message(STATUS "Conan: Automatic detection of conan settings from cmake") + + conan_parse_arguments(${ARGV}) + + _conan_detect_build_type(${ARGV}) + + _conan_check_system_name() + + _conan_check_language() + + _conan_detect_compiler(${ARGV}) + + # If profile is defined it is used + if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND ARGUMENTS_DEBUG_PROFILE) + set(_APPLIED_PROFILES ${ARGUMENTS_DEBUG_PROFILE}) + elseif(CMAKE_BUILD_TYPE STREQUAL "Release" AND ARGUMENTS_RELEASE_PROFILE) + set(_APPLIED_PROFILES ${ARGUMENTS_RELEASE_PROFILE}) + elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" AND ARGUMENTS_RELWITHDEBINFO_PROFILE) + set(_APPLIED_PROFILES ${ARGUMENTS_RELWITHDEBINFO_PROFILE}) + elseif(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel" AND ARGUMENTS_MINSIZEREL_PROFILE) + set(_APPLIED_PROFILES ${ARGUMENTS_MINSIZEREL_PROFILE}) + elseif(ARGUMENTS_PROFILE) + set(_APPLIED_PROFILES ${ARGUMENTS_PROFILE}) + endif() + + foreach(ARG ${_APPLIED_PROFILES}) + set(_SETTINGS ${_SETTINGS} -pr=${ARG}) + endforeach() + foreach(ARG ${ARGUMENTS_PROFILE_BUILD}) + conan_check(VERSION 1.24.0 REQUIRED DETECT_QUIET) + set(_SETTINGS ${_SETTINGS} -pr:b=${ARG}) + endforeach() + + if(NOT _SETTINGS OR ARGUMENTS_PROFILE_AUTO STREQUAL "ALL") + set(ARGUMENTS_PROFILE_AUTO arch build_type compiler compiler.version + compiler.runtime compiler.libcxx compiler.toolset) + endif() + + # remove any manually specified settings from the autodetected settings + foreach(ARG ${ARGUMENTS_SETTINGS}) + string(REGEX MATCH "[^=]*" MANUAL_SETTING "${ARG}") + message(STATUS "Conan: ${MANUAL_SETTING} was added as an argument. Not using the autodetected one.") + list(REMOVE_ITEM ARGUMENTS_PROFILE_AUTO "${MANUAL_SETTING}") + endforeach() + + # Automatic from CMake + foreach(ARG ${ARGUMENTS_PROFILE_AUTO}) + string(TOUPPER ${ARG} _arg_name) + string(REPLACE "." "_" _arg_name ${_arg_name}) + if(_CONAN_SETTING_${_arg_name}) + set(_SETTINGS ${_SETTINGS} -s ${ARG}=${_CONAN_SETTING_${_arg_name}}) + endif() + endforeach() + + foreach(ARG ${ARGUMENTS_SETTINGS}) + set(_SETTINGS ${_SETTINGS} -s ${ARG}) + endforeach() + + message(STATUS "Conan: Settings= ${_SETTINGS}") + + set(${result} ${_SETTINGS} PARENT_SCOPE) +endfunction() + + +function(conan_cmake_detect_unix_libcxx result) + # Take into account any -stdlib in compile options + get_directory_property(compile_options DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_OPTIONS) + string(GENEX_STRIP "${compile_options}" compile_options) + + # Take into account any _GLIBCXX_USE_CXX11_ABI in compile definitions + get_directory_property(defines DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS) + string(GENEX_STRIP "${defines}" defines) + + foreach(define ${defines}) + if(define MATCHES "_GLIBCXX_USE_CXX11_ABI") + if(define MATCHES "^-D") + set(compile_options ${compile_options} "${define}") + else() + set(compile_options ${compile_options} "-D${define}") + endif() + endif() + endforeach() + + # add additional compiler options ala cmRulePlaceholderExpander::ExpandRuleVariable + set(EXPAND_CXX_COMPILER ${CMAKE_CXX_COMPILER}) + if(CMAKE_CXX_COMPILER_ARG1) + # CMake splits CXX="foo bar baz" into CMAKE_CXX_COMPILER="foo", CMAKE_CXX_COMPILER_ARG1="bar baz" + # without this, ccache, winegcc, or other wrappers might lose all their arguments + separate_arguments(SPLIT_CXX_COMPILER_ARG1 NATIVE_COMMAND ${CMAKE_CXX_COMPILER_ARG1}) + list(APPEND EXPAND_CXX_COMPILER ${SPLIT_CXX_COMPILER_ARG1}) + endif() + + if(CMAKE_CXX_COMPILE_OPTIONS_TARGET AND CMAKE_CXX_COMPILER_TARGET) + # without --target= we may be calling the wrong underlying GCC + list(APPEND EXPAND_CXX_COMPILER "${CMAKE_CXX_COMPILE_OPTIONS_TARGET}${CMAKE_CXX_COMPILER_TARGET}") + endif() + + if(CMAKE_CXX_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN AND CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN) + list(APPEND EXPAND_CXX_COMPILER "${CMAKE_CXX_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN}${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN}") + endif() + + if(CMAKE_CXX_COMPILE_OPTIONS_SYSROOT) + # without --sysroot= we may find the wrong #include + if(CMAKE_SYSROOT_COMPILE) + list(APPEND EXPAND_CXX_COMPILER "${CMAKE_CXX_COMPILE_OPTIONS_SYSROOT}${CMAKE_SYSROOT_COMPILE}") + elseif(CMAKE_SYSROOT) + list(APPEND EXPAND_CXX_COMPILER "${CMAKE_CXX_COMPILE_OPTIONS_SYSROOT}${CMAKE_SYSROOT}") + endif() + endif() + + separate_arguments(SPLIT_CXX_FLAGS NATIVE_COMMAND ${CMAKE_CXX_FLAGS}) + + if(CMAKE_OSX_SYSROOT) + set(xcode_sysroot_option "--sysroot=${CMAKE_OSX_SYSROOT}") + endif() + + execute_process( + COMMAND ${CMAKE_COMMAND} -E echo "#include " + COMMAND ${EXPAND_CXX_COMPILER} ${SPLIT_CXX_FLAGS} -x c++ ${xcode_sysroot_option} ${compile_options} -E -dM - + OUTPUT_VARIABLE string_defines + ) + + if(string_defines MATCHES "#define __GLIBCXX__") + # Allow -D_GLIBCXX_USE_CXX11_ABI=ON/OFF as argument to cmake + if(DEFINED _GLIBCXX_USE_CXX11_ABI) + if(_GLIBCXX_USE_CXX11_ABI) + set(${result} libstdc++11 PARENT_SCOPE) + return() + else() + set(${result} libstdc++ PARENT_SCOPE) + return() + endif() + endif() + + if(string_defines MATCHES "#define _GLIBCXX_USE_CXX11_ABI 1\n") + set(${result} libstdc++11 PARENT_SCOPE) + else() + # Either the compiler is missing the define because it is old, and so + # it can't use the new abi, or the compiler was configured to use the + # old abi by the user or distro (e.g. devtoolset on RHEL/CentOS) + set(${result} libstdc++ PARENT_SCOPE) + endif() + else() + set(${result} libc++ PARENT_SCOPE) + endif() +endfunction() + +function(conan_cmake_detect_vs_runtime result) + + conan_parse_arguments(${ARGV}) + if(ARGUMENTS_BUILD_TYPE) + set(build_type "${ARGUMENTS_BUILD_TYPE}") + elseif(CMAKE_BUILD_TYPE) + set(build_type "${CMAKE_BUILD_TYPE}") + else() + message(FATAL_ERROR "Please specify in command line CMAKE_BUILD_TYPE (-DCMAKE_BUILD_TYPE=Release)") + endif() + + if(build_type) + string(TOUPPER "${build_type}" build_type) + endif() + set(variables CMAKE_CXX_FLAGS_${build_type} CMAKE_C_FLAGS_${build_type} CMAKE_CXX_FLAGS CMAKE_C_FLAGS) + foreach(variable ${variables}) + if(NOT "${${variable}}" STREQUAL "") + string(REPLACE " " ";" flags "${${variable}}") + foreach (flag ${flags}) + if("${flag}" STREQUAL "/MD" OR "${flag}" STREQUAL "/MDd" OR "${flag}" STREQUAL "/MT" OR "${flag}" STREQUAL "/MTd") + string(SUBSTRING "${flag}" 1 -1 runtime) + set(${result} "${runtime}" PARENT_SCOPE) + return() + endif() + endforeach() + endif() + endforeach() + if("${build_type}" STREQUAL "DEBUG") + set(${result} "MDd" PARENT_SCOPE) + else() + set(${result} "MD" PARENT_SCOPE) + endif() +endfunction() + +function(_collect_settings result) + set(ARGUMENTS_PROFILE_AUTO arch build_type compiler compiler.version + compiler.runtime compiler.libcxx compiler.toolset + compiler.cppstd) + foreach(ARG ${ARGUMENTS_PROFILE_AUTO}) + string(TOUPPER ${ARG} _arg_name) + string(REPLACE "." "_" _arg_name ${_arg_name}) + if(_CONAN_SETTING_${_arg_name}) + set(detected_setings ${detected_setings} ${ARG}=${_CONAN_SETTING_${_arg_name}}) + endif() + endforeach() + set(${result} ${detected_setings} PARENT_SCOPE) +endfunction() + +function(conan_cmake_autodetect detected_settings) + _conan_detect_build_type(${ARGV}) + _conan_check_system_name() + _conan_check_language() + _conan_detect_compiler(${ARGV}) + _collect_settings(collected_settings) + set(${detected_settings} ${collected_settings} PARENT_SCOPE) +endfunction() + +macro(conan_parse_arguments) + set(options BASIC_SETUP CMAKE_TARGETS UPDATE KEEP_RPATHS NO_LOAD NO_OUTPUT_DIRS OUTPUT_QUIET NO_IMPORTS SKIP_STD) + set(oneValueArgs CONANFILE ARCH BUILD_TYPE INSTALL_FOLDER OUTPUT_FOLDER CONAN_COMMAND) + set(multiValueArgs DEBUG_PROFILE RELEASE_PROFILE RELWITHDEBINFO_PROFILE MINSIZEREL_PROFILE + PROFILE REQUIRES OPTIONS IMPORTS SETTINGS BUILD ENV GENERATORS PROFILE_AUTO + INSTALL_ARGS CONFIGURATION_TYPES PROFILE_BUILD BUILD_REQUIRES) + cmake_parse_arguments(ARGUMENTS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) +endmacro() + +function(old_conan_cmake_install) + # Calls "conan install" + # Argument BUILD is equivalant to --build={missing, PkgName,...} or + # --build when argument is 'BUILD all' (which builds all packages from source) + # Argument CONAN_COMMAND, to specify the conan path, e.g. in case of running from source + # cmake does not identify conan as command, even if it is +x and it is in the path + conan_parse_arguments(${ARGV}) + + if(CONAN_CMAKE_MULTI) + set(ARGUMENTS_GENERATORS ${ARGUMENTS_GENERATORS} cmake_multi) + else() + set(ARGUMENTS_GENERATORS ${ARGUMENTS_GENERATORS} cmake) + endif() + + set(CONAN_BUILD_POLICY "") + foreach(ARG ${ARGUMENTS_BUILD}) + if(${ARG} STREQUAL "all") + set(CONAN_BUILD_POLICY ${CONAN_BUILD_POLICY} --build) + break() + else() + set(CONAN_BUILD_POLICY ${CONAN_BUILD_POLICY} --build=${ARG}) + endif() + endforeach() + if(ARGUMENTS_CONAN_COMMAND) + set(CONAN_CMD ${ARGUMENTS_CONAN_COMMAND}) + else() + conan_check(REQUIRED) + endif() + set(CONAN_OPTIONS "") + if(ARGUMENTS_CONANFILE) + if(IS_ABSOLUTE ${ARGUMENTS_CONANFILE}) + set(CONANFILE ${ARGUMENTS_CONANFILE}) + else() + set(CONANFILE ${CMAKE_CURRENT_SOURCE_DIR}/${ARGUMENTS_CONANFILE}) + endif() + else() + set(CONANFILE ".") + endif() + foreach(ARG ${ARGUMENTS_OPTIONS}) + set(CONAN_OPTIONS ${CONAN_OPTIONS} -o=${ARG}) + endforeach() + if(ARGUMENTS_UPDATE) + set(CONAN_INSTALL_UPDATE --update) + endif() + if(ARGUMENTS_NO_IMPORTS) + set(CONAN_INSTALL_NO_IMPORTS --no-imports) + endif() + set(CONAN_INSTALL_FOLDER "") + if(ARGUMENTS_INSTALL_FOLDER) + set(CONAN_INSTALL_FOLDER -if=${ARGUMENTS_INSTALL_FOLDER}) + endif() + set(CONAN_OUTPUT_FOLDER "") + if(ARGUMENTS_OUTPUT_FOLDER) + set(CONAN_OUTPUT_FOLDER -of=${ARGUMENTS_OUTPUT_FOLDER}) + endif() + foreach(ARG ${ARGUMENTS_GENERATORS}) + set(CONAN_GENERATORS ${CONAN_GENERATORS} -g=${ARG}) + endforeach() + foreach(ARG ${ARGUMENTS_ENV}) + set(CONAN_ENV_VARS ${CONAN_ENV_VARS} -e=${ARG}) + endforeach() + set(conan_args install ${CONANFILE} ${settings} ${CONAN_ENV_VARS} ${CONAN_GENERATORS} ${CONAN_BUILD_POLICY} ${CONAN_INSTALL_UPDATE} ${CONAN_INSTALL_NO_IMPORTS} ${CONAN_OPTIONS} ${CONAN_INSTALL_FOLDER} ${ARGUMENTS_INSTALL_ARGS}) + + string (REPLACE ";" " " _conan_args "${conan_args}") + message(STATUS "Conan executing: ${CONAN_CMD} ${_conan_args}") + + if(ARGUMENTS_OUTPUT_QUIET) + execute_process(COMMAND ${CONAN_CMD} ${conan_args} + RESULT_VARIABLE return_code + OUTPUT_VARIABLE conan_output + ERROR_VARIABLE conan_output + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + else() + execute_process(COMMAND ${CONAN_CMD} ${conan_args} + RESULT_VARIABLE return_code + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + endif() + + if(NOT "${return_code}" STREQUAL "0") + message(FATAL_ERROR "Conan install failed='${return_code}'") + endif() + +endfunction() + +function(conan_cmake_install) + if(DEFINED CONAN_COMMAND) + set(CONAN_CMD ${CONAN_COMMAND}) + else() + conan_check(REQUIRED) + endif() + + set(installOptions UPDATE NO_IMPORTS OUTPUT_QUIET ERROR_QUIET) + set(installOneValueArgs PATH_OR_REFERENCE REFERENCE REMOTE LOCKFILE LOCKFILE_OUT LOCKFILE_NODE_ID INSTALL_FOLDER OUTPUT_FOLDER) + set(installMultiValueArgs GENERATOR BUILD ENV ENV_HOST ENV_BUILD OPTIONS_HOST OPTIONS OPTIONS_BUILD PROFILE + PROFILE_HOST PROFILE_BUILD SETTINGS SETTINGS_HOST SETTINGS_BUILD) + cmake_parse_arguments(ARGS "${installOptions}" "${installOneValueArgs}" "${installMultiValueArgs}" ${ARGN}) + foreach(arg ${installOptions}) + if(ARGS_${arg}) + set(${arg} ${${arg}} ${ARGS_${arg}}) + endif() + endforeach() + foreach(arg ${installOneValueArgs}) + if(DEFINED ARGS_${arg}) + if("${arg}" STREQUAL "REMOTE") + set(flag "--remote") + elseif("${arg}" STREQUAL "LOCKFILE") + set(flag "--lockfile") + elseif("${arg}" STREQUAL "LOCKFILE_OUT") + set(flag "--lockfile-out") + elseif("${arg}" STREQUAL "LOCKFILE_NODE_ID") + set(flag "--lockfile-node-id") + elseif("${arg}" STREQUAL "INSTALL_FOLDER") + set(flag "--install-folder") + elseif("${arg}" STREQUAL "OUTPUT_FOLDER") + set(flag "--output-folder") + endif() + set(${arg} ${${arg}} ${flag} ${ARGS_${arg}}) + endif() + endforeach() + foreach(arg ${installMultiValueArgs}) + if(DEFINED ARGS_${arg}) + if("${arg}" STREQUAL "GENERATOR") + set(flag "--generator") + elseif("${arg}" STREQUAL "BUILD") + set(flag "--build") + elseif("${arg}" STREQUAL "ENV") + set(flag "--env") + elseif("${arg}" STREQUAL "ENV_HOST") + set(flag "--env:host") + elseif("${arg}" STREQUAL "ENV_BUILD") + set(flag "--env:build") + elseif("${arg}" STREQUAL "OPTIONS") + set(flag "--options") + elseif("${arg}" STREQUAL "OPTIONS_HOST") + set(flag "--options:host") + elseif("${arg}" STREQUAL "OPTIONS_BUILD") + set(flag "--options:build") + elseif("${arg}" STREQUAL "PROFILE") + set(flag "--profile") + elseif("${arg}" STREQUAL "PROFILE_HOST") + set(flag "--profile:host") + elseif("${arg}" STREQUAL "PROFILE_BUILD") + set(flag "--profile:build") + elseif("${arg}" STREQUAL "SETTINGS") + set(flag "--settings") + elseif("${arg}" STREQUAL "SETTINGS_HOST") + set(flag "--settings:host") + elseif("${arg}" STREQUAL "SETTINGS_BUILD") + set(flag "--settings:build") + endif() + list(LENGTH ARGS_${arg} numargs) + foreach(item ${ARGS_${arg}}) + if(${item} STREQUAL "all" AND ${arg} STREQUAL "BUILD") + set(${arg} "--build") + break() + endif() + set(${arg} ${${arg}} ${flag} ${item}) + endforeach() + endif() + endforeach() + if(DEFINED UPDATE) + set(UPDATE --update) + endif() + if(DEFINED NO_IMPORTS) + set(NO_IMPORTS --no-imports) + endif() + set(install_args install ${PATH_OR_REFERENCE} ${REFERENCE} ${UPDATE} ${NO_IMPORTS} ${REMOTE} ${LOCKFILE} ${LOCKFILE_OUT} ${LOCKFILE_NODE_ID} ${INSTALL_FOLDER} ${OUTPUT_FOLDER} + ${GENERATOR} ${BUILD} ${ENV} ${ENV_HOST} ${ENV_BUILD} ${OPTIONS} ${OPTIONS_HOST} ${OPTIONS_BUILD} + ${PROFILE} ${PROFILE_HOST} ${PROFILE_BUILD} ${SETTINGS} ${SETTINGS_HOST} ${SETTINGS_BUILD}) + + string(REPLACE ";" " " _install_args "${install_args}") + message(STATUS "Conan executing: ${CONAN_CMD} ${_install_args}") + + if(ARGS_OUTPUT_QUIET) + set(OUTPUT_OPT OUTPUT_QUIET) + endif() + if(ARGS_ERROR_QUIET) + set(ERROR_OPT ERROR_QUIET) + endif() + + execute_process(COMMAND ${CONAN_CMD} ${install_args} + RESULT_VARIABLE return_code + ${OUTPUT_OPT} + ${ERROR_OPT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + + if(NOT "${return_code}" STREQUAL "0") + if (ARGS_ERROR_QUIET) + message(WARNING "Conan install failed='${return_code}'") + else() + message(FATAL_ERROR "Conan install failed='${return_code}'") + endif() + endif() + +endfunction() + +function(conan_cmake_lock_create) + if(DEFINED CONAN_COMMAND) + set(CONAN_CMD ${CONAN_COMMAND}) + else() + conan_check(REQUIRED) + endif() + + set(lockCreateOptions UPDATE BASE OUTPUT_QUIET ERROR_QUIET) + set(lockCreateOneValueArgs PATH REFERENCE REMOTE LOCKFILE LOCKFILE_OUT) + set(lockCreateMultiValueArgs BUILD ENV ENV_HOST ENV_BUILD OPTIONS_HOST OPTIONS OPTIONS_BUILD PROFILE + PROFILE_HOST PROFILE_BUILD SETTINGS SETTINGS_HOST SETTINGS_BUILD) + cmake_parse_arguments(ARGS "${lockCreateOptions}" "${lockCreateOneValueArgs}" "${lockCreateMultiValueArgs}" ${ARGN}) + foreach(arg ${lockCreateOptions}) + if(ARGS_${arg}) + set(${arg} ${${arg}} ${ARGS_${arg}}) + endif() + endforeach() + foreach(arg ${lockCreateOneValueArgs}) + if(DEFINED ARGS_${arg}) + if("${arg}" STREQUAL "REMOTE") + set(flag "--remote") + elseif("${arg}" STREQUAL "LOCKFILE") + set(flag "--lockfile") + elseif("${arg}" STREQUAL "LOCKFILE_OUT") + set(flag "--lockfile-out") + endif() + set(${arg} ${${arg}} ${flag} ${ARGS_${arg}}) + endif() + endforeach() + foreach(arg ${lockCreateMultiValueArgs}) + if(DEFINED ARGS_${arg}) + if("${arg}" STREQUAL "BUILD") + set(flag "--build") + elseif("${arg}" STREQUAL "ENV") + set(flag "--env") + elseif("${arg}" STREQUAL "ENV_HOST") + set(flag "--env:host") + elseif("${arg}" STREQUAL "ENV_BUILD") + set(flag "--env:build") + elseif("${arg}" STREQUAL "OPTIONS") + set(flag "--options") + elseif("${arg}" STREQUAL "OPTIONS_HOST") + set(flag "--options:host") + elseif("${arg}" STREQUAL "OPTIONS_BUILD") + set(flag "--options:build") + elseif("${arg}" STREQUAL "PROFILE") + set(flag "--profile") + elseif("${arg}" STREQUAL "PROFILE_HOST") + set(flag "--profile:host") + elseif("${arg}" STREQUAL "PROFILE_BUILD") + set(flag "--profile:build") + elseif("${arg}" STREQUAL "SETTINGS") + set(flag "--settings") + elseif("${arg}" STREQUAL "SETTINGS_HOST") + set(flag "--settings:host") + elseif("${arg}" STREQUAL "SETTINGS_BUILD") + set(flag "--settings:build") + endif() + list(LENGTH ARGS_${arg} numargs) + foreach(item ${ARGS_${arg}}) + if(${item} STREQUAL "all" AND ${arg} STREQUAL "BUILD") + set(${arg} "--build") + break() + endif() + set(${arg} ${${arg}} ${flag} ${item}) + endforeach() + endif() + endforeach() + if(DEFINED UPDATE) + set(UPDATE --update) + endif() + if(DEFINED BASE) + set(BASE --base) + endif() + set(lock_create_Args lock create ${PATH} ${REFERENCE} ${UPDATE} ${BASE} ${REMOTE} ${LOCKFILE} ${LOCKFILE_OUT} ${LOCKFILE_NODE_ID} ${INSTALL_FOLDER} + ${GENERATOR} ${BUILD} ${ENV} ${ENV_HOST} ${ENV_BUILD} ${OPTIONS} ${OPTIONS_HOST} ${OPTIONS_BUILD} + ${PROFILE} ${PROFILE_HOST} ${PROFILE_BUILD} ${SETTINGS} ${SETTINGS_HOST} ${SETTINGS_BUILD}) + + string(REPLACE ";" " " _lock_create_Args "${lock_create_Args}") + message(STATUS "Conan executing: ${CONAN_CMD} ${_lock_create_Args}") + + if(ARGS_OUTPUT_QUIET) + set(OUTPUT_OPT OUTPUT_QUIET) + endif() + if(ARGS_ERROR_QUIET) + set(ERROR_OPT ERROR_QUIET) + endif() + + execute_process(COMMAND ${CONAN_CMD} ${lock_create_Args} + RESULT_VARIABLE return_code + ${OUTPUT_OPT} + ${ERROR_OPT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + + if(NOT "${return_code}" STREQUAL "0") + if (ARGS_ERROR_QUIET) + message(WARNING "Conan lock create failed='${return_code}'") + else() + message(FATAL_ERROR "Conan lock create failed='${return_code}'") + endif() + endif() +endfunction() + +function(conan_cmake_setup_conanfile) + conan_parse_arguments(${ARGV}) + if(ARGUMENTS_CONANFILE) + get_filename_component(_CONANFILE_NAME ${ARGUMENTS_CONANFILE} NAME) + # configure_file will make sure cmake re-runs when conanfile is updated + configure_file(${ARGUMENTS_CONANFILE} ${CMAKE_CURRENT_BINARY_DIR}/${_CONANFILE_NAME}.junk COPYONLY) + file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/${_CONANFILE_NAME}.junk) + else() + conan_cmake_generate_conanfile(ON ${ARGV}) + endif() +endfunction() + +function(conan_cmake_configure) + conan_cmake_generate_conanfile(OFF ${ARGV}) +endfunction() + +# Generate, writing in disk a conanfile.txt with the requires, options, and imports +# specified as arguments +# This will be considered as temporary file, generated in CMAKE_CURRENT_BINARY_DIR) +function(conan_cmake_generate_conanfile DEFAULT_GENERATOR) + + conan_parse_arguments(${ARGV}) + + set(_FN "${CMAKE_CURRENT_BINARY_DIR}/conanfile.txt") + file(WRITE ${_FN} "") + + if(DEFINED ARGUMENTS_REQUIRES) + file(APPEND ${_FN} "[requires]\n") + foreach(REQUIRE ${ARGUMENTS_REQUIRES}) + file(APPEND ${_FN} ${REQUIRE} "\n") + endforeach() + endif() + + if (DEFAULT_GENERATOR OR DEFINED ARGUMENTS_GENERATORS) + file(APPEND ${_FN} "[generators]\n") + if (DEFAULT_GENERATOR) + file(APPEND ${_FN} "cmake\n") + endif() + if (DEFINED ARGUMENTS_GENERATORS) + foreach(GENERATOR ${ARGUMENTS_GENERATORS}) + file(APPEND ${_FN} ${GENERATOR} "\n") + endforeach() + endif() + endif() + + if(DEFINED ARGUMENTS_BUILD_REQUIRES) + file(APPEND ${_FN} "[build_requires]\n") + foreach(BUILD_REQUIRE ${ARGUMENTS_BUILD_REQUIRES}) + file(APPEND ${_FN} ${BUILD_REQUIRE} "\n") + endforeach() + endif() + + if(DEFINED ARGUMENTS_IMPORTS) + file(APPEND ${_FN} "[imports]\n") + foreach(IMPORTS ${ARGUMENTS_IMPORTS}) + file(APPEND ${_FN} ${IMPORTS} "\n") + endforeach() + endif() + + if(DEFINED ARGUMENTS_OPTIONS) + file(APPEND ${_FN} "[options]\n") + foreach(OPTION ${ARGUMENTS_OPTIONS}) + file(APPEND ${_FN} ${OPTION} "\n") + endforeach() + endif() + +endfunction() + + +macro(conan_load_buildinfo) + if(CONAN_CMAKE_MULTI) + set(_CONANBUILDINFO conanbuildinfo_multi.cmake) + else() + set(_CONANBUILDINFO conanbuildinfo.cmake) + endif() + if(ARGUMENTS_INSTALL_FOLDER) + set(_CONANBUILDINFOFOLDER ${ARGUMENTS_INSTALL_FOLDER}) + else() + set(_CONANBUILDINFOFOLDER ${CMAKE_CURRENT_BINARY_DIR}) + endif() + # Checks for the existence of conanbuildinfo.cmake, and loads it + # important that it is macro, so variables defined at parent scope + if(EXISTS "${_CONANBUILDINFOFOLDER}/${_CONANBUILDINFO}") + message(STATUS "Conan: Loading ${_CONANBUILDINFO}") + include(${_CONANBUILDINFOFOLDER}/${_CONANBUILDINFO}) + else() + message(FATAL_ERROR "${_CONANBUILDINFO} doesn't exist in ${CMAKE_CURRENT_BINARY_DIR}") + endif() +endmacro() + + +macro(conan_cmake_run) + conan_parse_arguments(${ARGV}) + + if(ARGUMENTS_CONFIGURATION_TYPES AND NOT CMAKE_CONFIGURATION_TYPES) + message(WARNING "CONFIGURATION_TYPES should only be specified for multi-configuration generators") + elseif(ARGUMENTS_CONFIGURATION_TYPES AND ARGUMENTS_BUILD_TYPE) + message(WARNING "CONFIGURATION_TYPES and BUILD_TYPE arguments should not be defined at the same time.") + endif() + + if(CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE AND NOT CONAN_EXPORTED + AND NOT ARGUMENTS_BUILD_TYPE) + set(CONAN_CMAKE_MULTI ON) + if (NOT ARGUMENTS_CONFIGURATION_TYPES) + set(ARGUMENTS_CONFIGURATION_TYPES "Release;Debug") + endif() + message(STATUS "Conan: Using cmake-multi generator") + else() + set(CONAN_CMAKE_MULTI OFF) + endif() + + if(NOT CONAN_EXPORTED) + conan_cmake_setup_conanfile(${ARGV}) + if(CONAN_CMAKE_MULTI) + foreach(CMAKE_BUILD_TYPE ${ARGUMENTS_CONFIGURATION_TYPES}) + set(ENV{CONAN_IMPORT_PATH} ${CMAKE_BUILD_TYPE}) + conan_cmake_settings(settings ${ARGV}) + old_conan_cmake_install(SETTINGS ${settings} ${ARGV}) + endforeach() + set(CMAKE_BUILD_TYPE) + else() + conan_cmake_settings(settings ${ARGV}) + old_conan_cmake_install(SETTINGS ${settings} ${ARGV}) + endif() + endif() + + if (NOT ARGUMENTS_NO_LOAD) + conan_load_buildinfo() + endif() + + if(ARGUMENTS_BASIC_SETUP) + foreach(_option CMAKE_TARGETS KEEP_RPATHS NO_OUTPUT_DIRS SKIP_STD) + if(ARGUMENTS_${_option}) + if(${_option} STREQUAL "CMAKE_TARGETS") + list(APPEND _setup_options "TARGETS") + else() + list(APPEND _setup_options ${_option}) + endif() + endif() + endforeach() + conan_basic_setup(${_setup_options}) + endif() +endmacro() + +macro(conan_check) + # Checks conan availability in PATH + # Arguments REQUIRED, DETECT_QUIET and VERSION are optional + # Example usage: + # conan_check(VERSION 1.0.0 REQUIRED) + set(options REQUIRED DETECT_QUIET) + set(oneValueArgs VERSION) + cmake_parse_arguments(CONAN "${options}" "${oneValueArgs}" "" ${ARGN}) + if(NOT CONAN_DETECT_QUIET) + message(STATUS "Conan: checking conan executable") + endif() + + find_program(CONAN_CMD conan) + if(NOT CONAN_CMD AND CONAN_REQUIRED) + message(FATAL_ERROR "Conan executable not found! Please install conan.") + endif() + if(NOT CONAN_DETECT_QUIET) + message(STATUS "Conan: Found program ${CONAN_CMD}") + endif() + execute_process(COMMAND ${CONAN_CMD} --version + RESULT_VARIABLE return_code + OUTPUT_VARIABLE CONAN_VERSION_OUTPUT + ERROR_VARIABLE CONAN_VERSION_OUTPUT) + + if(NOT "${return_code}" STREQUAL "0") + message(FATAL_ERROR "Conan --version failed='${return_code}'") + endif() + + if(NOT CONAN_DETECT_QUIET) + string(STRIP "${CONAN_VERSION_OUTPUT}" _CONAN_VERSION_OUTPUT) + message(STATUS "Conan: Version found ${_CONAN_VERSION_OUTPUT}") + endif() + + if(DEFINED CONAN_VERSION) + string(REGEX MATCH ".*Conan version ([0-9]+\\.[0-9]+\\.[0-9]+)" FOO + "${CONAN_VERSION_OUTPUT}") + if(${CMAKE_MATCH_1} VERSION_LESS ${CONAN_VERSION}) + message(FATAL_ERROR "Conan outdated. Installed: ${CMAKE_MATCH_1}, \ + required: ${CONAN_VERSION}. Consider updating via 'pip \ + install conan==${CONAN_VERSION}'.") + endif() + endif() +endmacro() + +function(conan_add_remote) + # Adds a remote + # Arguments URL and NAME are required, INDEX, COMMAND and VERIFY_SSL are optional + # Example usage: + # conan_add_remote(NAME bincrafters INDEX 1 + # URL https://api.bintray.com/conan/bincrafters/public-conan + # VERIFY_SSL True) + set(oneValueArgs URL NAME INDEX COMMAND VERIFY_SSL) + cmake_parse_arguments(CONAN "" "${oneValueArgs}" "" ${ARGN}) + + if(DEFINED CONAN_INDEX) + set(CONAN_INDEX_ARG "-i ${CONAN_INDEX}") + endif() + if(DEFINED CONAN_COMMAND) + set(CONAN_CMD ${CONAN_COMMAND}) + else() + conan_check(REQUIRED DETECT_QUIET) + endif() + set(CONAN_VERIFY_SSL_ARG "True") + if(DEFINED CONAN_VERIFY_SSL) + set(CONAN_VERIFY_SSL_ARG ${CONAN_VERIFY_SSL}) + endif() + message(STATUS "Conan: Adding ${CONAN_NAME} remote repository (${CONAN_URL}) verify ssl (${CONAN_VERIFY_SSL_ARG})") + execute_process(COMMAND ${CONAN_CMD} remote add ${CONAN_NAME} ${CONAN_INDEX_ARG} -f ${CONAN_URL} ${CONAN_VERIFY_SSL_ARG} + RESULT_VARIABLE return_code) + if(NOT "${return_code}" STREQUAL "0") + message(FATAL_ERROR "Conan remote failed='${return_code}'") + endif() +endfunction() + +macro(conan_config_install) + # install a full configuration from a local or remote zip file + # Argument ITEM is required, arguments TYPE, SOURCE, TARGET and VERIFY_SSL are optional + # Example usage: + # conan_config_install(ITEM https://github.com/conan-io/cmake-conan.git + # TYPE git SOURCE source-folder TARGET target-folder VERIFY_SSL false) + set(oneValueArgs ITEM TYPE SOURCE TARGET VERIFY_SSL) + set(multiValueArgs ARGS) + cmake_parse_arguments(CONAN "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(DEFINED CONAN_COMMAND) + set(CONAN_CMD ${CONAN_COMMAND}) + else() + conan_check(REQUIRED) + endif() + + if(DEFINED CONAN_VERIFY_SSL) + set(CONAN_VERIFY_SSL_ARG "--verify-ssl=${CONAN_VERIFY_SSL}") + endif() + + if(DEFINED CONAN_TYPE) + set(CONAN_TYPE_ARG "--type=${CONAN_TYPE}") + endif() + + if(DEFINED CONAN_ARGS) + set(CONAN_ARGS_ARGS "--args=\"${CONAN_ARGS}\"") + endif() + + if(DEFINED CONAN_SOURCE) + set(CONAN_SOURCE_ARGS "--source-folder=${CONAN_SOURCE}") + endif() + + if(DEFINED CONAN_TARGET) + set(CONAN_TARGET_ARGS "--target-folder=${CONAN_TARGET}") + endif() + + set (CONAN_CONFIG_INSTALL_ARGS ${CONAN_VERIFY_SSL_ARG} + ${CONAN_TYPE_ARG} + ${CONAN_ARGS_ARGS} + ${CONAN_SOURCE_ARGS} + ${CONAN_TARGET_ARGS}) + + message(STATUS "Conan: Installing config from ${CONAN_ITEM}") + execute_process(COMMAND ${CONAN_CMD} config install ${CONAN_ITEM} ${CONAN_CONFIG_INSTALL_ARGS} + RESULT_VARIABLE return_code) + if(NOT "${return_code}" STREQUAL "0") + message(FATAL_ERROR "Conan config failed='${return_code}'") + endif() +endmacro() diff --git a/cmake/just-simple.cmake b/cmake/just-simple.cmake new file mode 100644 index 000000000..3180da403 --- /dev/null +++ b/cmake/just-simple.cmake @@ -0,0 +1,505 @@ +# just simple cmake +# +# main commands: just_add_library() just_add_executable() just_add_tests() +# - target name generated "project-folder[-test]" +# - sources are taken by globbing +# - INCLUDE "^.*/namespace/.*$" ... is applied before EXCLUDE +# - EXCLUDE "^.*TEST$" ... is applied after INCLUDE +# - LINK [lib1 ...] (tests linking automatically against target under test) +# - DEPENDS [custom_command_1 ...] +# - SKIP_SUBDIRECTORIES if a subfolder contains a CMakeLists.txt its automatically added, but not with this argument +# - SUFFIX "asd" project-folder -> project-folder-asd +# +# util commands: +# - just_limit_jobs(COMPILE 1000 LINK 4000) calculates the compile / link job pools according to your current available memory. +# You configure the amount of expected memory usage in mb per compile / link job. +# Get rid of out-of-memory crashes, manually setting jobs with `ninja -j x`. +# - just_copy_resource(project-NAME) copies resources from given target into current binary dir +# +# other features: +# + resource/config/server.json -> just create the structure and your test will find it in config/server.json +# + run tests with ctest (Labels = target under test) +# + generate Coverage with cmake ... -DCOVERAGE=ON ninja ccov-all +# + conanfile.txt handling + auto generated if not present +# + doxygen incremental generation +# +# setup: +# 0. pip install conan +# 1. Copy to your project `cmake/just-simple.cmake` +# 2. Your project invokes before include: [`project(NAME)`](https://cmake.org/cmake/help/latest/command/project.html) +# 3. Include it from your main file `include("cmake/just-simple.cmake")` +# 4. Target names are generated `project-folder[-test]` therefore suggested folder structure: +# . +# ├── CMakeLists.txt // project(...), include("cmake/just-simple.cmake"), add_subdirector(project/target1), ... +# ├── CMakePresets +# ├── conanfile.txt // [requires] sqlite3/[>=3.30.0 <4.0.0] +# ├── cmake +# │ └── just-simple.cmake +# └── project +# ├── target1 // project-target1 +# │ ├── CMakeLists.txt // just_add_executable(LINK project-target2) +# │ ├── include +# │ │ └── namespace +# │ │ └── public_include.hpp +# │ └── src +# │ └── namespace +# │ └── main.cpp +# └── target2 // project-target2 +# ├── CMakeLists.txt // just_add_library(LINK sqlite3) test folder autoloaded because it contains CMakeLists.txt +# ├── include +# │ └── namespace +# │ └── lib.h +# ├── resource +# │ └── config +# │ └── server.cfg +# ├── src +# │ └── namespace +# │ └── lib.cpp +# └── test // project-target2-test +# ├── CMakeLists.txt // just_add_tests() auto linked vs project-target2 gtest_main, gmock_main +# ├── include +# │ └── .gitkeep +# ├── resource +# │ └── config +# │ └── test.cfg // tests can load(config/test.cfg) and load(config/server.cfg) +# └── src +# └── simple_test.cpp + +if (${CMAKE_MINIMUM_REQUIRED_VERSION} VERSION_LESS "3.21") # for --output-junit + message(FATAL_ERROR " + just-simple.cmake requires min cmake version 3.21 + if this is an issue you can quick fix it with conan: + conan install \"cmake/[>3.21 <4.0]@\" -g virtualenv + source activate_run.sh + ") +endif() + +include(GNUInstallDirs) +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug") +endif () + +# download cmake dependencies if not present +set(JUST_SIMPLE_conan "${CMAKE_CURRENT_LIST_DIR}/conan.cmake") +if(NOT EXISTS "${JUST_SIMPLE_conan}") + file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/0.18.1/conan.cmake" + "${JUST_SIMPLE_conan}" + EXPECTED_HASH SHA256=5cdb3042632da3efff558924eecefd580a0e786863a857ca097c3d1d43df5dcd + TLS_VERIFY ON) +endif() +include(${JUST_SIMPLE_conan}) + +set(JUST_SIMPLE_coverage "${CMAKE_CURRENT_LIST_DIR}/code-coverage.cmake") +if (NOT EXISTS "${JUST_SIMPLE_coverage}") + file(DOWNLOAD "https://raw.githubusercontent.com/StableCoder/cmake-scripts/ed79fb95f7bd39b2cb158d7ff83a5dbb639343e8/code-coverage.cmake" + "${JUST_SIMPLE_coverage}" + EXPECTED_HASH SHA256=58900f7280f43cab6c66e793bc8cd8aa06c9c8b4d6f0c10dd5e86e19efb46718 + TLS_VERIFY ON) +endif() + +# setup conan +# create basic conanfile.txt if not present +if (NOT CONAN_EXPORTED) # only if conan not already set up + if (NOT CONANFILE) + set(CONANFILE "${PROJECT_SOURCE_DIR}/conanfile.txt") + endif() + if (NOT EXISTS "${CONANFILE}") + file(WRITE "${CONANFILE}" "# doc: https://docs.conan.io/en/latest/reference/conanfile_txt.html\n\n") + file(APPEND "${CONANFILE}" "[requires]\ngtest/1.12.1\ndoxygen/1.9.4\n#package_name/version@user/channel (default @_/_)\n\n") + file(APPEND "${CONANFILE}" "[generators]\ncmake\n\n") + file(APPEND "${CONANFILE}" "[options]\n#package_name:shared=False\n\n") + endif() + conan_cmake_run( + BASIC_SETUP + CONANFILE "${CONANFILE}" + BUILD missing) +else() + conan_cmake_run(BASIC_SETUP) +endif() + +# debugging CMAKE https://cliutils.gitlab.io/modern-cmake/chapters/features/debug.html +#include(CMakePrintHelpers) +# cmake_print_variables(MY_VARIABLE) +# cmake_print_properties(TARGETS my_target PROPERTIES POSITION_INDEPENDENT_CODE) +# --warn-uninitialized --trace --trace-expand + +# before "limit linking jobs", sets the same property rather than extending +# but its a dependency so we shouldnt modify it, will break on update +include("${JUST_SIMPLE_coverage}") +add_code_coverage_all_targets(EXCLUDE ".conan/.*" ".*/test/.*") # TODO its allowed to call it something else, move name enforcing to config? + +enable_testing() #enable ctest +set(CMAKE_CTEST_ARGUMENTS "--output-junit;${CMAKE_BINARY_DIR}/Testing/Temporary/JUnit.xml;--output-on-failure;") # for ci import +include(GoogleTest) + +# generates compile_commands.json used by IDEs to resolve includes aso +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# TODO offer a diagnostic run with link / compile = 1, job = 1 and check mem usage with "sar -r cmd" (sysstat package) automatically? +function(just_limit_jobs) + # Argument parsing + set(options ) + set(oneValueArgs LINK COMPILE) + set(multiValueArgs ) + cmake_parse_arguments(PARSE_ARGV "0" "just_limit" "${options}" "${oneValueArgs}" "${multiValueArgs}") + + if(just_limit_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "target \"${TARGET}\" has unparsed arguments \"${just_limit_UNPARSED_ARGUMENTS}\", LINK \"expected ram usage per link process\" COMPILE \"expected ram usage per compile process\"?") + endif() + + cmake_host_system_information(RESULT system_ram QUERY AVAILABLE_PHYSICAL_MEMORY) + # linking / compiling is done at the same time and to much memory consumption will break ci / slow done it a lot + # upper limit for link/compile job is automatically set by job count + math(EXPR system_ram_possible_jobs "${system_ram} / ${just_limit_LINK}" OUTPUT_FORMAT DECIMAL) + if (system_ram_possible_jobs LESS 1) + set(system_ram_possible_jobs 1) + endif() + cmake_host_system_information(RESULT system_cores QUERY NUMBER_OF_LOGICAL_CORES) + + message(STATUS "resources: cores=${system_cores} memory=${system_ram}") + if (system_ram_possible_jobs LESS system_cores) + math(EXPR compile_jobs "${system_ram} / ${just_limit_COMPILE}" OUTPUT_FORMAT DECIMAL) + if (compile_jobs LESS 1) + set(compile_jobs 1) + endif() + message("Your System is Memory limited, linking jobs: ${system_ram_possible_jobs} compile jobs: ${compile_jobs}") + set_property(GLOBAL APPEND PROPERTY JOB_POOLS linking=${system_ram_possible_jobs} compiling=${compile_jobs}) + else() + message("Your System is CPU limited, linking jobs: ${system_cores} compile jobs: ${system_cores}") + set_property(GLOBAL APPEND PROPERTY JOB_POOLS linking=${system_cores} compiling=${system_cores}) + endif() + + if (NOT CMAKE_JOB_POOL_LINK) + set(CMAKE_JOB_POOL_LINK linking PARENT_SCOPE) + else() + message("Using provided job pool list for linking: ${CMAKE_JOB_POOL_LINK}") + endif() + if (NOT CMAKE_JOB_POOL_COMPILE) + set(CMAKE_JOB_POOL_COMPILE compiling PARENT_SCOPE) + else() + message("Using provided job pool list for linking: ${CMAKE_JOB_POOL_COMPILE}") + endif() +endfunction() + +function(_just_add_check TARGET) + if (TARGET "${TARGET}") + message(FATAL_ERROR "cant add executable because the target ${TARGET} is already defined, please create just one executable per directory") + endif() + + if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/include") + else() + message(FATAL_ERROR "_just_add_check: ${TARGET} has no include folder, please add it") + endif() + + if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src") + else() + message(FATAL_ERROR "_just_add_check: ${TARGET} has no src folder, please add it") + endif() +endfunction() + +function(_just_add_subdirectory) + FILE(GLOB files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) + + foreach(file ${files}) + if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${file}/CMakeLists.txt") + add_subdirectory("${file}") + endif() + endforeach() +endfunction() + +function(_just_add_resource SRC) + if (EXISTS "${SRC}/resource") + message(NOTICE "found resources in: ${SRC}/resource") + file(GLOB_RECURSE files RELATIVE "${SRC}/resource" LIST_DIRECTORIES false "${SRC}/resource/*") + foreach(file ${files}) + configure_file("${SRC}/resource/${file}" "${CMAKE_CURRENT_BINARY_DIR}/${file}" COPYONLY) + endforeach() + else() + message(NOTICE "no resource folder: ${SRC}/resource") + endif() +endfunction() + +function(just_copy_resource TARGET) + get_target_property(target_folder "${TARGET}" SOURCE_DIR) + _just_add_resource("${target_folder}") +endfunction() + +function(_just_check_library_order) + set(options) + set(oneValueArgs TARGET) + set(multiValueArgs LINK) + cmake_parse_arguments(PARSE_ARGV "0" "just_check" "${options}" "${oneValueArgs}" "${multiValueArgs}") + + set(index -1) + set(wrong_order OFF) + set(correct_order) + foreach(available_lib ${CONAN_LIBS}) + list(FIND just_check_LINK ${available_lib} found) + if (found GREATER -1) + list(APPEND correct_order "${available_lib}") + if (found LESS index) + set(wrong_order ON) + endif() + set(index "${found}") + endif() + endforeach() + + if (${wrong_order}) + message(WARNING "${just_check_TARGET} LINK order looks incorrect, expecting: ${correct_order}") + endif() +endfunction() + +function(just_add_library) + # Argument parsing + set(options SKIP_SUBDIRECTORIES SKIP_DOXYGEN) + set(oneValueArgs SUFFIX) + set(multiValueArgs INCLUDE EXCLUDE LINK DEPENDS) + cmake_parse_arguments(PARSE_ARGV "0" "just_add" "${options}" "${oneValueArgs}" "${multiValueArgs}") + + # get name from + get_filename_component(TARGET "${CMAKE_CURRENT_SOURCE_DIR}" NAME) + set(TARGET "${CMAKE_PROJECT_NAME}-${TARGET}${just_add_SUFFIX}") + if(just_add_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "target \"${TARGET}\" has unparsed arguments \"${just_add_UNPARSED_ARGUMENTS}\" maybe LINK in front of it?") + endif() + _just_add_check("${TARGET}") + + if (just_add_LINK) + _just_check_library_order(TARGET "${TARGET}" LINK ${just_add_LINK}) + endif() + + # create filelist + file(GLOB_RECURSE files include/* src/*) + list(FILTER files EXCLUDE REGEX "^.*/\.gitkeep$") #XXX filter others to? only whitelist for .cpp? Variable for it? + if(just_add_INCLUDE) + foreach(pattern ${just_add_INCLUDE}) + set(just_add_temp ${files}) + list(FILTER just_add_temp INCLUDE REGEX ${pattern}) + list(APPEND all_includes ${just_add_temp}) + endforeach() + set(files ${all_includes}) + endif() + if(just_add_EXCLUDE) + foreach(pattern ${just_add_EXCLUDE}) + list(FILTER files EXCLUDE REGEX ${pattern}) + endforeach() + endif() + + set(is_header_only OFF) + list(APPEND files_src ${files}) + list(FILTER files_src EXCLUDE REGEX "^.*/include/.*$") + if (NOT files_src) + set(is_header_only ON) + endif() + + # create target + if(is_header_only) + message(NOTICE "just_add_library ${TARGET}: header only library, skip linking") + add_library("${TARGET}" INTERFACE ${files}) + target_include_directories("${TARGET}" INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include" ) + # XXX for header only libs, but really needed? + set_target_properties("${TARGET}" PROPERTIES LINKER_LANGUAGE CXX) + if (just_add_LINK) + message(NOTICE "just_add_library ${TARGET}: linking to ${just_add_LINK}") + target_link_libraries("${TARGET}" INTERFACE ${just_add_LINK}) + endif() + else() + add_library("${TARGET}" ${files}) + target_include_directories("${TARGET}" PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) + if (just_add_LINK) + message(NOTICE "just_add_library ${TARGET}: linking to ${just_add_LINK}") + target_link_libraries("${TARGET}" PUBLIC ${just_add_LINK}) + endif() + endif() + if (just_add_DEPENDS) + message(NOTICE "just_add_library ${TARGET}: adding dependency ${just_add_LINK}") + add_dependencies("${TARGET}" ${just_add_DEPENDS}) + endif() + if(NOT is_header_only) + target_code_coverage(${TARGET} AUTO EXTERNAL ALL EXCLUDE ".conan/.*" ".*/test/.*") + endif() + + if(NOT "${just_add_SKIP_SUBDIRECTORIES}") + _just_add_subdirectory() + endif() + _just_add_resource("${CMAKE_CURRENT_SOURCE_DIR}") + + if(NOT "${just_add_SKIP_DOXYGEN}") + _just_add_doxygen(TARGET ${TARGET} FILES ${files}) + endif() + + install(TARGETS ${TARGET} EXPORT ${TARGET}) + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +endfunction() + +include(FindDoxygen) +set_property(DIRECTORY "${PROJECT_SOURCE_DIR}" PROPERTY just_doc_counter 0) +set_property(DIRECTORY "${PROJECT_SOURCE_DIR}" PROPERTY just_doc_files) +function(_just_add_doxygen) + set(oneValueArgs TARGET) + set(multiValueArgs FILES) + cmake_parse_arguments(PARSE_ARGV "0" "just_doc" "" "${oneValueArgs}" "${multiValueArgs}") + # 1. doxygen module support to generate for a one target + # 2. there is no merge for multiple generation e.g. to merge generation of two libs + # 3. I dont want the user to invoke a command at the end + + # => add per invocation a new target which contains source files of current and recent invocations + only this is part of all target + + get_property(just_doc_files DIRECTORY "${PROJECT_SOURCE_DIR}" PROPERTY just_doc_files) + list(APPEND just_doc_files "${just_doc_FILES}") + + get_property(just_doc_counter DIRECTORY "${PROJECT_SOURCE_DIR}" PROPERTY just_doc_counter) + if (${just_doc_counter} GREATER 0) + set_target_properties("${CMAKE_PROJECT_NAME}-doc-${just_doc_counter}" PROPERTIES EXCLUDE_FROM_ALL TRUE) + else() + if (DOXYGEN_USE_MDFILE_AS_MAINPAGE) + list(APPEND just_doc_files "${DOXYGEN_USE_MDFILE_AS_MAINPAGE}") + endif() + endif() + + math(EXPR just_doc_counter "${just_doc_counter} + 1") + + if(NOT DOXYGEN_OUTPUT_DIRECTORY) + set(DOXYGEN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") + endif() + doxygen_add_docs("${CMAKE_PROJECT_NAME}-doc-${just_doc_counter}" "${just_doc_files}" ALL USE_STAMP_FILE WORKING_DIRECTORY "${CMAKE_BINARY_DIR}") + + set_property(DIRECTORY "${PROJECT_SOURCE_DIR}" PROPERTY just_doc_counter ${just_doc_counter}) + set_property(DIRECTORY "${PROJECT_SOURCE_DIR}" PROPERTY just_doc_files ${just_doc_files}) +endfunction() + +function(just_add_executable) + # Argument parsing + set(options SKIP_SUBDIRECTORIES) + set(oneValueArgs SUFFIX) + set(multiValueArgs INCLUDE EXCLUDE LINK DEPENDS) + cmake_parse_arguments(PARSE_ARGV "0" "just_add" "${options}" "${oneValueArgs}" "${multiValueArgs}") + + # get name from + get_filename_component(TARGET "${CMAKE_CURRENT_SOURCE_DIR}" NAME) + set(TARGET "${CMAKE_PROJECT_NAME}-${TARGET}${just_add_SUFFIX}") + if(just_add_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "target \"${TARGET}\" has unparsed arguments \"${just_add_UNPARSED_ARGUMENTS}\" maybe LINK in front of it?") + endif() + _just_add_check("${TARGET}") + + if (just_add_LINK) + _just_check_library_order(TARGET "${TARGET}" LINK ${just_add_LINK}) + endif() + + # create filelist + file(GLOB_RECURSE files include/* src/*) + if(just_add_INCLUDE) + foreach(pattern ${just_add_INCLUDE}) + set(just_add_temp ${files}) + list(FILTER just_add_temp INCLUDE REGEX ${pattern}) + list(APPEND all_includes ${just_add_temp}) + endforeach() + set(files ${all_includes}) + endif() + if(just_add_EXCLUDE) + foreach(pattern ${just_add_EXCLUDE}) + list(FILTER files EXCLUDE REGEX ${pattern}) + endforeach() + endif() + + # create target + add_executable("${TARGET}" ${files}) + string(TOUPPER "RUNTIME_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}" binary_folder) + set_target_properties("${TARGET}" PROPERTIES "${binary_folder}" "${CMAKE_CURRENT_BINARY_DIR}") + + target_include_directories("${TARGET}" PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) + if (just_add_LINK) + message(NOTICE "just_add_executable ${TARGET}: linking to ${just_add_LINK}") + target_link_libraries("${TARGET}" PUBLIC ${just_add_LINK}) + endif() + if (just_add_DEPENDS) + message(NOTICE "just_add_executable ${TARGET}: adding dependency ${just_add_LINK}") + add_dependencies("${TARGET}" ${just_add_DEPENDS}) + endif() + # failing and probably not needed if not lib or test + # target_code_coverage(${TARGET} AUTO EXTERNAL ALL EXCLUDE ".conan/.*" ".*/test/.*") + if(NOT "${just_add_SKIP_SUBDIRECTORIES}") + _just_add_subdirectory() + endif() + + _just_add_resource("${CMAKE_CURRENT_SOURCE_DIR}") + + install(TARGETS ${TARGET} EXPORT ${TARGET}) +endfunction() + +function(just_add_tests) + # Argument parsing + set(options SKIP_SUBDIRECTORIES SKIP_DEFAULT_LINK) + set(oneValueArgs SUFFIX) + set(multiValueArgs INCLUDE EXCLUDE LINK DEPENDS) + cmake_parse_arguments(PARSE_ARGV "0" "just_add" "${options}" "${oneValueArgs}" "${multiValueArgs}") + + get_filename_component(TARGET_UNDER_TEST "${CMAKE_CURRENT_SOURCE_DIR}" DIRECTORY) + get_filename_component(TARGET_UNDER_TEST "${TARGET_UNDER_TEST}" NAME) + set(TARGET_UNDER_TEST "${CMAKE_PROJECT_NAME}-${TARGET_UNDER_TEST}") + + # get name from + get_filename_component(TEST_TARGET "${CMAKE_CURRENT_SOURCE_DIR}" NAME) + set(TARGET "${TARGET_UNDER_TEST}-${TEST_TARGET}${just_add_SUFFIX}") + + if (just_add_LINK) + _just_check_library_order(TARGET "${TARGET}" LINK ${just_add_LINK}) + endif() + + if (NOT TARGET "${TARGET_UNDER_TEST}") + message(FATAL_ERROR "just_add_tests: Expected to create tests for target ${TARGET_UNDER_TEST} but this target doesn't exists.") + endif() + if(just_add_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "target \"${TARGET}\" has unparsed arguments \"${just_add_UNPARSED_ARGUMENTS}\" maybe LINK in front of it?") + endif() + _just_add_check("${TARGET}") + + # create filelist + file(GLOB_RECURSE files include/* src/*) + if(just_add_INCLUDE) + foreach(pattern ${just_add_INCLUDE}) + set(just_add_temp ${files}) + list(FILTER just_add_temp INCLUDE REGEX ${pattern}) + list(APPEND all_includes ${just_add_temp}) + endforeach() + set(files ${all_includes}) + endif() + if(just_add_EXCLUDE) + foreach(pattern ${just_add_EXCLUDE}) + list(FILTER files EXCLUDE REGEX ${pattern}) + endforeach() + endif() + + # create target + add_executable("${TARGET}" ${files}) + string(TOUPPER "RUNTIME_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}" binary_folder) + set_target_properties("${TARGET}" PROPERTIES "${binary_folder}" "${CMAKE_CURRENT_BINARY_DIR}") + gtest_discover_tests("${TARGET}" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" DISCOVERY_TIMEOUT 60 PROPERTIES LABELS ${TARGET_UNDER_TEST}) + target_include_directories("${TARGET}" PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) + + set(LINK_DEPENDENCIES) + if(NOT "${just_add_SKIP_DEFAULT_LINK}") + list(APPEND LINK_DEPENDENCIES ${TARGET_UNDER_TEST} ${CONAN_LIBS_GTEST} pthread) + endif() + list(APPEND LINK_DEPENDENCIES ${just_add_LINK}) + + message(NOTICE "just_add_tests ${TARGET}: linking to ${LINK_DEPENDENCIES}") + target_link_libraries("${TARGET}" PUBLIC ${LINK_DEPENDENCIES}) + target_code_coverage("${TARGET}" AUTO EXTERNAL ALL EXCLUDE ".conan/.*" ".*/test/.*") + + if (just_add_DEPENDS) + message(NOTICE "just_add_tests ${TARGET}: adding dependency ${just_add_LINK}") + add_dependencies("${TARGET}" ${just_add_DEPENDS}) + endif() + + if(NOT "${just_add_SKIP_SUBDIRECTORIES}") + _just_add_subdirectory() + endif() + + # if target under tests has resources, the tests need them as well + get_target_property(target_under_test_source_dir "${TARGET_UNDER_TEST}" "SOURCE_DIR") + _just_add_resource("${target_under_test_source_dir}") + # but also allow them to overwrite & have other dependencies too + _just_add_resource("${CMAKE_CURRENT_SOURCE_DIR}") +endfunction() diff --git a/cmake/options.cmake b/cmake/options.cmake new file mode 100644 index 000000000..743c9763f --- /dev/null +++ b/cmake/options.cmake @@ -0,0 +1,218 @@ +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build mode ('DebugSan' or 'Debug' or 'Release', default is 'Debug')" FORCE) +endif () + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -MP -fvisibility-inlines-hidden -fstack-protector-strong -ffunction-sections -fdata-sections -pipe") +if(CMAKE_BUILD_TYPE STREQUAL "DebugSan") + message(STATUS "Selected Debug Build with sanitizers") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fno-omit-frame-pointer -fsanitize=address,undefined") + set(CMAKE_BUILD_TYPE "Debug") +elseif(CMAKE_BUILD_TYPE STREQUAL "Debug") + message(STATUS "Selected Debug Build") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") +else() + set(CMAKE_BUILD_TYPE "Release") + message(STATUS "Selected Release Build") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") +endif() + + + + +# default option always preset +option(BUILD_SHARED_LIBS "Build shared libraries (default is OFF)" OFF) +if(BUILD_SHARED_LIBS) + set(CONANFILE "${PROJECT_SOURCE_DIR}/conanfile.shared.txt") +endif() + + + +option(PHASAR_BUILD_DYNLIB "Build one fat shared library. Requires BUILD_SHARED_LIBS to be turned OFF (default is OFF)" OFF) + + + +if (NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) +elseif(${CMAKE_CXX_STANDARD} LESS 17) + message(FATAL_ERROR "phasar requires CMAKE_CXX_STANDARD >= 17") +endif() +set(CMAKE_CXX_STANDARD_REQUIRED ON) + + + +# Check if we build within the llvm source tree +if (DEFINED LLVM_MAIN_SRC_DIR) + if (BUILD_SHARED_LIBS) + message(FATAL_ERROR "currently phasar in tree need to be static") + endif() + set(CMAKE_PROJECT_NAME "phasar") + set(PHASAR_BUILD_UNITTESTS OFF) + + set(CONANFILE "${PROJECT_SOURCE_DIR}/conanfile.in_llvm_tree.txt") + + # TODO code below was used before migration + # remove after PHASAR_IN_TREE is successfuly tested + + # export given target "nlohmann_json_schema_validator" which is not built by this project. + #set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS nlohmann_json_schema_validator) + + # if(NOT CLANG_INCLUDE_DIR) + # set(CLANG_INCLUDE_DIR ${LLVM_MAIN_SRC_DIR}/../clang/include ) + # cmake_path(ABSOLUTE_PATH CLANG_INCLUDE_DIR NORMALIZE) + # endif() + # set(CLANG_INCLUDE_DIR ${LLVM_MAIN_SRC_DIR}/../clang/include ) + # # Specify TableGen output dir for things like DiagnosticCommonKinds.inc, + # # DiagnosticDriverKinds.inc (required for reporting diagnostics) + # set(CLANG_TABLEGEN_OUTPUT_DIR ${CMAKE_BINARY_DIR}/tools/clang/include) + # include_directories(SYSTEM ${CLANG_TABLEGEN_OUTPUT_DIR}) + # Phasar needs clang headers, specificaly some that are generated by clangs table-gen + # TODO: migrate this to cmake property reading! Why not simply link against the correct target? + #message(FATAL_ERROR "> PHASAR_IN_TREE debug:\n clang include: ${CLANG_INCLUDE_DIR}\ncurrent source: ${CMAKE_CURRENT_SOURCE_DIR}\nproject-source: ${PROJECT_SOURCE_DIR}\nproject binary: ${PROJECT_BINARY_DIR}\ncmake-source: ${CMAKE_SOURCE_DIR}") + + # should actually be resolved if linked to it, for testing uncommented + message(WARNING "For testing not explicitly added includes: ${CLANG_INCLUDE_DIR} ${PROJECT_BINARY_DIR}/tools/clang/include") + # include_directories( + # ${CLANG_INCLUDE_DIR} + # ${PHASAR_SRC_DIR}/../clang/include # is identical to ${CLANG_INCLUDE_DIR} + # ${PROJECT_BINARY_DIR}/tools/clang/include + # ) + + # TODO: Get all lib targets + # install(TARGETS ${name} + # EXPORT LLVMExports + # LIBRARY DESTINATION lib + # ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) +endif() + + +# merged PHASAR_BUILD_OPENSSL_TS_UNITTESTS / PHASAR_BUILD_IR +option(PHASAR_BUILD_UNITTESTS "Build all tests and IR files (default is ON)" ON) +set(OPTION_TESTS_DISABLED) +set(OPTION_DOXYGEN_DISABLED) +if (NOT PHASAR_BUILD_UNITTESTS) + set(OPTION_TESTS_DISABLED "SKIP_SUBDIRECTORIES") + set(OPTION_DOXYGEN_DISABLED "SKIP_DOXYGEN") +endif() + + + +option(PHASAR_ENABLE_CLANG_TIDY_DURING_BUILD "Run clang-tidy during build (default is OFF)" OFF) # should be fine +if (PHASAR_ENABLE_CLANG_TIDY_DURING_BUILD) + message(STATUS "Enabled clang-tidy during build") + set(CMAKE_CXX_CLANG_TIDY + clang-tidy; + -header-filter=phasar/.*h$; + # -warnings-as-errors=*; + ) +endif () + + + +set(DOXYGEN_PROJECT_BRIEF "Phasar a LLVM-based Static Analysis Framework") +set(DOXYGEN_PROJECT_LOGO "${PROJECT_SOURCE_DIR}/img/Logo_RGB/Phasar_Logo.png") +set(DOXYGEN_ABBREVIATE_BRIEF "") +set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "${PROJECT_SOURCE_DIR}/README.md") +# set(DOXYGEN_OPTIMIZE_OUTPUT_FOR_C YES) # according to doc if ONLY C files are used +set(DOXYGEN_EXTENSION_MAPPING "cu=C++ cuh=C++") +set(DOXYGEN_HTML_TIMESTAMP "YES") +# set(DOXYGEN_USE_MATHJAX "YES") # needed by option below +# set(DOXYGEN_MATHJAX_RELPATH "https://cdn.jsdelivr.net/npm/mathjax@3") # part of original phasar doxygen but not activated +set(DOXYGEN_HAVE_DOT "YES") # TODO graphviz needs to be there !? +set(DOXYGEN_DOT_MULTI_TARGETS "YES") +set(DOXYGEN_EXCLUDE_PATTERNS "*/llvm_test_code/*") + + + + +# TODO Basically only works if Phasars public API doesn't expose anything at all which is using the dependency, so a user would need to add the dependency on their own +# if private you have to manually handle include / compile +option(PHASAR_DEBUG_LIBDEPS "Debug internal library dependencies (private linkage)" OFF) +if (PHASAR_DEBUG_LIBDEPS) + message(FATAL_ERROR "PHASAR_DEBUG_LIBDEPS isn't migrated, sorry.") +endif() + + + + +option(PHASAR_ENABLE_WARNINGS "Enable warnings" ON) +if (PHASAR_ENABLE_WARNINGS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-return-type-c-linkage ") +endif() + + + + +option(PHASAR_ENABLE_PIC "Build Position-Independed Code" ON) +if (PHASAR_ENABLE_PIC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") +endif() + + + +if (NOT PHASAR_ENABLE_PAMM) + set(PHASAR_ENABLE_PAMM "Off" CACHE STRING "Enable the performance measurement mechanism ('Off', 'Core' or 'Full', default is 'Off')" FORCE) + set_property(CACHE PHASAR_ENABLE_PAMM PROPERTY STRINGS "Off" "Core" "Full") +endif() +if(PHASAR_BUILD_UNITTESTS) + message("PAMM metric severity level: Off (due to unittests)") +elseif(PHASAR_ENABLE_PAMM STREQUAL "Core") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPAMM_CORE") + message("PAMM metric severity level: Core") +elseif(PHASAR_ENABLE_PAMM STREQUAL "Full") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPAMM_FULL") + message("PAMM metric severity level: Full") +else() + message("PAMM metric severity level: Off") +endif() + + + +option(PHASAR_ENABLE_DYNAMIC_LOG "Makes it possible to switch the logger on and off at runtime (default is ON)" ON) +if (PHASAR_ENABLE_DYNAMIC_LOG) + message(STATUS "Dynamic log enabled") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDYNAMIC_LOG") +else() + message(STATUS "Dynamic log disabled") +endif() + + + +if (LLVM_ENABLE_LIBCXX) + set(PHASAR_STD_FILESYSTEM c++fs) +else() + set(PHASAR_STD_FILESYSTEM stdc++fs) +endif() + + + + +# TODO migrate install +# executables +# install (TARGETS ${name} +# RUNTIME DESTINATION bin +# ) +# libraries +# if(PHASAR_IN_TREE) +# install(TARGETS ${name} +# EXPORT LLVMExports +# LIBRARY DESTINATION lib +# ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) +# else() +# install(TARGETS ${name} +# EXPORT phasarTargets +# LIBRARY DESTINATION ${PHASAR_INSTALL_LIBDIR} +# ARCHIVE DESTINATION ${PHASAR_INSTALL_LIBDIR}) +# install(TARGETS ${name} +# EXPORT ${name}-targets +# COMPONENT ${component_name} +# DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/phasar +# LIBRARY DESTINATION ${PHASAR_INSTALL_LIBDIR} +# ARCHIVE DESTINATION ${PHASAR_INSTALL_LIBDIR}) +# install(EXPORT ${name}-targets +# FILE ${name}-targets.cmake +# NAMESPACE phasar:: +# DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/phasar +# COMPONENT ${component_name}) +# install(FILES ${name}-config.cmake +# DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/phasar) +# endif() diff --git a/cmake/phasar-config.cmake.in b/cmake/phasar-config.cmake.in new file mode 100644 index 000000000..973bbff3c --- /dev/null +++ b/cmake/phasar-config.cmake.in @@ -0,0 +1,59 @@ +set(PHASAR_VERSION 1.0.0) + +@PACKAGE_INIT@ +set_and_check(PHASAR_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") + +# TODO: add CPack support? https://youtu.be/bsXLMQ6WgIk?t=2700 + +# TODO: unused previously +#set_and_check(PHASAR_SYSCONFIG_DIR "@PACKAGE_SYSCONFIG_INSTALL_DIR@") +check_required_components(phasar) + +# reference: https://youtu.be/bsXLMQ6WgIk?t=2422 +# Maybe generate this from conanfile? Could also be helpful for different configurations. +include (CMakeFindDependencyMacro) +# find_dependency(...) +# include(.../FooTargets.cmake) +find_dependency(nlohmann_json) +find_dependency(nlohmann_json_schema_validator) +find_package(Boost 1.65.1 COMPONENTS program_options graph REQUIRED) + +# TODO: The order seems to be important. Fix this! + +set(PHASAR_COMPONENTS + utils + config + phasarllvm_utils + passes + db + pointer + typehierarchy + controlflow + taintconfig + ifdside +) + +foreach(component ${PHASAR_COMPONENTS}) + include("${CMAKE_CURRENT_LIST_DIR}/phasar_${component}-targets.cmake") + list(APPEND PHASAR_NEEDED_LIBS phasar::phasar_${component}) +endforeach() + +list(REMOVE_DUPLICATES PHASAR_NEEDED_LIBS) + +find_package(LLVM 14 REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) # TODO: just dont add to global! +link_directories(${LLVM_LIB_PATH} ${LLVM_LIBRARY_DIRS}) # TODO: just dont add to global! +find_library(LLVM_LIBRARY NAMES LLVM HINTS ${LLVM_LIBRARY_DIRS}) + +function(phasar_config executable) + if(NOT ${LLVM_LIBRARY} STREQUAL "LLVM_LIBRARY-NOTFOUND") + llvm_config(${executable} USE_SHARED ${PHASAR_LLVM_DEPS}) # TODO: llvm_config shouldn't be used anymore! + else() + llvm_config(${executable} ${PHASAR_LLVM_DEPS}) + endif() + + target_link_libraries(${executable} + PUBLIC + ${PHASAR_NEEDED_LIBS} + ) +endfunction() \ No newline at end of file diff --git a/cmake/phasar_macros.cmake b/cmake/phasar_macros.cmake deleted file mode 100644 index db0096471..000000000 --- a/cmake/phasar_macros.cmake +++ /dev/null @@ -1,279 +0,0 @@ -function(add_phasar_unittest test_name) - message("Set-up unittest: ${test_name}") - get_filename_component(test ${test_name} NAME_WE) - add_executable(${test} - ${test_name} - ) - add_dependencies(PhasarUnitTests ${test}) - - if(USE_LLVM_FAT_LIB) - llvm_config(${test} USE_SHARED ${LLVM_LINK_COMPONENTS}) - else() - llvm_config(${test} ${LLVM_LINK_COMPONENTS}) - endif() - - target_link_libraries(${test} - LINK_PUBLIC - phasar - nlohmann_json_schema_validator - ${SQLITE3_LIBRARY} - ${Boost_LIBRARIES} - ${CMAKE_DL_LIBS} - ${CMAKE_THREAD_LIBS_INIT} - curl - gtest - ) - - add_test(NAME "${test}" - COMMAND ${test} ${CATCH_TEST_FILTER} - WORKING_DIRECTORY ${PHASAR_UNITTEST_DIR} - ) - set_tests_properties("${test}" PROPERTIES LABELS "all") - set(CTEST_OUTPUT_ON_FAILURE ON) -endfunction() - -function(generate_ll_file) - set(options MEM2REG DEBUG O1 O2 O3) - set(testfile FILE) - cmake_parse_arguments(GEN_LL "${options}" "${testfile}" "" ${ARGN}) - - # get file extension - get_filename_component(test_code_file_ext ${GEN_LL_FILE} EXT) - string(REPLACE "." "_" ll_file_suffix ${test_code_file_ext}) - - # define .ll file name - # set(ll_file_suffix "_${test_code_file_ext}") - if(GEN_LL_MEM2REG) - set(ll_file_suffix "${ll_file_suffix}_m2r") - endif() - - if(GEN_LL_DEBUG) - set(ll_file_suffix "${ll_file_suffix}_dbg") - endif() - - # set(ll_file_suffix "${ll_file_suffix}.ll") - string(REPLACE ${test_code_file_ext} - "${ll_file_suffix}.ll" test_code_ll_file - ${GEN_LL_FILE} - ) - - # get file path - set(test_code_file_path "${CMAKE_CURRENT_SOURCE_DIR}/${GEN_LL_FILE}") - - # define custom target name - # target name = parentdir + test code file name + mem2reg + debug - get_filename_component(parent_dir ${CMAKE_CURRENT_SOURCE_DIR} NAME) - get_filename_component(test_code_file_name ${GEN_LL_FILE} NAME_WE) - set(test_code_file_target "${parent_dir}_${test_code_file_name}${ll_file_suffix}") - - # define compilation flags - set(GEN_CXX_FLAGS -std=c++17 -fno-discard-value-names -emit-llvm -S -w) - set(GEN_C_FLAGS -fno-discard-value-names -emit-llvm -S -w) - set(GEN_CMD_COMMENT "[LL]") - - if(GEN_LL_MEM2REG) - list(APPEND GEN_CXX_FLAGS -Xclang -disable-O0-optnone) - list(APPEND GEN_C_FLAGS -Xclang -disable-O0-optnone) - set(GEN_CMD_COMMENT "${GEN_CMD_COMMENT}[M2R]") - endif() - - if(GEN_LL_DEBUG) - list(APPEND GEN_CXX_FLAGS -g) - list(APPEND GEN_C_FLAGS -g) - set(GEN_CMD_COMMENT "${GEN_CMD_COMMENT}[DBG]") - endif() - - if(GEN_LL_O1) - list(APPEND GEN_CXX_FLAGS -O1) - list(APPEND GEN_C_FLAGS -O1) - set(GEN_CMD_COMMENT "${GEN_CMD_COMMENT}[O1]") - endif() - - if(GEN_LL_O2) - list(APPEND GEN_CXX_FLAGS -O2) - list(APPEND GEN_C_FLAGS -O2) - set(GEN_CMD_COMMENT "${GEN_CMD_COMMENT}[O2]") - endif() - - if(GEN_LL_03) - list(APPEND GEN_CXX_FLAGS -O3) - list(APPEND GEN_C_FLAGS -O3) - set(GEN_CMD_COMMENT "${GEN_CMD_COMMENT}[O3]") - endif() - - set(GEN_CMD_COMMENT "${GEN_CMD_COMMENT} ${GEN_LL_FILE}") - - # define .ll file generation command - if(${test_code_file_ext} STREQUAL ".cpp") - set(GEN_CMD ${CMAKE_CXX_COMPILER_LAUNCHER} ${CMAKE_CXX_COMPILER}) - list(APPEND GEN_CMD ${GEN_CXX_FLAGS}) - else() - set(GEN_CMD ${CMAKE_C_COMPILER_LAUNCHER} ${CMAKE_C_COMPILER}) - list(APPEND GEN_CMD ${GEN_C_FLAGS}) - endif() - - if(GEN_LL_MEM2REG) - add_custom_command( - OUTPUT ${test_code_ll_file} - COMMAND ${GEN_CMD} ${test_code_file_path} -o ${test_code_ll_file} - COMMAND ${CMAKE_CXX_COMPILER_LAUNCHER} opt -mem2reg -S ${test_code_ll_file} -o ${test_code_ll_file} - COMMENT ${GEN_CMD_COMMENT} - DEPENDS ${GEN_LL_FILE} - VERBATIM - ) - else() - add_custom_command( - OUTPUT ${test_code_ll_file} - COMMAND ${GEN_CMD} ${test_code_file_path} -o ${test_code_ll_file} - COMMENT ${GEN_CMD_COMMENT} - DEPENDS ${GEN_LL_FILE} - VERBATIM - ) - endif() - - add_custom_target(${test_code_file_target} - DEPENDS ${test_code_ll_file} - ) - add_dependencies(LLFileGeneration ${test_code_file_target}) -endfunction() - -macro(add_phasar_executable name) - set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin) - set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib) - add_llvm_executable(${name} ${ARGN}) - set_target_properties(${name} PROPERTIES FOLDER "phasar_executables") - install(TARGETS ${name} - RUNTIME DESTINATION bin - ) -endmacro(add_phasar_executable) - -macro(add_phasar_library name) - set(srcs ${ARGN}) - - if(MSVC_IDE OR XCODE) - file(GLOB_RECURSE headers *.h *.td *.def) - set(srcs ${srcs} ${headers}) - string(REGEX MATCHALL "/[^/]" split_path ${CMAKE_CURRENT_SOURCE_DIR}) - list(GET split_path -1 dir) - file(GLOB_RECURSE headers - ../../include/phasar${dir}/*.h) - set(srcs ${srcs} ${headers}) - endif(MSVC_IDE OR XCODE) - - if(MODULE) - set(libkind MODULE) - elseif(SHARED_LIBRARY) - set(libkind SHARED) - else() - set(libkind) - endif() - - add_library(${name} ${libkind} ${srcs}) - add_library(phasar::${name} ALIAS ${name}) - - if(LLVM_COMMON_DEPENDS) - add_dependencies(${name} ${LLVM_COMMON_DEPENDS}) - endif(LLVM_COMMON_DEPENDS) - - if(LLVM_USED_LIBS) - foreach(lib ${LLVM_USED_LIBS}) - target_link_libraries(${name} ${lib}) - endforeach(lib) - endif(LLVM_USED_LIBS) - - if(PHASAR_LINK_LIBS) - foreach(lib ${PHASAR_LINK_LIBS}) - if(PHASAR_DEBUG_LIBDEPS) - target_link_libraries(${name} LINK_PRIVATE ${lib}) - else() - target_link_libraries(${name} LINK_PUBLIC ${lib}) - endif(PHASAR_DEBUG_LIBDEPS) - endforeach(lib) - endif(PHASAR_LINK_LIBS) - - if(LLVM_LINK_COMPONENTS) - if(USE_LLVM_FAT_LIB) - llvm_config(${name} USE_SHARED ${LLVM_LINK_COMPONENTS}) - else() - llvm_config(${name} ${LLVM_LINK_COMPONENTS}) - endif() - endif(LLVM_LINK_COMPONENTS) - - if(MSVC) - get_target_property(cflag ${name} COMPILE_FLAGS) - - if(NOT cflag) - set(cflag "") - endif(NOT cflag) - - set(cflag "${cflag} /Za") - set_target_properties(${name} PROPERTIES COMPILE_FLAGS ${cflag}) - endif(MSVC) - - # cut off prefix phasar_ for convenient component names - string(REGEX REPLACE phasar_ "" name component_name) - - if(PHASAR_IN_TREE) - install(TARGETS ${name} - EXPORT LLVMExports - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) - else() - install(TARGETS ${name} - EXPORT ${name}-targets - COMPONENT ${component_name} - - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - - # NOTE: Library, archive and runtime destination are automatically set by - # GNUInstallDirs which is included in the top-level CMakeLists.txt - ) - install(EXPORT ${name}-targets - FILE ${name}-targets.cmake - NAMESPACE phasar:: - DESTINATION lib/cmake/phasar - COMPONENT ${component_name} - ) - endif() - - set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS ${name}) -endmacro(add_phasar_library) - -macro(add_phasar_loadable_module name) - set(srcs ${ARGN}) - - # klduge: pass different values for MODULE with multiple targets in same dir - # this allows building shared-lib and module in same dir - # there must be a cleaner way to achieve this.... - if(MODULE) - else() - set(GLOBAL_NOT_MODULE TRUE) - endif() - - set(MODULE TRUE) - add_phasar_library(${name} ${srcs}) - - if(GLOBAL_NOT_MODULE) - unset(MODULE) - endif() - - if(APPLE) - # Darwin-specific linker flags for loadable modules. - set_target_properties(${name} PROPERTIES - LINK_FLAGS "-Wl,-flat_namespace -Wl,-undefined -Wl,suppress") - endif() -endmacro(add_phasar_loadable_module) - -macro(subdirlist result curdir) - file(GLOB children RELATIVE ${curdir} ${curdir}/*) - set(dirlist "") - - foreach(child ${children}) - if(IS_DIRECTORY ${curdir}/${child}) - list(APPEND dirlist ${child}) - endif() - endforeach() - - set(${result} ${dirlist}) -endmacro(subdirlist) diff --git a/conanfile.in_llvm_tree.txt b/conanfile.in_llvm_tree.txt new file mode 100644 index 000000000..ba114e439 --- /dev/null +++ b/conanfile.in_llvm_tree.txt @@ -0,0 +1,15 @@ +[requires] +boost/[>=1.72.0 <=1.81.0] +gtest/[>=1.10.0 <2.0.0] +sqlite3/[>=3.36.0 <4.0.0] +json-schema-validator/[>=2.1.0 <3.0.0] +nlohmann_json/[>=3.10.5 <3.11.0] +libcurl/[>=7.80.0 <8.0.0] +zlib/[>=1.2.0 <2.0.0] # fix boost / clash zlib +openssl/3.0.5 # includes needed for some test files +doxygen/[>=1.9.0 <2.0.0] + +[generators] +cmake + +[options] diff --git a/conanfile.shared.txt b/conanfile.shared.txt new file mode 100644 index 000000000..f9038ac3a --- /dev/null +++ b/conanfile.shared.txt @@ -0,0 +1,28 @@ +[requires] +llvm/14.0.6 +boost/[>=1.72.0 <=1.81.0] +gtest/[>=1.10.0 <2.0.0] +sqlite3/[>=3.36.0 <4.0.0] +json-schema-validator/[>=2.1.0 <3.0.0] +nlohmann_json/[>=3.10.5 <3.11.0] +libcurl/[>=7.80.0 <8.0.0] +zlib/[>=1.2.0 <2.0.0] # fix boost / clash zlib +openssl/3.0.5 # includes needed for some test files +doxygen/[>=1.9.0 <2.0.0] + +[generators] +cmake + +[options] +sqlite3:shared=True +llvm:shared=True +llvm:llvm_build_llvm_dylib=False +llvm:conan_center_index_limits=False +llvm:with_project_clang=True +llvm:with_project_openmp=True +llvm:keep_binaries_regex=^(clang|clang\+\+|opt)$ + +# not for phasar needed but the llvm conan recipe doesn't understand currently, +# that "with compiler-rt" can be used for without compiler-rt +# so it would compile llvm just without compiler-rt for no reason +llvm:with_runtime_compiler-rt=True diff --git a/conanfile.txt b/conanfile.txt new file mode 100644 index 000000000..3d6abf154 --- /dev/null +++ b/conanfile.txt @@ -0,0 +1,27 @@ +[requires] +llvm/14.0.6 +boost/[>=1.72.0 <=1.81.0] +gtest/[>=1.10.0 <2.0.0] +sqlite3/[>=3.36.0 <4.0.0] +json-schema-validator/[>=2.1.0 <3.0.0] +nlohmann_json/[>=3.10.5 <3.11.0] +libcurl/[>=7.80.0 <8.0.0] +zlib/[>=1.2.0 <2.0.0] # fix boost / clash zlib +openssl/3.0.5 # includes needed for some test files +doxygen/[>=1.9.0 <2.0.0] + +[generators] +cmake + +[options] +llvm:shared=False +llvm:llvm_build_llvm_dylib=False +llvm:conan_center_index_limits=False +llvm:with_project_clang=True +llvm:with_project_openmp=True +llvm:keep_binaries_regex=^(clang|clang\+\+|opt)$ + +# not for phasar needed but the llvm conan recipe doesn't understand currently, +# that "with compiler-rt" can be used for without compiler-rt +# so it would compile llvm just without compiler-rt for no reason +llvm:with_runtime_compiler-rt=True diff --git a/config.h.in b/config.h.in deleted file mode 100644 index ac0e9c09a..000000000 --- a/config.h.in +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __CONFIG_H__ -#define __CONFIG_H__ - -#define PHASAR_SRC_DIR "@CMAKE_SOURCE_DIR@" -#define PHASAR_BUILD_DIR "@CMAKE_BINARY_DIR@" - -#endif /* __CONFIG_H__ */ diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in deleted file mode 100644 index dbf9245f0..000000000 --- a/docs/Doxyfile.in +++ /dev/null @@ -1,2303 +0,0 @@ -# Doxyfile 1.8.6 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a double hash (##) is considered a comment and is placed in -# front of the TAG it is preceding. -# -# All text after a single hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists, items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (\" \"). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all text -# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv -# for the list of possible encodings. -# The default value is: UTF-8. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by -# double-quotes, unless you are using Doxywizard) that should identify the -# project for which the documentation is generated. This name is used in the -# title of most generated pages and in a few other places. -# The default value is: My Project. - -PROJECT_NAME = "Phasar" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. This -# could be handy for archiving the generated documentation or if some version -# control system is used. - -PROJECT_NUMBER = 1.1 - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer a -# quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = "Phasar a LLVM-based Static Analysis Framework" - -# With the PROJECT_LOGO tag one can specify an logo or icon that is included in -# the documentation. The maximum height of the logo should not exceed 55 pixels -# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo -# to the output directory. - -PROJECT_LOGO = ../img/Logo_RGB/Phasar_Logo.png - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path -# into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where doxygen was started. If -# left blank the current directory will be used. - -OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/docs/ - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this -# option can be useful when feeding doxygen a huge amount of source files, where -# putting all generated files in the same directory would otherwise causes -# performance problems for the file system. -# The default value is: NO. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. -# The default value is: English. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member -# descriptions after the members that are listed in the file and class -# documentation (similar to Javadoc). Set to NO to disable this. -# The default value is: YES. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief -# description of a member or function before the detailed description -# -# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. -# The default value is: YES. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator that is -# used to form the text in various listings. Each string in this list, if found -# as the leading text of the brief description, will be stripped from the text -# and the result, after processing the whole list, is used as the annotated -# text. Otherwise, the brief description is used as-is. If left blank, the -# following values are used ($name is automatically replaced with the name of -# the entity):The $name class, The $name widget, The $name file, is, provides, -# specifies, contains, represents, a, an and the. - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# doxygen will generate a detailed section even if there is only a brief -# description. -# The default value is: NO. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. -# The default value is: NO. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path -# before files name in the file list and in the header files. If set to NO the -# shortest path that makes the file name unique will be used -# The default value is: YES. - -FULL_PATH_NAMES = YES - -# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. -# Stripping is only done if one of the specified strings matches the left-hand -# part of the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the path to -# strip. -# -# Note that you can specify absolute paths here, but also relative paths, which -# will be relative from the directory where doxygen is started. -# This tag requires that the tag FULL_PATH_NAMES is set to YES. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the -# path mentioned in the documentation of a class, which tells the reader which -# header file to include in order to use a class. If left blank only the name of -# the header file containing the class definition is used. Otherwise one should -# specify the list of include paths that are normally passed to the compiler -# using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but -# less readable) file names. This can be useful is your file systems doesn't -# support long names like on DOS, Mac, or CD-ROM. -# The default value is: NO. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the -# first line (until the first dot) of a Javadoc-style comment as the brief -# description. If set to NO, the Javadoc-style will behave just like regular Qt- -# style comments (thus requiring an explicit @brief command for a brief -# description.) -# The default value is: NO. - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first -# line (until the first dot) of a Qt-style comment as the brief description. If -# set to NO, the Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) -# The default value is: NO. - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a -# multi-line C++ special comment block (i.e. a block of //! or /// comments) as -# a brief description. This used to be the default behavior. The new default is -# to treat a multi-line C++ comment block as a detailed description. Set this -# tag to YES if you prefer the old behavior instead. -# -# Note that setting this tag to YES also means that rational rose comments are -# not recognized any more. -# The default value is: NO. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the -# documentation from any documented member that it re-implements. -# The default value is: YES. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a -# new page for each member. If set to NO, the documentation of a member will be -# part of the file/class/namespace that contains it. -# The default value is: NO. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen -# uses this value to replace tabs by spaces in code fragments. -# Minimum value: 1, maximum value: 16, default value: 4. - -TAB_SIZE = 4 - -# This tag can be used to specify a number of aliases that act as commands in -# the documentation. An alias has the form: -# name=value -# For example adding -# "sideeffect=@par Side Effects:\n" -# will allow you to put the command \sideeffect (or @sideeffect) in the -# documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines. - -ALIASES = - -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding "class=itcl::class" -# will allow you to use the command class in the itcl::class meaning. - -TCL_SUBST = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. For -# instance, some of the names that are used will be different. The list of all -# members will be omitted, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or -# Python sources only. Doxygen will then generate output that is more tailored -# for that language. For instance, namespaces will be presented as packages, -# qualified scopes will look different, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources. Doxygen will then generate output that is tailored for Fortran. -# The default value is: NO. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for VHDL. -# The default value is: NO. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given -# extension. Doxygen has a built-in mapping, but you can override or extend it -# using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. -# -# Note For files without extension you can use no_extension as a placeholder. -# -# Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. - -EXTENSION_MAPPING = cu=C++ cuh=C++ - -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments -# according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in -# case of backward compatibilities issues. -# The default value is: YES. - -MARKDOWN_SUPPORT = YES - -# When enabled doxygen tries to link words that correspond to documented -# classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by by putting a % sign in front of the word -# or globally by setting AUTOLINK_SUPPORT to NO. -# The default value is: YES. - -AUTOLINK_SUPPORT = YES - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should set this -# tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. -# The default value is: NO. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. -# The default value is: NO. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen -# will parse them like normal C++ but will assume all classes use public instead -# of private inheritance when no explicit protection keyword is present. -# The default value is: NO. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES will make -# doxygen to replace the get and set methods by a property in the documentation. -# This will only work if the methods are indeed getting or setting a simple -# type. If this is not the case, or you want to show the methods anyway, you -# should set this option to NO. -# The default value is: YES. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. -# The default value is: NO. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES to allow class member groups of the same type -# (for instance a group of public functions) to be put as a subgroup of that -# type (e.g. under the Public Functions section). Set it to NO to prevent -# subgrouping. Alternatively, this can be done per class using the -# \nosubgrouping command. -# The default value is: YES. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions -# are shown inside the group in which they are included (e.g. using \ingroup) -# instead of on a separate page (for HTML and Man pages) or section (for LaTeX -# and RTF). -# -# Note that this feature does not work in combination with -# SEPARATE_MEMBER_PAGES. -# The default value is: NO. - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions -# with only public data fields or simple typedef fields will be shown inline in -# the documentation of the scope in which they are defined (i.e. file, -# namespace, or group documentation), provided this scope is documented. If set -# to NO, structs, classes, and unions are shown on a separate page (for HTML and -# Man pages) or section (for LaTeX and RTF). -# The default value is: NO. - -INLINE_SIMPLE_STRUCTS = NO - -# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or -# enum is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically be -# useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. -# The default value is: NO. - -TYPEDEF_HIDES_STRUCT = NO - -# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This -# cache is used to resolve symbols given their name and scope. Since this can be -# an expensive process and often the same symbol appears multiple times in the -# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# doxygen will become slower. If the cache is too large, memory is wasted. The -# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range -# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run doxygen will report the cache usage and suggest -# the optimal cache size from a speed point of view. -# Minimum value: 0, maximum value: 9, default value: 0. - -LOOKUP_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. Private -# class members and static file members will be hidden unless the -# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. -# Note: This will also disable the warnings about undocumented members that are -# normally produced when WARNINGS is set to YES. -# The default value is: NO. - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will -# be included in the documentation. -# The default value is: NO. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal -# scope will be included in the documentation. -# The default value is: NO. - -EXTRACT_PACKAGE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file will be -# included in the documentation. -# The default value is: NO. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined -# locally in source files will be included in the documentation. If set to NO -# only classes defined in header files are included. Does not have any effect -# for Java sources. -# The default value is: YES. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local methods, -# which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO only methods in the interface are -# included. -# The default value is: NO. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base name of -# the file that contains the anonymous namespace. By default anonymous namespace -# are hidden. -# The default value is: NO. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all -# undocumented members inside documented classes or files. If set to NO these -# members will be included in the various overviews, but no documentation -# section is generated. This option has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. If set -# to NO these classes will be included in the various overviews. This option has -# no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO these declarations will be -# included in the documentation. -# The default value is: NO. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any -# documentation blocks found inside the body of a function. If set to NO these -# blocks will be appended to the function's detailed documentation block. -# The default value is: NO. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation that is typed after a -# \internal command is included. If the tag is set to NO then the documentation -# will be excluded. Set it to YES to include the internal documentation. -# The default value is: NO. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. -# The default value is: system dependent. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with -# their full class and namespace scopes in the documentation. If set to YES the -# scope will be hidden. -# The default value is: NO. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of -# the files that are included by a file in the documentation of that file. -# The default value is: YES. - -SHOW_INCLUDE_FILES = YES - -# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each -# grouped member an include statement to the documentation, telling the reader -# which file to include in order to use the member. -# The default value is: NO. - -SHOW_GROUPED_MEMB_INC = NO - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include -# files with double quotes in the documentation rather than with sharp brackets. -# The default value is: NO. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the -# documentation for inline members. -# The default value is: YES. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the -# (detailed) documentation of file and class members alphabetically by member -# name. If set to NO the members will appear in declaration order. -# The default value is: YES. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief -# descriptions of file, namespace and class members alphabetically by member -# name. If set to NO the members will appear in declaration order. Note that -# this will also influence the order of the classes in the class list. -# The default value is: NO. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the -# (brief and detailed) documentation of class members so that constructors and -# destructors are listed first. If set to NO the constructors will appear in the -# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. -# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief -# member documentation. -# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting -# detailed member documentation. -# The default value is: NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy -# of group names into alphabetical order. If set to NO the group names will -# appear in their defined order. -# The default value is: NO. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by -# fully-qualified names, including namespaces. If set to NO, the class list will -# be sorted only by class name, not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the alphabetical -# list. -# The default value is: NO. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper -# type resolution of all parameters of a function it will reject a match between -# the prototype and the implementation of a member function even if there is -# only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still -# accept a match between prototype and implementation in such cases. -# The default value is: NO. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the -# todo list. This list is created by putting \todo commands in the -# documentation. -# The default value is: YES. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the -# test list. This list is created by putting \test commands in the -# documentation. -# The default value is: YES. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug -# list. This list is created by putting \bug commands in the documentation. -# The default value is: YES. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) -# the deprecated list. This list is created by putting \deprecated commands in -# the documentation. -# The default value is: YES. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional documentation -# sections, marked by \if ... \endif and \cond -# ... \endcond blocks. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the -# initial value of a variable or macro / define can have for it to appear in the -# documentation. If the initializer consists of more lines than specified here -# it will be hidden. Use a value of 0 to hide initializers completely. The -# appearance of the value of individual variables and macros / defines can be -# controlled using \showinitializer or \hideinitializer command in the -# documentation regardless of this setting. -# Minimum value: 0, maximum value: 10000, default value: 30. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at -# the bottom of the documentation of classes and structs. If set to YES the list -# will mention the files that were used to generate the documentation. -# The default value is: YES. - -SHOW_USED_FILES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This -# will remove the Files entry from the Quick Index and from the Folder Tree View -# (if specified). -# The default value is: YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces -# page. This will remove the Namespaces entry from the Quick Index and from the -# Folder Tree View (if specified). -# The default value is: YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command command input-file, where command is the value of the -# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided -# by doxygen. Whatever the program writes to standard output is used as the file -# version. For an example see the documentation. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. You can -# optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. -# -# Note that if you run doxygen from a directory containing a file called -# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE -# tag is left empty. - -LAYOUT_FILE = - -# The CITE_BIB_FILES tag can be used to specify one or more bib files containing -# the reference definitions. This must be a list of .bib files. The .bib -# extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. -# For LaTeX the style of the bibliography can be controlled using -# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the -# search path. Do not use file names with spaces, bibtex cannot handle them. See -# also \cite for info how to create references. - -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# Configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by doxygen. If QUIET is set to YES this implies that the -# messages are off. -# The default value is: NO. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES -# this implies that the warnings are on. -# -# Tip: Turn warnings on while writing the documentation. -# The default value is: YES. - -WARNINGS = YES - -# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate -# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag -# will automatically be disabled. -# The default value is: YES. - -WARN_IF_UNDOCUMENTED = YES - -# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. -# The default value is: YES. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that -# are documented, but have no documentation for their parameters or return -# value. If set to NO doxygen will only warn about wrong or incomplete parameter -# documentation, but not about the absence of documentation. -# The default value is: NO. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that doxygen -# can produce. The string should contain the $file, $line, and $text tags, which -# will be replaced by the file and line number from which the warning originated -# and the warning text. Optionally the format may contain $version, which will -# be replaced by the version of the file (if it could be obtained via -# FILE_VERSION_FILTER) -# The default value is: $file:$line: $text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning and error -# messages should be written. If left blank the output is written to standard -# error (stderr). - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag is used to specify the files and/or directories that contain -# documented source files. You may enter file names like myfile.cpp or -# directories like /usr/src/myproject. Separate the files or directories with -# spaces. -# Note: If this tag is empty the current directory is searched. - -INPUT = @CMAKE_CURRENT_SOURCE_DIR@/include/ @CMAKE_CURRENT_SOURCE_DIR@/lib/ @CMAKE_CURRENT_SOURCE_DIR@/docs - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses -# libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: http://www.gnu.org/software/libiconv) for the list of -# possible encodings. -# The default value is: UTF-8. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank the -# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, -# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, -# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, -# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, -# *.qsf, *.as and *.js. - -FILE_PATTERNS = *.dox *.c *.h *.cpp *.hh *.cu *.cuh - -# The RECURSIVE tag can be used to specify whether or not subdirectories should -# be searched for input files as well. -# The default value is: NO. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. -# The default value is: NO. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or directories -# that contain example code fragments that are included (see the \include -# command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank all -# files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude commands -# irrespective of the value of the RECURSIVE tag. -# The default value is: NO. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or directories -# that contain images that are to be included in the documentation (see the -# \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command: -# -# -# -# where is the value of the INPUT_FILTER tag, and is the -# name of an input file. Doxygen will then use the output that the filter -# program writes to standard output. If FILTER_PATTERNS is specified, this tag -# will be ignored. -# -# Note that the filter must not add or remove lines; it is applied before the -# code is scanned, but not when the output code is generated. If lines are added -# or removed, the anchors will not be placed correctly. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: pattern=filter -# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how -# filters are used. If the FILTER_PATTERNS tag is empty or if none of the -# patterns match the file name, INPUT_FILTER is applied. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER ) will also be used to filter the input files that are used for -# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). -# The default value is: NO. - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and -# it is also possible to disable source filtering for a specific pattern using -# *.ext= (so without naming a filter). -# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. - -FILTER_SOURCE_PATTERNS = - -# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that -# is part of the input, its contents will be placed on the main page -# (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the doxygen output. - -USE_MDFILE_AS_MAINPAGE = - -#--------------------------------------------------------------------------- -# Configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will be -# generated. Documented entities will be cross-referenced with these sources. -# -# Note: To get rid of all source code in the generated output, make sure that -# also VERBATIM_HEADERS is set to NO. -# The default value is: NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. -# The default value is: NO. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any -# special comment blocks from generated source code fragments. Normal C, C++ and -# Fortran comments will always remain visible. -# The default value is: YES. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# function all documented functions referencing it will be listed. -# The default value is: NO. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES then for each documented function -# all documented entities called/used by that function will be listed. -# The default value is: NO. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set -# to YES, then the hyperlinks from functions in REFERENCES_RELATION and -# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will -# link to the documentation. -# The default value is: YES. - -REFERENCES_LINK_SOURCE = YES - -# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the -# source code will show a tooltip with additional information such as prototype, -# brief description and links to the definition and documentation. Since this -# will make the HTML file larger and loading of large files a bit slower, you -# can opt to disable this feature. -# The default value is: YES. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -SOURCE_TOOLTIPS = YES - -# If the USE_HTAGS tag is set to YES then the references to source code will -# point to the HTML generated by the htags(1) tool instead of doxygen built-in -# source browser. The htags tool is part of GNU's global source tagging system -# (see http://www.gnu.org/software/global/global.html). You will need version -# 4.8.6 or higher. -# -# To use it do the following: -# - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the config file -# - Make sure the INPUT points to the root of the source tree -# - Run doxygen as normal -# -# Doxygen will invoke htags (and that will in turn invoke gtags), so these -# tools must be available from the command line (i.e. in the search path). -# -# The result: instead of the source browser generated by doxygen, the links to -# source code will now point to the output of htags. -# The default value is: NO. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a -# verbatim copy of the header file for each class for which an include is -# specified. Set to NO to disable this. -# See also: Section \class. -# The default value is: YES. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# Configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all -# compounds will be generated. Enable this if the project contains a lot of -# classes, structs, unions or interfaces. -# The default value is: YES. - -ALPHABETICAL_INDEX = YES - -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output -# The default value is: YES. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each -# generated HTML page (for example: .htm, .php, .asp). -# The default value is: .html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank doxygen will generate a -# standard header. -# -# To get valid HTML the header file that includes any scripts and style sheets -# that doxygen needs, which is dependent on the configuration options used (e.g. -# the setting GENERATE_TREEVIEW). It is highly recommended to start with a -# default header using -# doxygen -w html new_header.html new_footer.html new_stylesheet.css -# YourConfigFile -# and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that doxygen normally -# uses. -# Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. For a description -# of the possible markers and block names see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank doxygen will generate a standard -# footer. See HTML_HEADER for more information on how to generate a default -# footer and what special commands can be used inside the footer. See also -# section "Doxygen usage" for information on how to generate the default footer -# that doxygen normally uses. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style -# sheet that is used by each HTML page. It can be used to fine-tune the look of -# the HTML output. If left blank doxygen will generate a default style sheet. -# See also section "Doxygen usage" for information on how to generate the style -# sheet that doxygen normally uses. -# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as -# it is more robust and this tag (HTML_STYLESHEET) will in the future become -# obsolete. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_STYLESHEET = - -# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- -# defined cascading style sheet that is included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. -# This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefor more robust against future updates. -# Doxygen will copy the style sheet file to the output directory. For an example -# see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that the -# files will be copied as-is; there are no commands or markers available. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the stylesheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value -# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 -# purple, and 360 is red again. -# Minimum value: 0, maximum value: 359, default value: 220. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A -# value of 255 will produce the most vivid colors. -# Minimum value: 0, maximum value: 255, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the -# luminance component of the colors in the HTML output. Values below 100 -# gradually make the output lighter, whereas values above 100 make the output -# darker. The value divided by 100 is the actual gamma applied, so 80 represents -# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not -# change the gamma. -# Minimum value: 40, maximum value: 240, default value: 80. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to NO can help when comparing the output of multiple runs. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_SECTIONS = NO - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries -# shown in the various tree structured indices initially; the user can expand -# and collapse entries dynamically later on. Doxygen will expand the tree to -# such a level that at most the specified number of entries are visible (unless -# a fully collapsed tree already exceeds this amount). So setting the number of -# entries 1 will produce a full collapsed tree by default. 0 is a special value -# representing an infinite number of entries and will result in a full expanded -# tree by default. -# Minimum value: 0, maximum value: 9999, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_INDEX_NUM_ENTRIES = 100 - -# If the GENERATE_DOCSET tag is set to YES, additional index files will be -# generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with -# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_DOCSET = NO - -# This tag determines the name of the docset feed. A documentation feed provides -# an umbrella under which multiple documentation sets from a single provider -# (such as a company or product suite) can be grouped. -# The default value is: Doxygen generated docs. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# This tag specifies a string that should uniquely identify the documentation -# set bundle. This should be a reverse domain-name style string, e.g. -# com.mycompany.MyDocSet. Doxygen will append .docset to the name. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. -# The default value is: org.doxygen.Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. -# The default value is: Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three -# additional HTML index files: index.hhp, index.hhc, and index.hhk. The -# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. -# -# The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML -# files are now used as the Windows 98 help format, and will replace the old -# Windows help format (.hlp) on all Windows platforms in the future. Compressed -# HTML files also contain an index, a table of contents, and you can search for -# words in the documentation. The HTML workshop also contains a viewer for -# compressed HTML files. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_HTMLHELP = NO - -# The CHM_FILE tag can be used to specify the file name of the resulting .chm -# file. You can add a path in front of the file if the result should not be -# written to the html output directory. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_FILE = - -# The HHC_LOCATION tag can be used to specify the location (absolute path -# including file name) of the HTML help compiler ( hhc.exe). If non-empty -# doxygen will try to run the HTML help compiler on the generated index.hhp. -# The file has to be specified with full path. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -HHC_LOCATION = - -# The GENERATE_CHI flag controls if a separate .chi index file is generated ( -# YES) or that it should be included in the master .chm file ( NO). -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -GENERATE_CHI = NO - -# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) -# and project file content. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_INDEX_ENCODING = - -# The BINARY_TOC flag controls whether a binary table of contents is generated ( -# YES) or a normal table of contents ( NO) in the .chm file. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members to -# the table of contents of the HTML help documentation and to the tree view. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that -# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help -# (.qch) of the generated HTML documentation. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify -# the file name of the resulting .qch file. The path specified is relative to -# the HTML output folder. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help -# Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt -# Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- -# folders). -# The default value is: doc. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_VIRTUAL_FOLDER = doc - -# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom -# filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_SECT_FILTER_ATTRS = - -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be -# generated, together with the HTML files, they form an Eclipse help plugin. To -# install this plugin and make it available under the help contents menu in -# Eclipse, the contents of the directory containing the HTML and XML files needs -# to be copied into the plugins directory of eclipse. The name of the directory -# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. -# After copying Eclipse needs to be restarted before the help appears. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the Eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have this -# name. Each documentation set should have its own identifier. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# If you want full control over the layout of the generated HTML pages it might -# be necessary to disable the index and replace it with your own. The -# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top -# of each HTML page. A value of NO enables the index and the value YES disables -# it. Since the tabs in the index contain the same information as the navigation -# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. If the tag -# value is set to YES, a side panel will be generated containing a tree-like -# index structure (just like the one that is generated for HTML Help). For this -# to work a browser that supports JavaScript, DHTML, CSS and frames is required -# (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_TREEVIEW = NO - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. -# -# Note that a value of 0 will completely suppress the enum values from appearing -# in the overview section. -# Minimum value: 0, maximum value: 20, default value: 4. -# This tag requires that the tag GENERATE_HTML is set to YES. - -ENUM_VALUES_PER_LINE = 4 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used -# to set the initial width (in pixels) of the frame in which the tree is shown. -# Minimum value: 0, maximum value: 1500, default value: 250. -# This tag requires that the tag GENERATE_HTML is set to YES. - -TREEVIEW_WIDTH = 250 - -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to -# external symbols imported via tag files in a separate window. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of LaTeX formulas included as images in -# the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML -# output directory to force them to be regenerated. -# Minimum value: 8, maximum value: 50, default value: 10. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering -# instead of using prerendered bitmaps. Use this if you do not have LaTeX -# installed or if you want to formulas look prettier in the HTML output. When -# enabled you may also need to install MathJax separately and configure the path -# to it using the MATHJAX_RELPATH option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -USE_MATHJAX = NO - -# When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. -# Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. -# The default value is: HTML-CSS. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_FORMAT = HTML-CSS - -# When MathJax is enabled you need to specify the location relative to the HTML -# output directory using the MATHJAX_RELPATH option. The destination directory -# should contain the MathJax.js script. For instance, if the mathjax directory -# is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax -# Content Delivery Network so you can quickly see the result without installing -# MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest - -# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax -# extension names that should be enabled during MathJax rendering. For example -# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_EXTENSIONS = - -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces -# of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an -# example see the documentation. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_CODEFILE = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and -# should work on any modern browser. Note that when using HTML help -# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) -# there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then -# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to -# search using the keyboard; to jump to the search box use + S -# (what the is depends on the OS and browser, but it is typically -# , /