From 0e1e46836d234bd59916586cf9090ceaf2b327d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Matos?= Date: Fri, 29 Sep 2023 18:34:37 +0100 Subject: [PATCH] Update to Clang 16 for MSVC 2022 support (#1724) * support clang 15.0.7 * Fix Premake archive logic to work with official releases. * Try and upgrade CI to latest OS versions. * Try and fix LLD link call in parser. * CI fixes. * Enable VS 2019 and VS 2022 for LLVM windows workflow. * Update to a more recent LLVM revision. * More build fixes. * Use the system linker for linking symbols libraries outside Windows. Builtin lld is giving some weird linking errors when linking with the new LLVM version. We probably need to set some custom options. Using the system linker should be a better idea anyway, more robust and future proof. --------- Co-authored-by: you74674 --- .github/workflows/llvm-win.yml | 6 +- .github/workflows/main.yml | 7 +- Directory.Build.props | 1 - build/LLVM.lua | 13 +- build/build.sh | 16 +- build/llvm/LLVM-commit | 2 +- build/llvm/LLVM.lua | 7 +- src/Core/Toolchains/MSVCToolchain.cs | 6 +- src/CppParser/CppParser.cpp | 2 +- src/CppParser/Link.cpp | 13 +- src/CppParser/ParseExpr.cpp | 14 +- src/CppParser/ParseStmt.cpp | 2 +- src/CppParser/Parser.cpp | 37 ++-- src/CppParser/premake5.lua | 4 + src/Generator/Driver.cs | 1 - .../Generators/CSharp/CSharpCommentPrinter.cs | 1 + src/Generator/Passes/GenerateSymbolsPass.cs | 74 ++++++-- src/Parser/LinkerOptions.cs | 158 +++++++++++++++++- src/Parser/ParserOptions.cs | 16 +- 19 files changed, 310 insertions(+), 70 deletions(-) diff --git a/.github/workflows/llvm-win.yml b/.github/workflows/llvm-win.yml index 455c4f4dcf..43b9891fba 100644 --- a/.github/workflows/llvm-win.yml +++ b/.github/workflows/llvm-win.yml @@ -9,8 +9,8 @@ jobs: fail-fast: false matrix: config: - - { os: windows-2022, platform: x86, vs: 2022 } - - { os: windows-2022, platform: x64, vs: 2022 } + - { os: windows-2022, platform: x86, vs: "Program Files/Microsoft Visual Studio/2022" } + - { os: windows-2022, platform: x64, vs: "Program Files/Microsoft Visual Studio/2022" } runs-on: ${{ matrix.config.os }} @@ -35,7 +35,7 @@ jobs: - name: Environment shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\%VS_VERSION%\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" %PLATFORM% + call "C:\%VS_VERSION%\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" %PLATFORM% :: Loop over all environment variables and make them global using set-env. :: See: https://stackoverflow.com/a/39184941 setlocal diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6756de7613..d26b7adcb0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,15 +9,16 @@ jobs: fail-fast: false matrix: config: - - { os: ubuntu-20.04, platform: x64, cxx: g++-10, cc: gcc-10 } + - { os: ubuntu-22.04, platform: x64, cxx: g++-11, cc: gcc-11 } - { os: macos-11, platform: x64, cxx: clang++, cc: clang } - - { os: windows-2019, platform: x64, vs: msvc } + - { os: windows-2022, platform: x64, vs: "Program Files/Microsoft Visual Studio/2022" } runs-on: ${{ matrix.config.os }} env: CC: ${{ matrix.config.cc }} CXX: ${{ matrix.config.cxx }} + VS_VERSION: ${{ matrix.config.vs }} PLATFORM: ${{ matrix.config.platform }} DOTNET_NOLOGO: true DOTNET_CLI_TELEMETRY_OPTOUT: true @@ -38,7 +39,7 @@ jobs: - name: Environment if: matrix.config.vs shell: bash - run: echo "/c/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/MSBuild/Current/Bin" >> $GITHUB_PATH + run: echo "/c/$VS_VERSION/Enterprise/MSBuild/Current/Bin" >> $GITHUB_PATH - name: Setup shell: bash diff --git a/Directory.Build.props b/Directory.Build.props index 3fe84b36b1..e6c25f85f5 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -52,7 +52,6 @@ - \ No newline at end of file diff --git a/build/LLVM.lua b/build/LLVM.lua index d2781b7451..86fa1be6b3 100644 --- a/build/LLVM.lua +++ b/build/LLVM.lua @@ -42,6 +42,7 @@ function SetupLLVMIncludes() includedirs { path.join(LLVMRootDirDebug, "include"), + path.join(LLVMRootDirDebug, "llvm/include"), path.join(LLVMRootDirDebug, "lld/include"), path.join(LLVMRootDirDebug, "clang/include"), path.join(LLVMRootDirDebug, "clang/lib"), @@ -53,6 +54,7 @@ function SetupLLVMIncludes() includedirs { path.join(LLVMRootDirRelease, "include"), + path.join(LLVMRootDirRelease, "llvm/include"), path.join(LLVMRootDirRelease, "lld/include"), path.join(LLVMRootDirRelease, "clang/include"), path.join(LLVMRootDirRelease, "clang/lib"), @@ -64,6 +66,7 @@ function SetupLLVMIncludes() includedirs { path.join(LLVMRootDir, "include"), + path.join(LLVMRootDir, "llvm/include"), path.join(LLVMRootDir, "lld/include"), path.join(LLVMRootDir, "clang/include"), path.join(LLVMRootDir, "clang/lib"), @@ -144,18 +147,22 @@ function SetupLLVMLibs() "clangCodeGen", "clangParse", "clangSema", + "clangSupport", "clangAnalysis", "clangEdit", "clangAST", "clangLex", "clangBasic", "clangIndex", + "clangASTMatchers", + "LLVMWindowsDriver", "LLVMWindowsManifest", "LLVMDebugInfoPDB", "LLVMLTO", "LLVMPasses", "LLVMObjCARCOpts", "LLVMLibDriver", + "LLVMFrontendHLSL", "LLVMFrontendOpenMP", "LLVMOption", "LLVMCoverage", @@ -170,6 +177,7 @@ function SetupLLVMLibs() "LLVMVectorize", "LLVMLinker", "LLVMIRReader", + "LLVMIRPrinter", "LLVMAsmParser", "LLVMMCDisassembler", "LLVMCFGuard", @@ -178,7 +186,9 @@ function SetupLLVMLibs() "LLVMAsmPrinter", "LLVMDebugInfoDWARF", "LLVMCodeGen", + "LLVMCodeGenTypes", "LLVMTarget", + "LLVMTargetParser", "LLVMScalarOpts", "LLVMInstCombine", "LLVMAggressiveInstCombine", @@ -202,7 +212,8 @@ function SetupLLVMLibs() "lldCommon", "lldCOFF", "lldELF", - "lldMachO" + "lldMachO", + "lldMinGW" } filter(c) diff --git a/build/build.sh b/build/build.sh index 6f7a086fee..5cd81557a2 100755 --- a/build/build.sh +++ b/build/build.sh @@ -2,7 +2,7 @@ set -e builddir=$(cd "$(dirname "$0")"; pwd) platform=x64 -vs=vs2019 +vs=vs2022 configuration=Release build_only=false ci=false @@ -104,18 +104,26 @@ download_premake() { premake_dir="$builddir/premake" premake_filename=premake5 + premake_archive_ext=tar.gz if [ $oshost = "windows" ]; then premake_filename=$premake_filename.exe + premake_archive_ext=zip fi premake_path=$premake_dir/$premake_filename if ! [ -f "$premake_path" ]; then echo "Downloading and unpacking Premake..." - premake_url=https://github.com/InteropAlliance/premake-core/releases/download/latest/premake-$oshost-$platform.zip + premake_version=5.0.0-beta2 + premake_archive=premake-$premake_version-$oshost.$premake_archive_ext + premake_url=https://github.com/premake/premake-core/releases/download/v$premake_version/$premake_archive curl -L -O $premake_url - unzip premake-$oshost-$platform.zip $premake_filename -d "$premake_dir" + if [ $oshost = "windows" ]; then + unzip $premake_archive $premake_filename -d "$premake_dir" + else + tar -xf $premake_archive -C "$premake_dir" ./$premake_filename + fi chmod +x "$premake_path" - rm premake-$oshost-$platform.zip + rm $premake_archive fi } diff --git a/build/llvm/LLVM-commit b/build/llvm/LLVM-commit index 8a0cb18633..1f1a216a13 100644 --- a/build/llvm/LLVM-commit +++ b/build/llvm/LLVM-commit @@ -1 +1 @@ -791523bae6153b13bb41ba05c9fc89e502cc4a1a \ No newline at end of file +6eb36aed86ea276695697093eb8136554c29286b \ No newline at end of file diff --git a/build/llvm/LLVM.lua b/build/llvm/LLVM.lua index 30a3943314..f375b39e92 100644 --- a/build/llvm/LLVM.lua +++ b/build/llvm/LLVM.lua @@ -251,6 +251,7 @@ function cmake(gen, conf, builddir, options) .. ' -DLLVM_ENABLE_LIBXML2=false' .. ' -DLLVM_ENABLE_TERMINFO=false' .. ' -DLLVM_ENABLE_ZLIB=false' + .. ' -DLLVM_ENABLE_ZSTD=false' .. ' -DLLVM_INCLUDE_DOCS=false' .. ' -DLLVM_INCLUDE_EXAMPLES=false' .. ' -DLLVM_TARGETS_TO_BUILD="X86"' @@ -370,6 +371,8 @@ function cmake(gen, conf, builddir, options) .. ' -DCLANG_TOOL_CLANG_FUZZER_BUILD=false' .. ' -DCLANG_TOOL_CLANG_IMPORT_TEST_BUILD=false' .. ' -DCLANG_TOOL_CLANG_NVLINK_WRAPPER_BUILD=false' + .. ' -DCLANG_TOOL_CLANG_LINKER_WRAPPER_BUILD=false' + .. ' -DCLANG_TOOL_CLANG_OFFLOAD_PACKAGER_BUILD=false' .. ' -DCLANG_TOOL_CLANG_OFFLOAD_BUNDLER_BUILD=false' .. ' -DCLANG_TOOL_CLANG_OFFLOAD_WRAPPER_BUILD=false' .. ' -DCLANG_TOOL_CLANG_REFACTOR_BUILD=false' @@ -456,7 +459,7 @@ function package_llvm(conf, llvm_base, llvm_build) if os.isdir(out) then os.rmdir(out) end os.mkdir(out) - os.copydir(llvm_base .. "/llvm/include", out .. "/include") + os.copydir(llvm_base .. "/llvm/include", out .. "/llvm/include") os.copydir(llvm_base .. "/lld/include", out .. "/lld/include") os.copydir(llvm_build .. "/include", out .. "/build/include") @@ -483,12 +486,10 @@ function package_llvm(conf, llvm_base, llvm_build) local out_lib_dir = out .. "/build/lib" if os.ishost("windows") then os.rmfiles(out_lib_dir, "clang*ARC*.lib") - os.rmfiles(out_lib_dir, "clang*Matchers*.lib") os.rmfiles(out_lib_dir, "clang*Rewrite*.lib") os.rmfiles(out_lib_dir, "clang*StaticAnalyzer*.lib") else os.rmfiles(out_lib_dir, "libclang*ARC*.a") - os.rmfiles(out_lib_dir, "libclang*Matchers*.a") os.rmfiles(out_lib_dir, "libclang*Rewrite*.a") os.rmfiles(out_lib_dir, "libclang*StaticAnalyzer*.a") end diff --git a/src/Core/Toolchains/MSVCToolchain.cs b/src/Core/Toolchains/MSVCToolchain.cs index 605825c31f..91964cd486 100644 --- a/src/Core/Toolchains/MSVCToolchain.cs +++ b/src/Core/Toolchains/MSVCToolchain.cs @@ -16,6 +16,7 @@ public enum VisualStudioVersion VS2015 = 14, VS2017 = 15, VS2019 = 16, + VS2022 = 17, Latest, } @@ -67,9 +68,12 @@ public static Version GetCLVersion(VisualStudioVersion vsVersion) clVersion = new Version { Major = 19, Minor = 10 }; break; case VisualStudioVersion.VS2019: - case VisualStudioVersion.Latest: clVersion = new Version { Major = 19, Minor = 20 }; break; + case VisualStudioVersion.VS2022: + case VisualStudioVersion.Latest: + clVersion = new Version { Major = 19, Minor = 30 }; + break; default: throw new Exception("Unknown Visual Studio version"); } diff --git a/src/CppParser/CppParser.cpp b/src/CppParser/CppParser.cpp index 0066458166..d6c1f7b36a 100644 --- a/src/CppParser/CppParser.cpp +++ b/src/CppParser/CppParser.cpp @@ -7,7 +7,7 @@ #include "CppParser.h" #include "Parser.h" -#include +#include #include namespace CppSharp { namespace CppParser { diff --git a/src/CppParser/Link.cpp b/src/CppParser/Link.cpp index 3514256d14..46d066218f 100644 --- a/src/CppParser/Link.cpp +++ b/src/CppParser/Link.cpp @@ -11,6 +11,11 @@ #include #include +LLD_HAS_DRIVER(coff) +LLD_HAS_DRIVER(elf) +LLD_HAS_DRIVER(mingw) +LLD_HAS_DRIVER(macho) + using namespace CppSharp::CppParser; bool Parser::Link(const std::string& File, const CppLinkerOptions* LinkerOptions) @@ -69,7 +74,7 @@ bool Parser::LinkWindows(const CppLinkerOptions* LinkerOptions, std::vector LibraryPaths; LibraryPaths.push_back("-libpath:" + TC.getSubDirectoryPath( - clang::driver::toolchains::MSVCToolChain::SubDirectoryType::Lib)); + llvm::SubDirectoryType::Lib)); std::string CRTPath; if (TC.getUniversalCRTLibraryPath(Args, CRTPath)) LibraryPaths.push_back("-libpath:" + CRTPath); @@ -100,7 +105,7 @@ bool Parser::LinkWindows(const CppLinkerOptions* LinkerOptions, std::string Out("-out:" + std::string(Output)); args.push_back(Out.data()); - return lld::coff::link(args, false, outs(), errs()); + return lld::coff::link(args, outs(), errs(), /*exitEarly=*/false, /*disableOutput=*/false); #else return false; #endif @@ -141,7 +146,7 @@ bool Parser::LinkELF(const CppLinkerOptions* LinkerOptions, std::string Out(Output); args.push_back(Out.data()); - return lld::elf::link(args, false, outs(), errs()); + return lld::elf::link(args, outs(), errs(), /*exitEarly=*/false, /*disableOutput=*/false); #else return false; #endif @@ -182,7 +187,7 @@ bool Parser::LinkMachO(const CppLinkerOptions* LinkerOptions, std::string Out(Output); args.push_back(Out.data()); - return lld::macho::link(args, false, outs(), errs()); + return lld::macho::link(args, outs(), errs(), /*exitEarly=*/false, /*disableOutput=*/false); #else return false; #endif diff --git a/src/CppParser/ParseExpr.cpp b/src/CppParser/ParseExpr.cpp index 4587d73fdd..27639a3d48 100644 --- a/src/CppParser/ParseExpr.cpp +++ b/src/CppParser/ParseExpr.cpp @@ -223,7 +223,7 @@ AST::Expr* Parser::WalkExpression(const clang::Expr* Expr) _S->length = S->getLength(); _S->charByteWidth = S->getCharByteWidth(); _S->kind = (StringLiteral::StringKind) S->getKind(); - _S->isAscii = S->isAscii(); + _S->isAscii = S->isOrdinary(); _S->isWide = S->isWide(); _S->isUTF8 = S->isUTF8(); _S->isUTF16 = S->isUTF16(); @@ -400,7 +400,7 @@ AST::Expr* Parser::WalkExpression(const clang::Expr* Expr) _S->calleeDecl = static_cast(WalkDeclaration(S->getCalleeDecl())); _S->directCallee = static_cast(WalkDeclaration(S->getDirectCallee())); _S->numArgs = S->getNumArgs(); - _S->numCommas = S->getNumCommas(); + _S->numCommas = 0; // Removed from Clang _S->builtinCallee = S->getBuiltinCallee(); _S->isCallToStdMove = S->isCallToStdMove(); for (auto _E : S->arguments()) @@ -1172,7 +1172,7 @@ AST::Expr* Parser::WalkExpression(const clang::Expr* Expr) _S->calleeDecl = static_cast(WalkDeclaration(S->getCalleeDecl())); _S->directCallee = static_cast(WalkDeclaration(S->getDirectCallee())); _S->numArgs = S->getNumArgs(); - _S->numCommas = S->getNumCommas(); + _S->numCommas = 0; // Removed from Clang _S->builtinCallee = S->getBuiltinCallee(); _S->isCallToStdMove = S->isCallToStdMove(); for (auto _E : S->arguments()) @@ -1207,7 +1207,7 @@ AST::Expr* Parser::WalkExpression(const clang::Expr* Expr) _S->calleeDecl = static_cast(WalkDeclaration(S->getCalleeDecl())); _S->directCallee = static_cast(WalkDeclaration(S->getDirectCallee())); _S->numArgs = S->getNumArgs(); - _S->numCommas = S->getNumCommas(); + _S->numCommas = 0; // Removed from Clang _S->builtinCallee = S->getBuiltinCallee(); _S->isCallToStdMove = S->isCallToStdMove(); for (auto _E : S->arguments()) @@ -1241,7 +1241,7 @@ AST::Expr* Parser::WalkExpression(const clang::Expr* Expr) _S->calleeDecl = static_cast(WalkDeclaration(S->getCalleeDecl())); _S->directCallee = static_cast(WalkDeclaration(S->getDirectCallee())); _S->numArgs = S->getNumArgs(); - _S->numCommas = S->getNumCommas(); + _S->numCommas = 0; // Removed from Clang _S->builtinCallee = S->getBuiltinCallee(); _S->isCallToStdMove = S->isCallToStdMove(); for (auto _E : S->arguments()) @@ -1391,7 +1391,7 @@ AST::Expr* Parser::WalkExpression(const clang::Expr* Expr) _S->calleeDecl = static_cast(WalkDeclaration(S->getCalleeDecl())); _S->directCallee = static_cast(WalkDeclaration(S->getDirectCallee())); _S->numArgs = S->getNumArgs(); - _S->numCommas = S->getNumCommas(); + _S->numCommas = 0; // Removed from Clang _S->builtinCallee = S->getBuiltinCallee(); _S->isCallToStdMove = S->isCallToStdMove(); for (auto _E : S->arguments()) @@ -1850,7 +1850,7 @@ AST::Expr* Parser::WalkExpression(const clang::Expr* Expr) _S->operatorDelete = static_cast(WalkDeclaration(S->getOperatorDelete())); _S->allocatedType = GetQualifiedType(S->getAllocatedType()); _S->isArray = S->isArray(); - _S->arraySize = static_cast(WalkExpression(S->getArraySize().getValue())); + _S->arraySize = static_cast(WalkExpression(S->getArraySize().value())); _S->numPlacementArgs = S->getNumPlacementArgs(); _S->isParenTypeId = S->isParenTypeId(); _S->isGlobalNew = S->isGlobalNew(); diff --git a/src/CppParser/ParseStmt.cpp b/src/CppParser/ParseStmt.cpp index 31f4703eec..c7eed096f6 100644 --- a/src/CppParser/ParseStmt.cpp +++ b/src/CppParser/ParseStmt.cpp @@ -356,7 +356,7 @@ AST::Stmt* Parser::WalkStatement(const clang::Stmt* Stmt) _S->allocate = static_cast(WalkExpression(S->getAllocate())); _S->deallocate = static_cast(WalkExpression(S->getDeallocate())); _S->returnValueInit = static_cast(WalkExpression(S->getReturnValueInit())); - _S->resultDecl = static_cast(WalkStatement(S->getResultDecl())); + _S->resultDecl = static_cast(WalkStatement(S->getReturnValue())); _S->returnStmt = static_cast(WalkStatement(S->getReturnStmt())); _S->returnStmtOnAllocFailure = static_cast(WalkStatement(S->getReturnStmtOnAllocFailure())); _Stmt = _S; diff --git a/src/CppParser/Parser.cpp b/src/CppParser/Parser.cpp index 4e55c574db..85be06a181 100644 --- a/src/CppParser/Parser.cpp +++ b/src/CppParser/Parser.cpp @@ -13,7 +13,7 @@ #include "ELFDumper.h" #include "APValuePrinter.h" -#include +#include #include #include #include @@ -880,11 +880,9 @@ static clang::CXXRecordDecl* GetCXXRecordDeclFromTemplateName(const clang::Templ switch (Name.getKind()) { case clang::TemplateName::Template: - return dyn_cast( - Name.getAsTemplateDecl()->getTemplatedDecl()); + return dyn_cast(Name.getAsTemplateDecl()->getTemplatedDecl()); case clang::TemplateName::QualifiedTemplate: - return dyn_cast( - Name.getAsQualifiedTemplateName()->getTemplateDecl()->getTemplatedDecl()); + return GetCXXRecordDeclFromTemplateName(Name.getAsQualifiedTemplateName()->getUnderlyingTemplate()); default: assert(0 && "Unknown template name kind"); return nullptr; @@ -902,7 +900,7 @@ static clang::CXXRecordDecl* GetCXXRecordDeclFromBaseType(const clang::QualType& else if (auto Injected = Ty->getAs()) return Injected->getDecl(); - assert("Could not get base CXX record from type"); + assert(0 && "Could not get base CXX record from type"); return nullptr; } @@ -2604,7 +2602,7 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, { auto TO = Type->getAs(); - Ty = WalkType(TO->getUnderlyingType()); + Ty = WalkType(TO->getUnmodifiedType()); break; } case clang::Type::TypeOfExpr: @@ -2666,8 +2664,7 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, TSTL = &TSpecTL; } - ArrayRef TSArgs(TS->getArgs(), TS->getNumArgs()); - TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TSArgs); + TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TS->template_arguments()); TST->Arguments = WalkTemplateArgumentList(&TArgs, TSTL); Ty = TST; @@ -2709,8 +2706,7 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, TSTL = &TSpecTL; } - ArrayRef TSArgs(TS->getArgs(), TS->getNumArgs()); - TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TSArgs); + TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TS->template_arguments()); TST->Arguments = WalkTemplateArgumentList(&TArgs, TSTL); Ty = TST; @@ -2773,9 +2769,9 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, auto RepTy = TP->getReplacementType(); TPT->replacement = GetQualifiedType(RepTy, &Next); TPT->replacedParameter = (TemplateParameterType*) - WalkType(clang::QualType(TP->getReplacedParameter(), 0), 0); + WalkType(c->getASTContext().getTypeDeclType(TP->getReplacedParameter()), 0); TPT->replacedParameter->parameter = WalkTypeTemplateParameter( - TP->getReplacedParameter()->getDecl()); + TP->getReplacedParameter()); Ty = TPT; break; @@ -4386,7 +4382,7 @@ void Parser::SetupLLVMCodegen() LLVMModule->setTargetTriple(c->getTarget().getTriple().getTriple()); LLVMModule->setDataLayout(c->getTarget().getDataLayoutString()); - CGM.reset(new clang::CodeGen::CodeGenModule(c->getASTContext(), + CGM.reset(new clang::CodeGen::CodeGenModule(c->getASTContext(), nullptr, c->getHeaderSearchOpts(), c->getPreprocessorOpts(), c->getCodeGenOpts(), *LLVMModule, c->getDiagnostics())); @@ -4397,10 +4393,8 @@ bool Parser::SetupSourceFiles(const std::vector& SourceFiles, std::vector& FileEntries) { // Check that the file is reachable. - const clang::DirectoryLookup *Dir; - llvm::SmallVector< - std::pair, - 0> Includers; + clang::ConstSearchDirIterator *Dir = 0; + llvm::ArrayRef> Includers; for (const auto& SourceFile : SourceFiles) { @@ -4863,8 +4857,7 @@ ParserResult* Parser::Compile(const std::string& File) const llvm::Triple Triple = c->getTarget().getTriple(); llvm::StringRef Dir(llvm::sys::path::parent_path(File)); llvm::SmallString<1024> Object(Dir); - llvm::sys::path::append(Object, - (Triple.isOSWindows() ? "" : "lib") + Stem + ".o"); + llvm::sys::path::append(Object, Stem + ".o"); c->getFrontendOpts().OutputFile = std::string(Object); llvm::LLVMContext context; @@ -4920,8 +4913,8 @@ ParserTargetInfo* Parser::GetTargetInfo() parserTargetInfo->longDoubleWidth = TI.getLongDoubleWidth(); parserTargetInfo->longLongAlign = TI.getLongLongAlign(); parserTargetInfo->longLongWidth = TI.getLongLongWidth(); - parserTargetInfo->pointerAlign = TI.getPointerAlign(0); - parserTargetInfo->pointerWidth = TI.getPointerWidth(0); + parserTargetInfo->pointerAlign = TI.getPointerAlign(clang::LangAS::Default); + parserTargetInfo->pointerWidth = TI.getPointerWidth(clang::LangAS::Default); parserTargetInfo->wCharAlign = TI.getWCharAlign(); parserTargetInfo->wCharWidth = TI.getWCharWidth(); parserTargetInfo->float128Align = TI.getFloat128Align(); diff --git a/src/CppParser/premake5.lua b/src/CppParser/premake5.lua index f744c9fa06..a668f77427 100644 --- a/src/CppParser/premake5.lua +++ b/src/CppParser/premake5.lua @@ -4,6 +4,7 @@ clang_msvc_flags = "/wd4355", "/wd4996", "/wd4624", "/wd4291", "/wd4251", "/wd4141", -- 'inline' : used more than once + "/Zc:preprocessor" -- needed for newer Clang Options.inc (VA_ARGS) } if EnableNativeProjects() then @@ -20,6 +21,9 @@ project "CppSharp.CppParser" linkgroups "On" end + filter "toolset:gcc*" + buildoptions { "-Wno-nonnull" } + filter "toolset:msc*" buildoptions { clang_msvc_flags } diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index 86156c93c5..0751fa1c72 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -87,7 +87,6 @@ public void Setup() ValidateOptions(); ParserOptions.Setup(Platform.Host); Context = new BindingContext(Options, ParserOptions); - Context.LinkerOptions.Setup(ParserOptions.TargetTriple, ParserOptions.LanguageVersion); Generator = CreateGeneratorFromKind(Options.GeneratorKind); } diff --git a/src/Generator/Generators/CSharp/CSharpCommentPrinter.cs b/src/Generator/Generators/CSharp/CSharpCommentPrinter.cs index dc7ec6cecd..6f7fe7e26b 100644 --- a/src/Generator/Generators/CSharp/CSharpCommentPrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpCommentPrinter.cs @@ -37,6 +37,7 @@ private static void GetCommentSections(this Comment comment, List
secti blockCommandComment.ParagraphComment.GetCommentSections(sections); break; case CommentCommandKind.Return: + case CommentCommandKind.Returns: sections.Add(new Section(CommentElement.Returns)); blockCommandComment.ParagraphComment.GetCommentSections(sections); break; diff --git a/src/Generator/Passes/GenerateSymbolsPass.cs b/src/Generator/Passes/GenerateSymbolsPass.cs index 385771ae36..cca88acbd2 100644 --- a/src/Generator/Passes/GenerateSymbolsPass.cs +++ b/src/Generator/Passes/GenerateSymbolsPass.cs @@ -63,19 +63,7 @@ private void GenerateSymbols() new[] { module }).SelectMany(d => d.Libraries)) linkerOptions.AddLibraries(library); - using (var result = Parser.ClangParser.Build( - Context.ParserOptions, linkerOptions, path, - Last: remainingCompilationTasks == 1)) - { - if (PrintDiagnostics(result)) - { - compiledLibraries[module] = new CompiledLibrary - { - OutputDir = Options.OutputDir, - Library = module.SymbolsLibraryName - }; - } - } + compiledLibraries[module] = Build(linkerOptions, path, module); } } @@ -83,6 +71,66 @@ private void GenerateSymbols() } } + private CompiledLibrary Build(LinkerOptions linkerOptions, string path, Module module) + { + var useBuiltinToolchain = Platform.IsWindows; + if (useBuiltinToolchain) + { + linkerOptions.Setup(Context.ParserOptions.TargetTriple, Context.ParserOptions.LanguageVersion); + using var result = Parser.ClangParser.Build( + Context.ParserOptions, linkerOptions, path, + Last: remainingCompilationTasks == 1); + + if (!PrintDiagnostics(result)) + return null; + } + else + { + using var result = Parser.ClangParser.Compile(Context.ParserOptions, path); + if (result != null) + { + if (!PrintDiagnostics(result)) + return null; + } + + linkerOptions.Setup(Context.ParserOptions.TargetTriple, Context.ParserOptions.LanguageVersion); + linkerOptions.AddArguments("-L" + Path.GetDirectoryName(path)); + + var objectFile = Path.ChangeExtension(path, "o"); + linkerOptions.AddArguments(objectFile); + + var targetPlatform = Options.Compilation.Platform.GetValueOrDefault(Platform.Host); + var sharedObjectFile = LinkerOptions.GetSharedObjectName(path, targetPlatform); + linkerOptions.AddArguments("-o " + sharedObjectFile); + linkerOptions.SetupLibraryArguments(); + + var linker = LinkerOptions.GetLinkerExecutableName(targetPlatform); + var invocation = linkerOptions.GetLinkerInvocation(); + + Diagnostics.Message($"Linking library {Path.GetFileName(sharedObjectFile)}..."); + if (Options.Verbose) + Diagnostics.Message($"Invoking the linker with: {linker} {invocation}"); + + var outMessage = ProcessHelper.Run( + linker, invocation, out var errorCode, out var errorMessage); + + if (errorCode != 0) + { + Diagnostics.Error($"Linking failed with: {outMessage} {errorMessage}"); + } + else + { + Diagnostics.Message($"Linking success."); + } + } + + return new CompiledLibrary + { + OutputDir = Options.OutputDir, + Library = module.SymbolsLibraryName + }; + } + public override bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecialization specialization) { if (!specialization.IsGenerated || diff --git a/src/Parser/LinkerOptions.cs b/src/Parser/LinkerOptions.cs index 6fab1a24a2..c460487aa8 100644 --- a/src/Parser/LinkerOptions.cs +++ b/src/Parser/LinkerOptions.cs @@ -1,4 +1,8 @@ -using System.Linq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; namespace CppSharp.Parser { @@ -8,6 +12,8 @@ public LinkerOptions() { } + public static bool UseCompilerDriverAsLinker = true; + public LinkerOptions(LinkerOptions other) { for (uint i = 0; i < other.ArgumentsCount; i++) @@ -45,7 +51,7 @@ public void Setup(string triple, LanguageVersion? languageVersion) AddArguments("-L" + (SystemLibraryPath ?? "/usr/lib/x86_64-linux-gnu")); AddArguments("-lc"); AddArguments("--shared"); - AddArguments("-rpath"); + AddArguments(UseCompilerDriverAsLinker ? "-Wl,-rpath" : "-rpath"); AddArguments("."); break; case TargetPlatform.MacOS: @@ -70,5 +76,153 @@ public void Setup(string triple, LanguageVersion? languageVersion) break; } } + + public void SetupLibraryArguments() + { + for (uint i = 0; i < LibraryDirsCount; i++) + { + var dir = GetLibraryDirs(i); + AddArguments("-L" + dir); + } + + for (uint i = 0; i < LibrariesCount; i++) + { + var lib = GetLibraries(i); + AddArguments("-l" + lib); + } + } + + public string GetLinkerInvocation() + { + var args = new List(); + for (uint i = 0; i < ArgumentsCount; i++) + { + var arg = GetArguments(i); + args.Add(arg); + } + + return string.Join(" ", args); + } + + public static string GetSharedObjectName(string path, TargetPlatform targetPlatform) + { + var prefix = GetPlatformSharedObjectPrefix(targetPlatform); + var extension = GetPlatformSharedObjectExtension(targetPlatform); + var name = $"{prefix}{Path.GetFileNameWithoutExtension(path)}.{extension}"; + return Path.Join(Path.GetDirectoryName(path), name); + } + + public static string GetLinkerExecutableName(TargetPlatform targetPlatform) + { + // If LLD exists on the PATH, then prefer it. If not, use the host linker. + var lldLinkerExe = GetLLDLinkerExecutableName(targetPlatform); + return (ExistsOnPath(lldLinkerExe) && !UseCompilerDriverAsLinker) ? + lldLinkerExe : GetPlatformLinkerExecutableName(targetPlatform); + } + + public static string GetPlatformSharedObjectPrefix(TargetPlatform targetPlatform) + { + switch (targetPlatform) + { + case TargetPlatform.Windows: + return ""; + case TargetPlatform.Linux: + case TargetPlatform.Android: + case TargetPlatform.MacOS: + case TargetPlatform.iOS: + case TargetPlatform.WatchOS: + case TargetPlatform.TVOS: + case TargetPlatform.Emscripten: + return "lib"; + default: + throw new ArgumentOutOfRangeException(nameof(targetPlatform), targetPlatform, null); + } + } + + public static string GetPlatformSharedObjectExtension(TargetPlatform targetPlatform) + { + switch (targetPlatform) + { + case TargetPlatform.Windows: + return "dll"; + case TargetPlatform.Linux: + case TargetPlatform.Android: + case TargetPlatform.Emscripten: + return "so"; + case TargetPlatform.MacOS: + case TargetPlatform.iOS: + case TargetPlatform.WatchOS: + case TargetPlatform.TVOS: + return "dylib"; + default: + throw new ArgumentOutOfRangeException(nameof(targetPlatform), targetPlatform, null); + } + } + + public static string GetPlatformLinkerExecutableName(TargetPlatform targetPlatform) + { + switch (targetPlatform) + { + case TargetPlatform.Windows: + return "link.exe"; + case TargetPlatform.Linux: + return UseCompilerDriverAsLinker ? "gcc" : "ld"; + case TargetPlatform.Android: + case TargetPlatform.MacOS: + case TargetPlatform.iOS: + case TargetPlatform.WatchOS: + case TargetPlatform.TVOS: + return "ld"; + case TargetPlatform.Emscripten: + return GetLLDLinkerExecutableName(targetPlatform); + default: + throw new ArgumentOutOfRangeException(nameof(targetPlatform), targetPlatform, null); + } + } + + public static string GetLLDLinkerExecutableName(TargetPlatform targetPlatform) + { + switch (targetPlatform) + { + case TargetPlatform.Windows: + return "lld-link"; + case TargetPlatform.Linux: + case TargetPlatform.Android: + return "ld.lld"; + case TargetPlatform.MacOS: + case TargetPlatform.iOS: + case TargetPlatform.WatchOS: + case TargetPlatform.TVOS: + return "ld64.lld"; + case TargetPlatform.Emscripten: + return "wasm-ld"; + default: + throw new ArgumentOutOfRangeException(nameof(targetPlatform), targetPlatform, null); + } + } + + private static bool ExistsOnPath(string fileName) + { + return GetFullPath(fileName) != null; + } + + private static string GetFullPath(string fileName) + { + if (fileName == null) throw new ArgumentNullException(nameof(fileName)); + if (File.Exists(fileName)) + return Path.GetFullPath(fileName); + + var environmentVariablePath = Environment.GetEnvironmentVariable("PATH"); + if (environmentVariablePath == null) + throw new NullReferenceException(nameof(environmentVariablePath)); + + foreach (var path in environmentVariablePath.Split(Path.PathSeparator)) + { + var fullPath = Path.Combine(path, fileName); + if (File.Exists(fullPath)) + return fullPath; + } + return null; + } } } diff --git a/src/Parser/ParserOptions.cs b/src/Parser/ParserOptions.cs index 7cda0375e3..511709449f 100644 --- a/src/Parser/ParserOptions.cs +++ b/src/Parser/ParserOptions.cs @@ -136,6 +136,9 @@ public void SetupMSVC() case "vs2019": vsVersion = VisualStudioVersion.VS2019; break; + case "vs2022": + vsVersion = VisualStudioVersion.VS2022; + break; #pragma warning restore 162 @@ -374,6 +377,15 @@ private void SetupArguments(TargetPlatform targetPlatform) AddArguments("-fno-rtti"); } + internal string BuiltinsDirBasePath + { + get + { + var version = ClangVersion.Split(".").First(); + return Path.Combine("lib", "clang", version, "include"); + } + } + public string BuiltinsDir { get @@ -382,7 +394,7 @@ public string BuiltinsDir if (assemblyDir == null) throw new InvalidOperationException(); - return Path.Combine(assemblyDir, "lib", "clang", ClangVersion, "include"); + return Path.Combine(assemblyDir, BuiltinsDirBasePath); } } @@ -390,7 +402,7 @@ private void SetupIncludes(TargetPlatform targetPlatform) { // Check that the builtin includes folder exists. if (!Directory.Exists(BuiltinsDir)) - throw new Exception($"Clang resource folder 'lib/clang/{ClangVersion}/include' was not found."); + throw new Exception($"Clang resource folder '{BuiltinsDirBasePath}' was not found."); switch (targetPlatform) {