From 41849b1a78dc572217204549c5d9532935a75d19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Sat, 21 Jan 2023 11:55:36 +0100 Subject: [PATCH] generate `*.vcxproj` file lists with `dmake` (#4652) --- cli/cli.vcxproj | 15 ++- cli/cli.vcxproj.filters | 6 +- cppcheck.sln | 17 +++ lib/astutils.h | 24 ++-- lib/cppcheck.vcxproj | 22 ++-- lib/cppcheck.vcxproj.filters | 4 +- lib/lib.pri | 13 ++- test/testrunner.vcxproj | 24 ++-- test/testrunner.vcxproj.filters | 12 +- tools/dmake.cpp | 197 ++++++++++++++++++++++++++++++-- tools/dmake.sln | 25 ---- 11 files changed, 271 insertions(+), 88 deletions(-) delete mode 100644 tools/dmake.sln diff --git a/cli/cli.vcxproj b/cli/cli.vcxproj index bd852bf1c..d266995de 100644 --- a/cli/cli.vcxproj +++ b/cli/cli.vcxproj @@ -1,4 +1,4 @@ - + @@ -403,24 +403,23 @@ - - + - - + + - + {c183db5b-ad6c-423d-80ca-1f9549555a1a} - + @@ -429,8 +428,8 @@ - + diff --git a/cli/cli.vcxproj.filters b/cli/cli.vcxproj.filters index 604a28dd7..e8385a6c8 100644 --- a/cli/cli.vcxproj.filters +++ b/cli/cli.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -13,7 +13,7 @@ {6d3be647-edb6-43e6-a7eb-3031a2c7b655} - + Header Files @@ -45,7 +45,7 @@ Header Files - + Source Files diff --git a/cppcheck.sln b/cppcheck.sln index a5c6cef56..80fb1b90a 100644 --- a/cppcheck.sln +++ b/cppcheck.sln @@ -15,6 +15,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testrunner", "test\testrunn EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cppcheck", "lib\cppcheck.vcxproj", "{C183DB5B-AD6C-423D-80CA-1F9549555A1A}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dmake", "tools\dmake.vcxproj", "{19EC86CD-0004-4917-B852-E6BD110B6E6F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -75,8 +77,23 @@ Global {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Release-PCRE|Win32.Build.0 = Release-PCRE|Win32 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Release-PCRE|x64.ActiveCfg = Release-PCRE|x64 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Release-PCRE|x64.Build.0 = Release-PCRE|x64 + {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Debug|Win32.ActiveCfg = Debug|Win32 + {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Debug|Win32.Build.0 = Debug|Win32 + {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Debug|x64.ActiveCfg = Debug|Win32 + {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Debug-PCRE|Win32.ActiveCfg = Debug|Win32 + {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Debug-PCRE|Win32.Build.0 = Debug|Win32 + {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Debug-PCRE|x64.ActiveCfg = Debug|Win32 + {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Release|Win32.ActiveCfg = Release|Win32 + {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Release|Win32.Build.0 = Release|Win32 + {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Release|x64.ActiveCfg = Release|Win32 + {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Release-PCRE|Win32.ActiveCfg = Release|Win32 + {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Release-PCRE|Win32.Build.0 = Release|Win32 + {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Release-PCRE|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8CB50DEA-06DB-48E8-9C7B-F917494480A1} + EndGlobalSection EndGlobal diff --git a/lib/astutils.h b/lib/astutils.h index 30c141edb..a5479a1cd 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -178,7 +178,7 @@ bool isTemporary(bool cpp, const Token* tok, const Library* library, bool unknow const Token* previousBeforeAstLeftmostLeaf(const Token* tok); Token* previousBeforeAstLeftmostLeaf(Token* tok); -const Token * nextAfterAstRightmostLeaf(const Token * tok); +CPPCHECKLIB const Token * nextAfterAstRightmostLeaf(const Token * tok); Token* nextAfterAstRightmostLeaf(Token* tok); Token* astParentSkipParens(Token* tok); @@ -240,7 +240,7 @@ SmallVector followAllReferences(const Token* tok, int depth = 20); const Token* followReferences(const Token* tok, ErrorPath* errors = nullptr); -bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const Library& library, bool pure, bool followVar, ErrorPath* errors=nullptr); +CPPCHECKLIB bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const Library& library, bool pure, bool followVar, ErrorPath* errors=nullptr); bool isEqualKnownValue(const Token * const tok1, const Token * const tok2); @@ -251,7 +251,7 @@ const Token* isInLoopCondition(const Token* tok); /** * Is token used a boolean, that is to say cast to a bool, or used as a condition in a if/while/for */ -bool isUsedAsBool(const Token * const tok); +CPPCHECKLIB bool isUsedAsBool(const Token * const tok); /** * Are two conditions opposite @@ -277,10 +277,10 @@ bool isUniqueExpression(const Token* tok); bool isEscapeFunction(const Token* ftok, const Library* library); /** Is scope a return scope (scope will unconditionally return) */ -bool isReturnScope(const Token* const endToken, - const Library* library = nullptr, - const Token** unknownFunc = nullptr, - bool functionScope = false); +CPPCHECKLIB bool isReturnScope(const Token* const endToken, + const Library* library = nullptr, + const Token** unknownFunc = nullptr, + bool functionScope = false); /** Is tok within a scope of the given type, nested within var's scope? */ bool isWithinScope(const Token* tok, @@ -312,10 +312,10 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, nonneg int * @param settings program settings * @param inconclusive pointer to output variable which indicates that the answer of the question is inconclusive */ -bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Settings *settings, bool *inconclusive); +CPPCHECKLIB bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Settings *settings, bool *inconclusive); /** Is variable changed in block of code? */ -bool isVariableChanged(const Token *start, const Token *end, const nonneg int exprid, bool globalvar, const Settings *settings, bool cpp, int depth = 20); +CPPCHECKLIB bool isVariableChanged(const Token *start, const Token *end, const nonneg int exprid, bool globalvar, const Settings *settings, bool cpp, int depth = 20); bool isVariableChanged(const Token *start, const Token *end, int indirect, const nonneg int exprid, bool globalvar, const Settings *settings, bool cpp, int depth = 20); bool isVariableChanged(const Token *tok, int indirect, const Settings *settings, bool cpp, int depth = 20); @@ -380,14 +380,14 @@ int getArgumentPos(const Variable* var, const Function* f); */ bool isIteratorPair(std::vector args); -const Token *findLambdaStartToken(const Token *last); +CPPCHECKLIB const Token *findLambdaStartToken(const Token *last); /** * find lambda function end token * \param first The [ token * \return nullptr or the } */ -const Token *findLambdaEndToken(const Token *first); +CPPCHECKLIB const Token *findLambdaEndToken(const Token *first); Token* findLambdaEndToken(Token* first); bool isLikelyStream(bool cpp, const Token *stream); @@ -418,7 +418,7 @@ const Token* findAllocFuncCallToken(const Token *expr, const Library &library); bool isScopeBracket(const Token* tok); -bool isNullOperand(const Token *expr); +CPPCHECKLIB bool isNullOperand(const Token *expr); bool isGlobalData(const Token *expr, bool cpp); diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index a22a55b71..667fdd90c 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -33,7 +33,7 @@ x64 - + @@ -56,9 +56,8 @@ - - + @@ -68,6 +67,7 @@ + @@ -79,7 +79,9 @@ + + @@ -88,8 +90,8 @@ - + @@ -101,10 +103,8 @@ - - - + @@ -120,9 +120,8 @@ - - + @@ -132,6 +131,7 @@ + @@ -144,8 +144,9 @@ - + + @@ -155,7 +156,6 @@ - diff --git a/lib/cppcheck.vcxproj.filters b/lib/cppcheck.vcxproj.filters index ef5b2620d..f725d9b65 100644 --- a/lib/cppcheck.vcxproj.filters +++ b/lib/cppcheck.vcxproj.filters @@ -10,7 +10,7 @@ cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx - + Source Files @@ -192,7 +192,7 @@ Source Files - + Header Files diff --git a/lib/lib.pri b/lib/lib.pri index 6b81248b1..426fc2877 100644 --- a/lib/lib.pri +++ b/lib/lib.pri @@ -3,8 +3,10 @@ include($$PWD/pcrerules.pri) include($$PWD/../externals/externals.pri) INCLUDEPATH += $$PWD -HEADERS += $${PWD}/analyzerinfo.h \ +HEADERS += $${PWD}/analyzer.h \ + $${PWD}/analyzerinfo.h \ $${PWD}/astutils.h \ + $${PWD}/calculate.h \ $${PWD}/check.h \ $${PWD}/check64bit.h \ $${PWD}/checkassert.h \ @@ -33,6 +35,7 @@ HEADERS += $${PWD}/analyzerinfo.h \ $${PWD}/checkvaarg.h \ $${PWD}/clangimport.h \ $${PWD}/color.h \ + $${PWD}/config.h \ $${PWD}/cppcheck.h \ $${PWD}/ctu.h \ $${PWD}/errorlogger.h \ @@ -47,10 +50,13 @@ HEADERS += $${PWD}/analyzerinfo.h \ $${PWD}/pathanalysis.h \ $${PWD}/pathmatch.h \ $${PWD}/platform.h \ + $${PWD}/precompiled.h \ $${PWD}/preprocessor.h \ $${PWD}/programmemory.h \ $${PWD}/reverseanalyzer.h \ $${PWD}/settings.h \ + $${PWD}/smallvector.h \ + $${PWD}/standards.h \ $${PWD}/summaries.h \ $${PWD}/suppressions.h \ $${PWD}/symboldatabase.h \ @@ -59,8 +65,11 @@ HEADERS += $${PWD}/analyzerinfo.h \ $${PWD}/token.h \ $${PWD}/tokenize.h \ $${PWD}/tokenlist.h \ + $${PWD}/tokenrange.h \ $${PWD}/utils.h \ - $${PWD}/valueflow.h + $${PWD}/valueflow.h \ + $${PWD}/valueptr.h \ + $${PWD}/version.h SOURCES += $${PWD}/analyzerinfo.cpp \ $${PWD}/astutils.cpp \ diff --git a/test/testrunner.vcxproj b/test/testrunner.vcxproj index 9e4b48c71..cf2cf4b11 100755 --- a/test/testrunner.vcxproj +++ b/test/testrunner.vcxproj @@ -1,4 +1,4 @@ - + @@ -23,15 +23,16 @@ {c183db5b-ad6c-423d-80ca-1f9549555a1a} - + - + + + - @@ -51,6 +52,7 @@ + @@ -61,7 +63,6 @@ - @@ -80,10 +81,10 @@ + Create Create Create Create - Create @@ -104,11 +105,16 @@ - + + + + + + + - @@ -320,4 +326,4 @@ - + \ No newline at end of file diff --git a/test/testrunner.vcxproj.filters b/test/testrunner.vcxproj.filters index 6f2e3aebc..fe61875f4 100644 --- a/test/testrunner.vcxproj.filters +++ b/test/testrunner.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -18,7 +18,7 @@ cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx - + Source Files @@ -211,9 +211,6 @@ Source Files - - Source Files - Source Files @@ -230,7 +227,7 @@ Source Files - + Header Files @@ -252,9 +249,6 @@ Header Files - - Header Files - Header Files diff --git a/tools/dmake.cpp b/tools/dmake.cpp index d450c0c38..96a9be8aa 100644 --- a/tools/dmake.cpp +++ b/tools/dmake.cpp @@ -21,6 +21,7 @@ #include #include #include // IWYU pragma: keep +#include #include #include #include @@ -157,6 +158,105 @@ static void makeConditionalVariable(std::ostream &os, const std::string &variabl << "\n"; } +static int write_vcxproj(const std::string &proj_name, const std::function &source_f, const std::function &header_f) +{ + std::string outstr; + + { + // treat as binary to prevent inplicit line ending conversions + std::ifstream in(proj_name, std::ios::binary); + if (!in.is_open()) { + std::cerr << "Could not open " << proj_name << std::endl; + return EXIT_FAILURE; + } + + std::string line; + bool in_itemgroup = false; + while (std::getline(in, line)) { + if (in_itemgroup) { + if (line.find("") == std::string::npos) + continue; + in_itemgroup = false; + } + + // strip all remaining line endings + const std::string::size_type pos = line.find_last_not_of("\r\n"); + if (pos != std::string::npos) + line.resize(pos+1, '\0'); + + outstr += line; + outstr += "\r\n"; + + if (line.find("") != std::string::npos) { + in_itemgroup = true; + + source_f(outstr); + } + + if (line.find("") != std::string::npos) { + in_itemgroup = true; + + header_f(outstr); + } + } + } + + // strip trailing \r\n + { + const std::string::size_type pos = outstr.find_last_not_of("\r\n"); + if (pos != std::string::npos) + outstr.resize(pos+1, '\0'); + } + + // treat as binary to prevent inplicit line ending conversions + std::ofstream out(proj_name, std::ios::binary|std::ios::trunc); + out << outstr; + + return EXIT_SUCCESS; +} + +enum ClType { Compile, Include, Precompile, PrecompileNoPCRE }; + +static std::string make_vcxproj_cl_entry(const std::string& file, ClType type) +{ + std::string outstr; + if (type == Precompile || type == PrecompileNoPCRE) { + outstr += R"( )"; + outstr += "\r\n"; + outstr += R"( Create)"; + outstr += "\r\n"; + outstr += R"( Create)"; + outstr += "\r\n"; + if (type == Precompile) { + outstr += R"( Create)"; + outstr += "\r\n"; + outstr += R"( Create)"; + outstr += "\r\n"; + } + outstr += R"( Create)"; + outstr += "\r\n"; + outstr += R"( Create)"; + outstr += "\r\n"; + if (type == Precompile) { + outstr += R"( Create)"; + outstr += "\r\n"; + outstr += R"( Create)"; + outstr += "\r\n"; + } + outstr += " \r\n"; + return outstr; + } + outstr += " <"; + outstr += (type == Compile) ? "ClCompile" : "ClInclude"; + outstr += R"( Include=")"; + outstr += file; + outstr += R"(" />)"; + outstr += "\r\n"; + return outstr; +} + int main(int argc, char **argv) { const bool release(argc >= 2 && std::string(argv[1]) == "--release"); @@ -202,6 +302,93 @@ int main(int argc, char **argv) return EXIT_FAILURE; } + // TODO: add files without source via parsing + std::vector libfiles_h; + for (const std::string &libfile : libfiles) { + std::string fname(libfile.substr(4)); + fname.erase(fname.find(".cpp")); + libfiles_h.emplace_back(fname + ".h"); + } + libfiles_h.emplace_back("analyzer.h"); + libfiles_h.emplace_back("calculate.h"); + libfiles_h.emplace_back("config.h"); + libfiles_h.emplace_back("precompiled.h"); + libfiles_h.emplace_back("smallvector.h"); + libfiles_h.emplace_back("standards.h"); + libfiles_h.emplace_back("tokenrange.h"); + libfiles_h.emplace_back("valueptr.h"); + libfiles_h.emplace_back("version.h"); + std::sort(libfiles_h.begin(), libfiles_h.end()); + + std::vector clifiles_h; + for (const std::string &clifile : clifiles) { + std::string fname(clifile.substr(4)); + if (fname == "main.cpp") + continue; + fname.erase(fname.find(".cpp")); + clifiles_h.emplace_back(fname + ".h"); + } + + std::vector testfiles_h; + testfiles_h.emplace_back("options.h"); + testfiles_h.emplace_back("precompiled.h"); + testfiles_h.emplace_back("redirect.h"); + testfiles_h.emplace_back("testsuite.h"); + testfiles_h.emplace_back("testutils.h"); + std::sort(testfiles_h.begin(), testfiles_h.end()); + + // TODO: write filter files + // Visual Studio projects + write_vcxproj("cli/cli.vcxproj", [&](std::string &outstr){ + for (const std::string &clifile: clifiles) { + outstr += make_vcxproj_cl_entry(clifile.substr(4), Compile); + } + }, [&](std::string &outstr){ + for (const std::string &clifile_h: clifiles_h) { + outstr += make_vcxproj_cl_entry(clifile_h, Include); + } + }); + + write_vcxproj("lib/cppcheck.vcxproj", [&](std::string &outstr){ + outstr += make_vcxproj_cl_entry(R"(..\externals\simplecpp\simplecpp.cpp)", Compile); + outstr += make_vcxproj_cl_entry(R"(..\externals\tinyxml2\tinyxml2.cpp)", Compile); + + for (const std::string &libfile: libfiles) { + const std::string l = libfile.substr(4); + outstr += make_vcxproj_cl_entry(l, l == "check.cpp" ? Precompile : Compile); + } + }, [&](std::string &outstr){ + outstr += make_vcxproj_cl_entry(R"(..\externals\simplecpp\simplecpp.h)", Include); + outstr += make_vcxproj_cl_entry(R"(..\externals\tinyxml2\tinyxml2.h)", Include); + + for (const std::string &libfile_h: libfiles_h) { + outstr += make_vcxproj_cl_entry(libfile_h, Include); + } + }); + + write_vcxproj("test/testrunner.vcxproj", [&](std::string &outstr){ + for (const std::string &clifile: clifiles) { + if (clifile == "cli/main.cpp") + continue; + const std::string c = R"(..\cli\)" + clifile.substr(4); + outstr += make_vcxproj_cl_entry(c, Compile); + } + + for (const std::string &testfile: testfiles) { + const std::string t = testfile.substr(5); + outstr += make_vcxproj_cl_entry(t, t == "testsuite.cpp" ? PrecompileNoPCRE : Compile); + } + }, [&](std::string &outstr){ + for (const std::string &clifile_h: clifiles_h) { + const std::string c = R"(..\cli\)" + clifile_h; + outstr += make_vcxproj_cl_entry(c, Include); + } + + for (const std::string &testfile_h: testfiles_h) { + outstr += make_vcxproj_cl_entry(testfile_h, Include); + } + }); + // QMAKE - lib/lib.pri { std::ofstream fout1("lib/lib.pri"); @@ -211,13 +398,9 @@ int main(int argc, char **argv) fout1 << "include($$PWD/../externals/externals.pri)\n"; fout1 << "INCLUDEPATH += $$PWD\n"; fout1 << "HEADERS += "; - for (const std::string &libfile : libfiles) { - std::string fname(libfile.substr(4)); - if (fname.find(".cpp") == std::string::npos) - continue; // shouldn't happen - fname.erase(fname.find(".cpp")); - fout1 << "$${PWD}/" << fname << ".h"; - if (libfile != libfiles.back()) + for (const std::string &libfile_h : libfiles_h) { + fout1 << "$${PWD}/" << libfile_h; + if (libfile_h != libfiles_h.back()) fout1 << " \\\n" << std::string(11, ' '); } fout1 << "\n\nSOURCES += "; diff --git a/tools/dmake.sln b/tools/dmake.sln deleted file mode 100644 index 7c065aa6d..000000000 --- a/tools/dmake.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29519.87 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dmake", "dmake.vcxproj", "{19EC86CD-0004-4917-B852-E6BD110B6E6F}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Debug|Win32.ActiveCfg = Debug|Win32 - {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Debug|Win32.Build.0 = Debug|Win32 - {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Release|Win32.ActiveCfg = Release|Win32 - {19EC86CD-0004-4917-B852-E6BD110B6E6F}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {3C0A1D1C-BDE8-453D-9FB3-EC4DEB9BC733} - EndGlobalSection -EndGlobal