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 455c4f4d..43b9891f 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 6756de76..d26b7adc 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 3fe84b36..e6c25f85 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 d2781b74..86fa1be6 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 6f7a086f..5cd81557 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 8a0cb186..1f1a216a 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 30a39433..f375b39e 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 605825c3..91964cd4 100644 --- a/src/Core/Toolchains/MSVCToolchain.cs +++ b/src/Core/Toolchains/MSVCToolchain.cs @@ -16,6 +16,7 @@ namespace CppSharp VS2015 = 14, VS2017 = 15, VS2019 = 16, + VS2022 = 17, Latest, } @@ -67,9 +68,12 @@ namespace CppSharp 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 00664581..d6c1f7b3 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 3514256d..46d06621 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 4587d73f..27639a3d 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 31f4703e..c7eed096 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 4e55c574..85be06a1 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 f744c9fa..a668f774 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 86156c93..0751fa1c 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -87,7 +87,6 @@ namespace CppSharp 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 dc7ec6ce..6f7fe7e2 100644 --- a/src/Generator/Generators/CSharp/CSharpCommentPrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpCommentPrinter.cs @@ -37,6 +37,7 @@ namespace CppSharp.Generators.CSharp 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 385771ae..cca88acb 100644 --- a/src/Generator/Passes/GenerateSymbolsPass.cs +++ b/src/Generator/Passes/GenerateSymbolsPass.cs @@ -63,19 +63,7 @@ namespace CppSharp.Passes 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 @@ namespace CppSharp.Passes } } + 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 6fab1a24..c460487a 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 @@ namespace CppSharp.Parser { } + public static bool UseCompilerDriverAsLinker = true; + public LinkerOptions(LinkerOptions other) { for (uint i = 0; i < other.ArgumentsCount; i++) @@ -45,7 +51,7 @@ namespace CppSharp.Parser 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 @@ namespace CppSharp.Parser 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 7cda0375..51170944 100644 --- a/src/Parser/ParserOptions.cs +++ b/src/Parser/ParserOptions.cs @@ -136,6 +136,9 @@ namespace CppSharp.Parser case "vs2019": vsVersion = VisualStudioVersion.VS2019; break; + case "vs2022": + vsVersion = VisualStudioVersion.VS2022; + break; #pragma warning restore 162 @@ -374,6 +377,15 @@ namespace CppSharp.Parser 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 @@ namespace CppSharp.Parser if (assemblyDir == null) throw new InvalidOperationException(); - return Path.Combine(assemblyDir, "lib", "clang", ClangVersion, "include"); + return Path.Combine(assemblyDir, BuiltinsDirBasePath); } } @@ -390,7 +402,7 @@ namespace CppSharp.Parser { // 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) {