├── .gitignore ├── Data ├── shader.hlsl └── shader.inc ├── Example └── main.cpp ├── README.md ├── Sandworm ├── Include │ └── Sandworm.h └── Source │ └── Sandworm.cpp ├── ThirdParty └── clang │ └── readme.txt ├── genie.exe ├── genie.lua └── license.txt /.gitignore: -------------------------------------------------------------------------------- 1 | Build/ 2 | Bin/ 3 | -------------------------------------------------------------------------------- /Data/shader.hlsl: -------------------------------------------------------------------------------- 1 | #include "shader.inc" 2 | 3 | /* 4 | This is simple shader example for Sandworm preprocessor. 5 | */ 6 | float4 main(float4 v : TEXCOORD0) : SV_Target 7 | { 8 | 9 | #if (UBER_SHADER & 1) 10 | return Foo(float4 (1,1,1,ALPHA), v); 11 | #elif (UBER_SHADER & 2) 12 | return Foo(float4 (2,1,1,ALPHA), v); 13 | #elif (UBER_SHADER & 4) 14 | return Foo(float4 (4,1,1,ALPHA), v); 15 | #elif (UBER_SHADER & 8) 16 | return Foo(float4 (8,1,1,ALPHA), v); 17 | #elif (UBER_SHADER & 16) 18 | return Foo(float4 (16,1,1,ALPHA), v); 19 | #else 20 | return Foo(float4 (32,1,1,ALPHA), v); 21 | #endif 22 | } 23 | -------------------------------------------------------------------------------- /Data/shader.inc: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Some simple shader includes for sandworm preprocessor 4 | float4 Foo(float4 a, float4 b) 5 | { 6 | return a + b; 7 | } 8 | -------------------------------------------------------------------------------- /Example/main.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2017 Sergey Makeev 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | // GetFileVersionInfoSize and GetFileVersionInfo from clang 29 | #pragma comment( lib, "version.lib" ) 30 | 31 | 32 | std::string ReadFileToString(const char* name) 33 | { 34 | std::string fpath = "Data/"; 35 | fpath.append(name); 36 | std::ifstream t(fpath.c_str()); 37 | return std::string((std::istreambuf_iterator(t)), std::istreambuf_iterator()); 38 | } 39 | 40 | int main(/*int argc, char *argv[]*/) 41 | { 42 | const char* hlslName = "shader.hlsl"; 43 | std::string hlsl = ReadFileToString(hlslName); 44 | 45 | const char* headerName = "shader.inc"; 46 | std::string header = ReadFileToString(headerName); 47 | 48 | std::unique_ptr preprocessor( Sandworm::Preprocessor::Create() ); 49 | 50 | preprocessor->AddFile(hlslName, hlsl.c_str()); 51 | preprocessor->AddFile(headerName, header.c_str()); 52 | 53 | const char* macro[] = { "UBER_SHADER=3", "ALPHA=2.0f" }; 54 | 55 | std::unique_ptr result( preprocessor->DoPreprocess(hlslName, ¯o[0], 2) ); 56 | 57 | if (!result || result->GetErrorsCount() > 0) 58 | { 59 | printf("ERROR list:\n"); 60 | for (uint32_t i = 0; i < result->GetErrorsCount(); i++) 61 | { 62 | printf("Error : %s\n", result->GetErrorString(i)); 63 | } 64 | return -1; 65 | } 66 | 67 | if (result->GetWarningsCount() > 0) 68 | { 69 | printf("Warning list:\n"); 70 | for (uint32_t i = 0; i < result->GetWarningsCount(); i++) 71 | { 72 | printf("Warning : %s\n", result->GetWarningString(i)); 73 | } 74 | } 75 | 76 | printf("%s\n", result->GetResult()); 77 | return 0; 78 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Sandworm 2 | Sandworm is an embeddable preprocessor based on clang. 3 | Created to compile ubershaders, but can preprocess anything you like. 4 | 5 | Compiles and runs on MSVC 2015 but in theory can be used on any platform that supports clang. 6 | 7 | The clang preprocessor supports expression evaluation and integer arithmetic, so it is much more powerful than the default preprocessor for HLSL. 8 | 9 | See Example for usage example. 10 | 11 | -------------------------------------------------------------------------------- /Sandworm/Include/Sandworm.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2017 Sergey Makeev 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | #pragma once 23 | 24 | #include 25 | 26 | namespace Sandworm 27 | { 28 | struct Preprocessor 29 | { 30 | struct Result 31 | { 32 | virtual ~Result() {} 33 | virtual const char* GetResult() const = 0; 34 | virtual uint32_t GetWarningsCount() const = 0; 35 | virtual const char* GetWarningString(uint32_t warningIndex) const = 0; 36 | virtual uint32_t GetErrorsCount() const = 0; 37 | virtual const char* GetErrorString(uint32_t errorIndex) const = 0; 38 | 39 | //static Result* Create(); 40 | static void Destroy(Result* p); 41 | }; 42 | 43 | virtual ~Preprocessor() {} 44 | 45 | virtual void AddFile(const char* fileName, const char* fileContent) = 0; 46 | virtual Result* DoPreprocess(const char* fileName, const char** pDefines, uint32_t definesCount) = 0; 47 | 48 | static Preprocessor* Create(); 49 | static void Destroy(Preprocessor* p); 50 | }; 51 | 52 | struct PreprocessorDeleter { 53 | void operator()(Preprocessor* p) { Preprocessor::Destroy(p); } 54 | }; 55 | 56 | struct ResultDeleter { 57 | void operator()(Preprocessor::Result* p) { Preprocessor::Result::Destroy(p); } 58 | }; 59 | 60 | } 61 | 62 | -------------------------------------------------------------------------------- /Sandworm/Source/Sandworm.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2017 Sergey Makeev 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | #include 23 | #include 24 | 25 | #pragma warning( push ) 26 | #pragma warning( disable : 4141 ) // warning C4141: 'inline': used more than once 27 | #pragma warning( disable : 4146 ) // warning C4146: unary minus operator applied to unsigned type, result still unsigned 28 | #pragma warning( disable : 4244 ) // warning C4244: 'argument': conversion from 'uint64_t' to '::size_t', possible loss of data 29 | #pragma warning( disable : 4996 ) // warning C4996: 'std::copy::_Unchecked_iterators::_Deprecate': Call to 'std::copy' with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators' 30 | 31 | #include "clang/Frontend/PreprocessorOutputOptions.h" 32 | #include "clang/Frontend/Utils.h" 33 | #include "clang/Frontend/CompilerInstance.h" 34 | #include "clang/Frontend/FrontendActions.h" 35 | #include "clang/Basic/TargetInfo.h" 36 | #include "clang/Basic/DiagnosticOptions.h" 37 | #include "clang/Tooling/Tooling.h" 38 | #include "clang/Lex/PPCallbacks.h" 39 | #include "clang/Lex/Pragma.h" 40 | #include "llvm/ADT/SmallString.h" 41 | #include "clang/Lex/Preprocessor.h" 42 | #include "clang/Lex/PreprocessorOptions.h" 43 | 44 | #pragma warning( pop ) 45 | 46 | 47 | 48 | #pragma comment( lib, "clangFrontend.lib" ) 49 | #pragma comment( lib, "clangBasic.lib" ) 50 | #pragma comment( lib, "clangLex.lib" ) 51 | #pragma comment( lib, "clangSema.lib" ) 52 | #pragma comment( lib, "clangAST.lib" ) 53 | #pragma comment( lib, "clangSerialization.lib" ) 54 | #pragma comment( lib, "clangParse.lib" ) 55 | #pragma comment( lib, "clangDriver.lib" ) 56 | #pragma comment( lib, "clangEdit.lib" ) 57 | #pragma comment( lib, "clangAnalysis.lib" ) 58 | 59 | #pragma comment( lib, "LLVMBinaryFormat.lib" ) 60 | #pragma comment( lib, "LLVMCore.lib" ) 61 | #pragma comment( lib, "LLVMSupport.lib" ) 62 | #pragma comment( lib, "LLVMMC.lib" ) 63 | #pragma comment( lib, "LLVMBitReader.lib" ) 64 | #pragma comment( lib, "LLVMMCParser.lib" ) 65 | #pragma comment( lib, "LLVMOption.lib" ) 66 | #pragma comment( lib, "LLVMProfileData.lib" ) 67 | 68 | 69 | //#pragma comment( lib, "Mincore.lib" ) 70 | 71 | 72 | #define SOURCE_FILES_ROOT "sandworm" 73 | 74 | namespace Sandworm 75 | { 76 | 77 | 78 | class ResultImpl : public Preprocessor::Result 79 | { 80 | std::string results; 81 | std::vector warnings; 82 | std::vector errors; 83 | 84 | public: 85 | 86 | ResultImpl() 87 | { 88 | } 89 | 90 | virtual ~ResultImpl() 91 | { 92 | } 93 | 94 | virtual const char* GetResult() const override 95 | { 96 | return results.c_str(); 97 | } 98 | 99 | virtual uint32_t GetWarningsCount() const override 100 | { 101 | return (uint32_t)warnings.size(); 102 | } 103 | 104 | virtual const char* GetWarningString(uint32_t warningIndex) const override 105 | { 106 | return warnings[warningIndex].c_str(); 107 | } 108 | 109 | virtual uint32_t GetErrorsCount() const override 110 | { 111 | return (uint32_t)errors.size(); 112 | } 113 | 114 | virtual const char* GetErrorString(uint32_t errorIndex) const override 115 | { 116 | return errors[errorIndex].c_str(); 117 | } 118 | 119 | std::string& GetMutableResultString() 120 | { 121 | return results; 122 | } 123 | 124 | void AddError(const char* desc) 125 | { 126 | errors.push_back(desc); 127 | } 128 | 129 | void AddWarning(const char* desc) 130 | { 131 | warnings.push_back(desc); 132 | } 133 | 134 | 135 | static ResultImpl* Create() 136 | { 137 | return new ResultImpl(); 138 | } 139 | }; 140 | 141 | 142 | void Preprocessor::Result::Destroy(Preprocessor::Result* p) 143 | { 144 | delete p; 145 | } 146 | 147 | 148 | class PreprocessorImpl : public Preprocessor 149 | { 150 | class CLangDiagnostic : public clang::DiagnosticConsumer 151 | { 152 | PreprocessorImpl* preprocessor; 153 | int errorsCount; 154 | int warningsCount; 155 | 156 | public: 157 | 158 | CLangDiagnostic(PreprocessorImpl* _preprocessor) 159 | : preprocessor(_preprocessor) 160 | { 161 | ResetErrorsCounter(); 162 | } 163 | 164 | virtual void BeginSourceFile(const clang::LangOptions &LangOpts, const clang::Preprocessor *PP = 0) override 165 | { 166 | } 167 | 168 | virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level Level, const clang::Diagnostic &Info) override 169 | { 170 | if (Level == clang::DiagnosticsEngine::Warning) 171 | { 172 | warningsCount++; 173 | } 174 | else 175 | { 176 | if (Level >= clang::DiagnosticsEngine::Error) 177 | { 178 | errorsCount++; 179 | } 180 | } 181 | 182 | const clang::SourceManager& sm = Info.getSourceManager(); 183 | 184 | clang::SmallString<4096> messageStr; 185 | Info.FormatDiagnostic(messageStr); 186 | const clang::SourceLocation& sourceLocation = Info.getLocation(); 187 | messageStr.append(" ("); 188 | messageStr.append(sourceLocation.printToString(sm)); 189 | messageStr.append(")"); 190 | preprocessor->ReportError(Level, messageStr.c_str()); 191 | } 192 | 193 | void ResetErrorsCounter() 194 | { 195 | errorsCount = 0; 196 | warningsCount = 0; 197 | } 198 | 199 | bool HaveErrors() const 200 | { 201 | return errorsCount > 0; 202 | } 203 | 204 | bool HaveWarinngs() const 205 | { 206 | return warningsCount > 0; 207 | } 208 | }; 209 | 210 | class CLangDependencyGraphCallback : public clang::PPCallbacks 211 | { 212 | std::set* includes; 213 | 214 | public: 215 | 216 | CLangDependencyGraphCallback() 217 | : includes(nullptr) 218 | { 219 | } 220 | 221 | ~CLangDependencyGraphCallback() 222 | { 223 | } 224 | 225 | void SetTarget(std::set & _includes) 226 | { 227 | includes = &_includes; 228 | } 229 | 230 | virtual void InclusionDirective(clang::SourceLocation HashLoc, 231 | const clang::Token &IncludeTok, 232 | llvm::StringRef FileName, 233 | bool IsAngled, 234 | clang::CharSourceRange FilenameRange, 235 | const clang::FileEntry *File, 236 | llvm::StringRef SearchPath, 237 | llvm::StringRef RelativePath, 238 | const clang::Module *Imported) 239 | { 240 | if (includes) 241 | { 242 | clang::SmallString<4096> dependencyFileName(FileName); 243 | const char* includedFile = dependencyFileName.c_str(); 244 | includes->insert(includedFile); 245 | } 246 | } 247 | 248 | virtual void EndOfMainFile() 249 | { 250 | } 251 | }; 252 | 253 | 254 | 255 | void Create() 256 | { 257 | diagnosticClient = new CLangDiagnostic(this); 258 | 259 | diagnosticOptions = llvm::IntrusiveRefCntPtr(new clang::DiagnosticOptions()); 260 | diagnosticOptions->setFormat(clang::DiagnosticOptions::MSVC); 261 | 262 | diagIDs = llvm::IntrusiveRefCntPtr(new clang::DiagnosticIDs()); 263 | diagnosticEngine = llvm::IntrusiveRefCntPtr(new clang::DiagnosticsEngine(diagIDs, diagnosticOptions.get(), diagnosticClient)); 264 | 265 | clang::FileSystemOptions fsOptions; 266 | fileManager = llvm::IntrusiveRefCntPtr(new clang::FileManager(fsOptions)); 267 | sourceManager = llvm::IntrusiveRefCntPtr(new clang::SourceManager(*diagnosticEngine.get(), *fileManager.get())); 268 | 269 | std::shared_ptr options(new clang::TargetOptions()); 270 | options->Triple = "x86_64"; 271 | target = llvm::IntrusiveRefCntPtr(clang::TargetInfo::CreateTargetInfo(*diagnosticEngine.get(), options)); 272 | 273 | compiler.setDiagnostics(diagnosticEngine.get()); 274 | compiler.setFileManager(fileManager.get()); 275 | compiler.setSourceManager(sourceManager.get()); 276 | compiler.setTarget(target.get()); 277 | 278 | clang::LangOptions& languageOpts = compiler.getLangOpts(); 279 | languageOpts.CPlusPlus = true; 280 | languageOpts.NoBuiltin = true; 281 | languageOpts.AsmPreprocessor = false; 282 | languageOpts.Modules = false; 283 | languageOpts.MicrosoftExt = true; 284 | 285 | clang::HeaderSearchOptions& hopt = compiler.getHeaderSearchOpts(); 286 | 287 | hopt.AddPath(SOURCE_FILES_ROOT, clang::frontend::Angled, false, true); 288 | hopt.AddPath(SOURCE_FILES_ROOT, clang::frontend::Quoted, false, true); 289 | hopt.UseStandardCXXIncludes = false; 290 | hopt.UseStandardSystemIncludes = false; 291 | hopt.UseBuiltinIncludes = false; 292 | hopt.Verbose = 0; 293 | } 294 | 295 | 296 | void Destroy() 297 | { 298 | diagnosticOptions.resetWithoutRelease(); 299 | diagIDs.resetWithoutRelease(); 300 | diagnosticEngine.resetWithoutRelease(); 301 | fileManager.resetWithoutRelease(); 302 | sourceManager.resetWithoutRelease(); 303 | target.resetWithoutRelease(); 304 | } 305 | 306 | 307 | 308 | public: 309 | 310 | PreprocessorImpl::PreprocessorImpl() 311 | : diagnosticClient(nullptr) 312 | , resultContext(nullptr) 313 | { 314 | Create(); 315 | } 316 | 317 | PreprocessorImpl::~PreprocessorImpl() 318 | { 319 | Destroy(); 320 | } 321 | 322 | 323 | void AdjustFileName(const char* fileName, clang::SmallString<4096>& result) 324 | { 325 | result = SOURCE_FILES_ROOT; 326 | result.append("/"); 327 | result.append(fileName); 328 | } 329 | 330 | virtual void PreprocessorImpl::AddFile(const char* fileName, const char* fileContent) override 331 | { 332 | clang::FileManager & fm = *fileManager.get(); 333 | clang::SourceManager & sm = *sourceManager.get(); 334 | 335 | std::unique_ptr fileData = llvm::MemoryBuffer::getMemBufferCopy(fileContent); 336 | // std::unique_ptr fileData3( new DebugMemoryBuffer()); 337 | 338 | clang::SmallString<4096> fullPath; 339 | AdjustFileName(fileName, fullPath); 340 | 341 | const clang::FileEntry* virtualFile = fm.getVirtualFile(fullPath, fileData->getBufferSize(), 0); 342 | sm.overrideFileContents(virtualFile, std::move(fileData)); 343 | } 344 | 345 | virtual Result* PreprocessorImpl::DoPreprocess(const char* fileName, const char** pDefines, uint32_t definesCount) override 346 | { 347 | clang::SmallString<4096> fullPath; 348 | AdjustFileName(fileName, fullPath); 349 | 350 | ResultImpl* result = ResultImpl::Create(); 351 | resultContext = result; 352 | 353 | // Find target file 354 | clang::FileManager & fm = *fileManager.get(); 355 | if (!fm.getFile(fullPath.c_str())) 356 | { 357 | clang::SmallString<4096> message; 358 | message.append("Can't find '"); 359 | message.append(fullPath); 360 | message.append("'. All filenames are Case Sensitive!"); 361 | ReportError(clang::DiagnosticsEngine::Error, message.c_str()); 362 | resultContext = nullptr; 363 | return result; 364 | } 365 | 366 | //std::unique_ptr tmp = llvm::MemoryBuffer::getMemBufferCopy(1024*1024); 367 | ///////////////////////////////////////////////////////////////////////////////////////////////// 368 | const clang::FileEntry* vf = fm.getVirtualFile(fullPath.c_str(), 1024 * 1024, 0); 369 | llvm::StringRef nm = vf->getName(); 370 | ///////////////////////////////////////////////////////////////////////////////////////////////// 371 | 372 | 373 | clang::PreprocessorOptions& opts = compiler.getPreprocessorOpts(); 374 | //opts.etailedRecord = false; 375 | opts.TokenCache.clear(); 376 | opts.Macros.clear(); 377 | opts.UsePredefines = false; 378 | opts.ObjCXXARCStandardLibrary = clang::ARCXX_nolib; 379 | for (uint32_t i = 0; i < definesCount; i++) 380 | { 381 | const char* macroDef = pDefines[i]; 382 | opts.addMacroDef(macroDef); 383 | } 384 | 385 | diagnosticClient->ResetErrorsCounter(); 386 | 387 | compiler.getSourceManager().clearIDTables(); 388 | clang::FrontendInputFile infile(fullPath.c_str(), clang::InputKind(clang::InputKind::C)); 389 | compiler.InitializeSourceManager(infile); 390 | 391 | ///////////////////////////////////////////////////////////////////////////////////////////////// 392 | clang::FileID mainId = sourceManager->getMainFileID(); 393 | 394 | bool inv = false; 395 | llvm::MemoryBuffer* fileBuffer = sourceManager->getBuffer(mainId, &inv); 396 | const char* srctxt = fileBuffer->getBufferStart(); 397 | ///////////////////////////////////////////////////////////////////////////////////////////////// 398 | 399 | compiler.createPreprocessor(clang::TU_Complete); 400 | 401 | clang::PreprocessorOutputOptions preprocessorOutOptions; 402 | preprocessorOutOptions.ShowCPP = true; 403 | preprocessorOutOptions.ShowComments = false; 404 | preprocessorOutOptions.ShowLineMarkers = true; 405 | preprocessorOutOptions.UseLineDirectives = true; 406 | preprocessorOutOptions.ShowMacroComments = false; 407 | preprocessorOutOptions.ShowMacros = false; 408 | preprocessorOutOptions.RewriteIncludes = false; 409 | 410 | clang::Preprocessor& pp = compiler.getPreprocessor(); 411 | 412 | std::unique_ptr depGraph(new CLangDependencyGraphCallback()); 413 | includes.clear(); 414 | depGraph->SetTarget(includes); 415 | compiler.getPreprocessor().addPPCallbacks(std::move(depGraph)); 416 | 417 | llvm::raw_string_ostream outputStream(result->GetMutableResultString()); 418 | 419 | clang::DoPrintPreprocessedInput(pp, &outputStream, preprocessorOutOptions); 420 | 421 | //clang::ASTReader::ClearPreprocessorHack(&pp); 422 | compiler.setPreprocessor(nullptr); 423 | resultContext = nullptr; 424 | outputStream.flush(); 425 | return result; 426 | } 427 | 428 | 429 | void ReportError(clang::DiagnosticsEngine::Level Level, const char* message) 430 | { 431 | if (!resultContext) 432 | { 433 | return; 434 | } 435 | 436 | if (Level == clang::DiagnosticIDs::Warning) 437 | { 438 | resultContext->AddWarning(message); 439 | } 440 | else if (Level >= clang::DiagnosticIDs::Error) 441 | { 442 | resultContext->AddError(message); 443 | } 444 | } 445 | 446 | 447 | private: 448 | 449 | std::set includes; 450 | CLangDiagnostic* diagnosticClient; 451 | llvm::IntrusiveRefCntPtr diagnosticOptions; 452 | llvm::IntrusiveRefCntPtr diagIDs; 453 | llvm::IntrusiveRefCntPtr diagnosticEngine; 454 | llvm::IntrusiveRefCntPtr fileManager; 455 | llvm::IntrusiveRefCntPtr sourceManager; 456 | llvm::IntrusiveRefCntPtr target; 457 | 458 | clang::CompilerInstance compiler; 459 | 460 | ResultImpl* resultContext; 461 | }; 462 | 463 | 464 | Preprocessor* Preprocessor::Create() 465 | { 466 | return new PreprocessorImpl(); 467 | } 468 | 469 | void Preprocessor::Destroy(Preprocessor* p) 470 | { 471 | delete p; 472 | } 473 | 474 | 475 | } -------------------------------------------------------------------------------- /ThirdParty/clang/readme.txt: -------------------------------------------------------------------------------- 1 | CMake from https://cmake.org/ should be installed and placed to the system PATH. 2 | 3 | 4 | 1. Download LLVM and Clang source code from 5 | http://releases.llvm.org/download.html#5.0.0 6 | 7 | Direct links 8 | http://releases.llvm.org/5.0.0/llvm-5.0.0.src.tar.xz 9 | http://releases.llvm.org/5.0.0/cfe-5.0.0.src.tar.xz 10 | 11 | 2. Unpack "cfe-5.0.0.src.tar" to "llvm-5.0.0" 12 | 13 | 3. Unpack "cfe-5.0.0.src.tar" to "llvm-5.0.0/tools/clang" 14 | 15 | 4. The directory structure should look like this: 16 | 17 | llvm-5.0.0 18 | | 19 | +- (files from "llvm-5.0.0.src.tar") 20 | | 21 | +-tools 22 | | 23 | +-clang 24 | | 25 | +- (files from "cfe-5.0.0.src.tar") 26 | 27 | 5. mkdir build 28 | 6. cd build 29 | 7. cmake ../llvm-5.0.0 30 | 8. Now open LLVM.sln and build ALL_BUILD project. 31 | -------------------------------------------------------------------------------- /genie.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SergeyMakeev/Sandworm/9dcd22fbbccc4aa052f743c887dd78d1574b3151/genie.exe -------------------------------------------------------------------------------- /genie.lua: -------------------------------------------------------------------------------- 1 | -- build script 2 | if not _ACTION then 3 | print "Sandworm buildscript. You should specify an action." 4 | os.exit(1) 5 | end 6 | 7 | solution "Sandworm" 8 | language "C++" 9 | 10 | flags { 11 | "NoManifest", 12 | "FloatFast", 13 | } 14 | 15 | buildoptions { 16 | "/wd4800", --forcing value to bool 'true' or 'false' 17 | } 18 | 19 | 20 | debugdir( "." ) 21 | 22 | defines { 23 | "_CRT_SECURE_NO_WARNINGS", 24 | "_HAS_EXCEPTIONS=0", 25 | "_SCL_SECURE=0", 26 | "_SECURE_SCL=0", 27 | } 28 | 29 | location ( "Build/" .. _ACTION ) 30 | 31 | local config_list = { 32 | "Debug", 33 | "Release", 34 | } 35 | 36 | local platform_list = { 37 | "x32", 38 | "x64", 39 | } 40 | 41 | configurations(config_list) 42 | platforms(platform_list) 43 | 44 | configuration "Debug" 45 | defines { 46 | "_DEBUG", 47 | "_CRTDBG_MAP_ALLOC" 48 | } 49 | flags { 50 | "Symbols" 51 | } 52 | 53 | libdirs { 54 | "ThirdParty/clang/build/Debug/lib/", 55 | } 56 | 57 | 58 | configuration "Release" 59 | defines { 60 | "NDEBUG", 61 | } 62 | flags { 63 | "Symbols", 64 | "OptimizeSpeed" 65 | } 66 | 67 | libdirs { 68 | "ThirdParty/clang/build/Release/lib/", 69 | } 70 | 71 | configuration "x32" 72 | flags { 73 | "EnableSSE2", 74 | } 75 | defines { 76 | "WIN32", 77 | } 78 | 79 | configuration "x64" 80 | defines { 81 | "WIN32", 82 | } 83 | 84 | -- give each configuration/platform a unique output/target directory 85 | for _, config in ipairs(config_list) do 86 | for _, plat in ipairs(platform_list) do 87 | configuration { config, plat } 88 | objdir( "Build/" .. _ACTION .. "/tmp/" .. config .. "-" .. plat ) 89 | targetdir( "Bin/" .. _ACTION .. "/" .. config .. "-" .. plat ) 90 | end 91 | end 92 | 93 | project "Sandworm" 94 | kind "StaticLib" 95 | 96 | flags { 97 | "NoPCH", 98 | } 99 | 100 | files { 101 | "Sandworm/Source/**.*", 102 | "Sandworm/Include/**.*", 103 | } 104 | 105 | includedirs { 106 | "Sandworm/Include/", 107 | "ThirdParty/clang/build/include/", 108 | "ThirdParty/Clang/build/tools/clang/include/", 109 | "ThirdParty/CLang/llvm-5.0.0/include/", 110 | "ThirdParty/CLang/llvm-5.0.0/tools/clang/include/", 111 | } 112 | 113 | project "Example" 114 | kind "ConsoleApp" 115 | 116 | flags { 117 | "NoPCH", 118 | "ExtraWarnings", 119 | } 120 | 121 | files { 122 | "Example/**.*", 123 | } 124 | 125 | includedirs { 126 | "Sandworm/Include/", 127 | } 128 | 129 | links { 130 | "Sandworm", 131 | } 132 | 133 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Sergey Makeev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | --------------------------------------------------------------------------------