diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..004dcac --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,110 @@ +cmake_minimum_required(VERSION 2.8.8) + +# Start project, set version here. +project("RoSA") + +set(ROSA_VERSION_MAJOR 0) +set(ROSA_VERSION_MINOR 1) +set(ROSA_VERSION_PATCH 0) + +# Add path for custom modules +set(CMAKE_MODULE_PATH + ${CMAKE_MODULE_PATH} + "${CMAKE_CURRENT_SOURCE_DIR}/cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" + ) + +# Package information +if( NOT PACKAGE_VERSION ) + set(PACKAGE_VERSION "${ROSA_VERSION_MAJOR}.${ROSA_VERSION_MINOR}.${ROSA_VERSION_PATCH}") +endif() + +set(PACKAGE_NAME "Research on Self-Awareness Framework") +set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") +set(PACKAGE_BUGREPORT "david.juhasz@tuwien.ac.at") + +#TODO: cpack? + +# Sanity check we are to make out-of-tree build +if( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR ) + message(FATAL_ERROR "In-source builds are not allowed.") +endif() + +string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE) + +# Set various paths +set(ROSA_MAIN_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(ROSA_MAIN_INCLUDE_DIR ${ROSA_MAIN_SRC_DIR}/include) +set(ROSA_MAIN_BIN_DIR ${ROSA_MAIN_SRC_DIR}/bin) +set(ROSA_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) +set(ROSA_RUNTIME_OUTPUT_INTDIR ${ROSA_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin) +set(ROSA_LIBRARY_OUTPUT_INTDIR ${ROSA_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib) +set(ROSA_TOOLS_BINARY_DIR ${ROSA_RUNTIME_OUTPUT_INTDIR}) +set(ROSA_LIBRARY_DIR ${ROSA_LIBRARY_OUTPUT_INTDIR}) +set(ROSA_INCLUDE_DIR ${ROSA_BINARY_DIR}/include) + +# Set build options +option(ROSA_INCLUDE_TOOLS "Generate build targets for RoSA tools." ON) +option(ROSA_INCLUDE_EXAMPLES "Generate build target for RoSA examples." ON) +option(ROSA_ENABLE_CXX1Y "Compile with C++1y enabled." ON) +option(ROSA_ENABLE_PEDANTIC "Compile with pedantic enabled." ON) + +if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" ) + option(ROSA_ENABLE_ASSERTIONS "Enable assertions." OFF) +else() + option(ROSA_ENABLE_ASSERTIONS "Enable assertions." ON) +endif() + +include(HandleROSAOptions) + +# Configure the ROSA configuration header file. + +macro(to_int_value name) + if(${name}) + set(${name}_INT 1) + else() + set(${name}_INT -1) + endif() +endmacro() + +to_int_value(ROSA_ENABLE_ASSERTIONS) + +configure_file( + ${ROSA_MAIN_INCLUDE_DIR}/rosa/config/rosa-config.h.cmake + ${ROSA_INCLUDE_DIR}/rosa/config/rosa-config.h + ) + +# They are not referenced. See set_output_directory(). +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ROSA_BINARY_DIR}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${ROSA_BINARY_DIR}/lib) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${ROSA_BINARY_DIR}/lib) + +# Set include directories +set(CMAKE_INCLUDE_CURRENT_DIR ON) +include_directories(${ROSA_INCLUDE_DIR} ${ROSA_MAIN_INCLUDE_DIR}) + +# Set extra compiler options for Visual Studio +if ( MSVC ) + add_definitions(-EHsc) # Use Exception Handling +endif() + +# Set up YCM +set(CMAKE_EXPORT_COMPILE_COMMANDS 1) +message("Set compilation_database_folder in .ymc_extra_conf.py in the source directory if you want to use YMC.") + +# Add parts of the project + +include(AddROSATools) + +add_subdirectory(lib) + +if( ROSA_INCLUDE_TOOLS ) + add_subdirectory(tools) +endif() + +if( ROSA_INCLUDE_EXAMPLES ) + add_subdirectory(examples) +endif() + +#TODO: install? + diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..889fa69 --- /dev/null +++ b/README.txt @@ -0,0 +1,55 @@ + ==================================== + Research on Self-Awareness Framework + ==================================== + +Build: +----- + +The provided CMake project supports only out-of-tree builds, i.e. one needs to +create a build directory and run cmake in that using the source directory path +as argument. + +Prerequisites: +------------- + +Nothing yet. + +Build options: +------------- + +Beyond the usual CMake options, the following project-related options are +available: + * ROSA_INCLUDE_TOOLS, defaults to ON + * ROSA_INCLUDE_EXAMPLES, defaults to ON + * ROSA_ENABLE_CXX1Y, defaults to ON + * ROSA_ENABLE_PEDANTIC, defaults to ON + * ROSA_ENABLE_ASSERTIONS, defaults to ON only for debug builds, and + its value is respected only for non-debug builds + +Set C and C++ compilers with the environment variables CC and CXX, +respectively. Use the CMake variable CMAKE_BUILD_TYPE for single-configuration +generators to set the type of build: Debug, Release. + +Using YCM: +--------- + +If you happen to use YMC, just make a copy of the provided +ycm_extra_conf.py.template file as .ycm_extra_conf.py in the project directory, +and set the following two variables in it: + * compilation_database_folder: the absolute path of your build directory + * extra_system_include_dirs: any system include directory which might not be + search by libclang. + See: https://github.com/Valloric/YouCompleteMe/issues/303; use the + following command to figure out the used system directories: + 'echo | clang -std=c++11 -v -E -x c++ -'. + +You probably want compile with clang if you use YCM, so run cmake with +environment variables CC=clang and CXX=clang++ set. + +Also note that headers file in the include directory are compiled for YCM with +the compiler flags of a corresponding source file in the lib directory, if any. +Header files in other locations are supposed to have a corresponding source +file in the same directory. +If the project's include directory (include/rosa) would be ever changed, then +that needs to be also modified in the YCM configuration file. + diff --git a/cmake/modules/AddROSATools.cmake b/cmake/modules/AddROSATools.cmake new file mode 100644 index 0000000..24d6c5c --- /dev/null +++ b/cmake/modules/AddROSATools.cmake @@ -0,0 +1,18 @@ +# Use this to set include paths which needs to be used by any target depending +# on a library. After the library name, you pass any number of paths. +macro(ROSA_set_external_include_reqs library) + set(${library}_EXTERNAL_INCLUDES ${ARGN} + CACHE INTERNAL "Externally required include paths for ${library}") +endmacro() + +# Use this for a target to register library dependencies. +# It also adds external include paths if the library have set any. +macro(ROSA_add_library_dependencies target dependencies) + foreach( dependency ${dependencies} ) + target_link_libraries(${target} ${dependency}) + if( ${dependency}_EXTERNAL_INCLUDES ) + include_directories(${${dependency}_EXTERNAL_INCLUDES}) + endif() + endforeach() +endmacro() + diff --git a/cmake/modules/HandleROSAOptions.cmake b/cmake/modules/HandleROSAOptions.cmake new file mode 100644 index 0000000..6b30861 --- /dev/null +++ b/cmake/modules/HandleROSAOptions.cmake @@ -0,0 +1,83 @@ +# This CMake module is responsible for interpreting the user defined ROSA_ +# options and executing the appropriate CMake commands to realize the users' +# selections. + +include(CheckCCompilerFlag) +include(CheckCXXCompilerFlag) + +if( CMAKE_COMPILER_IS_GNUCXX ) + set(ROSA_COMPILER_IS_GCC_COMPATIBLE ON) +elseif( MSVC ) + set(ROSA_COMPILER_IS_GCC_COMPATIBLE OFF) +elseif( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) + set(ROSA_COMPILER_IS_GCC_COMPATIBLE ON) +endif() + +function(append value) + foreach(variable ${ARGN}) + set(${variable} "${${variable}} ${value}" PARENT_SCOPE) + endforeach(variable) +endfunction() + +function(append_if condition value) + if (${condition}) + foreach(variable ${ARGN}) + set(${variable} "${${variable}} ${value}" PARENT_SCOPE) + endforeach(variable) + endif() +endfunction() + +# NDEBUG on non-Debug builds +append("-DNDEBUG" CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS_MINSIZEREL + CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_RELWITHDEBINFO + CMAKE_C_FLAGS_MINSIZEREL) + +# Assertions are always enabled on Debug builds, this is interesting for +# non-Debug builds. +if( ROSA_ENABLE_ASSERTIONS ) + # MSVC doesn't like _DEBUG on release builds. See PR 4379. + if( NOT MSVC ) + add_definitions( -D_DEBUG ) + set(ENABLE_ASSERTIONS "1") + else() + set(ENABLE_ASSERTIONS "0") + endif() + # On non-Debug builds we NDEBUG, but in this case we need to undefine it: + add_definitions(-UNDEBUG) + # Also remove /D NDEBUG to avoid MSVC warnings about conflicting defines. + foreach (flags_var_to_scrub + CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS_MINSIZEREL + CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_RELWITHDEBINFO + CMAKE_C_FLAGS_MINSIZEREL) + string (REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" " " + "${flags_var_to_scrub}" "${${flags_var_to_scrub}}") + endforeach() +endif( ROSA_ENABLE_ASSERTIONS ) + +if( ROSA_COMPILER_IS_GCC_COMPATIBLE ) + append("-Wall -Wextra -Werror" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + append_if(ROSA_ENABLE_PEDANTIC "-pedantic -Wno-long-long" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + + # Newer Clang versions cannot parse cstdio in c++1y mode. + if( ROSA_ENABLE_CXX1Y AND NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + check_cxx_compiler_flag("-std=c++1y" CXX_SUPPORTS_CXX1Y) + append_if(CXX_SUPPORTS_CXX1Y "-std=c++1y" CMAKE_CXX_FLAGS) + if( NOT CMAKE_CXX_FLAGS ) + message(FATAL_ERROR "Your compiler does not support '-std=c++1y' flag, use ROSA_ENABLE_CXX1Y=FALSE.") + endif() + else() + check_cxx_compiler_flag("-std=c++11" CXX_SUPPORTS_CXX11) + if (CXX_SUPPORTS_CXX11) + append("-std=c++11" CMAKE_CXX_FLAGS) + else() + message(FATAL_ERROR "RoSA requires C++11 support but the '-std=c++11' flag isn't supported.") + endif() + endif() +endif( ROSA_COMPILER_IS_GCC_COMPATIBLE ) + diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..615687a --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,2 @@ +# Add the different subdirectories + diff --git a/include/rosa/config/config.h b/include/rosa/config/config.h new file mode 100644 index 0000000..0a37957 --- /dev/null +++ b/include/rosa/config/config.h @@ -0,0 +1,35 @@ +/******************************************************************************* + * + * File: config.h + * + * Contents: Configuration nformation on the build of the library. + * + * Copyright 2017 + * + * Author: David Juhasz (david.juhasz@tuwien.ac.at) + * + ******************************************************************************/ + +#ifndef __ROSA_CONFIG_SYSTEM_H__ +#define __ROSA_CONFIG_SYSTEM_H__ + +// Various preprocessor macros containing config information. +#include "rosa-config.h" + +// This OS-specific block defines one of the following: +// - ROSA_LINUX +// - ROSA_WINDOWS +// It also defines ROSA_POSIX for POSIX-compatible systems +#if defined(__linux__) +#define ROSA_LINUX +#elif defined(WIN32) || defined(_WIN32) +#define ROSA_WINDOWS +#else +#error Platform and/or compiler not supported +#endif +#if defined(ROSA_LINUX) +#define ROSA_POSIX +#endif + +#endif // __ROSA_CONFIG_SYSTEM_H__ + diff --git a/include/rosa/config/rosa-config.h.cmake b/include/rosa/config/rosa-config.h.cmake new file mode 100644 index 0000000..a1b0606 --- /dev/null +++ b/include/rosa/config/rosa-config.h.cmake @@ -0,0 +1,38 @@ + +#ifndef __ROSA_CONFIG_ROSA_CONFIG_H__ +#define __ROSA_CONFIG_ROSA_CONFIG_H__ + +#define CMAKE_SYSTEM "${CMAKE_SYSTEM}" + +#define CMAKE_GENERATOR "${CMAKE_GENERATOR}" + +#define CMAKE_C_COMPILER_ID "${CMAKE_C_COMPILER_ID}" + +#define CMAKE_C_COMPILER_VERSION "${CMAKE_C_COMPILER_VERSION}" + +#define CMAKE_CXX_COMPILER_ID "${CMAKE_CXX_COMPILER_ID}" + +#define CMAKE_CXX_COMPILER_VERSION "${CMAKE_CXX_COMPILER_VERSION}" + +#define ROSA_VERSION_MAJOR ${ROSA_VERSION_MAJOR} + +#define ROSA_VERSION_MINOR ${ROSA_VERSION_MINOR} + +#define ROSA_VERSION_PATCH ${ROSA_VERSION_PATCH} + +#define PACKAGE_NAME "${PACKAGE_NAME}" + +#define PACKAGE_STRING "${PACKAGE_STRING}" + +#define PACKAGE_VERSION "${PACKAGE_VERSION}" + +#define PACKAGE_BUGREPORT "${PACKAGE_BUGREPORT}" + +#define BUILD_DATE __DATE__ " " __TIME__ + +#if @ROSA_ENABLE_ASSERTIONS_INT@ != -1 +#define ROSA_ENABLE_ASSERTIONS +#endif + +#endif // __ROSA_CONFIG_ROSA_CONFIG_H__ + diff --git a/include/rosa/config/version.h b/include/rosa/config/version.h new file mode 100644 index 0000000..df9e453 --- /dev/null +++ b/include/rosa/config/version.h @@ -0,0 +1,35 @@ +/******************************************************************************* + * + * File: version.h + * + * Contents: Version information about the build of the library. + * + * Copyright 2017 + * + * Author: David Juhasz (david.juhasz@tuwien.ac.at) + * + ******************************************************************************/ + +#ifndef _ROSA__CONFIG_VERSION_H_ +#define _ROSA__CONFIG_VERSION_H_ + +#include + +// Various preprocessor macros containing the information. +#include "rosa/config/rosa-config.h" + +namespace rosa { + +// Returns a string containing the name of the library followed by its version. +std::string library_string(void); + +// Returns a string containing the version number of the library. +std::string version(void); + +// Returns a multi-line string containing verbose information on the library. +std::string verbose_version(void); + +} // End namespace rosa + +#endif // _ROSA__CONFIG_VERSION_H_ + diff --git a/include/rosa/support/debug.hpp b/include/rosa/support/debug.hpp new file mode 100644 index 0000000..0b93355 --- /dev/null +++ b/include/rosa/support/debug.hpp @@ -0,0 +1,81 @@ +/******************************************************************************* + * + * File: debug.hpp + * + * Contents: Facility for debugging + * + * Copyright 2017 + * + * Author: David Juhasz (david.juhasz@tuwien.ac.at) + * + ******************************************************************************/ + +#ifndef _ROSA__SUPPORT_DEBUG_HPP_ +#define _ROSA__SUPPORT_DEBUG_HPP_ + +#include "rosa/support/types.hpp" +#include +#include + +namespace rosa { + +// Returns an output stream to use for debugging. +std::ostream &dbgs(void); + +// Prints an array to the ostream. +template +std::ostream &operator<<(std::ostream &os, const std::array &arr) { + os << '['; + for (unsigned i = 0; i < size; ++i) { + if (i) { + os << ','; + } + os << (PRINTABLE(T)) arr[i]; + } + os << ']'; + return os; +} + +} // End namespace rosa + +#ifndef ROSA_ENABLE_ASSERTIONS +#define ASSERT(unused) static_cast(0) +#elif defined(ROSA_WINDOWS) +#define ASSERT(stmt) \ + if (static_cast(stmt) == false) { \ + rosa::dbgs() << __FILE__ << ":" << __LINE__ << ": requirement failed '" \ + << #stmt << "'" << std::endl; \ + ::abort(); \ + } \ + static_cast(0) +#else // defined(ROSA_LINUX) +#include +#define ASSERT(stmt) \ + if (static_cast(stmt) == false) { \ + rosa::dbgs() << __FILE__ << ":" << __LINE__ << ": requirement failed '" \ + << #stmt << "'" << std::endl; \ + void *array[20]; \ + auto bt_size = ::backtrace(array, 20); \ + ::backtrace_symbols_fd(array, bt_size, 2); \ + ::abort(); \ + } \ + static_cast(0) +#endif // defined(ROSA_ENABLE_ASSERTIONS) + +#ifndef NDEBUG +#define DEBUG(X) \ + do { \ + X; \ + } while (0) +#define DEBUGVAR(V) \ + do { \ + rosa::dbgs() << #V << " (" << __FILE__ << ":" << __LINE__ << "): " << (V) \ + << std::endl; \ + } while (0) +#else // defined(NDEBUG) +#define DEBUG(X) static_cast(0) +#define DEBUGVAR(X) static_cast(0) +#endif // defined(NDEBUG) + +#endif // _ROSA__SUPPORT_DEBUG_HPP_ + diff --git a/include/rosa/support/types.hpp b/include/rosa/support/types.hpp new file mode 100644 index 0000000..ee503d7 --- /dev/null +++ b/include/rosa/support/types.hpp @@ -0,0 +1,46 @@ +/******************************************************************************* + * + * File: types.hpp + * + * Contents: Facility for type-related things + * + * Copyright 2016 + * + * Author: David Juhasz (david.juhasz@tuwien.ac.at) + * + ******************************************************************************/ + +#ifndef _ROSA__SUPPORT_TYPES_HPP_ +#define _ROSA__SUPPORT_TYPES_HPP_ + +#include + +namespace rosa { + +// A value of type [u]int8_t is treated as a character when being put to an +// output stream, which can result in invisible characters being printed. To +// avoid that, such a value needs to be casted to a wider type. It can be done +// by using the following template to find a target type to cast our value to. +// NOTE: There is a preprocessor macro below which can be used instead of the +// tedious typename stuff. +template +struct PrintableType { + typedef T type; +}; + +template <> +struct PrintableType { + typedef unsigned int type; +}; + +template <> +struct PrintableType { + typedef int type; +}; + +#define PRINTABLE(T) typename PrintableType::type + +} // End namespace rosa + +#endif // _ROSA__SUPPORT_TYPES_HPP_ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000..af8b846 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,4 @@ +# Add the different subdirectories. +add_subdirectory(config) +add_subdirectory(support) + diff --git a/lib/config/CMakeLists.txt b/lib/config/CMakeLists.txt new file mode 100644 index 0000000..abea00b --- /dev/null +++ b/lib/config/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(ROSAConfig + version.cpp + ) diff --git a/lib/config/version.cpp b/lib/config/version.cpp new file mode 100644 index 0000000..069f145 --- /dev/null +++ b/lib/config/version.cpp @@ -0,0 +1,41 @@ +/******************************************************************************* + * + * File: version.cpp + * + * Contents: Implementation for version.h. + * + * Copyright 2016 + * + * Author: David Juhasz (david.juhasz@tuwien.ac.at) + * + ******************************************************************************/ + +#include "rosa/config/version.h" +#include + +namespace rosa { + +std::string library_string(void) { + return PACKAGE_STRING; +} + +std::string version(void) { + return PACKAGE_VERSION; +} + +std::string verbose_version(void) { + std::stringstream ss; + ss << PACKAGE_STRING << std::endl + << "Built by " << CMAKE_GENERATOR + << " with " << CMAKE_CXX_COMPILER_ID + << ' ' << CMAKE_CXX_COMPILER_VERSION << std::endl + << "on a(n) " << CMAKE_SYSTEM << " system." << std::endl + << "Build date: " << BUILD_DATE << std::endl + << "Package name: " << PACKAGE_NAME << std::endl + << "Package version: " << PACKAGE_VERSION << std::endl + << "Report issues: " << PACKAGE_BUGREPORT << std::endl; + return ss.str(); +} + +} // End namespace rosa + diff --git a/lib/support/CMakeLists.txt b/lib/support/CMakeLists.txt new file mode 100644 index 0000000..aa8e4cd --- /dev/null +++ b/lib/support/CMakeLists.txt @@ -0,0 +1,4 @@ +add_library(ROSASupport + debug.cpp + ) + diff --git a/lib/support/debug.cpp b/lib/support/debug.cpp new file mode 100644 index 0000000..b1ee0e1 --- /dev/null +++ b/lib/support/debug.cpp @@ -0,0 +1,24 @@ +/******************************************************************************* + * + * File: debug.cpp + * + * Contents: Implementation for debug.hpp. + * + * Copyright 2016 + * + * Author: David Juhasz (david.juhasz@tuwien.ac.at) + * + ******************************************************************************/ + +#include "rosa/support/debug.hpp" +#include + +namespace rosa { + +std::ostream &dbgs(void) { + // Always return the standard error stream. + return std::cerr; +} + +} // End namespace rosa + diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 0000000..615687a --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,2 @@ +# Add the different subdirectories + diff --git a/ycm_extra_conf.py.template b/ycm_extra_conf.py.template new file mode 100644 index 0000000..0adecb8 --- /dev/null +++ b/ycm_extra_conf.py.template @@ -0,0 +1,150 @@ +# This file is NOT licensed under the GPLv3, which is the license for the rest +# of YouCompleteMe. +# +# Here's the license text for this file: +# +# This is free and unencumbered software released into the public domain. +# +# Anyone is free to copy, modify, publish, use, compile, sell, or +# distribute this software, either in source code form or as a compiled +# binary, for any purpose, commercial or non-commercial, and by any +# means. +# +# In jurisdictions that recognize copyright laws, the author or authors +# of this software dedicate any and all copyright interest in the +# software to the public domain. We make this dedication for the benefit +# of the public at large and to the detriment of our heirs and +# successors. We intend this dedication to be an overt act of +# relinquishment in perpetuity of all present and future rights to this +# software under copyright law. +# +# 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 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. +# +# For more information, please refer to + +import os +import ycm_core + +# Set this to the absolute path of any system include directory which might not +# be search by libclang. +# See: https://github.com/Valloric/YouCompleteMe/issues/303. +extra_system_include_dirs = [ +] + +# Set this to the absolute path to the folder (NOT the file!) containing the +# compile_commands.json file to use that instead of 'flags'. See here for +# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html +# +# You can get CMake to generate this file for you by adding: +# set( CMAKE_EXPORT_COMPILE_COMMANDS 1 ) +# to your CMakeLists.txt file. +# +# Most projects will NOT need to set this to anything; you can just change the +# 'flags' list of compilation flags. Notice that YCM itself uses that approach. +compilation_database_folder = '' + +if os.path.exists( compilation_database_folder ): + database = ycm_core.CompilationDatabase( compilation_database_folder ) +else: + database = None + +# These are the compilation flags that will be used in case there's no +# compilation database set (by default, one is not set). +# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR. +flags = [] + +SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ] + +def DirectoryOfThisScript(): + return os.path.dirname( os.path.abspath( __file__ ) ) + + +def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): + if not working_directory: + return list( flags ) + new_flags = [] + make_next_absolute = False + path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] + for flag in flags: + new_flag = flag + + if make_next_absolute: + make_next_absolute = False + if not flag.startswith( '/' ): + new_flag = os.path.join( working_directory, flag ) + + for path_flag in path_flags: + if flag == path_flag: + make_next_absolute = True + break + + if flag.startswith( path_flag ): + path = flag[ len( path_flag ): ] + new_flag = path_flag + os.path.join( working_directory, path ) + break + + if new_flag: + new_flags.append( new_flag ) + return new_flags + + +def IsHeaderFile( filename ): + extension = os.path.splitext( filename )[ 1 ] + return extension in [ '.h', '.hxx', '.hpp', '.hh' ] + + +def GetCompilationInfoForFile( filename ): + # The compilation_commands.json file generated by CMake does not have entries + # for header files. So we do our best by asking the db for flags for a + # corresponding source file, if any. If one exists, the flags for that file + # should be good enough. + # NOTE that headers in the include directory should match a corresponding + # source file in the lib directory. + if IsHeaderFile( filename ): + basename = os.path.splitext( filename )[ 0 ] + loc = basename.rfind( '/include/rosa' ) + if loc != -1: + basename = basename[ :loc ] + '/lib' + basename[ loc+16: ] + for extension in SOURCE_EXTENSIONS: + replacement_file = basename + extension + if os.path.exists( replacement_file ): + compilation_info = database.GetCompilationInfoForFile( + replacement_file ) + if compilation_info.compiler_flags_: + return compilation_info + return None + return database.GetCompilationInfoForFile( filename ) + + +def FlagsForFile( filename, **kwargs ): + if database: + # Bear in mind that compilation_info.compiler_flags_ does NOT return a + # python list, but a "list-like" StringVec object + compilation_info = GetCompilationInfoForFile( filename ) + if not compilation_info: + return None + + final_flags = MakeRelativePathsInFlagsAbsolute( + compilation_info.compiler_flags_, + compilation_info.compiler_working_dir_ ) + + else: + relative_to = DirectoryOfThisScript() + final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) + + # Add any extra system include directories to the flags + for sysdir in extra_system_include_dirs: + final_flags.append( '-isystem' ) + final_flags.append( sysdir ) + + return { + 'flags': final_flags, + 'do_cache': True + } +