ui: autodetect java on windows

* implemented a more generic approach to detecting filepaths
* reimplemented standard header detection using this approach
* added auto detection of JVM dynamic library on windows
* fixed java tests that were broken when updating the java_indexer project before this commit.
This commit is contained in:
malte_langkabel
2016-08-24 15:21:04 +02:00
parent 01f740276b
commit 8dfc1ea9d9
30 changed files with 508 additions and 370 deletions
@@ -1,62 +0,0 @@
#include "utility/headerSearch/CompilerDetector.h"
#include "utility/utilityApp.h"
#include "utility/utilityString.h"
CompilerDetector::CompilerDetector(const std::string& name)
: DetectorBase(name)
{
}
CompilerDetector::~CompilerDetector()
{
}
std::vector<FilePath> CompilerDetector::getStandardHeaderPaths()
{
std::vector<std::string> paths = getHeaderPaths();
std::vector<FilePath> headerPaths;
for (const std::string& path : paths)
{
if (!utility::isPostfix(" (framework directory)", path))
{
headerPaths.push_back(FilePath(path).canonical());
}
}
return headerPaths;
}
std::vector<FilePath> CompilerDetector::getStandardFrameworkPaths()
{
std::vector<std::string> paths = getHeaderPaths();
std::vector<FilePath> frameworkPaths;
for (const std::string& path : paths)
{
if (utility::isPostfix(" (framework directory)", path))
{
frameworkPaths.push_back(FilePath(utility::replace(path, " (framework directory)", "")).canonical());
}
}
return frameworkPaths;
}
std::vector<std::string> CompilerDetector::getHeaderPaths()
{
std::string command = m_name + " -x c++ -v -E /dev/null";
std::string clangOutput = utility::executeProcess(command.c_str());
std::string standardHeaders =
utility::substrBetween(clangOutput, "#include <...> search starts here:\n","\nEnd of search list");
std::vector<std::string> paths;
if (!standardHeaders.empty())
{
for (std::string s : utility::splitToVector(standardHeaders, '\n'))
{
paths.push_back(utility::trim(s));
}
}
return paths;
}
@@ -1,21 +0,0 @@
#ifndef COMPILER_DETECTOR_H
#define COMPILER_DETECTOR_H
#include "utility/headerSearch/DetectorBase.h"
class CompilerDetector
: public DetectorBase
{
public:
CompilerDetector(const std::string& name);
virtual ~CompilerDetector();
virtual std::vector<FilePath> getStandardHeaderPaths();
virtual std::vector<FilePath> getStandardFrameworkPaths();
private:
std::vector<std::string> getHeaderPaths();
};
#endif // COMPILER_DETECTOR_H
@@ -1,20 +0,0 @@
#include "utility/headerSearch/DetectorBase.h"
DetectorBase::DetectorBase(const std::string name)
: m_name(name)
{
}
DetectorBase::~DetectorBase()
{
}
std::string DetectorBase::getName() const
{
return m_name;
}
bool DetectorBase::isWorking()
{
return !getStandardHeaderPaths().empty();
}
@@ -1,24 +0,0 @@
#ifndef DETECTOR_BASE_H
#define DETECTOR_BASE_H
#include <vector>
#include "utility/file/FilePath.h"
class DetectorBase
{
public:
DetectorBase(const std::string name);
virtual ~DetectorBase();
std::string getName() const;
bool isWorking();
virtual std::vector<FilePath> getStandardHeaderPaths() = 0;
virtual std::vector<FilePath> getStandardFrameworkPaths() = 0;
protected:
std::string m_name;
};
#endif // DETECTOR_BASE_H
@@ -1,102 +0,0 @@
#include "utility/headerSearch/StandardHeaderDetection.h"
#include <cstdlib>
#include <iostream>
#include <utility>
#include "utility/headerSearch/CompilerDetector.h"
#include "utility/headerSearch/VisualStudioDetector.h"
#include "utility/logging/logging.h"
StandardHeaderDetection::DetectorMap StandardHeaderDetection::s_availableDetectors;
StandardHeaderDetection::DetectorMap StandardHeaderDetection::s_workingDetectors;
StandardHeaderDetection::StandardHeaderDetection()
{
if (!s_availableDetectors.size())
{
addDetector(std::make_shared<CompilerDetector>("gcc"));
addDetector(std::make_shared<CompilerDetector>("clang"));
addDetector(std::make_shared<VisualStudioDetector>("Visual Studio 2010", 9, false));
addDetector(std::make_shared<VisualStudioDetector>("Visual Studio 2010 Express", 9, true));
addDetector(std::make_shared<VisualStudioDetector>("Visual Studio 2012", 11, false));
addDetector(std::make_shared<VisualStudioDetector>("Visual Studio 2012 Express", 11, true));
addDetector(std::make_shared<VisualStudioDetector>("Visual Studio 2013", 12, false));
addDetector(std::make_shared<VisualStudioDetector>("Visual Studio 2013 Express", 12, true));
addDetector(std::make_shared<VisualStudioDetector>("Visual Studio 2015", 14, false));
addDetector(std::make_shared<VisualStudioDetector>("Visual Studio 2015 Express", 14, true));
detectHeaders();
}
}
StandardHeaderDetection::~StandardHeaderDetection()
{
}
void StandardHeaderDetection::addDetector(std::shared_ptr<DetectorBase> detector)
{
s_availableDetectors.emplace(detector->getName(), detector);
}
void StandardHeaderDetection::detectHeaders()
{
for (DetectorPair detector: s_availableDetectors)
{
if (detector.second->isWorking())
{
s_workingDetectors.insert(detector);
}
}
}
std::vector<std::string> StandardHeaderDetection::getWorkingDetectorNames()
{
std::vector<std::string> detectorNames;
for (DetectorPair detector: s_workingDetectors)
{
detectorNames.push_back(detector.first);
}
return detectorNames;
}
std::vector<FilePath> StandardHeaderDetection::getStandardHeaderPaths(std::string detectorName)
{
DetectorMap::const_iterator it = s_workingDetectors.find(detectorName);
if (it != s_workingDetectors.end())
{
return it->second->getStandardHeaderPaths();
}
return std::vector<FilePath>();
}
std::vector<FilePath> StandardHeaderDetection::getStandardFrameworkPaths(std::string detectorName)
{
DetectorMap::const_iterator it = s_workingDetectors.find(detectorName);
if (it != s_workingDetectors.end())
{
return it->second->getStandardFrameworkPaths();
}
return std::vector<FilePath>();
}
void StandardHeaderDetection::logAvailableDetectors()
{
LOG_INFO("Available Header Detectors:");
for (DetectorPair detector: s_availableDetectors)
{
LOG_INFO("Detector: " + detector.first);
}
}
void StandardHeaderDetection::logWorkingDetectors()
{
LOG_INFO("Working Header Detectors:");
for (std::string detectorName: getWorkingDetectorNames())
{
LOG_INFO("Detector: " + detectorName);
}
}
@@ -1,42 +0,0 @@
#ifndef STANDARD_HEADER_DETECTION_H
#define STANDARD_HEADER_DETECTION_H
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "utility/headerSearch/DetectorBase.h"
class FilePath;
class StandardHeaderDetection
{
public:
StandardHeaderDetection();
~StandardHeaderDetection();
void addDetector(std::shared_ptr<DetectorBase> detector);
/// Checks all availabe detectors and saves found Compilers
void detectHeaders();
std::vector<std::string> getWorkingDetectorNames();
/// Returns the headerpaths from a found compiler
std::vector<FilePath> getStandardHeaderPaths(std::string detectorName);
std::vector<FilePath> getStandardFrameworkPaths(std::string detectorName);
/// Debugging Output
void logAvailableDetectors();
void logWorkingDetectors();
private:
typedef std::map<std::string, std::shared_ptr<DetectorBase>> DetectorMap;
typedef std::pair<std::string, std::shared_ptr<DetectorBase>> DetectorPair;
static DetectorMap s_availableDetectors;
static DetectorMap s_workingDetectors;
};
#endif // STANDARD_HEADER_DETECTION_H
@@ -1,27 +0,0 @@
#ifndef VISUAL_STUDIO_DETECTOR_H
#define VISUAL_STUDIO_DETECTOR_H
#include <vector>
#include "utility/headerSearch/DetectorBase.h"
class FilePath;
class VisualStudioDetector: public DetectorBase
{
public:
VisualStudioDetector(const std::string name, int version, bool isExpress);
virtual ~VisualStudioDetector();
virtual std::vector<FilePath> getStandardHeaderPaths();
virtual std::vector<FilePath> getStandardFrameworkPaths();
private:
FilePath getVsInstallPathUsingRegistry();
FilePath getWindowsSdkPathUsingRegistry(const std::string& version);
int m_version;
bool m_isExpress;
};
#endif // VISUAL_STUDIO_DETECTOR_H
@@ -0,0 +1,54 @@
#include "utility/path_detector/CombinedPathDetector.h"
CombinedPathDetector::CombinedPathDetector()
: PathDetector("combined")
{
}
CombinedPathDetector::~CombinedPathDetector()
{
}
void CombinedPathDetector::addDetector(std::shared_ptr<PathDetector> detector)
{
m_detectors[detector->getName()] = detector;
}
std::vector<std::string> CombinedPathDetector::getWorkingDetectorNames()
{
std::vector<std::string> names;
for (DetectorPair detectorEntry: m_detectors)
{
if (detectorEntry.second->isWorking())
{
names.push_back(detectorEntry.first);
}
}
return names;
}
std::vector<FilePath> CombinedPathDetector::getPaths() const
{
for (DetectorPair detectorEntry: m_detectors)
{
std::vector<FilePath> detectedPaths = detectorEntry.second->getPaths();
if (!detectedPaths.empty())
{
return detectedPaths;
}
}
return std::vector<FilePath>();
}
std::vector<FilePath> CombinedPathDetector::getPaths(std::string detectorName) const
{
std::vector<FilePath> paths;
DetectorMap::const_iterator it = m_detectors.find(detectorName);
if (it != m_detectors.end())
{
paths = it->second->getPaths();
}
return paths;
}
@@ -0,0 +1,31 @@
#ifndef COMBINED_PATH_DETECTOR_H
#define COMBINED_PATH_DETECTOR_H
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "utility/path_detector/PathDetector.h"
class CombinedPathDetector: public PathDetector
{
public:
CombinedPathDetector();
virtual ~CombinedPathDetector();
void addDetector(std::shared_ptr<PathDetector> detector);
std::vector<std::string> getWorkingDetectorNames();
virtual std::vector<FilePath> getPaths() const;
std::vector<FilePath> getPaths(std::string detectorName) const;
private:
typedef std::map<std::string, std::shared_ptr<PathDetector>> DetectorMap;
typedef std::pair<std::string, std::shared_ptr<PathDetector>> DetectorPair;
DetectorMap m_detectors;
};
#endif // COMBINED_PATH_DETECTOR_H
@@ -0,0 +1,20 @@
#include "utility/path_detector/PathDetector.h"
PathDetector::PathDetector(const std::string& name)
: m_name(name)
{
}
PathDetector::~PathDetector()
{
}
std::string PathDetector::getName() const
{
return m_name;
}
bool PathDetector::isWorking() const
{
return (!getPaths().empty());
}
@@ -0,0 +1,23 @@
#ifndef PATH_DETECTOR_BASE_H
#define PATH_DETECTOR_BASE_H
#include <string>
#include <vector>
#include "utility/file/FilePath.h"
class PathDetector
{
public:
PathDetector(const std::string& name);
virtual ~PathDetector();
std::string getName() const;
bool isWorking() const;
virtual std::vector<FilePath> getPaths() const = 0;
protected:
const std::string m_name;
};
#endif // PATH_DETECTOR_BASE_H
@@ -0,0 +1,29 @@
#include "utility/path_detector/cxx_header/CxxFrameworkPathDetector.h"
#include "utility/path_detector/cxx_header/utilityCxxHeaderDetection.h"
#include "utility/utilityApp.h"
#include "utility/utilityString.h"
CxxFrameworkPathDetector::CxxFrameworkPathDetector(const std::string& compilerName)
: PathDetector(compilerName)
, m_compilerName(compilerName)
{
}
CxxFrameworkPathDetector::~CxxFrameworkPathDetector()
{
}
std::vector<FilePath> CxxFrameworkPathDetector::getPaths() const
{
std::vector<std::string> paths = utility::getCxxHeaderPaths(m_compilerName);
std::vector<FilePath> frameworkPaths;
for (const std::string& path : paths)
{
if (utility::isPostfix(" (framework directory)", path))
{
frameworkPaths.push_back(FilePath(utility::replace(path, " (framework directory)", "")).canonical());
}
}
return frameworkPaths;
}
@@ -0,0 +1,18 @@
#ifndef CXX_FRAMEWORK_PATH_DETECTOR_H
#define CXX_FRAMEWORK_PATH_DETECTOR_H
#include "utility/path_detector/PathDetector.h"
class CxxFrameworkPathDetector: public PathDetector
{
public:
CxxFrameworkPathDetector(const std::string& compilerName);
virtual ~CxxFrameworkPathDetector();
virtual std::vector<FilePath> getPaths() const;
private:
const std::string m_compilerName;
};
#endif // CXX_FRAMEWORK_PATH_DETECTOR_H
@@ -0,0 +1,29 @@
#include "utility/path_detector/cxx_header/CxxHeaderPathDetector.h"
#include "utility/path_detector/cxx_header/utilityCxxHeaderDetection.h"
#include "utility/utilityApp.h"
#include "utility/utilityString.h"
CxxHeaderPathDetector::CxxHeaderPathDetector(const std::string& compilerName)
: PathDetector(compilerName)
, m_compilerName(compilerName)
{
}
CxxHeaderPathDetector::~CxxHeaderPathDetector()
{
}
std::vector<FilePath> CxxHeaderPathDetector::getPaths() const
{
std::vector<std::string> paths = utility::getCxxHeaderPaths(m_compilerName);
std::vector<FilePath> headerPaths;
for (const std::string& path : paths)
{
if (!utility::isPostfix(" (framework directory)", path))
{
headerPaths.push_back(FilePath(path).canonical());
}
}
return headerPaths;
}
@@ -0,0 +1,18 @@
#ifndef CXX_HEADER_PATH_DETECTOR_H
#define CXX_HEADER_PATH_DETECTOR_H
#include "utility/path_detector/PathDetector.h"
class CxxHeaderPathDetector: public PathDetector
{
public:
CxxHeaderPathDetector(const std::string& compilerName);
virtual ~CxxHeaderPathDetector();
virtual std::vector<FilePath> getPaths() const;
private:
const std::string m_compilerName;
};
#endif // CXX_HEADER_PATH_DETECTOR_H
@@ -1,4 +1,4 @@
#include "utility/headerSearch/VisualStudioDetector.h"
#include "utility/path_detector/cxx_header/CxxVsHeaderPathDetector.h"
#include <string>
@@ -8,18 +8,18 @@
#include "utility/file/FilePath.h"
#include "utility/logging/logging.h"
VisualStudioDetector::VisualStudioDetector(const std::string name, int version, bool isExpress)
: DetectorBase(name)
CxxVsHeaderPathDetector::CxxVsHeaderPathDetector(int version, bool isExpress)
: PathDetector("Visual Studio " + std::to_string(version) + (isExpress ? " Express" : ""))
, m_version(version)
, m_isExpress(isExpress)
{
}
VisualStudioDetector::~VisualStudioDetector()
CxxVsHeaderPathDetector::~CxxVsHeaderPathDetector()
{
}
std::vector<FilePath> VisualStudioDetector::getStandardHeaderPaths()
std::vector<FilePath> CxxVsHeaderPathDetector::getPaths() const
{
FilePath vsInstallPath = getVsInstallPathUsingRegistry();
@@ -86,12 +86,7 @@ std::vector<FilePath> VisualStudioDetector::getStandardHeaderPaths()
return headerPaths;
}
std::vector<FilePath> VisualStudioDetector::getStandardFrameworkPaths()
{
return std::vector<FilePath>();
}
FilePath VisualStudioDetector::getVsInstallPathUsingRegistry()
FilePath CxxVsHeaderPathDetector::getVsInstallPathUsingRegistry() const
{
QString key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\";
if (QSysInfo::currentCpuArchitecture() == "x86_64")
@@ -114,7 +109,7 @@ FilePath VisualStudioDetector::getVsInstallPathUsingRegistry()
return FilePath();
}
FilePath VisualStudioDetector::getWindowsSdkPathUsingRegistry(const std::string& version)
FilePath CxxVsHeaderPathDetector::getWindowsSdkPathUsingRegistry(const std::string& version) const
{
QString key(("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\" + version).c_str());
@@ -0,0 +1,22 @@
#ifndef CXX_VS_HEADER_PATH_DETECTOR_H
#define CXX_VS_HEADER_PATH_DETECTOR_H
#include "utility/path_detector/PathDetector.h"
class CxxVsHeaderPathDetector: public PathDetector
{
public:
CxxVsHeaderPathDetector(int version, bool isExpress);
virtual ~CxxVsHeaderPathDetector();
virtual std::vector<FilePath> getPaths() const;
private:
FilePath getVsInstallPathUsingRegistry() const;
FilePath getWindowsSdkPathUsingRegistry(const std::string& version) const;
const int m_version;
const bool m_isExpress;
};
#endif // CXX_VS_HEADER_PATH_DETECTOR_H
@@ -0,0 +1,26 @@
#include "utility/path_detector/cxx_header/utilityCxxHeaderDetection.h"
#include "utility/utilityApp.h"
#include "utility/utilityString.h"
namespace utility
{
std::vector<std::string> getCxxHeaderPaths(const std::string& compilerName)
{
std::string command = compilerName + " -x c++ -v -E /dev/null";
std::string clangOutput = utility::executeProcess(command.c_str());
std::string standardHeaders =
utility::substrBetween(clangOutput, "#include <...> search starts here:\n","\nEnd of search list");
std::vector<std::string> paths;
if (!standardHeaders.empty())
{
for (std::string s : utility::splitToVector(standardHeaders, '\n'))
{
paths.push_back(utility::trim(s));
}
}
return paths;
}
}
@@ -0,0 +1,12 @@
#ifndef UTILITY_CXX_HEADER_DETECTION_H
#define UTILITY_CXX_HEADER_DETECTION_H
#include <string>
#include <vector>
namespace utility
{
std::vector<std::string> getCxxHeaderPaths(const std::string& compilerName);
}
#endif // UTILITY_CXX_HEADER_DETECTION_H
@@ -0,0 +1,11 @@
#include "utility/path_detector/java_runtime/JavaPathDetector.h"
JavaPathDetector::JavaPathDetector(const std::string& name, const std::string& javaVersion)
: PathDetector(name)
, m_javaVersion(javaVersion)
{
}
JavaPathDetector::~JavaPathDetector()
{
}
@@ -0,0 +1,17 @@
#ifndef JAVA_PATH_DETECTOR_H
#define JAVA_PATH_DETECTOR_H
#include "utility/path_detector/PathDetector.h"
#include "utility/file/FilePath.h"
class JavaPathDetector: public PathDetector
{
public:
JavaPathDetector(const std::string& name, const std::string& javaVersion);
virtual ~JavaPathDetector();
protected:
const std::string m_javaVersion;
};
#endif // JAVA_PATH_DETECTOR_H
@@ -0,0 +1,34 @@
#include "utility/path_detector/java_runtime/JavaPathDetectorWindows.h"
#include <QSettings>
#include <QSysInfo>
JavaPathDetectorWindows::JavaPathDetectorWindows(const std::string javaVersion)
: JavaPathDetector("Java " + javaVersion + " for Windows", javaVersion)
{
}
JavaPathDetectorWindows::~JavaPathDetectorWindows()
{
}
std::vector<FilePath> JavaPathDetectorWindows::getPaths() const
{
QString key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\";
key += "Wow6432Node\\"; // we need java 32 bit
key += ("JavaSoft\\Java Runtime Environment\\" + m_javaVersion).c_str();
QSettings expressKey(key, QSettings::NativeFormat); // NativeFormat means from Registry on Windows.
QString value = expressKey.value("RuntimeLib").toString();
FilePath path(value.toStdString());
std::vector<FilePath> paths;
if (path.exists())
{
paths.push_back(path.parentDirectory());
}
return paths;
}
@@ -0,0 +1,15 @@
#ifndef JAVA_PATH_DETECTOR_WINDOWS_H
#define JAVA_PATH_DETECTOR_WINDOWS_H
#include "utility/path_detector/java_runtime/JavaPathDetector.h"
class JavaPathDetectorWindows: public JavaPathDetector
{
public:
JavaPathDetectorWindows(const std::string javaVersion);
virtual ~JavaPathDetectorWindows();
virtual std::vector<FilePath> getPaths() const;
};
#endif // JAVA_PATH_DETECTOR_WINDOWS_H