diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py old mode 100755 new mode 100644 index b38cf07..a90307b --- a/.ycm_extra_conf.py +++ b/.ycm_extra_conf.py @@ -1,172 +1,139 @@ +# Generated by YCM Generator at 2019-01-29 22:35:09.802732 + +# 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 os.path -import fnmatch -import logging import ycm_core -import re -BASE_FLAGS = [ - '-Wall', - '-Wuninitialized', - '-Wextra', - '-Wno-long-long', - '-Wno-variadic-macros', - '-fexceptions', - '-ferror-limit=10000', - '-DNDEBUG', - '-std=c++17', - '-xc++', - '-I/usr/lib/', - '-I/usr/include/', - ] - -SOURCE_EXTENSIONS = [ - '.cpp', - ] - -SOURCE_DIRECTORIES = [ - 'src' - ] - -HEADER_EXTENSIONS = [ - '.h', - ] - -HEADER_DIRECTORIES = [ - ] - -def IsHeaderFile(filename): - extension = os.path.splitext(filename)[1] - return extension in HEADER_EXTENSIONS - -def GetCompilationInfoForFile(database, filename): - if IsHeaderFile(filename): - basename = os.path.splitext(filename)[0] - for extension in SOURCE_EXTENSIONS: - # Get info from the source files by replacing the extension. - replacement_file = basename + extension - if os.path.exists(replacement_file): - compilation_info = database.GetCompilationInfoForFile(replacement_file) - if compilation_info.compiler_flags_: - return compilation_info - # If that wasn't successful, try replacing possible header directory with possible source directories. - for header_dir in HEADER_DIRECTORIES: - for source_dir in SOURCE_DIRECTORIES: - src_file = replacement_file.replace(header_dir, source_dir) - if os.path.exists(src_file): - compilation_info = database.GetCompilationInfoForFile(src_file) - if compilation_info.compiler_flags_: - return compilation_info - return None - return database.GetCompilationInfoForFile(filename) - -def FindNearest(path, target, build_folder): - candidate = os.path.join(path, target) - if(os.path.isfile(candidate) or os.path.isdir(candidate)): - logging.info("Found nearest " + target + " at " + candidate) - return candidate; - - parent = os.path.dirname(os.path.abspath(path)); - if(parent == path): - raise RuntimeError("Could not find " + target); - - if(build_folder): - candidate = os.path.join(parent, build_folder, target) - if(os.path.isfile(candidate) or os.path.isdir(candidate)): - logging.info("Found nearest " + target + " in build folder at " + candidate) - return candidate; - - return FindNearest(parent, target, build_folder) - -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 +flags = [ + '-x', + 'c++', + '-D_DEBUG', + '-std=c++17', +] -def FlagsForClangComplete(root): - try: - clang_complete_path = FindNearest(root, '.clang_complete') - clang_complete_flags = open(clang_complete_path, 'r').read().splitlines() - return clang_complete_flags - except: - return None +# 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 = '' -def FlagsForInclude(root): - try: - include_path = FindNearest(root, 'include') - flags = [] - for dirroot, dirnames, filenames in os.walk(include_path): - for dir_path in dirnames: - real_path = os.path.join(dirroot, dir_path) - flags = flags + ["-I" + real_path] - return flags - except: - return None +if os.path.exists( compilation_database_folder ): + database = ycm_core.CompilationDatabase( compilation_database_folder ) +else: + database = None -def FlagsForCompilationDatabase(root, filename): - try: - # Last argument of next function is the name of the build folder for - # out of source projects - compilation_db_path = FindNearest(root, 'compile_commands.json', 'build') - compilation_db_dir = os.path.dirname(compilation_db_path) - logging.info("Set compilation database directory to " + compilation_db_dir) - compilation_db = ycm_core.CompilationDatabase(compilation_db_dir) - if not compilation_db: - logging.info("Compilation database file found but unable to load") - return None - compilation_info = GetCompilationInfoForFile(compilation_db, filename) - if not compilation_info: - logging.info("No compilation info for " + filename + " in compilation database") - return None - return MakeRelativePathsInFlagsAbsolute( - compilation_info.compiler_flags_, - compilation_info.compiler_working_dir_) - except: - return None +SOURCE_EXTENSIONS = [ '.C', '.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', '.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. + if IsHeaderFile( filename ): + basename = os.path.splitext( filename )[ 0 ] + 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 ) + + return { + 'flags': final_flags, + 'do_cache': True + } -def FlagsForFile(filename): - root = os.path.realpath(filename); - compilation_db_flags = FlagsForCompilationDatabase(root, filename) - confPath = os.path.dirname(os.path.abspath(__file__)) - - for dir in HEADER_DIRECTORIES: - BASE_FLAGS.append('-I'+confPath+'/'+dir) - - if compilation_db_flags: - final_flags = compilation_db_flags - else: - final_flags = BASE_FLAGS - clang_flags = FlagsForClangComplete(root) - if clang_flags: - final_flags = final_flags + clang_flags - include_flags = FlagsForInclude(root) - if include_flags: - final_flags = final_flags + include_flags - return { - 'flags': final_flags, - 'do_cache': True - } diff --git a/Makefile b/Makefile index 4d97070..bc1ebb9 100755 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# This Makefile was generated using MakeGen v1.0.8 made by Tim HÃ¥kansson +# This Makefile was generated using MakeGen v1.0.9 made by Tim HÃ¥kansson # and is licensed under MIT. Full source of the project can be found at # https://github.com/Thraix/MakeGen CC=@g++ diff --git a/src/Common.h b/src/Common.h index 9a6112c..208f21a 100755 --- a/src/Common.h +++ b/src/Common.h @@ -12,7 +12,7 @@ // Release , should be backwards compatible with any minor version #define MAKEGEN_VERSION_RELEASE 0 // Minor changes, should be compatible with any other minor version with same major and release. -#define MAKEGEN_VERSION_MINOR 8 +#define MAKEGEN_VERSION_MINOR 9 #define MAKEGEN_VERSION ("v" STR(MAKEGEN_VERSION_MAJOR) "." STR(MAKEGEN_VERSION_RELEASE) "." STR(MAKEGEN_VERSION_MINOR)) const static unsigned int FLAG_HELP = BIT(0); diff --git a/src/ConfigFile.cpp b/src/ConfigFile.cpp index d8dc51f..34af385 100755 --- a/src/ConfigFile.cpp +++ b/src/ConfigFile.cpp @@ -13,7 +13,7 @@ ConfigFile::ConfigFile() } -ConfigFile ConfigFile::Load() +ConfigFile ConfigFile::Load(const std::string& filename) { ConfigFile conf; unsigned int loadFlag = 0; @@ -22,94 +22,97 @@ ConfigFile ConfigFile::Load() std::string* s; bool* b; - std::ifstream file("makegen.conf"); + std::ifstream file(filename); std::string line; - while(std::getline(file,line)) + if(file.is_open()) { - if(line[0]=='#') + while(std::getline(file,line)) { - if(line == "#libs") + if(line[0]=='#') { - vec = &conf.libs; - loadFlag = FLAG_VECTOR; - } - else if(line == "#libdirs") - { - vec = &conf.libdirs; - loadFlag = FLAG_VECTOR; - } - else if(line == "#includedirs") - { - vec = &conf.includedirs; - loadFlag = FLAG_VECTOR; - } - else if(line == "#compileflags") - { - vec = &conf.flags; - loadFlag = FLAG_VECTOR; - } - else if(line == "#srcdirs") - { - vec = &conf.srcdirs; - loadFlag = FLAG_VECTOR; - } - else if(line == "#defines") - { - vec = &conf.defines; - loadFlag = FLAG_VECTOR; - } - else if(line == "#outputdir") - { - s = &conf.outputdir; - loadFlag = FLAG_STRING; - } - else if(line == "#outputname") - { - s = &conf.outputname; - loadFlag = FLAG_STRING; - } - else if(line == "#projectname") - { - s = &conf.projectname; - loadFlag = FLAG_STRING; - } - else if(line == "#executable") - { - b = &conf.executable; - loadFlag = FLAG_BOOL; - } - else if(line == "#shared") - { - b = &conf.shared; - loadFlag = FLAG_BOOL; + if(line == "#libs") + { + vec = &conf.libs; + loadFlag = FLAG_VECTOR; + } + else if(line == "#libdirs") + { + vec = &conf.libdirs; + loadFlag = FLAG_VECTOR; + } + else if(line == "#includedirs") + { + vec = &conf.includedirs; + loadFlag = FLAG_VECTOR; + } + else if(line == "#compileflags") + { + vec = &conf.flags; + loadFlag = FLAG_VECTOR; + } + else if(line == "#srcdirs") + { + vec = &conf.srcdirs; + loadFlag = FLAG_VECTOR; + } + else if(line == "#defines") + { + vec = &conf.defines; + loadFlag = FLAG_VECTOR; + } + else if(line == "#outputdir") + { + s = &conf.outputdir; + loadFlag = FLAG_STRING; + } + else if(line == "#outputname") + { + s = &conf.outputname; + loadFlag = FLAG_STRING; + } + else if(line == "#projectname") + { + s = &conf.projectname; + loadFlag = FLAG_STRING; + } + else if(line == "#executable") + { + b = &conf.executable; + loadFlag = FLAG_BOOL; + } + else if(line == "#shared") + { + b = &conf.shared; + loadFlag = FLAG_BOOL; + } + else + { + LOG_ERROR("Invalid flag: ", line); + loadFlag = FLAG_NONE; + } } else { - LOG_ERROR("Invalid flag: ", line); - loadFlag = FLAG_NONE; - } - } - else - { - if(loadFlag == FLAG_STRING) - { - *s = line; - } - else if(loadFlag == FLAG_VECTOR) - { - vec->push_back(line); - } - else if(loadFlag == FLAG_BOOL) - { - if(line == "true") - *b = true; - else - *b = false; + if(loadFlag == FLAG_STRING) + { + *s = line; + } + else if(loadFlag == FLAG_VECTOR) + { + vec->push_back(line); + } + else if(loadFlag == FLAG_BOOL) + { + if(line == "true") + *b = true; + else + *b = false; + } } } + return conf; } - return conf; } void ConfigFile::InputMultiple(const std::string& inputText, std::vector& vec, bool needEnding) diff --git a/src/ConfigFile.h b/src/ConfigFile.h index 2a5788c..0b1b9c5 100755 --- a/src/ConfigFile.h +++ b/src/ConfigFile.h @@ -21,7 +21,7 @@ class ConfigFile ConfigFile(); void Save() const; static ConfigFile Gen(); - static ConfigFile Load(); + static ConfigFile Load(const std::string& filename); private: static void InputMultiple(const std::string& inputText, std::vector& vec, bool needEnding); }; diff --git a/src/main.cpp b/src/main.cpp index ecf032f..9a29698 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,10 +11,38 @@ #include "Makefile.h" #include "Timer.h" -void GenMakefile() +void PrintHelp() { - ConfigFile conf = ConfigFile::Load(); - Makefile::Save(conf); + LOG_INFO("Usage: makegen [options]"); + LOG_INFO(" Options:"); + LOG_INFO(" --help\tDisplays this information"); + LOG_INFO(" --conf\tGenerate a config file for the project"); + LOG_INFO(" --version\tDisplays the version of this program"); + LOG_INFO(" install\tGenerates a Makefile and runs make install"); + LOG_INFO(" clean\t\tGenerates a Makefile and runs make clean"); + LOG_INFO(" rebuild\tGenerates a Makefile and runs make rebuild"); + LOG_INFO(" If no option is given it will run default make"); +} + +bool GenMakefile() +{ + std::ifstream f("makegen.conf"); + if(f.good()) + { + ConfigFile conf = ConfigFile::Load("makegen.conf"); + Makefile::Save(conf); + return true; + } + f.close(); + f = std::ifstream("Makefile"); + + if(!f.good()) + { + LOG_ERROR("No makegen.conf or Makefile found."); + PrintHelp(); + return false; + } + return true; } unsigned int ReadFlags(int argc, char** argv) @@ -50,15 +78,7 @@ int main(int argc, char** argv) unsigned int flags = ReadFlags(argc,argv); if(flags & FLAG_HELP) { - LOG_INFO("Usage: makegen [options]"); - LOG_INFO(" Options:"); - LOG_INFO(" --help\tDisplays this information"); - LOG_INFO(" --conf\tGenerate a config file for the project"); - LOG_INFO(" --version\tDisplays the version of this program"); - LOG_INFO(" install\tGenerates a Makefile and runs make install"); - LOG_INFO(" clean\t\tGenerates a Makefile and runs make clean"); - LOG_INFO(" rebuild\tGenerates a Makefile and runs make rebuild"); - LOG_INFO(" If no option is given it will generate a Makefile and run default make"); + PrintHelp(); return 0; } if(flags & FLAG_VERSION) @@ -73,7 +93,8 @@ int main(int argc, char** argv) } LOG_INFO("Generating Makefile..."); Timer timer; - GenMakefile(); + if(!GenMakefile()) + return 1; LOG_INFO("Took ", round(timer.Elapsed()*1000.0)/1000.0,"s"); LOG_INFO("Running Makefile..."); for(int i = 1;i