diff --git a/cmake/Modules/CMakePackagesSystem.cmake b/cmake/Modules/CMakePackagesSystem.cmake index 4f76dece0..238f7ca0b 100644 --- a/cmake/Modules/CMakePackagesSystem.cmake +++ b/cmake/Modules/CMakePackagesSystem.cmake @@ -1,1093 +1,1094 @@ #=============================================================================== # @file CMakePackagesSystem.cmake # # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @author Nicolas Richart <nicolas.richart@epfl.ch> # # @date creation: Wed Nov 05 2014 # @date last modification: Wed Jan 20 2016 # # @brief Set of macros used by akantu to handle the package system # # @section LICENSE # # Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory # (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see <http://www.gnu.org/licenses/>. # #=============================================================================== #[=======================================================================[.rst: #CMakePackagesSystem #------------------- # #This package defines multiple function to handle packages. This packages can #be of two kinds regular ones and extra_packages (ex: in akantu the LGPL part #is regular packages and extra packages are on Propetary license) # #Package are loaded with the help of the command: # #.. command:: package_list_packages # # package_list_packages(<regular_package_folder> # [ EXTRA_PACKAGE_FOLDER <extra_package_folder> ] # [ SOURCE_FOLDER <source_folder>] # [ TEST_FOLDER <test_folder> ] # [ MANUAL_FOLDER <manual_folder> ] # ) # # This command will look for packages name like ``<regular_package_folder>/<package>.cmake`` # OR ``<extra_package_folder>/<package>/package.cmake`` # #A package is a cmake script that should contain at list the declaration of a #package # #.. command:: package_declare # # package_declare(<package real name> # [EXTERNAL] [META] [ADVANCED] [NOT_OPTIONAL] # [DESCRIPTION <description>] [DEFAULT <default_value>] # [DEPENDS <pkg> ...] # [BOOST_COMPONENTS <pkg> ...] # [EXTRA_PACKAGE_OPTIONS <opt> ...] # [COMPILE_FLAGS <lang> <flags>] # [SYSTEM <ON|OFF|AUTO> [ <script_to_compile> ]] # [FEATURES_PUBLIC <feature> ...] # [FEATURES_PRIVATE <feature> ...] # [EXCLUDE_FROM_ALL] # ) # #.. command:: package_declare_sources # # It can also declare multiple informations: # source files: # # package_declare_sources(<package real name> # <src1> <src2> ... <srcn>) # #.. command:: package_declare_documentation # # a LaTeX documentation # package_declare_documentation(<package real name> # <line1> <line2> ...<linen>) # #.. command:: package_declare_documentation_files # # LaTeX documentation files # package_declare_documentation_files(<package real name> # <file1> <file2> ... <filen>) # #Different function can also be retrieved from the package system by using the #different accessors # #.. command:: package_get_name # package_get_name(<pkg> <retval>) # #.. command:: package_get_real_name # package_get_real_name(<pkg> <retval>) # #.. command:: package_get_option_name # package_get_option_name(<pkg> <retval>) # #.. command:: package_use_system # package_use_system(<pkg> <retval>) # #.. command:: package_get_nature # package_get_nature(<pkg> <retval>) # #.. command:: package_get_description # package_get_description(<pkg> <retval>) # #.. command:: package_get_filename # package_get_filename(<pkg> <retval>) # #.. command:: package_get_sources_folder # package_get_sources_folder(<pkg> <retval>) #.. command:: package_get_tests_folder # package_get_tests_folder(<pkg> <retval>) #.. command:: package_get_manual_folder # package_get_manual_folder(<pkg> <retval>) # #.. command:: package_get_find_package_extra_options # package_get_find_package_extra_options(<pkg> <retval>) # #.. command:: package_get_compile_flags # package_get_compile_flags(<pkg> <lang> <retval>) #.. command:: package_set_compile_flags # package_set_compile_flags(<pkg> <lang> <flag1> <flag2> ... <flagn>) # #.. command:: package_get_include_dir # package_get_include_dir(<pkg> <retval>) #.. command:: package_set_include_dir # package_set_include_dir(<pkg> <inc1> <inc2> ... <incn>) #.. command:: package_add_include_dir # package_add_include_dir(<pkg> <inc1> <inc2> ... <incn>) # #.. command:: package_get_libraries # package_get_libraries(<pkg> <retval>) #.. command:: package_set_libraries # package_set_libraries(<pkg> <lib1> <lib2> ... <libn>) # #.. command:: package_add_extra_dependency # package_add_extra_dependency(pkg <dep1> <dep2> ... <depn>) #.. command:: package_rm_extra_dependency # package_rm_extra_dependency(<pkg> <dep>) #.. command:: package_get_extra_dependencies # package_get_extra_dependencies(<pkg> <retval>) # #.. command:: package_is_activated # package_is_activated(<pkg> <retval>) #.. command:: package_is_deactivated # package_is_deactivated(<pkg> <retval>) # #.. command:: package_get_dependencies # package_get_dependencies(<pkg> <PRIVATE|INTERFACE> <retval>) #.. command:: package_add_dependencies # package_add_dependencies(<pkg> <PRIVATE|INTERFACE> <dep1> <dep2> ... <depn>) # package_remove_dependencies(<pkg> <dep1> <dep2> ... <depn>) # package_remove_dependency(<pkg> <dep>) # #.. command:: package_on_enabled_script # package_on_enabled_script(<pkg> <script>) # #.. command:: package_get_all_source_files # package_get_all_source_files(<srcs> <public_headers> <private_headers>) #.. command:: package_get_all_include_directories # package_get_all_include_directories(<inc_dirs>) #.. command:: package_get_all_external_informations # package_get_all_external_informations(<include_dir> <libraries>) #.. command:: package_get_all_definitions # package_get_all_definitions(<definitions>) #.. command:: package_get_all_extra_dependencies # package_get_all_extra_dependencies(<dependencies>) #.. command:: package_get_all_test_folders # package_get_all_test_folders(<test_dirs>) #.. command:: package_get_all_documentation_files # package_get_all_documentation_files(<doc_files>) #.. command:: package_get_all_activated_packages # package_get_all_activated_packages(<activated_list>) #.. command:: package_get_all_deactivated_packages # package_get_all_deactivated_packages(<deactivated_list>) #.. command:: package_get_all_packages # package_get_all_packages(<packages_list>) #.. command:: package_get_all_features_public # package_get_all_features_public(<features>) #.. command:: package_get_all_features_private # package_get_all_features_private(<features>) # # # .. command:: package_set_package_system_dependency # # package_set_package_system_dependency(<pkg> <system> <dep1> # <dep2> ... <depn>) # # .. command:: package_get_package_system_dependency # # package_get_package_system_dependency(<pkg> <var>) # # #]=======================================================================] include(CMakeParseArguments) #=============================================================================== # Package Management #=============================================================================== if(__CMAKE_PACKAGES_SYSTEM) return() endif() set(__CMAKE_PACKAGES_SYSTEM TRUE) if(CMAKE_VERSION VERSION_GREATER 3.1.2) cmake_policy(SET CMP0054 NEW) endif() #=============================================================================== option(AUTO_MOVE_UNKNOWN_FILES "Give to cmake the permission to move the unregistered files to the ${PROJECT_SOURCE_DIR}/tmp directory" FALSE) mark_as_advanced(AUTO_MOVE_UNKNOWN_FILES) include(CMakePackagesSystemGlobalFunctions) include(CMakePackagesSystemPrivateFunctions) # ============================================================================== # "Public" Accessors # ============================================================================== # ------------------------------------------------------------------------------ # Package name # ------------------------------------------------------------------------------ function(package_get_name pkg pkg_name) string(TOUPPER ${PROJECT_NAME} _project) string(REPLACE "-" "_" _str_pkg "${pkg}") string(TOUPPER ${_str_pkg} _u_package) set(${pkg_name} ${_project}_PKG_${_u_package} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Real name # ------------------------------------------------------------------------------ function(package_get_real_name pkg ret) package_get_name(${pkg} _pkg_name) _package_get_real_name(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Option name # ------------------------------------------------------------------------------ function(package_get_option_name pkg ret) package_get_name(${pkg} _pkg_name) _package_get_option_name(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Set if system package or compile external lib # ------------------------------------------------------------------------------ function(package_use_system pkg ret) package_get_name(${pkg} _pkg_name) _package_use_system(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() function(package_add_third_party_script_variable pkg var) package_get_name(${pkg} _pkg_name) _package_add_third_party_script_variable(${_pkg_name} ${var} ${ARGN}) set(${var} ${ARGN} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Set if system package or compile external lib # ------------------------------------------------------------------------------ function(package_add_to_export_list pkg) package_get_name(${pkg} _pkg_name) _package_add_to_export_list(${_pkg_name} ${ARGN}) endfunction() # ------------------------------------------------------------------------------ # Nature # ------------------------------------------------------------------------------ function(package_get_nature pkg ret) package_get_name(${pkg} _pkg_name) _package_get_nature(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Description # ------------------------------------------------------------------------------ function(package_get_description pkg ret) package_get_name(${pkg} _pkg_name) _package_get_description(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Package file name # ------------------------------------------------------------------------------ function(package_get_filename pkg ret) package_get_name(${pkg} _pkg_name) _package_get_filename(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Source files # ------------------------------------------------------------------------------ function(package_get_source_files pkg ret_srcs ret_pub ret_priv) package_get_name(${pkg} _pkg_name) _package_get_source_files(${_pkg_name} _tmp_srcs _tmp_pub _tmp_priv) set(${ret_srcs} ${_tmp_srcs} PARENT_SCOPE) set(${ret_pub} ${_tmp_pub} PARENT_SCOPE) set(${ret_priv} ${_tmp_pric} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Source folder # ------------------------------------------------------------------------------ function(package_get_sources_folder pkg ret) package_get_name(${pkg} _pkg_name) _package_get_sources_folder(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Test folder # ------------------------------------------------------------------------------ function(package_get_tests_folder pkg ret) package_get_name(${pkg} _pkg_name) _package_get_tests_folder(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Manual folder # ------------------------------------------------------------------------------ function(package_get_manual_folder pkg ret) package_get_name(${pkg} _pkg_name) _package_get_manual_folder(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Extra option for the find_package # ------------------------------------------------------------------------------ function(package_get_find_package_extra_options pkg ret) package_get_name(${pkg} _pkg_name) _package_get_find_package_extra_options(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() function(package_set_find_package_extra_options pkg) package_get_name(${pkg} _pkg_name) _package_set_find_package_extra_options(${_pkg_name} ${ARGN}) endfunction() # ------------------------------------------------------------------------------ # Compilation flags # ------------------------------------------------------------------------------ function(package_get_compile_flags pkg lang ret) package_get_name(${pkg} _pkg_name) _package_get_compile_flags(${_pkg_name} ${lang} _tmp) set(${ret} "${_tmp}" PARENT_SCOPE) endfunction() function(package_set_compile_flags pkg lang) package_get_name(${pkg} _pkg_name) _package_set_compile_flags(${_pkg_name} ${lang} ${ARGN}) endfunction() function(package_unset_compile_flags pkg lang) package_get_name(${pkg} _pkg_name) _package_unset_compile_flags(${_pkg_name} ${lang}) endfunction() # ------------------------------------------------------------------------------ # Include dir # ------------------------------------------------------------------------------ function(package_get_include_dir pkg ret) package_get_name(${pkg} _pkg_name) _package_get_include_dir(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() function(package_set_include_dir pkg) package_get_name(${pkg} _pkg_name) _package_set_include_dir(${_pkg_name} ${ARGN}) endfunction() function(package_add_include_dir pkg) package_get_name(${pkg} _pkg_name) _package_add_include_dir(${_pkg_name} ${ARGN}) endfunction() # ------------------------------------------------------------------------------ # Libraries # ------------------------------------------------------------------------------ function(package_get_libraries pkg ret) package_get_name(${pkg} _pkg_name) _package_get_libraries(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() function(package_set_libraries pkg) package_get_name(${pkg} _pkg_name) _package_set_libraries(${_pkg_name} ${ARGN}) endfunction() # ------------------------------------------------------------------------------ # Extra dependencies like custom commands of ExternalProject # ------------------------------------------------------------------------------ function(package_add_extra_dependency pkg) package_get_name(${pkg} _pkg_name) _package_add_extra_dependency(${_pkg_name} ${ARGN}) endfunction() function(package_rm_extra_dependency pkg dep) package_get_name(${pkg} _pkg_name) _package_rm_extra_dependency(${_pkg_name} ${dep}) endfunction() function(package_get_extra_dependencies pkg ret) package_get_name(${pkg} _pkg_name) _package_get_extra_dependencies(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Activate/deactivate # ------------------------------------------------------------------------------ function(package_is_activated pkg ret) package_get_name(${pkg} _pkg_name) _package_is_activated(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() function(package_is_deactivated pkg ret) package_get_name(${pkg} _pkg_name) _package_is_deactivated(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Direct dependencies # ------------------------------------------------------------------------------ function(package_get_dependencies pkg type ret) package_get_name(${pkg} _pkg_name) _package_get_dependencies(${_pkg_name} ${type} _tmp_name) _package_get_real_name(${_tmp_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() function(package_add_dependencies pkg type) package_get_name(${pkg} _pkg_name) foreach(_dep ${ARGN}) package_get_name(${_dep} _dep_pkg_name) list(APPEND _tmp_deps ${_dep_pkg_name}) endforeach() _package_add_dependencies(${_pkg_name} ${type} ${_tmp_deps}) endfunction() function(package_remove_dependencies pkg type) foreach(_dep ${ARGN}) package_remove_dependency(${pkg} _dep) endforeach() endfunction() function(package_remove_dependency pkg dep) package_get_name(${pkg} _pkg_name) package_get_name(${dep} _dep_pkg_name) _package_remove_dependency(${_pkg_name} PRIVATE ${_dep_pkg_name}) _package_remove_dependency(${_pkg_name} INTERFACE ${_dep_pkg_name}) endfunction() # ------------------------------------------------------------------------------ # Documentation related functions # ------------------------------------------------------------------------------ function(package_declare_documentation pkg) package_get_name(${pkg} _pkg_name) _package_set_documentation(${_pkg_name} ${ARGN}) endfunction() function(package_declare_documentation_files pkg) package_get_name(${pkg} _pkg_name) _package_set_documentation_files(${_pkg_name} ${ARGN}) endfunction() # ------------------------------------------------------------------------------ # Set any user variables needed # ------------------------------------------------------------------------------ function(package_set_variable variable pkg) package_get_name(${pkg} _pkg_name) _package_set_variable(${variable} ${_pkg_name} ${ARGN}) endfunction() function(package_add_to_variable variable pkg) package_get_name(${pkg} _pkg_name) _package_add_to_variable(${variable} ${_pkg_name} ${ARGN}) endfunction() function(package_get_variable variable pkg value) package_get_name(${pkg} _pkg_name) _package_get_variable(${variable} ${_pkg_name} _value_tmp) if(_value_tmp) set(${value} ${_value_tmp} PARENT_SCOPE) else() unset(${value} PARENT_SCOPE) endif() endfunction() # ------------------------------------------------------------------------------ # Exteral package system as apt rpm dependencies # ------------------------------------------------------------------------------ function(package_set_package_system_dependency pkg system) package_get_name(${pkg} _pkg_name) _package_set_package_system_dependency(${_pkg_name} ${system} ${ARGN}) endfunction() function(package_get_package_system_dependency pkg system var) package_get_name(${pkg} _pkg_name) _package_set_package_system_dependency(${_pkg_name} ${sytem} _tmp) set(${var} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # ============================================================================== # Global accessors # ============================================================================== # ------------------------------------------------------------------------------ # get the list of source files # ------------------------------------------------------------------------------ function(package_get_all_source_files SRCS PUBLIC_HEADERS PRIVATE_HEADERS) string(TOUPPER ${PROJECT_NAME} _project) unset(_tmp_srcs) unset(_tmp_public_headers) unset(_tmp_private_headers) package_get_all_activated_packages(_activated_list) foreach(_pkg_name ${_activated_list}) _package_get_source_files(${_pkg_name} _pkg_srcs _pkg_public_headers _pkg_private_headers ) list(APPEND _tmp_srcs ${_pkg_srcs}) list(APPEND _tmp_public_headers ${_pkg_public_headers}) list(APPEND _tmp_private_headers ${_pkg_private_headers}) endforeach() set(${SRCS} ${_tmp_srcs} PARENT_SCOPE) set(${PUBLIC_HEADERS} ${_tmp_public_headers} PARENT_SCOPE) set(${PRIVATE_HEADERS} ${_tmp_private_headers} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get include directories # ------------------------------------------------------------------------------ function(package_get_all_include_directories inc_dirs) set(_tmp) package_get_all_activated_packages(_activated_list) foreach(_pkg_name ${_activated_list}) foreach(_type SRCS PUBLIC_HEADERS PRIVATE_HEADERS) foreach(_file ${${_pkg_name}_${_type}}) get_filename_component(_path "${_file}" PATH) list(APPEND _tmp "${_path}") endforeach() endforeach() endforeach() if(_tmp) list(REMOVE_DUPLICATES _tmp) endif() set(${inc_dirs} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get external libraries informations # ------------------------------------------------------------------------------ function(package_get_all_external_informations) cmake_parse_arguments(_opt "" "PRIVATE_INCLUDE;INTERFACE_INCLUDE;LIBRARIES" "" ${ARGN}) foreach(_type PRIVATE INTERFACE) if(_opt_${_type}_INCLUDE) _package_get_variable_for_external_dependencies(INCLUDE_DIR ${_type} tmp_INCLUDE_DIR) foreach(_dir ${tmp_INCLUDE_DIR}) string(FIND "${_dir}" "${CMAKE_CURRENT_SOURCE_DIR}" _pos) if(NOT _pos EQUAL -1) list(REMOVE_ITEM tmp_INCLUDE_DIR ${_dir}) endif() endforeach() set(${_opt_${_type}_INCLUDE} ${tmp_INCLUDE_DIR} PARENT_SCOPE) endif() endforeach() if(_opt_LIBRARIES) _package_get_variable_for_external_dependencies(LIBRARIES PRIVATE tmp_LIBRARIES) _package_get_variable_for_external_dependencies(LIBRARIES INTERFACE tmp_LIBRARIES_INTERFACE) set(${_opt_LIBRARIES} ${tmp_LIBRARIES} ${tmp_LIBRARIES_INTERFACE} PARENT_SCOPE) endif() endfunction() # ------------------------------------------------------------------------------ # Get export list for all activated packages # ------------------------------------------------------------------------------ function(package_get_all_export_list export_list) _package_get_variable_for_activated(EXPORT_LIST _tmp) set(${export_list} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get definitions like external projects # ------------------------------------------------------------------------------ function(package_get_all_definitions definitions) _package_get_variable_for_activated(OPTION_NAME _tmp) set(${definitions} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get extra dependencies like external projects # ------------------------------------------------------------------------------ function(package_get_all_extra_dependencies deps) _package_get_variable_for_activated(EXTRA_DEPENDENCY _tmp) set(${deps} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get extra infos # ------------------------------------------------------------------------------ function(package_get_all_test_folders TEST_DIRS) _package_get_variable_for_activated(TEST_FOLDER _tmp) set(${TEST_DIRS} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get compilation flags # ------------------------------------------------------------------------------ function(package_get_all_compilation_flags LANG FLAGS) _package_get_variable_for_activated(COMPILE_${LANG}_FLAGS _tmp_flags) string(REPLACE ";" " " _flags "${_tmp_flags}") set(${FLAGS} ${_flags} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Documentation informations # ------------------------------------------------------------------------------ function(package_get_all_documentation_files doc_files) set(_tmp_DOC_FILES) package_get_all_activated_packages(_activated_list) foreach(_pkg_name ${_activated_list}) _package_get_manual_folder(${_pkg_name} _doc_dir) _package_get_documentation_files(${_pkg_name} _doc_files) foreach(_doc_file ${_doc_files}) list(APPEND _tmp_DOC_FILES ${_doc_dir}/${_doc_file}) endforeach() endforeach() if(_tmp_DOC_FILES) list(REMOVE_DUPLICATES _tmp_DOC_FILES) endif() set(${doc_files} ${_tmp_DOC_FILES} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get package systems dependencies # ------------------------------------------------------------------------------ function(package_get_all_package_system_dependency system deps) string(TOUPPER ${system} _u_system) _package_get_variable_for_activated(PACKAGE_SYSTEM_${_u_system} _tmp) set(${deps} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # List packages # ------------------------------------------------------------------------------ function(package_get_all_activated_packages activated_list) package_get_project_variable(ACTIVATED_PACKAGE_LIST _activated_list) set(${activated_list} ${_activated_list} PARENT_SCOPE) endfunction() function(package_get_all_deactivated_packages deactivated_list) package_get_project_variable(DEACTIVATED_PACKAGE_LIST _deactivated_list) set(${deactivated_list} ${_deactivated_list} PARENT_SCOPE) endfunction() function(package_get_all_packages packages_list) package_get_project_variable(ALL_PACKAGES_LIST _packages_list) set(${packages_list} ${_packages_list} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # List all the needed features # ------------------------------------------------------------------------------ function(package_get_all_features_public features) _package_get_variable_for_activated(FEATURES_PUBLIC _tmp) set(${features} ${_tmp} PARENT_SCOPE) endfunction() function(package_get_all_features_private features) _package_get_variable_for_activated(FEATURES_PRIVATE _tmp) set(${features} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Callbacks # ------------------------------------------------------------------------------ function(package_on_enabled_script pkg script) package_get_name(${pkg} _pkg_name) _package_on_enable_script(${_pkg_name} "${script}") endfunction() # ------------------------------------------------------------------------------ # list all the packages in the PACKAGE_FOLDER # extra packages can be given with an EXTRA_PACKAGE_FOLDER # <package_folder>/<package>.cmake # # Extra packages folder structure # <extra_package_folder>/<package>/package.cmake # /src # /test # /manual # # ------------------------------------------------------------------------------ function(package_list_packages PACKAGE_FOLDER) cmake_parse_arguments(_opt_pkg "NO_AUTO_COMPILE_FLAGS" "SOURCE_FOLDER;EXTRA_PACKAGES_FOLDER;TEST_FOLDER;MANUAL_FOLDER" "" ${ARGN}) string(TOUPPER ${PROJECT_NAME} _project) # Cleaning some states to start correctly package_get_all_packages(_already_loaded_pkg) foreach(_pkg_name ${_already_loaded_pkg}) _package_unset_extra_dependencies(${_pkg_name}) _package_unset_dependencies(${_pkg_name} PRIVATE) _package_unset_dependencies(${_pkg_name} INTERFACE) _package_unset_activated(${_pkg_name}) endforeach() if(_opt_pkg_SOURCE_FOLDER) set(_src_folder "${_opt_pkg_SOURCE_FOLDER}") else() set(_src_folder "src/") endif() get_filename_component(_abs_src_folder ${_src_folder} ABSOLUTE) if(_opt_pkg_TEST_FOLDER) set(_test_folder "${_opt_pkg_TEST_FOLDER}") else() set(_test_folder "test/") endif() if(_opt_pkg_MANUAL_FOLDER) set(_manual_folder "${_opt_pkg_MANUAL_FOLDER}") else() set(_manual_folder "doc/manual") endif() if(_opt_pkg_NO_AUTO_COMPILE_FLAGS) package_set_project_variable(NO_AUTO_COMPILE_FLAGS TRUE) else() package_set_project_variable(NO_AUTO_COMPILE_FLAGS FALSE) endif() get_filename_component(_abs_test_folder ${_test_folder} ABSOLUTE) get_filename_component(_abs_manual_folder ${_manual_folder} ABSOLUTE) # check all the packages in the <package_folder> file(GLOB _package_list "${PACKAGE_FOLDER}/*.cmake") set(_package_files) foreach(_pkg ${_package_list}) get_filename_component(_basename ${_pkg} NAME) if(NOT _basename MATCHES "^\\.#.*") list(APPEND _package_files ${_basename}) endif() endforeach() if(_package_files) list(SORT _package_files) endif() # check all packages set(_packages_list_all) foreach(_pkg_file ${_package_files}) string(REGEX REPLACE "[0-9]+_" "" _pkg_file_stripped ${_pkg_file}) string(REGEX REPLACE "\\.cmake" "" _pkg ${_pkg_file_stripped}) set(_current_src_folder "${_abs_src_folder}" CACHE INTERNAL "" FORCE) set(_current_test_folder "${_abs_test_folder}" CACHE INTERNAL "" FORCE) set(_current_manual_folder "${_abs_manual_folder}" CACHE INTERNAL "" FORCE) include("${PACKAGE_FOLDER}/${_pkg_file}") unset(_current_src_folder CACHE) unset(_current_test_folder CACHE) unset(_current_manual_folder CACHE) endforeach() # check the extra_packages if they exists if(_opt_pkg_EXTRA_PACKAGES_FOLDER) file(GLOB _extra_package_list RELATIVE "${_opt_pkg_EXTRA_PACKAGES_FOLDER}" "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/*") foreach(_pkg ${_extra_package_list}) if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake") package_get_name(${_pkg} _pkg_name) _package_set_filename(${_pkg_name} "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake") set(_current_src_folder "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/src" CACHE INTERNAL "" FORCE) if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/test") set(_current_test_folder "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/test" CACHE INTERNAL "" FORCE) endif() if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/manual") set(_current_manual_folder "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/manual" CACHE INTERNAL "" FORCE) endif() list(APPEND _extra_pkg_src_folders "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/src") include("${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake") unset(_current_src_folder CACHE) unset(_current_test_folder CACHE) unset(_current_manual_folder CACHE) endif() endforeach() endif() _package_build_rdependencies() _package_load_packages() _package_check_files_exists() _package_check_files_registered(${_abs_src_folder} ${_extra_pkg_src_folders}) # Load boost components if boost was loaded package_is_activated(Boost _ret) if(_ret) _package_load_boost_components() endif() endfunction() # ------------------------------------------------------------------------------ # macro to include internal/external packages packages # package_declare(<package real name> # [EXTERNAL] [META] [ADVANCED] [NOT_OPTIONAL] # [DESCRIPTION <description>] [DEFAULT <default_value>] # [DEPENDS <pkg> ...] # [BOOST_COMPONENTS <pkg> ...] # [EXTRA_PACKAGE_OPTIONS <opt> ...] # [COMPILE_FLAGS <lang> <flags>] # [SYSTEM <bool> [ <script_to_compile> ]] # [FEATURES_PUBLIC <feature> ...] # [FEATURES_PRIVATE <feature> ...]) # ------------------------------------------------------------------------------ function(package_declare pkg) package_get_name(${pkg} _pkg_name) _package_set_real_name(${_pkg_name} ${pkg}) _package_set_filename(${_pkg_name} "${CMAKE_CURRENT_LIST_FILE}") _package_set_sources_folder(${_pkg_name} "${_current_src_folder}") _package_variable_unset(SRCS ${_pkg_name}) _package_variable_unset(PUBLIC_HEADERS ${_pkg_name}) _package_variable_unset(PRIVATE_HEADERS ${_pkg_name}) if(_current_test_folder) _package_set_tests_folder(${_pkg_name} "${_current_test_folder}") endif() if(_current_manual_folder) _package_set_manual_folder(${_pkg_name} "${_current_manual_folder}") endif() package_get_project_variable(ALL_PACKAGES_LIST _tmp_pkg_list) list(APPEND _tmp_pkg_list ${_pkg_name}) list(REMOVE_DUPLICATES _tmp_pkg_list) package_set_project_variable(ALL_PACKAGES_LIST ${_tmp_pkg_list}) set(_options EXTERNAL NOT_OPTIONAL META ADVANCED EXCLUDE_FROM_ALL) set(_one_valued_options DEFAULT DESCRIPTION) set(_multi_valued_options DEPENDS EXTRA_PACKAGE_OPTIONS COMPILE_FLAGS BOOST_COMPONENTS SYSTEM FEATURES_PUBLIC FEATURES_PRIVATE) cmake_parse_arguments(_opt_pkg "${_options}" "${_one_valued_options}" "${_multi_valued_options}" ${ARGN}) if(_opt_pkg_UNPARSED_ARGUMENTS) message("You gave to many arguments while registering the package ${pkg} \"${_opt_pkg_UNPARSED_ARGUMENTS}\"") endif() # set the nature if(_opt_pkg_EXTERNAL) _package_set_nature(${_pkg_name} "external") elseif(_opt_pkg_META) _package_set_nature(${_pkg_name} "meta") else() _package_set_nature(${_pkg_name} "internal") endif() _package_declare_option(${_pkg_name}) # set description if(_opt_pkg_DESCRIPTION) _package_set_description(${_pkg_name} ${_opt_pkg_DESCRIPTION}) else() _package_set_description(${_pkg_name} "") endif() _package_get_option_name(${_pkg_name} _option_name) _package_get_description(${_pkg_name} _description) # get the default value if(DEFINED _opt_pkg_DEFAULT) set(_default ${_opt_pkg_DEFAULT}) else() if(_opt_pkg_NOT_OPTIONAL) set(_default ON) else() set(_default OFF) endif() endif() # set the option if needed if(_opt_pkg_NOT_OPTIONAL) _package_get_nature(${_pkg_name} _nature) _package_set_nature(${_pkg_name} "${_nature}_not_optional") set(${_option_name} ${_default} CACHE INTERNAL "${_description}" FORCE) mark_as_advanced(${_option_name}) else() option(${_option_name} "${_description}" ${_default}) if(_opt_pkg_ADVANCED OR _opt_pkg_EXTERNAL) mark_as_advanced(${_option_name}) endif() endif() # Set the option for third-partie that can be compiled as an ExternalProject if(DEFINED _opt_pkg_SYSTEM) list(LENGTH _opt_pkg_SYSTEM _length) list(GET _opt_pkg_SYSTEM 0 _bool) _package_set_system_option(${_pkg_name} ${_bool}) if(_length GREATER 1) list(GET _opt_pkg_SYSTEM 1 _script) _package_set_system_script(${_pkg_name} ${_script}) endif() endif() # set the dependecies if(_opt_pkg_DEPENDS) set(_deps_types PRIVATE INTERFACE) cmake_parse_arguments(_pkg_deps "" "" "${_deps_types}" ${_opt_pkg_DEPENDS}) list(APPEND _pkg_deps_PRIVATE ${_pkg_deps_UNPARSED_ARGUMENTS}) foreach(_type ${_deps_types}) set(_depends) foreach(_dep ${_pkg_deps_${_type}}) package_get_name(${_dep} _dep_pkg_name) list(APPEND _depends ${_dep_pkg_name}) endforeach() _package_add_dependencies(${_pkg_name} ${_type} ${_depends}) endforeach() endif() # keep the extra option for the future find package if(_opt_pkg_EXTRA_PACKAGE_OPTIONS) _package_set_find_package_extra_options(${_pkg_name} "${_opt_pkg_EXTRA_PACKAGE_OPTIONS}") endif() # register the compilation flags if(_opt_pkg_COMPILE_FLAGS) set(_languages C CXX Fortran) cmake_parse_arguments(_compile_flags "" "" "${_languages}" ${_opt_pkg_COMPILE_FLAGS} ) # this is done to maintain backward compatibility if(_compile_flags_UNPARSED_ARGUMENTS) set(_compile_flags_CXX ${_compile_flags_UNPARSED_ARGUMENTS}) endif() foreach(_lang ${_languages}) if(_compile_flags_${_lang}) _package_set_compile_flags(${_pkg_name} ${_lang} ${_compile_flags_${_lang}}) else() _package_unset_compile_flags(${_pkg_name} ${_lang}) endif() endforeach() endif() # set the boost dependencies if(_opt_pkg_BOOST_COMPONENTS) _package_set_boost_component_needed(${_pkg_name} "${_opt_pkg_BOOST_COMPONENTS}") endif() set(_variables FEATURES_PUBLIC FEATURES_PRIVATE EXCLUDE_FROM_ALL) foreach(_variable ${_variables}) if(_opt_pkg_${_variable}) _package_set_variable(${_variable} ${_pkg_name} "${_opt_pkg_${_variable}}") endif() endforeach() endfunction() # ------------------------------------------------------------------------------ # declare the source files of a given package # # package_declare_sources(<package> <list of sources> # SOURCES <source file> ... # PUBLIC_HEADER <header file> ... # PRIVATE_HEADER <header file> ...) # ------------------------------------------------------------------------------ function(package_declare_sources pkg) package_get_name(${pkg} _pkg_name) # get 3 lists, if none of the options given try to distinguish the different lists cmake_parse_arguments(_opt_pkg "" "" "SOURCES;PUBLIC_HEADERS;PRIVATE_HEADERS" ${ARGN}) set(_tmp_srcs ${_opt_pkg_SOURCES}) set(_tmp_pub_hdrs ${_opt_pkg_PUBLIC_HEADER}) set(_tmp_pri_hdrs ${_opt_pkg_PRIVATE_HEADERS}) foreach(_file ${_opt_pkg_UNPARSED_ARGUMENTS}) if(${_file} MATCHES ".*inline.*\\.cc") list(APPEND _tmp_pub_hdrs ${_file}) elseif(${_file} MATCHES ".*\\.h+") list(APPEND _tmp_pub_hdrs ${_file}) else() list(APPEND _tmp_srcs ${_file}) endif() endforeach() _package_get_sources_folder(${_pkg_name} _src_folder) foreach(_type _srcs _pub_hdrs _pri_hdrs) set(${_type}) foreach(_file ${_tmp${_type}}) # get the full name - list(APPEND ${_type} "${_src_folder}/${_file}") + set(_full_path "${_src_folder}/${_file}") + list(APPEND ${_type} "${_full_path}") endforeach() endforeach() set(${_pkg_name}_SRCS "${_srcs}" CACHE INTERNAL "List of sources files" FORCE) set(${_pkg_name}_PUBLIC_HEADERS "${_pub_hdrs}" CACHE INTERNAL "List of public header files" FORCE) set(${_pkg_name}_PRIVATE_HEADERS "${_pri_hdrs}" CACHE INTERNAL "List of private header files" FORCE) endfunction() # ------------------------------------------------------------------------------ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fbe0b1ed8..80c9e4b78 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,223 +1,231 @@ #=============================================================================== # @file CMakeLists.txt # # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @author Nicolas Richart <nicolas.richart@epfl.ch> # # @date creation: Mon Jun 14 2010 # @date last modification: Tue Feb 13 2018 # # @brief CMake file for the library # # @section LICENSE # # Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License along with Akantu. If not, see <http://www.gnu.org/licenses/>. # #=============================================================================== #=============================================================================== # Package Management #=============================================================================== package_get_all_source_files( AKANTU_LIBRARY_SRCS AKANTU_LIBRARY_PUBLIC_HDRS AKANTU_LIBRARY_PRIVATE_HDRS ) package_get_all_include_directories( AKANTU_LIBRARY_INCLUDE_DIRS ) package_get_all_external_informations( PRIVATE_INCLUDE AKANTU_PRIVATE_EXTERNAL_INCLUDE_DIR INTERFACE_INCLUDE AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR LIBRARIES AKANTU_EXTERNAL_LIBRARIES ) package_get_all_compilation_flags(CXX _cxx_flags) set(AKANTU_EXTRA_CXX_FLAGS "${_cxx_flags}" CACHE STRING "Extra flags defined by loaded packages" FORCE) mark_as_advanced(AKANTU_EXTRA_CXX_FLAGS) foreach(src_ ${AKANTU_SPIRIT_SOURCES}) set_property(SOURCE ${src_} PROPERTY COMPILE_FLAGS "-g0 -Werror") endforeach() #=========================================================================== # header for blas/lapack (any other fortran libraries) #=========================================================================== package_is_activated(BLAS _blas_activated) package_is_activated(LAPACK _lapack_activated) if(_blas_activated OR _lapack_activated) if(CMAKE_Fortran_COMPILER) # ugly hack set(CMAKE_Fortran_COMPILER_LOADED TRUE) endif() include(FortranCInterface) FortranCInterface_HEADER( "${CMAKE_CURRENT_BINARY_DIR}/aka_fortran_mangling.hh" MACRO_NAMESPACE "AKA_FC_") mark_as_advanced(CDEFS) list(APPEND AKANTU_LIBRARY_PUBLIC_HDRS "${CMAKE_CURRENT_BINARY_DIR}/aka_fortran_mangling.hh" ) endif() list(APPEND AKANTU_LIBRARY_INCLUDE_DIRS "${CMAKE_CURRENT_BINARY_DIR}") set(AKANTU_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} ${AKANTU_LIBRARY_INCLUDE_DIRS} CACHE INTERNAL "Internal include directories to link with Akantu as a subproject") #=========================================================================== # configurations #=========================================================================== package_get_all_material_includes(AKANTU_MATERIAL_INCLUDES) package_get_all_material_lists(AKANTU_MATERIAL_LISTS) configure_file(model/solid_mechanics/material_list.hh.in "${CMAKE_CURRENT_BINARY_DIR}/material_list.hh" @ONLY) package_get_element_lists() configure_file(common/aka_element_classes_info.hh.in "${CMAKE_CURRENT_BINARY_DIR}/aka_element_classes_info.hh" @ONLY) configure_file(common/aka_config.hh.in "${CMAKE_CURRENT_BINARY_DIR}/aka_config.hh" @ONLY) list(APPEND AKANTU_LIBRARY_PUBLIC_HDRS "${CMAKE_CURRENT_BINARY_DIR}/material_list.hh" "${CMAKE_CURRENT_BINARY_DIR}/aka_element_classes_info.hh" "${CMAKE_CURRENT_BINARY_DIR}/aka_config.hh") #=============================================================================== # Debug infos #=============================================================================== set(AKANTU_GDB_DIR ${PROJECT_SOURCE_DIR}/cmake) if(UNIX) string(TOUPPER "${CMAKE_BUILD_TYPE}" _u_build_type) if(_u_build_type STREQUAL "DEBUG" OR _u_build_type STREQUAL "RELWITHDEBINFO") configure_file(${PROJECT_SOURCE_DIR}/cmake/libakantu-gdb.py.in "${PROJECT_BINARY_DIR}/libakantu-gdb.py" @ONLY) configure_file(${PROJECT_SOURCE_DIR}/cmake/akantu-debug.cc.in "${PROJECT_BINARY_DIR}/akantu-debug.cc" @ONLY) list(APPEND AKANTU_LIBRARY_SRCS ${PROJECT_BINARY_DIR}/akantu-debug.cc) endif() else() find_program(GDB_EXECUTABLE gdb) if(GDB_EXECUTABLE) execute_process(COMMAND ${GDB_EXECUTABLE} --batch -x "${PROJECT_SOURCE_DIR}/cmake/gdb_python_path" OUTPUT_VARIABLE AKANTU_PYTHON_GDB_DIR ERROR_QUIET RESULT_VARIABLE _res) if(_res EQUAL 0 AND UNIX) set(GDB_USER_CONFIG $ENV{HOME}/.gdb/auto-load) file(MAKE_DIRECTORY ${GDB_USER_CONFIG}) configure_file(${PROJECT_SOURCE_DIR}/cmake/libakantu-gdb.py.in "${GDB_USER_CONFIG}/${CMAKE_SHARED_LIBRARY_PREFIX}akantu${CMAKE_SHARED_LIBRARY_SUFFIX}.${AKANTU_VERSION}-gdb.py" @ONLY) endif() endif() endif() #=============================================================================== # Library generation #=============================================================================== add_library(akantu ${AKANTU_LIBRARY_SRCS}) target_include_directories(akantu PRIVATE $<BUILD_INTERFACE:${AKANTU_INCLUDE_DIRS}> INTERFACE $<INSTALL_INTERFACE:include/akantu> ) # small trick for build includes in public set_property(TARGET akantu APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES $<BUILD_INTERFACE:${AKANTU_INCLUDE_DIRS}>) target_include_directories(akantu SYSTEM PUBLIC ${AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR} ) target_include_directories(akantu SYSTEM PRIVATE ${AKANTU_PRIVATE_EXTERNAL_INCLUDE_DIR} ) target_link_libraries(akantu ${AKANTU_EXTERNAL_LIBRARIES}) set_target_properties(akantu PROPERTIES ${AKANTU_LIBRARY_PROPERTIES} # this contains the version COMPILE_FLAGS "${_cxx_flags}" #PRIVATE_HEADER ${AKANTU_LIBRARY_PRIVATE_HDRS} ) if(AKANTU_LIBRARY_PUBLIC_HDRS) set_property(TARGET akantu PROPERTY PUBLIC_HEADER ${AKANTU_LIBRARY_PUBLIC_HDRS}) endif() if(AKANTU_LIBRARY_PRIVATE_HDRS) set_property(TARGET akantu PROPERTY PRIVATE_HEADER ${AKANTU_LIBRARY_PRIVATE_HDRS}) endif() if(NOT CMAKE_VERSION VERSION_LESS 3.1) package_get_all_features_public(_PUBLIC_features) package_get_all_features_private(_PRIVATE_features) foreach(_type PRIVATE PUBLIC) if(_${_type}_features) target_compile_features(akantu ${_type} ${_${_type}_features}) endif() endforeach() else() set_target_properties(akantu PROPERTIES CXX_STANDARD 14 ) endif() package_get_all_extra_dependencies(_extra_target_dependencies) if(_extra_target_dependencies) # This only adding todo: find a solution for when a dependency was add the is removed... add_dependencies(akantu ${_extra_target_dependencies}) endif() package_get_all_export_list(AKANTU_EXPORT_LIST) list(APPEND AKANTU_EXPORT_LIST akantu) # TODO separate public from private headers install(TARGETS akantu EXPORT ${AKANTU_TARGETS_EXPORT} LIBRARY DESTINATION lib COMPONENT lib ARCHIVE DESTINATION lib COMPONENT lib RUNTIME DESTINATION bin COMPONENT bin PUBLIC_HEADER DESTINATION include/akantu/ COMPONENT dev ) if("${AKANTU_TARGETS_EXPORT}" STREQUAL "AkantuTargets") install(EXPORT AkantuTargets DESTINATION share/cmake/${PROJECT_NAME} COMPONENT dev) #Export for build tree export(EXPORT AkantuTargets FILE "${CMAKE_BINARY_DIR}/AkantuTargets.cmake") export(PACKAGE Akantu) endif() - - +#=============================================================================== +# Adding module names for debug +package_get_all_packages(_pkg_list) +foreach(_pkg ${_pkg_list}) + _package_get_real_name(${_pkg} _pkg_name) + _package_get_source_files(${_pkg} _srcs _public_hdrs _private_hdrs) + string(TOLOWER "${_pkg_name}" _l_package_name) + set_property(SOURCE ${_srcs} ${_public_hdrs} ${_private_hdrs} + APPEND PROPERTY COMPILE_DEFINITIONS AKANTU_MODULE=${_l_package_name}) +endforeach() # print out the list of materials generate_material_list() register_target_to_tidy(akantu) diff --git a/src/common/aka_error.hh b/src/common/aka_error.hh index cf737bbc8..bf0c3fe78 100644 --- a/src/common/aka_error.hh +++ b/src/common/aka_error.hh @@ -1,339 +1,358 @@ /** * @file aka_error.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Jun 14 2010 * @date last modification: Tue Feb 20 2018 * * @brief error management and internal exceptions * * @section LICENSE * * Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <sstream> #include <typeinfo> #include <utility> +#include <set> /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ERROR_HH__ #define __AKANTU_ERROR_HH__ namespace akantu { /* -------------------------------------------------------------------------- */ enum DebugLevel { dbl0 = 0, dblError = 0, dblAssert = 0, dbl1 = 1, dblException = 1, dblCritical = 1, dbl2 = 2, dblMajor = 2, dbl3 = 3, dblCall = 3, dblSecondary = 3, dblHead = 3, dbl4 = 4, dblWarning = 4, dbl5 = 5, dblInfo = 5, dbl6 = 6, dblIn = 6, dblOut = 6, dbl7 = 7, dbl8 = 8, dblTrace = 8, dbl9 = 9, dblAccessory = 9, dbl10 = 10, dblDebug = 42, dbl100 = 100, dblDump = 100, dblTest = 1337 }; /* -------------------------------------------------------------------------- */ #define AKANTU_LOCATION \ "(" << __func__ << "(): " << __FILE__ << ":" << __LINE__ << ")" /* -------------------------------------------------------------------------- */ namespace debug { void setDebugLevel(const DebugLevel & level); const DebugLevel & getDebugLevel(); void initSignalHandler(); std::string demangle(const char * symbol); #ifndef SWIG std::string exec(const std::string & cmd); #endif void printBacktrace(int sig); void exit(int status) __attribute__((noreturn)); /* ------------------------------------------------------------------------ */ /// exception class that can be thrown by akantu class Exception : public std::exception { /* ---------------------------------------------------------------------- */ /* Constructors/Destructors */ /* ---------------------------------------------------------------------- */ protected: explicit Exception(std::string info = "") : _info(std::move(info)), _file("") {} public: //! full constructor Exception(std::string info, std::string file, unsigned int line) : _info(std::move(info)), _file(std::move(file)), _line(line) {} //! destructor ~Exception() noexcept override = default; /* ---------------------------------------------------------------------- */ /* Methods */ /* ---------------------------------------------------------------------- */ public: const char * what() const noexcept override { return _info.c_str(); } virtual const std::string info() const noexcept { std::stringstream stream; stream << debug::demangle(typeid(*this).name()) << " : " << _info << " [" << _file << ":" << _line << "]"; return stream.str(); } public: void setInfo(const std::string & info) { _info = info; } void setFile(const std::string & file) { _file = file; } void setLine(unsigned int line) { _line = line; } /* ---------------------------------------------------------------------- */ /* Class Members */ /* ---------------------------------------------------------------------- */ protected: /// exception description and additionals std::string _info; private: /// file it is thrown from std::string _file; /// ligne it is thrown from unsigned int _line{0}; }; class CriticalError : public Exception {}; class AssertException : public Exception {}; class NotImplementedException : public Exception {}; /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const Exception & _this) { stream << _this.what(); return stream; } /* -------------------------------------------------------------------------- */ class Debugger { public: Debugger(); virtual ~Debugger(); Debugger(const Debugger &) = default; Debugger & operator=(const Debugger &) = default; void exit(int status) __attribute__((noreturn)); void throwException(const std::string & info, const std::string & file, unsigned int line, bool, const std::string &) const noexcept(false) __attribute__((noreturn)); /*----------------------------------------------------------------------- */ template <class Except> void throwCustomException(const Except & ex, const std::string & info, const std::string & file, unsigned int line) const noexcept(false) __attribute__((noreturn)); /*----------------------------------------------------------------------- */ template <class Except> void throwCustomException(const Except & ex, const std::string & file, unsigned int line) const noexcept(false) __attribute__((noreturn)); void printMessage(const std::string & prefix, const DebugLevel & level, const std::string & info) const; void setOutStream(std::ostream & out) { cout = &out; } std::ostream & getOutStream() { return *cout; } public: void setParallelContext(int rank, int size); void setDebugLevel(const DebugLevel & level); const DebugLevel & getDebugLevel() const; void setLogFile(const std::string & filename); std::ostream & getOutputStream(); - inline bool testLevel(const DebugLevel & level) const { - return (this->level >= (level)); + inline bool testLevel(const DebugLevel & level, + const std::string & module = "core") const { + auto level_reached = (this->level >= (level)); + auto correct_module = + (level <= dblCritical) or (modules_to_debug.size() == 0) or + (modules_to_debug.find(module) != modules_to_debug.end()); + return level_reached and correct_module; } void printBacktrace(bool on_off) { this->print_backtrace = on_off; } bool printBacktrace() { return this->print_backtrace; } + void addModuleToDebug(const std::string & id) { + modules_to_debug.insert(id); + } + void removeModuleToDebug(const std::string & id) { + auto it = modules_to_debug.find(id); + if(it != modules_to_debug.end()) + modules_to_debug.erase(it); + } private: std::string parallel_context; std::ostream * cout; bool file_open; DebugLevel level; bool print_backtrace; + std::set<std::string> modules_to_debug; }; extern Debugger debugger; } // namespace debug +/* -------------------------------------------------------------------------- */ +#define AKANTU_STRINGIZE_(str) #str +#define AKANTU_STRINGIZE(str) AKANTU_STRINGIZE_(str) /* -------------------------------------------------------------------------- */ #define AKANTU_STRINGSTREAM_IN(_str, _sstr) \ ; \ do { \ std::stringstream _dbg_s_info; \ _dbg_s_info << _sstr; \ _str = _dbg_s_info.str(); \ } while (false) /* -------------------------------------------------------------------------- */ #define AKANTU_EXCEPTION(info) AKANTU_EXCEPTION_(info, false) #define AKANTU_SILENT_EXCEPTION(info) AKANTU_EXCEPTION_(info, true) #define AKANTU_EXCEPTION_(info, silent) \ do { \ std::stringstream _dbg_str; \ _dbg_str << info; \ std::stringstream _dbg_loc; \ _dbg_loc << AKANTU_LOCATION; \ ::akantu::debug::debugger.throwException( \ _dbg_str.str(), __FILE__, __LINE__, silent, _dbg_loc.str()); \ } while (false) #define AKANTU_CUSTOM_EXCEPTION_INFO(ex, info) \ do { \ std::stringstream _dbg_str; \ _dbg_str << info; \ ::akantu::debug::debugger.throwCustomException(ex, _dbg_str.str(), \ __FILE__, __LINE__); \ } while (false) #define AKANTU_CUSTOM_EXCEPTION(ex) \ do { \ ::akantu::debug::debugger.throwCustomException(ex, __FILE__, __LINE__); \ } while (false) /* -------------------------------------------------------------------------- */ #ifdef AKANTU_NDEBUG #define AKANTU_DEBUG_TEST(level) (false) #define AKANTU_DEBUG_LEVEL_IS_TEST() \ - (::akantu::debug::debugger.testLevel(dblTest)) + (::akantu::debug::debugger.testLevel(dblTest, AKANTU_STRINGIZE(AKANTU_MODULE))) #define AKANTU_DEBUG(level, info) #define AKANTU_DEBUG_(pref, level, info) #define AKANTU_DEBUG_IN() #define AKANTU_DEBUG_OUT() #define AKANTU_DEBUG_INFO(info) #define AKANTU_DEBUG_WARNING(info) #define AKANTU_DEBUG_TRACE(info) #define AKANTU_DEBUG_ASSERT(test, info) #define AKANTU_ERROR(info) \ AKANTU_CUSTOM_EXCEPTION_INFO(::akantu::debug::CriticalError(), info) /* -------------------------------------------------------------------------- */ #else #define AKANTU_DEBUG(level, info) AKANTU_DEBUG_(" ", level, info) #define AKANTU_DEBUG_(pref, level, info) \ do { \ std::string _dbg_str; \ AKANTU_STRINGSTREAM_IN(_dbg_str, info << " " << AKANTU_LOCATION); \ ::akantu::debug::debugger.printMessage(pref, level, _dbg_str); \ } while (false) -#define AKANTU_DEBUG_TEST(level) (::akantu::debug::debugger.testLevel(level)) +#define AKANTU_DEBUG_TEST(level) \ + (::akantu::debug::debugger.testLevel(level, AKANTU_STRINGIZE(AKANTU_MODULE))) #define AKANTU_DEBUG_LEVEL_IS_TEST() \ (::akantu::debug::debugger.testLevel(dblTest)) #define AKANTU_DEBUG_IN() \ AKANTU_DEBUG_("==>", ::akantu::dblIn, __func__ << "()") #define AKANTU_DEBUG_OUT() \ AKANTU_DEBUG_("<==", ::akantu::dblOut, __func__ << "()") #define AKANTU_DEBUG_INFO(info) AKANTU_DEBUG_("---", ::akantu::dblInfo, info) #define AKANTU_DEBUG_WARNING(info) \ AKANTU_DEBUG_("/!\\", ::akantu::dblWarning, info) #define AKANTU_DEBUG_TRACE(info) AKANTU_DEBUG_(">>>", ::akantu::dblTrace, info) #define AKANTU_DEBUG_ASSERT(test, info) \ do { \ if (not(test)) \ AKANTU_CUSTOM_EXCEPTION_INFO(::akantu::debug::AssertException(), \ "assert [" << #test << "] " << info); \ } while (false) #define AKANTU_ERROR(info) \ do { \ AKANTU_DEBUG_("!!! ", ::akantu::dblError, info); \ AKANTU_CUSTOM_EXCEPTION_INFO(::akantu::debug::CriticalError(), info); \ } while (false) #endif // AKANTU_NDEBUG #define AKANTU_TO_IMPLEMENT() \ AKANTU_CUSTOM_EXCEPTION_INFO(::akantu::debug::NotImplementedException(), \ __func__ << " : not implemented yet !") /* -------------------------------------------------------------------------- */ namespace debug { /* ------------------------------------------------------------------------ */ template <class Except> void Debugger::throwCustomException(const Except & ex, const std::string & info, const std::string & file, unsigned int line) const noexcept(false) { auto & nc_ex = const_cast<Except &>(ex); nc_ex.setInfo(info); nc_ex.setFile(file); nc_ex.setLine(line); throw ex; } /* ------------------------------------------------------------------------ */ template <class Except> void Debugger::throwCustomException(const Except & ex, const std::string & file, unsigned int line) const noexcept(false) { auto & nc_ex = const_cast<Except &>(ex); nc_ex.setFile(file); nc_ex.setLine(line); throw ex; } } // namespace debug } // namespace akantu #endif /* __AKANTU_ERROR_HH__ */