diff --git a/.clang-tidy b/.clang-tidy index 8103eae9..65767475 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1 +1,2 @@ Checks: '-*,modernize-*,cppcoreguidelines-*' +HeaderFilterRegex: 'app4triqs' diff --git a/.travis.yml b/.travis.yml index 7ebf8f58..8ccba8e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,15 +37,11 @@ script: - make -j8 install - cd $TRAVIS_BUILD_DIR - source root_install/share/triqsvars.sh - # ===== Set up CTINT and Test using fsanitize=address + # ===== Set up CTINT and Test with Sanitizer Checks - mkdir build && cd build - - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DGTAU_IS_COMPLEX=ON -DINTERACTION_IS_COMPLEX=ON -DCMAKE_CXX_FLAGS='-fsanitize=address -fno-omit-frame-pointer -fuse-ld=gold -Wno-register -Wno-macro-redefined' - - make -j8 + - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DASAN=ON -DUBSAN=ON + - export UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer - export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer - export ASAN_OPTIONS=symbolize=1:detect_leaks=0 - export CTEST_OUTPUT_ON_FAILURE=1 - - cd test/c++ && ctest - - if [ "$CXX" = g++ ]; then export LD_PRELOAD=/usr/lib/gcc/x86_64-linux-gnu/7/libasan.so; elif [ "$CXX" = clang++ ]; then export LD_PRELOAD=/usr/lib/llvm-5.0/lib/clang/5.0.1/lib/linux/libclang_rt.asan-x86_64.so; fi - - cd ../python && ctest - - cd ../../ - - unset LD_PRELOAD + - make -j8 && make test diff --git a/CMakeLists.txt b/CMakeLists.txt index 854ebccb..cae84058 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ set(APP4TRIQS_VERSION "1.5") # Start configuration -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.6) project(app4triqs CXX) # Default to Release build type @@ -14,13 +14,10 @@ message( STATUS "-------- BUILD-TYPE: ${CMAKE_BUILD_TYPE} --------") # Use shared libraries set(BUILD_SHARED_LIBS ON) -# Load TRIQS and Cpp2Py +# Load Dependencies find_package(TRIQS ${APP4TRIQS_VERSION} EXACT REQUIRED) find_package(Cpp2Py ${APP4TRIQS_VERSION} EXACT REQUIRED) -# We will need the FindNNFT of triqs, so we adjust CMake Module Path to find it -list(APPEND CMAKE_MODULE_PATH ${TRIQS_ROOT}/share/cmake) - # Default Install directory to TRIQS_ROOT if not given. Checks an absolute name is given. if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR (NOT IS_ABSOLUTE ${CMAKE_INSTALL_PREFIX})) message(STATUS "No install prefix given (or invalid). Defaulting to TRIQS_ROOT") @@ -35,9 +32,12 @@ message(STATUS "app4triqs git hash: ${APP4TRIQS_GIT_HASH}") # Set up the rpath for compiled executable triqs_set_rpath_for_all_targets() +# Build and install the app4triqs library add_subdirectory(c++/app4triqs) + +# Build and install the app4triqs python module if(${TRIQS_WITH_PYTHON_SUPPORT}) - add_subdirectory(python/app4triqs) + add_subdirectory(python/app4triqs) endif() # Tests diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt index fefb6564..70777499 100644 --- a/c++/app4triqs/CMakeLists.txt +++ b/c++/app4triqs/CMakeLists.txt @@ -1,20 +1,77 @@ -file(GLOB_RECURSE sources RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) +file(GLOB_RECURSE sources *.cpp *.hpp) add_library(app4triqs_c ${sources}) target_link_libraries(app4triqs_c PUBLIC triqs) target_compile_options(app4triqs_c PUBLIC -std=c++17) target_include_directories(app4triqs_c PUBLIC $) - target_compile_definitions(app4triqs_c PRIVATE APP4TRIQS_GIT_HASH=${APP4TRIQS_GIT_HASH} TRIQS_GIT_HASH=${TRIQS_GIT_HASH} - $<$:DEBUG_APP4TRIQS> + $<$:APP4TRIQS_DEBUG> $<$:TRIQS_ARRAYS_ENFORCE_BOUNDCHECK> - #$<$:MYOPTION> # Add compile definintions for option ) -# Install +# Install library and headers install(TARGETS app4triqs_c EXPORT app4triqs-targets DESTINATION lib) - -# If other applications need our headers, we can install them as well install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h") + + +# ========= Static Analyzer Checks ========== + +# Locate static analyzer tools +find_program(CPPCHECK_EXECUTABLE NAMES "cppcheck" PATHS ENV PATH) +find_program(CLANG_TIDY_EXECUTABLE NAMES "clang-tidy" PATHS ENV PATH) + +# Run clang-tidy if found +if(CLANG_TIDY_EXECUTABLE) + message(STATUS "clang-tidy found: ${CLANG_TIDY_EXECUTABLE}") + set_target_properties(app4triqs_c PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXECUTABLE}") +else() + message(STATUS "clang-tidy not found in $PATH. Please consider installing clang-tidy for additional checks!") +endif() + +# Run cppcheck if found +if(CPPCHECK_EXECUTABLE) + message(STATUS "cppcheck found: ${CPPCHECK_EXECUTABLE}") + add_custom_command( + TARGET app4triqs_c + COMMAND echo "--- Running cppcheck ---\n" + COMMAND ${CPPCHECK_EXECUTABLE} + --enable=warning,style,performance,portability + --std=c++14 + --template=gcc + --verbose + --quiet + ${sources} + COMMAND echo "------------------------\n" + ) +else() + message(STATUS "cppcheck not found in $PATH. Please consider installing cppcheck for additional checks!") +endif() + + +# ========= Dynamic Analyzer Checks ========== + +# Address Sanitizer +option(ASAN OFF "Compile library and executables with LLVM Address Sanitizer") +if(ASAN) + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + message(FATAL_ERROR "Address Sanitizer Checks currently not compatible with OSX.") + endif() + list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/share/cmake) + find_package(libasan_rt REQUIRED) + target_compile_options(app4triqs_c PUBLIC -fsanitize=address -fno-omit-frame-pointer) + target_link_libraries(app4triqs_c INTERFACE "-fsanitize=address -fno-omit-frame-pointer") +endif() + +# Undefined Behavior Sanitizer +option(UBSAN OFF "Compile library and executables with LLVM Undefined Behavior Sanitizer") +if(UBSAN) + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + message(FATAL_ERROR "Undefined Behavior Sanitizer Checks currently not compatible with OSX.") + endif() + list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/share/cmake) + find_package(libubsan_rt REQUIRED) + target_compile_options(app4triqs_c PUBLIC -fsanitize=undefined -fno-omit-frame-pointer -fno-sanitize=vptr) + target_link_libraries(app4triqs_c INTERFACE "-fsanitize=undefined -fno-omit-frame-pointer") +endif() diff --git a/c++/app4triqs/toto.hpp b/c++/app4triqs/toto.hpp index 17c4df2b..44e6195b 100644 --- a/c++/app4triqs/toto.hpp +++ b/c++/app4triqs/toto.hpp @@ -14,20 +14,22 @@ namespace app4triqs { int i = 0.0; public: - toto() = default; - - // Copy construction - toto(toto const &) = default; - toto(toto &&) = default; + toto() = default; /** * Construct from integer * * @param i_ a scalar */ - toto(int i_) : i(i_) {} + explicit toto(int i_) : i(i_) {} - /// Copy assignment + ~toto() = default; + + // Copy/Move construction + toto(toto const &) = default; + toto(toto &&) = default; + + /// Copy/Move assignment toto &operator=(toto const &) = default; toto &operator=(toto &&) = default; @@ -45,7 +47,6 @@ namespace app4triqs { static std::string hdf5_scheme() { return "Toto"; } friend void h5_write(triqs::h5::group grp, std::string subgroup_name, toto const &m); - friend void h5_read(triqs::h5::group grp, std::string subgroup_name, toto &m); /// Serialization @@ -58,7 +59,7 @@ namespace app4triqs { * Chain the decimal digits of two integers i and j, and return the result * * @param :math:`i` The first integer - * @param :math:`j` The second integer + * @param :math:`j` The second integer * @return An integer containing the digits of both i and j * * @remark diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 658139b9..24fccf0e 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -1,10 +1,9 @@ -# Generate the conf.py +# Generate the sphinx config file configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in ${CMAKE_CURRENT_BINARY_DIR}/conf.py @ONLY) # --------------------------------- # Top Sphinx target # --------------------------------- -# Sources file(GLOB_RECURSE sources *.rst) set(sphinx_top ${CMAKE_CURRENT_BINARY_DIR}/html/contents.html) @@ -20,48 +19,45 @@ add_dependencies(docs_sphinx app4triqs_c) # cp_rs is a script in cpp2py/bin, it mimics cp -rs on Linux # and filters the relevant extension # ------------------------------------------------------------------------------------------------ - set(EXT_FOR_DOC "rst png txt css_t conf css js gif jpg py html bib") execute_process(COMMAND cp_rs ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${EXT_FOR_DOC}) # --------------------------------- # Generate C++ doc with c++2rst # --------------------------------- - add_custom_target(docs_cpp2rst) get_property(TRIQS_INCLUDE_DIRS TARGET triqs PROPERTY INTERFACE_INCLUDE_DIRECTORIES) get_property(APP4TRIQS_INCLUDE_DIRS TARGET app4triqs_c PROPERTY INTERFACE_INCLUDE_DIRECTORIES) - set(CPP2RST_INCLUDE_DIRS ${TRIQS_INCLUDE_DIRS} ${APP4TRIQS_INCLUDE_DIRS}) + foreach(I ${CPP2RST_INCLUDE_DIRS}) set (CPP2RST_INCLUDE_COMMAND ${CPP2RST_INCLUDE_COMMAND} --includes ${I}) endforeach() macro(generate_docs header_file) - add_custom_command (TARGET docs_cpp2rst - COMMAND c++2rst - ${header_file} - -N app4triqs - --output_directory ${CMAKE_CURRENT_BINARY_DIR}/cpp2rst_generated - ${CPP2RST_INCLUDE_COMMAND} - --cxxflags="-std=c++17" - -I ${CMAKE_SOURCE_DIR}/c++ - -I ${TRIQS_ROOT}/include - 2>&1 >> cpp2rst.log - ) + add_custom_command( + TARGET docs_cpp2rst + COMMAND c++2rst + ${header_file} + -N app4triqs + --output_directory ${CMAKE_CURRENT_BINARY_DIR}/cpp2rst_generated + ${CPP2RST_INCLUDE_COMMAND} + --cxxflags="-std=c++17" + -I ${CMAKE_SOURCE_DIR}/c++ + -I ${TRIQS_ROOT}/include + 2>&1 >> cpp2rst.log + ) endmacro(generate_docs) generate_docs(${CMAKE_SOURCE_DIR}/c++/app4triqs/toto.hpp) - add_dependencies(docs_sphinx docs_cpp2rst) # --------------------------------- # Install # --------------------------------- install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/ COMPONENT documentation DESTINATION share/doc/app4triqs - FILES_MATCHING - REGEX "\\.(html|pdf|png|gif|jpg|js|xsl|css|py|txt|inv|bib)$" - PATTERN "_*" - ) - + FILES_MATCHING + REGEX "\\.(html|pdf|png|gif|jpg|js|xsl|css|py|txt|inv|bib)$" + PATTERN "_*" +) diff --git a/python/app4triqs/CMakeLists.txt b/python/app4triqs/CMakeLists.txt index 2784e7ff..f7ec1c0c 100644 --- a/python/app4triqs/CMakeLists.txt +++ b/python/app4triqs/CMakeLists.txt @@ -12,7 +12,7 @@ configure_file(version.py.in version.py) # All Python files. Copy them in the build dir to have a complete package for the tests. set(PYTHON_SOURCES __init__.py) foreach(f ${PYTHON_SOURCES}) - configure_file(${f} ${f} COPYONLY) + configure_file(${f} ${f} COPYONLY) endforeach() # Install python module to proper location diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt index c12791b6..961203f6 100644 --- a/share/CMakeLists.txt +++ b/share/CMakeLists.txt @@ -2,22 +2,22 @@ add_subdirectory(cmake) if(NOT CMAKE_INSTALL_PREFIX STREQUAL TRIQS_ROOT) - configure_file(app4triqs.modulefile.in app4triqs.modulefile @ONLY) - configure_file(app4triqsvars.sh.in app4triqsvars.sh @ONLY) + configure_file(app4triqs.modulefile.in app4triqs.modulefile @ONLY) + configure_file(app4triqsvars.sh.in app4triqsvars.sh @ONLY) - install( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/app4triqs.modulefile - ${CMAKE_CURRENT_BINARY_DIR}/app4triqsvars.sh - DESTINATION share - ) + install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/app4triqs.modulefile + ${CMAKE_CURRENT_BINARY_DIR}/app4triqsvars.sh + DESTINATION share + ) - message(STATUS "***************************************************************") - message(STATUS "* Custom install Location. Use: ") - message(STATUS "* ") - message(STATUS "* source ${CMAKE_INSTALL_PREFIX}/share/app4triqsvars.sh ") - message(STATUS "* ") - message(STATUS "* to set up the environment variables ") - message(STATUS "***************************************************************") + message(STATUS "***************************************************************") + message(STATUS "* Custom install Location. Use: ") + message(STATUS "* ") + message(STATUS "* source ${CMAKE_INSTALL_PREFIX}/share/app4triqsvars.sh ") + message(STATUS "* ") + message(STATUS "* to set up the environment variables ") + message(STATUS "***************************************************************") endif() diff --git a/share/cmake/CMakeLists.txt b/share/cmake/CMakeLists.txt index 0ebacec0..80301486 100644 --- a/share/cmake/CMakeLists.txt +++ b/share/cmake/CMakeLists.txt @@ -1,10 +1,10 @@ configure_file(app4triqs-config.cmake.in app4triqs-config.cmake @ONLY) configure_file(app4triqs-config-version.cmake.in app4triqs-config-version.cmake @ONLY) install( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/app4triqs-config.cmake - ${CMAKE_CURRENT_BINARY_DIR}/app4triqs-config-version.cmake - DESTINATION share/cmake + FILES + ${CMAKE_CURRENT_BINARY_DIR}/app4triqs-config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/app4triqs-config-version.cmake + DESTINATION share/cmake ) install(EXPORT app4triqs-targets DESTINATION share/cmake) diff --git a/share/cmake/Findlibasan_rt.cmake b/share/cmake/Findlibasan_rt.cmake new file mode 100644 index 00000000..7e0c0f56 --- /dev/null +++ b/share/cmake/Findlibasan_rt.cmake @@ -0,0 +1,50 @@ +# Copyright Nils Wentzell 2018 +# Distributed under the GNU GENERAL PUBLIC LICENSE Version 3.0. +# See accompanying file LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt +# +# This cmake find module looks for the LLVM Address Sanitizer Runtime Library +# It sets up : ASAN_RT_LIBRARY + +# This module finds the LLVM Address Sanitizer Runtime Library +# latter case skip to the "Boost CMake" section below. For the former +# +# Use this module by invoking find_package with the form:: +# +# find_package(libasan_rt [REQUIRED]) +# +# Results are reported in:: +# +# ASAN_RT_LIBRARY Address Sanitizer Runtime Library + +if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") + set(name clang_rt.asan-x86_64) +elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") + set(name asan) +else() + message(FATAL_ERROR "LLVM Address Sanitizer is not available for your compiler") +endif() + +find_library(ASAN_RT_LIBRARY + NAMES ${name} + PATHS + ENV LIBRARY_PATH + ENV LD_INCLUDE_PATH + /usr/lib + /usr/local/lib + /usr/lib/gcc/*/* + /usr/lib/clang/*/lib/linux + /usr/lib/llvm-*/lib/clang/*/lib/linux + /usr/local/opt/llvm/lib/clang/*/lib/darwin +) + +mark_as_advanced(ASAN_RT_LIBRARY) + +# Imported target +add_library(libasan_rt SHARED IMPORTED) +set_property(TARGET libasan_rt PROPERTY IMPORTED_LOCATION ${ASAN_RT_LIBRARY}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args("Address Sanitizer Runtime Library" + REQUIRED_VARS ASAN_RT_LIBRARY + FAIL_MESSAGE "Address Sanitizer Runtime Libraries not found! Consider installing for additional checks!" +) diff --git a/share/cmake/Findlibubsan_rt.cmake b/share/cmake/Findlibubsan_rt.cmake new file mode 100644 index 00000000..a22990ae --- /dev/null +++ b/share/cmake/Findlibubsan_rt.cmake @@ -0,0 +1,50 @@ +# Copyright Nils Wentzell 2018 +# Distributed under the GNU GENERAL PUBLIC LICENSE Version 3.0. +# See accompanying file LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt +# +# This cmake find module looks for the LLVM Undefined Behavior Sanitizer Runtime Library +# It sets up : UBSAN_RT_LIBRARY + +# This module finds the LLVM Undefined Behavior Sanitizer Runtime Library +# latter case skip to the "Boost CMake" section below. For the former +# +# Use this module by invoking find_package with the form:: +# +# find_package(libubsan_rt [REQUIRED]) +# +# Results are reported in:: +# +# UBSAN_RT_LIBRARY Undefined Behavior Sanitizer Runtime Library + +if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") + set(name clang_rt.ubsan_standalone-x86_64) +elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") + set(name ubsan) +else() + message(FATAL_ERROR "Undefined Behavior Sanitizer is not available for your compiler") +endif() + +find_library(UBSAN_RT_LIBRARY + NAMES ${name} + PATHS + ENV LIBRARY_PATH + ENV LD_INCLUDE_PATH + /usr/lib + /usr/local/lib + /usr/lib/gcc/*/* + /usr/lib/clang/*/lib/linux + /usr/lib/llvm-*/lib/clang/*/lib/linux + /usr/local/opt/llvm/lib/clang/*/lib/darwin +) + +mark_as_advanced(UBSAN_RT_LIBRARY) + +# Imported target +add_library(libubsan_rt SHARED IMPORTED) +set_property(TARGET libubsan_rt PROPERTY IMPORTED_LOCATION ${UBSAN_RT_LIBRARY}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args("Undefined Behavior Sanitizer Runtime Library" + REQUIRED_VARS UBSAN_RT_LIBRARY + FAIL_MESSAGE "Undefined Behavior Sanitizer Runtime Libraries not found! Consider installing for additional checks!" +) diff --git a/test/c++/CMakeLists.txt b/test/c++/CMakeLists.txt index d3eb0202..3d81aa69 100644 --- a/test/c++/CMakeLists.txt +++ b/test/c++/CMakeLists.txt @@ -8,4 +8,21 @@ foreach(t ${all_tests}) add_executable(${t} ${CMAKE_CURRENT_SOURCE_DIR}/${t}.cpp) target_link_libraries(${t} app4triqs_c gtest) add_test(${t} ${CMAKE_CURRENT_BINARY_DIR}/${t}) + # Run clang-tidy if found + #if(CLANG_TIDY_EXECUTABLE) + #set_target_properties(${t} PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXECUTABLE}") + #endif() + ## Run cppcheck if found + #if(CPPCHECK_EXECUTABLE) + #add_custom_command( + #TARGET ${t} + #COMMAND ${CPPCHECK_EXECUTABLE} + #--enable=warning,style,performance,portability + #--std=c++14 + #--template=gcc + #--verbose + #--quiet + #${CMAKE_CURRENT_SOURCE_DIR}/${t}.cpp + #) + #endif() endforeach() diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt index 6864a634..6d7e7c44 100644 --- a/test/python/CMakeLists.txt +++ b/test/python/CMakeLists.txt @@ -9,4 +9,8 @@ foreach(t ${all_tests}) endforeach() # Set the PythonPath : put the build dir first (in case there is an installed version). -set_property(TEST ${all_tests} PROPERTY ENVIRONMENT PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} ) +set_property(TEST ${all_tests} PROPERTY + ENVIRONMENT + PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} + LD_PRELOAD=$<$:${ASAN_RT_LIBRARY}>:$<$:${UBSAN_RT_LIBRARY}> +)