mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-16 07:55:41 +00:00
192 lines
5.0 KiB
C++
192 lines
5.0 KiB
C++
/**
|
|
* \file os.cpp
|
|
* This file is part of LyX, the document processor.
|
|
* Licence details can be found in the file COPYING.
|
|
*
|
|
* \author Ruurd A. Reitsma
|
|
* \author Enrico Forestieri
|
|
*
|
|
* Full author contact details are available in file CREDITS.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#ifdef _WIN32
|
|
# define _WIN32_WINNT 0x0600
|
|
#endif
|
|
|
|
#include "support/convert.h"
|
|
#include "support/debug.h"
|
|
#include "support/filetools.h"
|
|
#include "support/qstring_helpers.h"
|
|
|
|
#include <QDir>
|
|
|
|
#include <regex>
|
|
|
|
#if defined(__CYGWIN__)
|
|
#include "support/os_cygwin.cpp"
|
|
#elif defined(_WIN32)
|
|
#include "support/os_win32.cpp"
|
|
#else
|
|
#include "support/os_unix.cpp"
|
|
#endif
|
|
|
|
// Static assert to break compilation on platforms where
|
|
// int/unsigned int is not 4 bytes. Added to make sure that
|
|
// e.g., the author hash is always 32-bit.
|
|
template<bool Condition> struct static_assert_helper;
|
|
template <> struct static_assert_helper<true> {};
|
|
enum {
|
|
dummy = sizeof(static_assert_helper<sizeof(int) == 4>)
|
|
};
|
|
|
|
namespace lyx {
|
|
namespace support {
|
|
namespace os {
|
|
|
|
int timeout_min()
|
|
{
|
|
return 3;
|
|
}
|
|
|
|
|
|
static string const python23_call(string const & binary, bool verbose = false)
|
|
{
|
|
const string version_info = " -c \"from __future__ import print_function;import sys; print(sys.version_info[:2], end=\\\"\\\")\"";
|
|
// Default to "python" if no binary is given.
|
|
if (binary.empty())
|
|
return "python -tt";
|
|
|
|
if (verbose)
|
|
lyxerr << "Examining " << binary << "\n";
|
|
// Check whether this is a python 2 or 3 binary.
|
|
cmd_ret const out = runCommand(binary + version_info);
|
|
|
|
smatch sm;
|
|
try {
|
|
static regex const python_reg("\\((\\d*), (\\d*)\\)");
|
|
if (!out.valid || !regex_match(out.result, sm, python_reg))
|
|
return string();
|
|
} catch(regex_error const & /*e*/) {
|
|
LYXERR0("Regex error! This should not happen.");
|
|
return string();
|
|
}
|
|
|
|
int major = convert<int>(sm.str(1));
|
|
int minor = convert<int>(sm.str(2));
|
|
if((major == 2 && minor < 7) || (major == 3 && minor < 5))
|
|
return string();
|
|
|
|
if (verbose)
|
|
lyxerr << "Found Python " << out.result << "\n";
|
|
// Add the -tt switch so that mixed tab/whitespace
|
|
// indentation is an error
|
|
return binary + " -tt";
|
|
}
|
|
|
|
|
|
static string const find_python_binary()
|
|
{
|
|
// This function takes inspiration from PEP 394 and PEP 397
|
|
// PEP 394 -- The "python" Command on Unix-Like Systems
|
|
// https://www.python.org/dev/peps/pep-0394/
|
|
// PEP 397 -- Python launcher for Windows
|
|
// https://www.python.org/dev/peps/pep-0397/
|
|
|
|
#ifdef _WIN32
|
|
// Check through python launcher whether python 3 is
|
|
// installed on computer.
|
|
string command = python23_call("py -3");
|
|
#else
|
|
// Check whether python3 in PATH is the right one.
|
|
string command = python23_call("python3");
|
|
#endif // _WIN32
|
|
if (!command.empty())
|
|
return command;
|
|
|
|
#ifndef _WIN32
|
|
// python3 does not exists, let us try to find python3.x in PATH
|
|
// the search is probably broader than required
|
|
// but we are trying hard to find a valid python binary
|
|
vector<string> const path = getEnvPath("PATH");
|
|
lyxerr << "Looking for python 3.x ...\n";
|
|
for (auto bin : path) {
|
|
QString const dir = toqstr(bin);
|
|
string const localdir = dir.toLocal8Bit().constData();
|
|
QDir qdir(dir);
|
|
qdir.setFilter(QDir::Files | QDir::Executable);
|
|
QStringList list = qdir.entryList(QStringList("python3*"));
|
|
for (auto bin2 : list) {
|
|
string const binary = "\"" + addName(localdir,
|
|
bin2.toLocal8Bit().constData()) + "\"";
|
|
command = python23_call(binary, true);
|
|
if (!command.empty())
|
|
return command;
|
|
}
|
|
}
|
|
#endif // !_WIN32
|
|
|
|
// python 3 was not found let us look for python 2
|
|
#ifdef _WIN32
|
|
command = python23_call("py -2");
|
|
#else
|
|
command = python23_call("python2");
|
|
#endif // _WIN32
|
|
if (!command.empty())
|
|
return command;
|
|
|
|
#ifdef _WIN32
|
|
// python launcher is not installed, let cmd auto check
|
|
// PATH for a python.exe
|
|
command = python23_call("python");
|
|
if (!command.empty())
|
|
return command;
|
|
|
|
//failed, prepare to search PATH manually
|
|
vector<string> const path = getEnvPath("PATH");
|
|
lyxerr << "Manually looking for python in PATH ...\n";
|
|
QString const exeName = "python*";
|
|
#else
|
|
// python2 does not exists, let us try to find python2.x in PATH
|
|
// the search is probably broader than required
|
|
// but we are trying hard to find a valid python binary
|
|
lyxerr << "Looking for python 2.x ...\n";
|
|
QString const exeName = "python2*";
|
|
#endif // _WIN32
|
|
|
|
for (auto bin : path) {
|
|
QString const dir = toqstr(bin);
|
|
string const localdir = dir.toLocal8Bit().constData();
|
|
QDir qdir(dir);
|
|
qdir.setFilter(QDir::Files | QDir::Executable);
|
|
QStringList list = qdir.entryList(QStringList(exeName));
|
|
for (auto bin2 : list) {
|
|
string const binary = "\"" + addName(localdir,
|
|
bin2.toLocal8Bit().constData()) + "\"";
|
|
command = python23_call(binary, true);
|
|
if (!command.empty())
|
|
return command;
|
|
}
|
|
}
|
|
|
|
// If this happens all hope is lost that this is a sane system
|
|
lyxerr << "Warning: No python v2.x or 3.x binary found.\n";
|
|
return python23_call("");
|
|
}
|
|
|
|
|
|
string const python(bool reset)
|
|
{
|
|
static string command = find_python_binary();
|
|
// FIXME THREAD
|
|
if (reset) {
|
|
command = find_python_binary();
|
|
}
|
|
return command;
|
|
}
|
|
|
|
} // namespace os
|
|
} // namespace support
|
|
} // namespace lyx
|