summaryrefslogtreecommitdiffstats
path: root/source/core/slang-cpp-compiler.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-06-14 12:20:12 -0400
committerGitHub <noreply@github.com>2019-06-14 12:20:12 -0400
commit8c56d83506ef92b15b15bdb5969008dd69c8d2a6 (patch)
treeb58218a85c108b49c2ce74f77e1f3de8c668ef21 /source/core/slang-cpp-compiler.cpp
parent7461e95210e7420d0ddf681279813f394a6fd0d8 (diff)
CPPCompiler improvements (#984)
* Removed the need for VisualStudio specific CPPCompiler Improved the version parsing for gcc/clang Removed need for slang-unix-cpp-compiler-util.cpp/.h Remove binary before compiling in the compile c tests * Moved VisualStudio calcArgs into CPPCompilerUtil - as code is not windows specific. * Set up compile time version for gcc and clang * Fix compilation on OSX - use remove instead of unlink for file deletion. * On OSX - clang uses different string format. * Removed /bin/sh invoking as not required for OSX.
Diffstat (limited to 'source/core/slang-cpp-compiler.cpp')
-rw-r--r--source/core/slang-cpp-compiler.cpp312
1 files changed, 282 insertions, 30 deletions
diff --git a/source/core/slang-cpp-compiler.cpp b/source/core/slang-cpp-compiler.cpp
index ef679d780..4bcdd068c 100644
--- a/source/core/slang-cpp-compiler.cpp
+++ b/source/core/slang-cpp-compiler.cpp
@@ -5,10 +5,11 @@
#include "../../slang-com-helper.h"
#include "slang-string-util.h"
+#include "slang-io.h"
+#include "slang-shared-library.h"
+
#if SLANG_VC
# include "windows/slang-win-visual-studio-util.h"
-#else
-# include "unix/slang-unix-cpp-compiler-util.h"
#endif
namespace Slang
@@ -18,14 +19,12 @@ namespace Slang
SlangResult GenericCPPCompiler::compile(const CompileOptions& options, ExecuteResult& outResult)
{
- CommandLine cmdLine;
+ // Copy the command line options
+ CommandLine cmdLine(m_cmdLine);
- // Calculate the command line options
+ // Append command line args to the end of cmdLine using the target specific function for the specified options
m_func(options, cmdLine);
- // Set the executable
- cmdLine.setExecutableFilename(m_exeName);
-
#if 0
// Test
{
@@ -49,16 +48,17 @@ static bool _isWhiteSpace(char c)
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
}
-/* static */SlangResult CPPCompilerUtil::parseGccFamilyVersion(const UnownedStringSlice& text, const UnownedStringSlice& versionPrefix, CPPCompiler::Desc& outDesc)
+/* static */SlangResult CPPCompilerUtil::parseGCCFamilyVersion(const UnownedStringSlice& text, const UnownedStringSlice& prefix, CPPCompiler::Desc& outDesc)
{
List<UnownedStringSlice> lines;
StringUtil::calcLines(text, lines);
for (auto line : lines)
{
- if (String(line).startsWith(versionPrefix))
+ // TODO(JS): Ugh - having to turn into a string to do this test isn't great.
+ if (String(line).startsWith(prefix))
{
- UnownedStringSlice versionSlice(line.begin() + versionPrefix.size(), line.end());
+ UnownedStringSlice versionSlice(line.begin() + prefix.size(), line.end());
List<Int> digits;
@@ -99,7 +99,6 @@ static bool _isWhiteSpace(char c)
outDesc.majorVersion = digits[0];
outDesc.minorVersion = digits[1];
-
return SLANG_OK;
}
}
@@ -107,7 +106,7 @@ static bool _isWhiteSpace(char c)
return SLANG_FAIL;
}
-SlangResult CPPCompilerUtil::calcGccFamilyVersion(const String& exeName, const UnownedStringSlice& versionPrefix, CPPCompiler::Desc& outDesc)
+SlangResult CPPCompilerUtil::calcGCCFamilyVersion(const String& exeName, CPPCompiler::Desc& outDesc)
{
CommandLine cmdLine;
cmdLine.setExecutableFilename(exeName);
@@ -115,7 +114,258 @@ SlangResult CPPCompilerUtil::calcGccFamilyVersion(const String& exeName, const U
ExecuteResult exeRes;
SLANG_RETURN_ON_FAIL(ProcessUtil::execute(cmdLine, exeRes));
- return parseGccFamilyVersion(exeRes.standardError.getUnownedSlice(), versionPrefix, outDesc);
+
+ const UnownedStringSlice prefixes[] =
+ {
+ UnownedStringSlice::fromLiteral("clang version"),
+ UnownedStringSlice::fromLiteral("gcc version"),
+ UnownedStringSlice::fromLiteral("Apple LLVM version"),
+ };
+ const CPPCompiler::Type types[] =
+ {
+ CPPCompiler::Type::Clang,
+ CPPCompiler::Type::GCC,
+ CPPCompiler::Type::Clang,
+ };
+
+ SLANG_COMPILE_TIME_ASSERT(SLANG_COUNT_OF(prefixes) == SLANG_COUNT_OF(types));
+
+ for (Index i = 0; i < SLANG_COUNT_OF(prefixes); ++i)
+ {
+ // Set the type
+ outDesc.type = types[i];
+ // Extract the version
+ if (SLANG_SUCCEEDED(parseGCCFamilyVersion(exeRes.standardError.getUnownedSlice(), prefixes[i], outDesc)))
+ {
+ return SLANG_OK;
+ }
+ }
+ return SLANG_FAIL;
+}
+
+/* static */void CPPCompilerUtil::calcVisualStudioArgs(const CompileOptions& options, CommandLine& cmdLine)
+{
+ // https://docs.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-alphabetically?view=vs-2019
+
+ cmdLine.addArg("/nologo");
+ // Generate complete debugging information
+ cmdLine.addArg("/Zi");
+ // Display full path of source files in diagnostics
+ cmdLine.addArg("/FC");
+
+ switch (options.optimizationLevel)
+ {
+ case OptimizationLevel::Debug:
+ {
+ // No optimization
+ cmdLine.addArg("/Od");
+
+ cmdLine.addArg("/MDd");
+ break;
+ }
+ case OptimizationLevel::Normal:
+ {
+ cmdLine.addArg("/O2");
+ // Multithreaded DLL
+ cmdLine.addArg("/MD");
+ break;
+ }
+ default: break;
+ }
+
+ // /Fd - followed by name of the pdb file
+ if (options.debugInfoType != DebugInfoType::None)
+ {
+ cmdLine.addPrefixPathArg("/Fd", options.modulePath, ".pdb");
+ }
+
+ switch (options.targetType)
+ {
+ case TargetType::SharedLibrary:
+ {
+ // Create dynamic link library
+ if (options.optimizationLevel == OptimizationLevel::Debug)
+ {
+ cmdLine.addArg("/LDd");
+ }
+ else
+ {
+ cmdLine.addArg("/LD");
+ }
+
+ cmdLine.addPrefixPathArg("/Fe", options.modulePath, ".dll");
+ break;
+ }
+ case TargetType::Executable:
+ {
+ cmdLine.addPrefixPathArg("/Fe", options.modulePath, ".exe");
+ break;
+ }
+ default: break;
+ }
+
+ // Object file specify it's location - needed if we are out
+ cmdLine.addPrefixPathArg("/Fo", options.modulePath, ".obj");
+
+ // Add defines
+ for (const auto& define : options.defines)
+ {
+ StringBuilder builder;
+ builder << define.nameWithSig;
+ if (define.value.getLength())
+ {
+ builder << "=" << define.value;
+ }
+
+ cmdLine.addArg(builder);
+ }
+
+ // Add includes
+ for (const auto& include : options.includePaths)
+ {
+ cmdLine.addArg("/I");
+ cmdLine.addArg(include);
+ }
+
+ // https://docs.microsoft.com/en-us/cpp/build/reference/eh-exception-handling-model?view=vs-2019
+ // /Eha - Specifies the model of exception handling. (a, s, c, r are options)
+
+ // Files to compile
+ for (const auto& sourceFile : options.sourceFiles)
+ {
+ cmdLine.addArg(sourceFile);
+ }
+
+ // Link options (parameters past /link go to linker)
+ cmdLine.addArg("/link");
+
+ for (const auto& libPath : options.libraryPaths)
+ {
+ // Note that any escaping of the path is handled in the ProcessUtil::
+ cmdLine.addPrefixPathArg("/LIBPATH:", libPath);
+ }
+}
+
+/* static */void CPPCompilerUtil::calcGCCFamilyArgs(const CompileOptions& options, CommandLine& cmdLine)
+{
+ cmdLine.addArg("-fvisibility=hidden");
+ // Use shared libraries
+ //cmdLine.addArg("-shared");
+
+ switch (options.optimizationLevel)
+ {
+ case OptimizationLevel::Debug:
+ {
+ // No optimization
+ cmdLine.addArg("-O0");
+ break;
+ }
+ case OptimizationLevel::Normal:
+ {
+ cmdLine.addArg("-Os");
+ break;
+ }
+ default: break;
+ }
+
+ if (options.debugInfoType != DebugInfoType::None)
+ {
+ cmdLine.addArg("-g");
+ }
+
+ switch (options.targetType)
+ {
+ case TargetType::SharedLibrary:
+ {
+ // Position independent
+ cmdLine.addArg("-fPIC");
+
+ String sharedLibraryPath;
+
+ // Work out the shared library name
+ {
+ String moduleDir = Path::getParentDirectory(options.modulePath);
+ String moduleFilename = Path::getFileName(options.modulePath);
+
+ StringBuilder sharedLibraryFilename;
+ SharedLibrary::appendPlatformFileName(moduleFilename.getUnownedSlice(), sharedLibraryFilename);
+
+ if (moduleDir.getLength() > 0)
+ {
+ sharedLibraryPath = Path::combine(moduleDir, sharedLibraryFilename);
+ }
+ else
+ {
+ sharedLibraryPath = sharedLibraryFilename;
+ }
+ }
+
+ cmdLine.addArg("-o");
+ cmdLine.addArg(sharedLibraryPath);
+ break;
+ }
+ case TargetType::Executable:
+ {
+ cmdLine.addArg("-o");
+
+ StringBuilder builder;
+ builder << options.modulePath;
+ builder << ProcessUtil::getExecutableSuffix();
+
+ cmdLine.addArg(options.modulePath);
+ break;
+ }
+ case TargetType::Object:
+ {
+ // Don't link, just produce object file
+ cmdLine.addArg("-c");
+ break;
+ }
+ default: break;
+ }
+
+ // Add defines
+ for (const auto& define : options.defines)
+ {
+ StringBuilder builder;
+ builder << define.nameWithSig;
+ if (define.value.getLength())
+ {
+ builder << "=" << define.value;
+ }
+
+ cmdLine.addArg(builder);
+ }
+
+ // Add includes
+ for (const auto& include : options.includePaths)
+ {
+ cmdLine.addArg("-I");
+ cmdLine.addArg(include);
+ }
+
+ // Link options
+ if (0)
+ {
+ StringBuilder linkOptions;
+ linkOptions << "Wl,";
+ cmdLine.addArg(linkOptions);
+ }
+
+ // Files to compile
+ for (const auto& sourceFile : options.sourceFiles)
+ {
+ cmdLine.addArg(sourceFile);
+ }
+
+ for (const auto& libPath : options.libraryPaths)
+ {
+ // Note that any escaping of the path is handled in the ProcessUtil::
+ cmdLine.addArg("-L");
+ cmdLine.addArg(libPath);
+ cmdLine.addArg("-F");
+ cmdLine.addArg(libPath);
+ }
}
static CPPCompiler::Desc _calcCompiledWithDesc()
@@ -126,12 +376,16 @@ static CPPCompiler::Desc _calcCompiledWithDesc()
desc = WinVisualStudioUtil::getDesc(WinVisualStudioUtil::getCompiledVersion());
#elif SLANG_CLANG
desc.type = CPPCompiler::Type::Clang;
+ desc.majorVersion = Int(__clang_major__);
+ desc.minorVersion = Int(__clang_minor__);
#elif SLANG_SNC
desc.type = CPPCompiler::Type::SNC;
#elif SLANG_GHS
desc.type = CPPCompiler::Type::GHS;
#elif SLANG_GCC
desc.type = CPPCompiler::Type::GCC;
+ desc.majorVersion = Int(__GNUC__);
+ desc.minorVersion = Int(__GNUC_MINOR__);
#else
desc.type = CPPCompiler::Type::Unknown;
#endif
@@ -246,6 +500,19 @@ const CPPCompiler::Desc& CPPCompilerUtil::getCompiledWithDesc()
return nullptr;
}
+// Have to do this conditionally because unreferenced static functions are a warning on VC, and warnings are errors.
+#if !SLANG_WINDOWS_FAMILY
+static void _addGCCFamilyCompiler(const String& exeName, CPPCompilerSet* compilerSet)
+{
+ CPPCompiler::Desc desc;
+ if (SLANG_SUCCEEDED(CPPCompilerUtil::calcGCCFamilyVersion(exeName, desc)))
+ {
+ RefPtr<CPPCompiler> compiler(new GenericCPPCompiler(desc, exeName, &CPPCompilerUtil::calcGCCFamilyArgs));
+ compilerSet->addCompiler(compiler);
+ }
+}
+#endif
+
/* static */CPPCompiler* CPPCompilerUtil::findClosestCompiler(const CPPCompilerSet* set, const CPPCompiler::Desc& desc)
{
CPPCompiler* compiler = set->getCompiler(desc);
@@ -258,28 +525,13 @@ const CPPCompiler::Desc& CPPCompilerUtil::getCompiledWithDesc()
return findClosestCompiler(compilers, desc);
}
-
/* static */SlangResult CPPCompilerUtil::initializeSet(CPPCompilerSet* set)
{
#if SLANG_WINDOWS_FAMILY
WinVisualStudioUtil::find(set);
#else
- {
- CPPCompiler::Desc desc(CPPCompiler::Type::Clang);
- if (SLANG_SUCCEEDED(calcGccFamilyVersion("clang", UnownedStringSlice::fromLiteral("clang version"), desc)))
- {
- RefPtr<CPPCompiler> compiler(new GenericCPPCompiler(desc, "clang", &UnixCPPCompilerUtil::calcArgs));
- set->addCompiler(compiler);
- }
- }
- {
- CPPCompiler::Desc desc(CPPCompiler::Type::GCC);
- if (SLANG_SUCCEEDED(calcGccFamilyVersion("g++", UnownedStringSlice::fromLiteral("gcc version"), desc)))
- {
- RefPtr<CPPCompiler> compiler(new GenericCPPCompiler(desc, "g++", &UnixCPPCompilerUtil::calcArgs));
- set->addCompiler(compiler);
- }
- }
+ _addGCCFamilyCompiler("clang", set);
+ _addGCCFamilyCompiler("g++", set);
#endif
// Set the default to the compiler closest to how this source was compiled