summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/core/core.vcxproj1
-rw-r--r--source/core/core.vcxproj.filters3
-rw-r--r--source/core/slang-cpp-compiler.h71
-rw-r--r--source/core/slang-string-util.cpp24
-rw-r--r--source/core/slang-string-util.h3
-rw-r--r--source/core/unix/slang-unix-cpp-compiler-util.cpp163
-rw-r--r--source/core/unix/slang-unix-cpp-compiler-util.h24
-rw-r--r--source/core/unix/slang-unix-process-util.cpp4
-rw-r--r--source/core/windows/slang-win-visual-studio-util.h43
-rw-r--r--tests/cross-compile/c-compile.c2
-rw-r--r--tools/slang-test/slang-test-main.cpp57
11 files changed, 328 insertions, 67 deletions
diff --git a/source/core/core.vcxproj b/source/core/core.vcxproj
index 684b5592c..a855630c2 100644
--- a/source/core/core.vcxproj
+++ b/source/core/core.vcxproj
@@ -176,6 +176,7 @@
<ClInclude Include="slang-basic.h" />
<ClInclude Include="slang-byte-encode-util.h" />
<ClInclude Include="slang-common.h" />
+ <ClInclude Include="slang-cpp-compiler.h" />
<ClInclude Include="slang-dictionary.h" />
<ClInclude Include="slang-exception.h" />
<ClInclude Include="slang-free-list.h" />
diff --git a/source/core/core.vcxproj.filters b/source/core/core.vcxproj.filters
index eec57c50b..df83072f8 100644
--- a/source/core/core.vcxproj.filters
+++ b/source/core/core.vcxproj.filters
@@ -27,6 +27,9 @@
<ClInclude Include="slang-common.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-cpp-compiler.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="slang-dictionary.h">
<Filter>Header Files</Filter>
</ClInclude>
diff --git a/source/core/slang-cpp-compiler.h b/source/core/slang-cpp-compiler.h
new file mode 100644
index 000000000..644d3d85b
--- /dev/null
+++ b/source/core/slang-cpp-compiler.h
@@ -0,0 +1,71 @@
+#ifndef SLANG_CPP_COMPILER_H
+#define SLANG_CPP_COMPILER_H
+
+#include "slang-common.h"
+#include "slang-string.h"
+
+namespace Slang
+{
+
+class CPPCompiler
+{
+public:
+ enum class Type
+ {
+ VisualStudio,
+ GCC,
+ Clang,
+ };
+
+ struct Version
+ {
+ Type type; ///< The compiler type
+ Int major; ///< The major version number
+ Int minor; ///< The minor version number
+ };
+};
+
+struct CPPCompileOptions
+{
+ enum class OptimizationLevel
+ {
+ Normal, ///< Normal optimization
+ Debug, ///< General has no optimizations
+ };
+
+ enum DebugInfoType
+ {
+ None, ///< Binary has no debug information
+ Maximum, ///< Has maximum debug information
+ Normal, ///< Has normal debug information
+ };
+ enum TargetType
+ {
+ Executable, ///< Produce an executable
+ SharedLibrary, ///< Produce a shared library object/dll
+ Object, ///< Produce an object file
+ };
+
+ struct Define
+ {
+ String nameWithSig; ///< If macro takes parameters include in brackets
+ String value;
+ };
+
+ OptimizationLevel optimizationLevel = OptimizationLevel::Debug;
+ DebugInfoType debugInfoType = DebugInfoType::Normal;
+ TargetType targetType = TargetType::Executable;
+
+ String modulePath; ///< The path/name of the output module. Should not have the extension, as that will be added for each of the target types
+
+ List<Define> defines;
+
+ List<String> sourceFiles;
+
+ List<String> includePaths;
+ List<String> libraryPaths;
+};
+
+}
+
+#endif
diff --git a/source/core/slang-string-util.cpp b/source/core/slang-string-util.cpp
index e571bbc99..60ebc45ba 100644
--- a/source/core/slang-string-util.cpp
+++ b/source/core/slang-string-util.cpp
@@ -243,4 +243,28 @@ ComPtr<ISlangBlob> StringUtil::createStringBlob(const String& string)
}
}
+/* static */bool StringUtil::areLinesEqual(const UnownedStringSlice& a, const UnownedStringSlice& b)
+{
+ List<UnownedStringSlice> slicesA;
+ List<UnownedStringSlice> slicesB;
+
+ calcLines(a, slicesA);
+ calcLines(b, slicesB);
+
+ const auto linesCount = slicesA.getCount();
+ if (linesCount != slicesB.getCount())
+ {
+ return false;
+ }
+
+ for (Index i = 0; i < linesCount; ++i)
+ {
+ if (slicesA[i] != slicesB[i])
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace Slang
diff --git a/source/core/slang-string-util.h b/source/core/slang-string-util.h
index dc0d7e546..6a3b60240 100644
--- a/source/core/slang-string-util.h
+++ b/source/core/slang-string-util.h
@@ -80,6 +80,9 @@ struct StringUtil
/// Given text, splits into lines stored in outLines. NOTE! That lines is only valid as long as textIn remains valid
static void calcLines(const UnownedStringSlice& textIn, List<UnownedStringSlice>& lines);
+
+ /// Equal if the lines are equal (in effect a way to ignore differences in line breaks)
+ static bool areLinesEqual(const UnownedStringSlice& a, const UnownedStringSlice& b);
};
} // namespace Slang
diff --git a/source/core/unix/slang-unix-cpp-compiler-util.cpp b/source/core/unix/slang-unix-cpp-compiler-util.cpp
new file mode 100644
index 000000000..a5459b665
--- /dev/null
+++ b/source/core/unix/slang-unix-cpp-compiler-util.cpp
@@ -0,0 +1,163 @@
+#include "slang-unix-cpp-compiler-util.h"
+
+#include "../slang-common.h"
+#include "../slang-process-util.h"
+#include "../slang-string-util.h"
+
+#include "../slang-shared-library.h"
+
+#include "../slang-io.h"
+
+// The method used to invoke VS was originally inspired by some ideas in
+// https://github.com/RuntimeCompiledCPlusPlus/RuntimeCompiledCPlusPlus/
+
+namespace Slang {
+
+
+/* static */void UnixCPPCompilerUtil::calcArgs(const CPPCompileOptions& options, CommandLine& cmdLine)
+{
+ typedef CPPCompileOptions::OptimizationLevel OptimizationLevel;
+ typedef CPPCompileOptions::TargetType TargetType;
+ typedef CPPCompileOptions::DebugInfoType DebugInfoType;
+
+ 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 */SlangResult UnixCPPCompilerUtil::executeCompiler(const CommandLine& commandLine, ExecuteResult& outResult)
+{
+ CommandLine cmdLine;
+ // We'll assume g++ for now
+ cmdLine.setExecutableFilename("g++");
+
+ // Append the command line options
+ cmdLine.addArgs(commandLine.m_args.getBuffer(), commandLine.m_args.getCount());
+
+#if 0
+ // Test
+ {
+ String line = ProcessUtil::getCommandLineString(cmdLine);
+ printf("%s", line.getBuffer());
+ }
+#endif
+
+ return ProcessUtil::execute(cmdLine, outResult);
+}
+
+} // namespace Slang
diff --git a/source/core/unix/slang-unix-cpp-compiler-util.h b/source/core/unix/slang-unix-cpp-compiler-util.h
new file mode 100644
index 000000000..03c1b5e2e
--- /dev/null
+++ b/source/core/unix/slang-unix-cpp-compiler-util.h
@@ -0,0 +1,24 @@
+#ifndef SLANG_UNIX_CPP_COMPILER_UTIL_H
+#define SLANG_UNIX_CPP_COMPILER_UTIL_H
+
+#include "../slang-list.h"
+#include "../slang-string.h"
+
+#include "../slang-process-util.h"
+
+#include "../slang-cpp-compiler.h"
+
+namespace Slang {
+
+struct UnixCPPCompilerUtil
+{
+ /// Run compiler with command line (typically generated by calcArgs). Output placed in outResult.
+ static SlangResult executeCompiler(const CommandLine& commandLine, ExecuteResult& outResult);
+
+ /// Calculate the command line args
+ static void calcArgs(const CPPCompileOptions& options, CommandLine& cmdLine);
+};
+
+} // namespace Slang
+
+#endif
diff --git a/source/core/unix/slang-unix-process-util.cpp b/source/core/unix/slang-unix-process-util.cpp
index 0447dd499..400f4f773 100644
--- a/source/core/unix/slang-unix-process-util.cpp
+++ b/source/core/unix/slang-unix-process-util.cpp
@@ -20,7 +20,11 @@ namespace Slang {
/* static */UnownedStringSlice ProcessUtil::getExecutableSuffix()
{
+#if __CYGWIN__
+ return UnownedStringSlice::fromLiteral(".exe");
+#else
return UnownedStringSlice::fromLiteral("");
+#endif
}
/* static */void ProcessUtil::appendCommandLineEscaped(const UnownedStringSlice& slice, StringBuilder& out)
diff --git a/source/core/windows/slang-win-visual-studio-util.h b/source/core/windows/slang-win-visual-studio-util.h
index fefb9ad0f..e8afbf418 100644
--- a/source/core/windows/slang-win-visual-studio-util.h
+++ b/source/core/windows/slang-win-visual-studio-util.h
@@ -6,48 +6,9 @@
#include "../slang-process-util.h"
-namespace Slang {
-
-struct CPPCompileOptions
-{
- enum class OptimizationLevel
- {
- Normal, ///< Normal optimization
- Debug, ///< General has no optimizations
- };
-
- enum DebugInfoType
- {
- None, ///< Binary has no debug information
- Maximum, ///< Has maximum debug information
- Normal, ///< Has normal debug information
- };
- enum TargetType
- {
- Executable, ///< Produce an executable
- SharedLibrary, ///< Produce a shared library object/dll
- Object, ///< Produce an object file
- };
+#include "../slang-cpp-compiler.h"
- struct Define
- {
- String nameWithSig; ///< If macro takes parameters include in brackets
- String value;
- };
-
- OptimizationLevel optimizationLevel = OptimizationLevel::Debug;
- DebugInfoType debugInfoType = DebugInfoType::Normal;
- TargetType targetType = TargetType::Executable;
-
- String modulePath; ///< The path/name of the output module. Should not have the extension, as that will be added for each of the target types
-
- List<Define> defines;
-
- List<String> sourceFiles;
-
- List<String> includePaths;
- List<String> libraryPaths;
-};
+namespace Slang {
struct WinVisualStudioUtil
{
diff --git a/tests/cross-compile/c-compile.c b/tests/cross-compile/c-compile.c
index 775d7b9d3..2151f7474 100644
--- a/tests/cross-compile/c-compile.c
+++ b/tests/cross-compile/c-compile.c
@@ -1,4 +1,4 @@
-//TEST:EXECUTE_C:
+//TEST(smoke):EXECUTE_C:
#include <stdlib.h>
#include <stdio.h>
diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp
index 96e5565fe..912d13b78 100644
--- a/tools/slang-test/slang-test-main.cpp
+++ b/tools/slang-test/slang-test-main.cpp
@@ -18,8 +18,12 @@ using namespace Slang;
#include "options.h"
#include "slangc-tool.h"
+#include "../../source/core/slang-cpp-compiler.h"
+
#ifdef _WIN32
# include "../../source/core/windows/slang-win-visual-studio-util.h"
+#else
+# include "../../source/core/unix/slang-unix-cpp-compiler-util.h"
#endif
#include "../../source/core/slang-process-util.h"
@@ -1090,7 +1094,6 @@ String getExpectedOutput(String const& outputStem)
static TestResult runExecuteC(TestContext* context, TestInput& input)
{
-#ifdef _WIN32
// If we are just collecting requirements, say it passed
if (context->isCollectingRequirements())
{
@@ -1100,6 +1103,21 @@ static TestResult runExecuteC(TestContext* context, TestInput& input)
auto filePath = input.filePath;
auto outputStem = input.outputStem;
+ // Make the module name the same as the source file
+ String directory = Path::getParentDirectory(input.outputStem);
+ String moduleName = Path::getFileNameWithoutExt(filePath);
+
+ String modulePath = Path::combine(directory, moduleName);
+
+ CPPCompileOptions options;
+
+ // Compile this source
+ options.sourceFiles.add(filePath);
+ options.modulePath = modulePath;
+
+ ExecuteResult exeRes;
+
+#ifdef _WIN32
// Find
List<WinVisualStudioUtil::VersionPath> versionPaths;
WinVisualStudioUtil::find(versionPaths);
@@ -1110,30 +1128,22 @@ static TestResult runExecuteC(TestContext* context, TestInput& input)
return TestResult::Ignored;
}
- // Make the module name the same as the source file
- String directory = Path::getParentDirectory(input.outputStem);
- String moduleName = Path::getFileNameWithoutExt(filePath);
-
- String modulePath = Path::combine(directory, moduleName);
+ CommandLine cmdLine;
+ WinVisualStudioUtil::calcArgs(options, cmdLine);
+ if (SLANG_FAILED(WinVisualStudioUtil::executeCompiler(versionPaths[0], cmdLine, exeRes)))
{
- CPPCompileOptions options;
-
- // Compile this source
- options.sourceFiles.add(filePath);
- options.modulePath = modulePath;
-
- CommandLine cmdLine;
- WinVisualStudioUtil::calcArgs(options, cmdLine);
-
- options.modulePath = moduleName;
+ return TestResult::Fail;
+ }
+#else
+ CommandLine cmdLine;
+ UnixCPPCompilerUtil::calcArgs(options, cmdLine);
- ExecuteResult exeRes;
- if (SLANG_FAILED(WinVisualStudioUtil::executeCompiler(versionPaths[0], cmdLine, exeRes)))
- {
- return TestResult::Fail;
- }
+ if (SLANG_FAILED(UnixCPPCompilerUtil::executeCompiler(cmdLine, exeRes)))
+ {
+ return TestResult::Fail;
}
+#endif
// Execute the binary and see what we get
{
@@ -1167,7 +1177,7 @@ static TestResult runExecuteC(TestContext* context, TestInput& input)
}
// Compare if they are the same
- if (actualOutput != expectedOutput)
+ if (!StringUtil::areLinesEqual(actualOutput.getUnownedSlice(), expectedOutput.getUnownedSlice()))
{
context->reporter->dumpOutputDifference(expectedOutput, actualOutput);
return TestResult::Fail;
@@ -1175,9 +1185,6 @@ static TestResult runExecuteC(TestContext* context, TestInput& input)
}
return TestResult::Pass;
-#else
- return TestResult::Ignored;
-#endif
}
TestResult runCrossCompilerTest(TestContext* context, TestInput& input)