From 0bb8fff4d481f5076639d28b55daf76dd2b2ea0f Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 7 Jan 2018 12:04:20 +0100 Subject: Add c/c++ language version option, compile c/cc files with c compiler --- backend/ninja/Ninja.cpp | 129 +++++++++++++++++++++++++++++++++++++++++------- include/Conf.hpp | 32 +++++++++++- packages.json | 7 --- src/Conf.cpp | 76 ++++++++++++++++++++++++++++ 4 files changed, 219 insertions(+), 25 deletions(-) delete mode 100644 packages.json diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp index 4e94fcf..6d871fd 100644 --- a/backend/ninja/Ninja.cpp +++ b/backend/ninja/Ninja.cpp @@ -159,6 +159,57 @@ namespace backend } return result; } + + string getLanguageVersionFlag(Compiler compiler, CVersion cVersion) + { + switch (compiler) + { + case Compiler::GCC: + { + switch(cVersion) + { + case CVersion::C89: return "-std=c89 -pedantic"; + case CVersion::C99: return "-std=c99 -pedantic"; + case CVersion::C11: return "-std=c11 -pedantic"; + } + } + case Compiler::MSVC: + { + // TODO: Is it possible to specify c version in msvc? + return ""; + } + } + assert(false); + return ""; + } + + string getLanguageVersionFlag(Compiler compiler, CPPVersion cppVersion) + { + switch (compiler) + { + case Compiler::GCC: + { + switch(cppVersion) + { + case CPPVersion::CPP11: return "-std=c++11 -pedantic"; + case CPPVersion::CPP14: return "-std=c++14 -pedantic"; + case CPPVersion::CPP17: return "-std=c++17 -pedantic"; + } + } + case Compiler::MSVC: + { + switch(cppVersion) + { + // Use /Za flag? + case CPPVersion::CPP11: return "/std=c++11"; + case CPPVersion::CPP14: return "/std=c++14"; + case CPPVersion::CPP17: return "/std=c++17"; + } + } + } + assert(false); + return ""; + } const char* getObjectFileExtension(Compiler compiler) { @@ -296,6 +347,12 @@ namespace backend return GlobalLib::getLibs(globalLibDependencies, config, globalLibDir, staticLinkerFlagCallbackFunc, dynamicLinkerFlagCallback, globalIncludeDirCallback); } + + enum class SourceFileLanguage + { + C, + CPP + }; Result Ninja::build(const SibsConfig &config, const _tinydir_char_t *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback) { @@ -429,17 +486,6 @@ namespace backend } #endif - string compilerName; - switch (config.getCompiler()) - { - case Compiler::GCC: - compilerName = "ccache c++"; - break; - case Compiler::MSVC: - compilerName = "cl.exe"; - break; - } - string buildJob; switch(libraryType) { @@ -454,6 +500,9 @@ namespace backend result += "rule cpp_BUILD_EXEC\n"; result += " command = ccache c++ $ARGS -o $out $in $LINK_ARGS $aliasing\n\n"; + + result += "rule c_COMPILER\n"; + result += " command = ccache cc $ARGS -c $in -o $out\n\n"; break; } case Compiler::MSVC: @@ -463,6 +512,9 @@ namespace backend result += "rule cpp_BUILD_EXEC\n"; result += " command = cl.exe $ARGS $in /Fe$out $LINK_ARGS\n\n"; + + result += "rule c_COMPILER\n"; + result += " command = cl.exe $ARGS /c $in /Fo$out\n\n"; break; } } @@ -484,6 +536,9 @@ namespace backend result += config.getPackageName(); result += ".a"; result += " $in\n\n"; + + result += "rule c_COMPILER\n"; + result += " command = ccache cc $ARGS -c -fPIC $in -o $out\n\n"; break; } case Compiler::MSVC: @@ -493,6 +548,9 @@ namespace backend result += "rule cpp_BUILD_STATIC\n"; result += " command = lib.exe /OUT:$out $in\n\n"; + + result += "rule c_COMPILER\n"; + result += " command = cl.exe $ARGS /c $in /Fo$out\n\n"; break; } } @@ -512,6 +570,9 @@ namespace backend // --whole-archive result += "rule cpp_BUILD_DYNAMIC\n"; result += " command = ccache c++ $in -shared -o $out $LINK_ARGS $aliasing\n\n"; + + result += "rule c_COMPILER\n"; + result += " command = ccache cc $ARGS -c -fPIC $in -o $out\n\n"; break; } case Compiler::MSVC: @@ -524,6 +585,9 @@ namespace backend result += "rule cpp_BUILD_DYNAMIC\n"; result += " command = lib.exe /OUT:$out $in\n\n"; + + result += "rule c_COMPILER\n"; + result += " command = cl.exe $ARGS /c $in /Fo$out\n\n"; break; } } @@ -580,27 +644,58 @@ namespace backend objectNames.reserve(sourceFiles.size()); for(const string &sourceFile : sourceFiles) { - string sourceFileLanguage = "c++"; - if(endsWith(sourceFile, ".c")) - sourceFileLanguage = "c"; + SourceFileLanguage sourceFileLanguage = SourceFileLanguage::CPP; + if(endsWith(sourceFile, ".c") || endsWith(sourceFile, ".cc")) + sourceFileLanguage = SourceFileLanguage::C; + + const char *buildTarget; + switch(sourceFileLanguage) + { + case SourceFileLanguage::C: + buildTarget = "c_COMPILER"; + break; + case SourceFileLanguage::CPP: + buildTarget = "cpp_COMPILER"; + break; + } + //string sourceFileEncoded = sourceFile; //replace(sourceFileEncoded, '/', '@'); string objectName = config.getPackageName() + "@exe/" + sourceFile; objectName += getObjectFileExtension(config.getCompiler()); result += "build "; result += objectName; - result += ": cpp_COMPILER ../../"; + result += ": "; + result += buildTarget; + result += " ../../"; result += sourceFile; result += "\n"; result += " ARGS = $globalIncDir "; if(!defines.empty()) result += defines; + + result += " "; + switch(sourceFileLanguage) + { + case SourceFileLanguage::C: + result += getLanguageVersionFlag(config.getCompiler(), config.getCversion()); + break; + case SourceFileLanguage::CPP: + result += getLanguageVersionFlag(config.getCompiler(), config.getCppVersion()); + break; + } + switch (config.getCompiler()) { case Compiler::GCC: { // -Werror - result += " '-I" + config.getPackageName() + "@exe' " + cflags + " '-I..' -Wall -Wextra -Werror=return-type -fexceptions -fdiagnostics-show-option '-fdiagnostics-color=always' '-pipe' '-D_FILE_OFFSET_BITS=64' '-Winvalid-pch' '-Wnon-virtual-dtor' " + optimizationFlags; + result += " '-I" + config.getPackageName() + "@exe' " + cflags + " '-I..' -Wall -Wextra -Werror=return-type -fdiagnostics-show-option '-fdiagnostics-color=always' '-pipe' '-D_FILE_OFFSET_BITS=64' '-Winvalid-pch' -fstack-protector " + optimizationFlags; + if(sourceFileLanguage == SourceFileLanguage::CPP) + { + result += " -fexceptions -Wnon-virtual-dtor"; + } + switch (config.getOptimizationLevel()) { case OPT_LEV_DEBUG: @@ -616,7 +711,7 @@ namespace backend { result += " "; result += optimizationFlags; - result += " /EHsc "; + result += " /EHsc /W3 "; result += cflags; switch (config.getOptimizationLevel()) { diff --git a/include/Conf.hpp b/include/Conf.hpp index 950b25a..3dd409d 100644 --- a/include/Conf.hpp +++ b/include/Conf.hpp @@ -110,6 +110,20 @@ namespace sibs PLATFORM_WIN64 }; + enum class CVersion + { + C89, // aka ansi + C99, + C11 + }; + + enum class CPPVersion + { + CPP11, + CPP14, + CPP17 + }; + const StringView CONFIGS[] = { "config.win32", "config.win32.static.debug", @@ -180,7 +194,9 @@ namespace sibs optimizationLevel(_optimizationLevel), finishedProcessing(false), useCmake(false), - buildTests(_buildTests) + buildTests(_buildTests), + cVersion(CVersion::C11), + cppVersion(CPPVersion::CPP11) { cmakeDirGlobal = projectPath; cmakeDirStatic = cmakeDirGlobal; @@ -313,6 +329,16 @@ namespace sibs return result; } + CVersion getCversion() const + { + return cVersion; + } + + CPPVersion getCppVersion() const + { + return cppVersion; + } + bool shouldUseCmake() const { return useCmake; @@ -342,6 +368,8 @@ namespace sibs void failInvalidFieldUnderObject(const StringView &fieldName) const; void validatePackageTypeDefined() const; private: + void parseCLang(const StringView &fieldName, const ConfigValue &fieldValue); + void parseCppLang(const StringView &fieldName, const ConfigValue &fieldValue); void parsePlatformConfigs(const StringView &fieldName, const ConfigValue &fieldValue); void parsePlatformConfig(const StringView &fieldName, const ConfigValue &fieldValue); void parsePlatformConfigStaticDebug(const StringView &fieldName, const ConfigValue &fieldValue); @@ -370,6 +398,8 @@ namespace sibs std::string cmakeArgsGlobal; std::string cmakeArgsStatic; std::string cmakeArgsDynamic; + CVersion cVersion; + CPPVersion cppVersion; bool useCmake; bool buildTests; bool finishedProcessing; diff --git a/packages.json b/packages.json deleted file mode 100644 index 3196663..0000000 --- a/packages.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "xxhash": { - "0.1.0": { - "urls": ["https://gateway.ipfs.io/ipfs/QmVJH2p3Y28iQ6te5wR6bCDnzDYzDFvEqJDuLf4Ykn2d3Z"] - } - } -} diff --git a/src/Conf.cpp b/src/Conf.cpp index f8b53e3..9f63833 100644 --- a/src/Conf.cpp +++ b/src/Conf.cpp @@ -792,6 +792,14 @@ namespace sibs { parseCmake(name, value, cmakeDirDynamic, cmakeArgsDynamic); } + else if(currentObject.equals("lang.c")) + { + parseCLang(name, value); + } + else if(currentObject.equals("lang.cpp")) + { + parseCppLang(name, value); + } else { string errMsg = "Invalid config object \""; @@ -801,6 +809,74 @@ namespace sibs } } + void SibsConfig::parseCLang(const StringView &fieldName, const ConfigValue &fieldValue) + { + if(fieldName.equals("version")) + { + // TODO: Support several versions (a list of versions where the latest possible version is used)? + if(fieldValue.isSingle()) + { + const StringView &cVersionStr = fieldValue.asSingle(); + if(cVersionStr.equals("c89") || cVersionStr.equals("ansi")) + { + cVersion = CVersion::C89; + } + else if(cVersionStr.equals("c99")) + { + cVersion = CVersion::C99; + } + else if(cVersionStr.equals("c11")) + { + cVersion = CVersion::C11; + } + else + { + string errMsg = "Expected lang.c.version to be c89, c99 or c11, was "; + errMsg += string(cVersionStr.data, cVersionStr.size); + throw ParserException(errMsg); + } + } + else + throw ParserException("Expected lang.c.version to be a single value, was a list"); + } + else + failInvalidFieldUnderObject(fieldName); + } + + void SibsConfig::parseCppLang(const StringView &fieldName, const ConfigValue &fieldValue) + { + if(fieldName.equals("version")) + { + // TODO: Support several versions (a list of versions where the latest possible version is used)? + if(fieldValue.isSingle()) + { + const StringView &cppVersionStr = fieldValue.asSingle(); + if(cppVersionStr.equals("c++11")) + { + cppVersion = CPPVersion::CPP11; + } + else if(cppVersionStr.equals("c++14")) + { + cppVersion = CPPVersion::CPP14; + } + else if(cppVersionStr.equals("c++17")) + { + cppVersion = CPPVersion::CPP17; + } + else + { + string errMsg = "Expected lang.cpp.version to be c89, c99 or c11, was "; + errMsg += string(cppVersionStr.data, cppVersionStr.size); + throw ParserException(errMsg); + } + } + else + throw ParserException("Expected lang.cpp.version to be a single value, was a list"); + } + else + failInvalidFieldUnderObject(fieldName); + } + void SibsConfig::parsePlatformConfigs(const StringView &fieldName, const ConfigValue &fieldValue) { for(int i = 0; i < NUM_CONFIGS; ++i) -- cgit v1.2.3