diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index f517107f0..f2945cc10 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -133,6 +133,9 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) else if (std::strncmp(argv[i], "--addon=", 8) == 0) mSettings->addons.emplace_back(argv[i]+8); + else if (std::strncmp(argv[i],"--addon-python=", 15) == 0) + mSettings->addonPython.assign(argv[i]+15); + else if (std::strcmp(argv[i], "--clang") == 0) mSettings->clang = true; @@ -973,6 +976,9 @@ void CmdLineParser::printHelp() "Options:\n" " --addon=\n" " Execute addon. i.e. cert.\n" + " --addon-python=\n" + " Use this python interpreter to run addons\n" + " If not present, defaults to \"python\"\n" " --cppcheck-build-dir=\n" " Analysis output directory. Useful for various data.\n" " Some possible usages are; whole program analysis,\n" diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 9beb2f084..54e279deb 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -67,6 +67,7 @@ namespace { std::string name; std::string scriptFile; std::string args; + std::string python; static std::string getFullPath(const std::string &fileName, const std::string &exename) { if (Path::fileExists(fileName)) @@ -131,16 +132,36 @@ namespace { args += " " + v.get(); } + if(obj.count("python")) { + // Python was defined in the config file + if (obj["python"].is()){ + return "Loading " + fileName +" failed. python must not be an array."; + } + python = obj["python"].get(); + } + else{ + python = ""; + } + return getAddonInfo(obj["script"].get(), exename); } }; } -static std::string executeAddon(const AddonInfo &addonInfo, const std::string &dumpFile) -{ +static std::string executeAddon(const AddonInfo &addonInfo, + const std::string &defaultPythonExe, + const std::string &dumpFile) { + + std::string pythonExe = (addonInfo.python != "") ? addonInfo.python : defaultPythonExe; + + if(pythonExe.find(" ") != std::string::npos){ + // popen strips the first quote. Needs 2 sets to fully quote. + pythonExe = "\"\"" + pythonExe + "\"\""; + } + // Can python be executed? { - const std::string cmd = "python --version 2>&1"; + const std::string cmd = pythonExe + " --version 2>&1"; #ifdef _WIN32 std::unique_ptr pipe(_popen(cmd.c_str(), "r"), _pclose); @@ -157,7 +178,7 @@ static std::string executeAddon(const AddonInfo &addonInfo, const std::string &d throw InternalError(nullptr, "Failed to execute '" + cmd + "' (" + result + ")"); } - const std::string cmd = "python \"" + addonInfo.scriptFile + "\" --cli" + addonInfo.args + " \"" + dumpFile + "\" 2>&1"; + const std::string cmd = pythonExe + " \"" + addonInfo.scriptFile + "\" --cli" + addonInfo.args + " \"" + dumpFile + "\" 2>&1"; #ifdef _WIN32 std::unique_ptr pipe(_popen(cmd.c_str(), "r"), _pclose); @@ -778,7 +799,8 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string mExitCode = 1; continue; } - const std::string results = executeAddon(addonInfo, dumpFile); + const std::string results = + executeAddon(addonInfo, mSettings.addonPython, dumpFile); std::istringstream istr(results); std::string line; diff --git a/lib/settings.cpp b/lib/settings.cpp index b48158771..364392a47 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -30,6 +30,7 @@ const char Settings::SafeChecks::XmlExternalVariables[] = "external-variables"; Settings::Settings() : mEnabled(0), + addonPython("python"), checkConfiguration(false), checkLibrary(false), checkHeaders(true), diff --git a/lib/settings.h b/lib/settings.h index 8cc9eafa4..ed357958f 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -73,6 +73,9 @@ public: std::list addons; + /** @brief Path to the python interpreter to be used to run addons. */ + std::string addonPython; + /** @brief Paths used as base for conversion to relative paths. */ std::vector basePaths;