Fix makegen creating Makefile if no config exist
This commit is contained in:
Executable → Regular
+85
-118
@@ -1,82 +1,68 @@
|
|||||||
|
# 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 <http://unlicense.org/>
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
|
||||||
import fnmatch
|
|
||||||
import logging
|
|
||||||
import ycm_core
|
import ycm_core
|
||||||
import re
|
|
||||||
|
|
||||||
BASE_FLAGS = [
|
flags = [
|
||||||
'-Wall',
|
'-x',
|
||||||
'-Wuninitialized',
|
'c++',
|
||||||
'-Wextra',
|
'-D_DEBUG',
|
||||||
'-Wno-long-long',
|
|
||||||
'-Wno-variadic-macros',
|
|
||||||
'-fexceptions',
|
|
||||||
'-ferror-limit=10000',
|
|
||||||
'-DNDEBUG',
|
|
||||||
'-std=c++17',
|
'-std=c++17',
|
||||||
'-xc++',
|
|
||||||
'-I/usr/lib/',
|
|
||||||
'-I/usr/include/',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
SOURCE_EXTENSIONS = [
|
|
||||||
'.cpp',
|
|
||||||
]
|
|
||||||
|
|
||||||
SOURCE_DIRECTORIES = [
|
# Set this to the absolute path to the folder (NOT the file!) containing the
|
||||||
'src'
|
# 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 = ''
|
||||||
|
|
||||||
HEADER_EXTENSIONS = [
|
if os.path.exists( compilation_database_folder ):
|
||||||
'.h',
|
database = ycm_core.CompilationDatabase( compilation_database_folder )
|
||||||
]
|
else:
|
||||||
|
database = None
|
||||||
|
|
||||||
HEADER_DIRECTORIES = [
|
SOURCE_EXTENSIONS = [ '.C', '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]
|
||||||
]
|
|
||||||
|
|
||||||
def IsHeaderFile(filename):
|
def DirectoryOfThisScript():
|
||||||
extension = os.path.splitext(filename)[1]
|
return os.path.dirname( os.path.abspath( __file__ ) )
|
||||||
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 ):
|
def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):
|
||||||
if not working_directory:
|
if not working_directory:
|
||||||
@@ -107,66 +93,47 @@ def MakeRelativePathsInFlagsAbsolute(flags, working_directory):
|
|||||||
return new_flags
|
return new_flags
|
||||||
|
|
||||||
|
|
||||||
def FlagsForClangComplete(root):
|
def IsHeaderFile( filename ):
|
||||||
try:
|
extension = os.path.splitext( filename )[ 1 ]
|
||||||
clang_complete_path = FindNearest(root, '.clang_complete')
|
return extension in [ '.H', '.h', '.hxx', '.hpp', '.hh' ]
|
||||||
clang_complete_flags = open(clang_complete_path, 'r').read().splitlines()
|
|
||||||
return clang_complete_flags
|
|
||||||
except:
|
|
||||||
return None
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
def FlagsForCompilationDatabase(root, filename):
|
def GetCompilationInfoForFile( filename ):
|
||||||
try:
|
# The compilation_commands.json file generated by CMake does not have entries
|
||||||
# Last argument of next function is the name of the build folder for
|
# for header files. So we do our best by asking the db for flags for a
|
||||||
# out of source projects
|
# corresponding source file, if any. If one exists, the flags for that file
|
||||||
compilation_db_path = FindNearest(root, 'compile_commands.json', 'build')
|
# should be good enough.
|
||||||
compilation_db_dir = os.path.dirname(compilation_db_path)
|
if IsHeaderFile( filename ):
|
||||||
logging.info("Set compilation database directory to " + compilation_db_dir)
|
basename = os.path.splitext( filename )[ 0 ]
|
||||||
compilation_db = ycm_core.CompilationDatabase(compilation_db_dir)
|
for extension in SOURCE_EXTENSIONS:
|
||||||
if not compilation_db:
|
replacement_file = basename + extension
|
||||||
logging.info("Compilation database file found but unable to load")
|
if os.path.exists( replacement_file ):
|
||||||
|
compilation_info = database.GetCompilationInfoForFile(
|
||||||
|
replacement_file )
|
||||||
|
if compilation_info.compiler_flags_:
|
||||||
|
return compilation_info
|
||||||
return None
|
return None
|
||||||
compilation_info = GetCompilationInfoForFile(compilation_db, filename)
|
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:
|
if not compilation_info:
|
||||||
logging.info("No compilation info for " + filename + " in compilation database")
|
|
||||||
return None
|
return None
|
||||||
return MakeRelativePathsInFlagsAbsolute(
|
|
||||||
|
final_flags = MakeRelativePathsInFlagsAbsolute(
|
||||||
compilation_info.compiler_flags_,
|
compilation_info.compiler_flags_,
|
||||||
compilation_info.compiler_working_dir_ )
|
compilation_info.compiler_working_dir_ )
|
||||||
except:
|
|
||||||
return None
|
|
||||||
|
|
||||||
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:
|
else:
|
||||||
final_flags = BASE_FLAGS
|
relative_to = DirectoryOfThisScript()
|
||||||
clang_flags = FlagsForClangComplete(root)
|
final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to )
|
||||||
if clang_flags:
|
|
||||||
final_flags = final_flags + clang_flags
|
|
||||||
include_flags = FlagsForInclude(root)
|
|
||||||
if include_flags:
|
|
||||||
final_flags = final_flags + include_flags
|
|
||||||
return {
|
return {
|
||||||
'flags': final_flags,
|
'flags': final_flags,
|
||||||
'do_cache': True
|
'do_cache': True
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
# and is licensed under MIT. Full source of the project can be found at
|
||||||
# https://github.com/Thraix/MakeGen
|
# https://github.com/Thraix/MakeGen
|
||||||
CC=@g++
|
CC=@g++
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@
|
|||||||
// Release , should be backwards compatible with any minor version
|
// Release , should be backwards compatible with any minor version
|
||||||
#define MAKEGEN_VERSION_RELEASE 0
|
#define MAKEGEN_VERSION_RELEASE 0
|
||||||
// Minor changes, should be compatible with any other minor version with same major and release.
|
// 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))
|
#define MAKEGEN_VERSION ("v" STR(MAKEGEN_VERSION_MAJOR) "." STR(MAKEGEN_VERSION_RELEASE) "." STR(MAKEGEN_VERSION_MINOR))
|
||||||
|
|
||||||
const static unsigned int FLAG_HELP = BIT(0);
|
const static unsigned int FLAG_HELP = BIT(0);
|
||||||
|
|||||||
+5
-2
@@ -13,7 +13,7 @@ ConfigFile::ConfigFile()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigFile ConfigFile::Load()
|
ConfigFile ConfigFile::Load(const std::string& filename)
|
||||||
{
|
{
|
||||||
ConfigFile conf;
|
ConfigFile conf;
|
||||||
unsigned int loadFlag = 0;
|
unsigned int loadFlag = 0;
|
||||||
@@ -22,9 +22,11 @@ ConfigFile ConfigFile::Load()
|
|||||||
std::string* s;
|
std::string* s;
|
||||||
bool* b;
|
bool* b;
|
||||||
|
|
||||||
std::ifstream file("makegen.conf");
|
std::ifstream file(filename);
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
|
if(file.is_open())
|
||||||
|
{
|
||||||
while(std::getline(file,line))
|
while(std::getline(file,line))
|
||||||
{
|
{
|
||||||
if(line[0]=='#')
|
if(line[0]=='#')
|
||||||
@@ -111,6 +113,7 @@ ConfigFile ConfigFile::Load()
|
|||||||
}
|
}
|
||||||
return conf;
|
return conf;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ConfigFile::InputMultiple(const std::string& inputText, std::vector<std::string>& vec, bool needEnding)
|
void ConfigFile::InputMultiple(const std::string& inputText, std::vector<std::string>& vec, bool needEnding)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ class ConfigFile
|
|||||||
ConfigFile();
|
ConfigFile();
|
||||||
void Save() const;
|
void Save() const;
|
||||||
static ConfigFile Gen();
|
static ConfigFile Gen();
|
||||||
static ConfigFile Load();
|
static ConfigFile Load(const std::string& filename);
|
||||||
private:
|
private:
|
||||||
static void InputMultiple(const std::string& inputText, std::vector<std::string>& vec, bool needEnding);
|
static void InputMultiple(const std::string& inputText, std::vector<std::string>& vec, bool needEnding);
|
||||||
};
|
};
|
||||||
|
|||||||
+33
-12
@@ -11,10 +11,38 @@
|
|||||||
#include "Makefile.h"
|
#include "Makefile.h"
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
|
|
||||||
void GenMakefile()
|
void PrintHelp()
|
||||||
{
|
{
|
||||||
ConfigFile conf = ConfigFile::Load();
|
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);
|
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)
|
unsigned int ReadFlags(int argc, char** argv)
|
||||||
@@ -50,15 +78,7 @@ int main(int argc, char** argv)
|
|||||||
unsigned int flags = ReadFlags(argc,argv);
|
unsigned int flags = ReadFlags(argc,argv);
|
||||||
if(flags & FLAG_HELP)
|
if(flags & FLAG_HELP)
|
||||||
{
|
{
|
||||||
LOG_INFO("Usage: makegen [options]");
|
PrintHelp();
|
||||||
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");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(flags & FLAG_VERSION)
|
if(flags & FLAG_VERSION)
|
||||||
@@ -73,7 +93,8 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
LOG_INFO("Generating Makefile...");
|
LOG_INFO("Generating Makefile...");
|
||||||
Timer timer;
|
Timer timer;
|
||||||
GenMakefile();
|
if(!GenMakefile())
|
||||||
|
return 1;
|
||||||
LOG_INFO("Took ", round(timer.Elapsed()*1000.0)/1000.0,"s");
|
LOG_INFO("Took ", round(timer.Elapsed()*1000.0)/1000.0,"s");
|
||||||
LOG_INFO("Running Makefile...");
|
LOG_INFO("Running Makefile...");
|
||||||
for(int i = 1;i<argc;i++)
|
for(int i = 1;i<argc;i++)
|
||||||
|
|||||||
Reference in New Issue
Block a user