2011-04-27 10:05:43 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2012-09-19 12:28:29 +00:00
|
|
|
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
|
|
|
|
** Contact: http://www.qt-project.org/legal
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
|
|
|
** This file is part of the tools applications of the Qt Toolkit.
|
|
|
|
**
|
|
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
2012-09-19 12:28:29 +00:00
|
|
|
** Commercial License Usage
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
** a written agreement between you and Digia. For licensing terms and
|
|
|
|
** conditions see http://qt.digia.com/licensing. For further information
|
|
|
|
** use the contact form at http://qt.digia.com/contact-us.
|
|
|
|
**
|
2011-04-27 10:05:43 +00:00
|
|
|
** GNU Lesser General Public License Usage
|
2012-09-19 12:28:29 +00:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
|
|
** General Public License version 2.1 as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
2012-09-19 12:28:29 +00:00
|
|
|
** In addition, as a special exception, Digia gives you certain additional
|
|
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
2011-04-27 10:05:43 +00:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
2011-05-24 09:34:08 +00:00
|
|
|
** GNU General Public License Usage
|
2012-09-19 12:28:29 +00:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
** General Public License version 3.0 as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.GPL included in the
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
** ensure the GNU General Public License version 3.0 requirements will be
|
|
|
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
2012-01-24 06:17:24 +00:00
|
|
|
**
|
2011-04-27 10:05:43 +00:00
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "environment.h"
|
|
|
|
|
2012-08-31 16:30:23 +00:00
|
|
|
#include <qdebug.h>
|
|
|
|
#include <qstringlist.h>
|
|
|
|
#include <qmap.h>
|
|
|
|
#include <qdir.h>
|
|
|
|
#include <qfile.h>
|
|
|
|
#include <qfileinfo.h>
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
#include <process.h>
|
2012-02-08 09:55:49 +00:00
|
|
|
#include <errno.h>
|
2011-04-27 10:05:43 +00:00
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
//#define CONFIGURE_DEBUG_EXECUTE
|
|
|
|
//#define CONFIGURE_DEBUG_CP_DIR
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
#include <qt_windows.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <windows/registry_p.h> // from tools/shared
|
|
|
|
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
|
|
|
struct CompilerInfo{
|
|
|
|
Compiler compiler;
|
|
|
|
const char *compilerStr;
|
|
|
|
const char *regKey;
|
|
|
|
const char *executable;
|
|
|
|
} compiler_info[] = {
|
|
|
|
// The compilers here are sorted in a reversed-preferred order
|
|
|
|
{CC_BORLAND, "Borland C++", 0, "bcc32.exe"},
|
|
|
|
{CC_MINGW, "MinGW (Minimalist GNU for Windows)", 0, "g++.exe"},
|
|
|
|
{CC_INTEL, "Intel(R) C++ Compiler for 32-bit applications", 0, "icl.exe"}, // xilink.exe, xilink5.exe, xilink6.exe, xilib.exe
|
|
|
|
{CC_NET2003, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2003 (7.1)", "Software\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir", "cl.exe"}, // link.exe, lib.exe
|
2012-02-24 14:56:44 +00:00
|
|
|
{CC_NET2003, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2003 (7.1)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir", "cl.exe"}, // link.exe, lib.exe
|
2011-04-27 10:05:43 +00:00
|
|
|
{CC_NET2005, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2005 (8.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\8.0", "cl.exe"}, // link.exe, lib.exe
|
2012-02-24 14:56:44 +00:00
|
|
|
{CC_NET2005, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2005 (8.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\8.0", "cl.exe"}, // link.exe, lib.exe
|
2011-04-27 10:05:43 +00:00
|
|
|
{CC_NET2008, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2008 (9.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\9.0", "cl.exe"}, // link.exe, lib.exe
|
2012-02-24 14:56:44 +00:00
|
|
|
{CC_NET2008, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2008 (9.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\9.0", "cl.exe"}, // link.exe, lib.exe
|
2011-04-27 10:05:43 +00:00
|
|
|
{CC_NET2010, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2010 (10.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\10.0", "cl.exe"}, // link.exe, lib.exe
|
2012-02-24 14:56:44 +00:00
|
|
|
{CC_NET2010, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2010 (10.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\10.0", "cl.exe"}, // link.exe, lib.exe
|
2012-08-07 17:12:41 +00:00
|
|
|
{CC_NET2012, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2012 (11.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\11.0", "cl.exe"}, // link.exe, lib.exe
|
|
|
|
{CC_NET2012, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2012 (11.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\11.0", "cl.exe"}, // link.exe, lib.exe
|
2011-04-27 10:05:43 +00:00
|
|
|
{CC_UNKNOWN, "Unknown", 0, 0},
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Initialize static variables
|
|
|
|
Compiler Environment::detectedCompiler = CC_UNKNOWN;
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Returns the pointer to the CompilerInfo for a \a compiler.
|
|
|
|
*/
|
|
|
|
CompilerInfo *Environment::compilerInfo(Compiler compiler)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
while(compiler_info[i].compiler != compiler && compiler_info[i].compiler != CC_UNKNOWN)
|
|
|
|
++i;
|
|
|
|
return &(compiler_info[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Returns the qmakespec for the compiler detected on the system.
|
|
|
|
*/
|
|
|
|
QString Environment::detectQMakeSpec()
|
|
|
|
{
|
|
|
|
QString spec;
|
|
|
|
switch (detectCompiler()) {
|
2012-08-07 17:12:41 +00:00
|
|
|
case CC_NET2012:
|
|
|
|
spec = "win32-msvc2012";
|
2012-05-16 06:50:55 +00:00
|
|
|
break;
|
2011-04-27 10:05:43 +00:00
|
|
|
case CC_NET2010:
|
|
|
|
spec = "win32-msvc2010";
|
|
|
|
break;
|
|
|
|
case CC_NET2008:
|
|
|
|
spec = "win32-msvc2008";
|
|
|
|
break;
|
|
|
|
case CC_NET2005:
|
|
|
|
spec = "win32-msvc2005";
|
|
|
|
break;
|
|
|
|
case CC_NET2003:
|
|
|
|
spec = "win32-msvc2003";
|
|
|
|
break;
|
|
|
|
case CC_INTEL:
|
|
|
|
spec = "win32-icc";
|
|
|
|
break;
|
|
|
|
case CC_MINGW:
|
|
|
|
spec = "win32-g++";
|
|
|
|
break;
|
|
|
|
case CC_BORLAND:
|
|
|
|
spec = "win32-borland";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return spec;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Returns the enum of the compiler which was detected on the system.
|
|
|
|
The compilers are detected in the order as entered into the
|
|
|
|
compiler_info list.
|
|
|
|
|
|
|
|
If more than one compiler is found, CC_UNKNOWN is returned.
|
|
|
|
*/
|
|
|
|
Compiler Environment::detectCompiler()
|
|
|
|
{
|
|
|
|
#ifndef Q_OS_WIN32
|
|
|
|
return CC_UNKNOWN; // Always generate CC_UNKNOWN on other platforms
|
|
|
|
#else
|
|
|
|
if(detectedCompiler != CC_UNKNOWN)
|
|
|
|
return detectedCompiler;
|
|
|
|
|
|
|
|
int installed = 0;
|
|
|
|
|
|
|
|
// Check for compilers in registry first, to see which version is in PATH
|
|
|
|
QString paths = qgetenv("PATH");
|
|
|
|
QStringList pathlist = paths.toLower().split(";");
|
|
|
|
for(int i = 0; compiler_info[i].compiler; ++i) {
|
|
|
|
QString productPath = qt_readRegistryKey(HKEY_LOCAL_MACHINE, compiler_info[i].regKey).toLower();
|
|
|
|
if (productPath.length()) {
|
|
|
|
QStringList::iterator it;
|
|
|
|
for(it = pathlist.begin(); it != pathlist.end(); ++it) {
|
|
|
|
if((*it).contains(productPath)) {
|
2012-02-27 10:21:10 +00:00
|
|
|
if (detectedCompiler != compiler_info[i].compiler) {
|
|
|
|
++installed;
|
|
|
|
detectedCompiler = compiler_info[i].compiler;
|
|
|
|
}
|
|
|
|
/* else {
|
|
|
|
|
|
|
|
We detected the same compiler again, which happens when
|
|
|
|
configure is build with the 64-bit compiler. Skip the
|
|
|
|
duplicate so that we don't think it's installed twice.
|
|
|
|
|
|
|
|
}
|
|
|
|
*/
|
2011-04-27 10:05:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now just go looking for the executables, and accept any executable as the lowest version
|
|
|
|
if (!installed) {
|
|
|
|
for(int i = 0; compiler_info[i].compiler; ++i) {
|
|
|
|
QString executable = QString(compiler_info[i].executable).toLower();
|
|
|
|
if (executable.length() && Environment::detectExecutable(executable)) {
|
2012-02-27 10:21:10 +00:00
|
|
|
if (detectedCompiler != compiler_info[i].compiler) {
|
|
|
|
++installed;
|
|
|
|
detectedCompiler = compiler_info[i].compiler;
|
|
|
|
}
|
|
|
|
/* else {
|
|
|
|
|
|
|
|
We detected the same compiler again, which happens when
|
|
|
|
configure is build with the 64-bit compiler. Skip the
|
|
|
|
duplicate so that we don't think it's installed twice.
|
|
|
|
|
|
|
|
}
|
|
|
|
*/
|
2011-04-27 10:05:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (installed > 1) {
|
|
|
|
cout << "Found more than one known compiler! Using \"" << compilerInfo(detectedCompiler)->compilerStr << "\"" << endl;
|
|
|
|
detectedCompiler = CC_UNKNOWN;
|
|
|
|
}
|
|
|
|
return detectedCompiler;
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Returns true if the \a executable could be loaded, else false.
|
|
|
|
This means that the executable either is in the current directory
|
|
|
|
or in the PATH.
|
|
|
|
*/
|
|
|
|
bool Environment::detectExecutable(const QString &executable)
|
|
|
|
{
|
|
|
|
PROCESS_INFORMATION procInfo;
|
|
|
|
memset(&procInfo, 0, sizeof(procInfo));
|
|
|
|
|
|
|
|
STARTUPINFO startInfo;
|
|
|
|
memset(&startInfo, 0, sizeof(startInfo));
|
|
|
|
startInfo.cb = sizeof(startInfo);
|
|
|
|
|
|
|
|
bool couldExecute = CreateProcess(0, (wchar_t*)executable.utf16(),
|
|
|
|
0, 0, false,
|
|
|
|
CREATE_NO_WINDOW | CREATE_SUSPENDED,
|
|
|
|
0, 0, &startInfo, &procInfo);
|
|
|
|
|
|
|
|
if (couldExecute) {
|
|
|
|
CloseHandle(procInfo.hThread);
|
|
|
|
TerminateProcess(procInfo.hProcess, 0);
|
|
|
|
CloseHandle(procInfo.hProcess);
|
|
|
|
}
|
|
|
|
return couldExecute;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Creates a commandling from \a program and it \a arguments,
|
|
|
|
escaping characters that needs it.
|
|
|
|
*/
|
|
|
|
static QString qt_create_commandline(const QString &program, const QStringList &arguments)
|
|
|
|
{
|
|
|
|
QString programName = program;
|
|
|
|
if (!programName.startsWith("\"") && !programName.endsWith("\"") && programName.contains(" "))
|
|
|
|
programName = "\"" + programName + "\"";
|
|
|
|
programName.replace("/", "\\");
|
|
|
|
|
|
|
|
QString args;
|
|
|
|
// add the prgram as the first arrg ... it works better
|
|
|
|
args = programName + " ";
|
|
|
|
for (int i=0; i<arguments.size(); ++i) {
|
|
|
|
QString tmp = arguments.at(i);
|
|
|
|
// in the case of \" already being in the string the \ must also be escaped
|
|
|
|
tmp.replace( "\\\"", "\\\\\"" );
|
|
|
|
// escape a single " because the arguments will be parsed
|
|
|
|
tmp.replace( "\"", "\\\"" );
|
|
|
|
if (tmp.isEmpty() || tmp.contains(' ') || tmp.contains('\t')) {
|
|
|
|
// The argument must not end with a \ since this would be interpreted
|
|
|
|
// as escaping the quote -- rather put the \ behind the quote: e.g.
|
|
|
|
// rather use "foo"\ than "foo\"
|
|
|
|
QString endQuote("\"");
|
|
|
|
int i = tmp.length();
|
|
|
|
while (i>0 && tmp.at(i-1) == '\\') {
|
|
|
|
--i;
|
|
|
|
endQuote += "\\";
|
|
|
|
}
|
|
|
|
args += QString(" \"") + tmp.left(i) + endQuote;
|
|
|
|
} else {
|
|
|
|
args += ' ' + tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return args;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Creates a QByteArray of the \a environment.
|
|
|
|
*/
|
|
|
|
static QByteArray qt_create_environment(const QStringList &environment)
|
|
|
|
{
|
|
|
|
QByteArray envlist;
|
|
|
|
if (environment.isEmpty())
|
|
|
|
return envlist;
|
|
|
|
|
|
|
|
int pos = 0;
|
|
|
|
// add PATH if necessary (for DLL loading)
|
|
|
|
QByteArray path = qgetenv("PATH");
|
|
|
|
if (environment.filter(QRegExp("^PATH=",Qt::CaseInsensitive)).isEmpty() && !path.isNull()) {
|
|
|
|
QString tmp = QString(QLatin1String("PATH=%1")).arg(QString::fromLocal8Bit(path));
|
|
|
|
uint tmpSize = sizeof(wchar_t) * (tmp.length() + 1);
|
|
|
|
envlist.resize(envlist.size() + tmpSize);
|
|
|
|
memcpy(envlist.data() + pos, tmp.utf16(), tmpSize);
|
|
|
|
pos += tmpSize;
|
|
|
|
}
|
|
|
|
// add the user environment
|
|
|
|
foreach (const QString &tmp, environment) {
|
|
|
|
uint tmpSize = sizeof(wchar_t) * (tmp.length() + 1);
|
|
|
|
envlist.resize(envlist.size() + tmpSize);
|
|
|
|
memcpy(envlist.data() + pos, tmp.utf16(), tmpSize);
|
|
|
|
pos += tmpSize;
|
|
|
|
}
|
|
|
|
// add the 2 terminating 0 (actually 4, just to be on the safe side)
|
|
|
|
envlist.resize(envlist.size() + 4);
|
|
|
|
envlist[pos++] = 0;
|
|
|
|
envlist[pos++] = 0;
|
|
|
|
envlist[pos++] = 0;
|
|
|
|
envlist[pos++] = 0;
|
|
|
|
|
|
|
|
return envlist;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Executes the command described in \a arguments, in the
|
|
|
|
environment inherited from the parent process, with the
|
|
|
|
\a additionalEnv settings applied.
|
|
|
|
\a removeEnv removes the specified environment variables from
|
|
|
|
the environment of the executed process.
|
|
|
|
|
|
|
|
Returns the exit value of the process, or -1 if the command could
|
|
|
|
not be executed.
|
|
|
|
|
|
|
|
This function uses _(w)spawnvpe to spawn a process by searching
|
|
|
|
through the PATH environment variable.
|
|
|
|
*/
|
|
|
|
int Environment::execute(QStringList arguments, const QStringList &additionalEnv, const QStringList &removeEnv)
|
|
|
|
{
|
|
|
|
#ifdef CONFIGURE_DEBUG_EXECUTE
|
|
|
|
qDebug() << "About to Execute: " << arguments;
|
|
|
|
qDebug() << " " << QDir::currentPath();
|
|
|
|
qDebug() << " " << additionalEnv;
|
|
|
|
qDebug() << " " << removeEnv;
|
|
|
|
#endif
|
|
|
|
// Create the full environment from the current environment and
|
|
|
|
// the additionalEnv strings, then remove all variables defined
|
|
|
|
// in removeEnv
|
|
|
|
QMap<QString, QString> fullEnvMap;
|
|
|
|
LPWSTR envStrings = GetEnvironmentStrings();
|
|
|
|
if (envStrings) {
|
|
|
|
int strLen = 0;
|
|
|
|
for (LPWSTR envString = envStrings; *(envString); envString += strLen + 1) {
|
|
|
|
strLen = wcslen(envString);
|
|
|
|
QString str = QString((const QChar*)envString, strLen);
|
|
|
|
if (!str.startsWith("=")) { // These are added by the system
|
|
|
|
int sepIndex = str.indexOf('=');
|
|
|
|
fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FreeEnvironmentStrings(envStrings);
|
|
|
|
|
|
|
|
// Add additionalEnv variables
|
|
|
|
for (int i = 0; i < additionalEnv.count(); ++i) {
|
|
|
|
const QString &str = additionalEnv.at(i);
|
|
|
|
int sepIndex = str.indexOf('=');
|
|
|
|
fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove removeEnv variables
|
|
|
|
for (int j = 0; j < removeEnv.count(); ++j)
|
|
|
|
fullEnvMap.remove(removeEnv.at(j).toUpper());
|
|
|
|
|
|
|
|
// Add all variables to a QStringList
|
|
|
|
QStringList fullEnv;
|
|
|
|
QMapIterator<QString, QString> it(fullEnvMap);
|
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
|
|
|
fullEnv += QString(it.key() + "=" + it.value());
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------
|
|
|
|
QString program = arguments.takeAt(0);
|
|
|
|
QString args = qt_create_commandline(program, arguments);
|
|
|
|
QByteArray envlist = qt_create_environment(fullEnv);
|
|
|
|
|
|
|
|
DWORD exitCode = DWORD(-1);
|
|
|
|
PROCESS_INFORMATION procInfo;
|
|
|
|
memset(&procInfo, 0, sizeof(procInfo));
|
|
|
|
|
|
|
|
STARTUPINFO startInfo;
|
|
|
|
memset(&startInfo, 0, sizeof(startInfo));
|
|
|
|
startInfo.cb = sizeof(startInfo);
|
|
|
|
|
|
|
|
bool couldExecute = CreateProcess(0, (wchar_t*)args.utf16(),
|
|
|
|
0, 0, true, CREATE_UNICODE_ENVIRONMENT,
|
|
|
|
envlist.isEmpty() ? 0 : envlist.data(),
|
|
|
|
0, &startInfo, &procInfo);
|
|
|
|
|
|
|
|
if (couldExecute) {
|
|
|
|
WaitForSingleObject(procInfo.hProcess, INFINITE);
|
|
|
|
GetExitCodeProcess(procInfo.hProcess, &exitCode);
|
|
|
|
CloseHandle(procInfo.hThread);
|
|
|
|
CloseHandle(procInfo.hProcess);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (exitCode == DWORD(-1)) {
|
|
|
|
switch(GetLastError()) {
|
|
|
|
case E2BIG:
|
|
|
|
cerr << "execute: Argument list exceeds 1024 bytes" << endl;
|
|
|
|
foreach (const QString &arg, arguments)
|
|
|
|
cerr << " (" << arg.toLocal8Bit().constData() << ")" << endl;
|
|
|
|
break;
|
|
|
|
case ENOENT:
|
|
|
|
cerr << "execute: File or path is not found (" << program.toLocal8Bit().constData() << ")" << endl;
|
|
|
|
break;
|
|
|
|
case ENOEXEC:
|
|
|
|
cerr << "execute: Specified file is not executable or has invalid executable-file format (" << program.toLocal8Bit().constData() << ")" << endl;
|
|
|
|
break;
|
|
|
|
case ENOMEM:
|
|
|
|
cerr << "execute: Not enough memory is available to execute new process." << endl;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cerr << "execute: Unknown error" << endl;
|
|
|
|
foreach (const QString &arg, arguments)
|
|
|
|
cerr << " (" << arg.toLocal8Bit().constData() << ")" << endl;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return exitCode;
|
|
|
|
}
|
|
|
|
|
2012-02-14 09:01:17 +00:00
|
|
|
/*!
|
|
|
|
Executes \a command with _popen() and returns the stdout of the command.
|
|
|
|
|
|
|
|
Taken from qmake's system() command.
|
|
|
|
*/
|
2011-12-30 00:44:16 +00:00
|
|
|
QString Environment::execute(const QString &command, int *returnCode)
|
2012-02-14 09:01:17 +00:00
|
|
|
{
|
|
|
|
QString output;
|
|
|
|
FILE *proc = _popen(command.toLatin1().constData(), "r");
|
|
|
|
char buff[256];
|
|
|
|
while (proc && !feof(proc)) {
|
|
|
|
int read_in = int(fread(buff, 1, 255, proc));
|
|
|
|
if (!read_in)
|
|
|
|
break;
|
|
|
|
buff[read_in] = '\0';
|
|
|
|
output += buff;
|
|
|
|
}
|
2011-12-30 00:44:16 +00:00
|
|
|
if (proc) {
|
|
|
|
int r = _pclose(proc);
|
|
|
|
if (returnCode)
|
|
|
|
*returnCode = r;
|
|
|
|
}
|
2012-02-14 09:01:17 +00:00
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
/*!
|
|
|
|
Copies the \a srcDir contents into \a destDir.
|
|
|
|
|
|
|
|
Returns true if copying was successful.
|
|
|
|
*/
|
2012-04-20 15:58:24 +00:00
|
|
|
bool Environment::cpdir(const QString &srcDir, const QString &destDir)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
QString cleanSrcName = QDir::cleanPath(srcDir);
|
|
|
|
QString cleanDstName = QDir::cleanPath(destDir);
|
|
|
|
|
|
|
|
#ifdef CONFIGURE_DEBUG_CP_DIR
|
|
|
|
qDebug() << "Attempt to cpdir " << cleanSrcName << "->" << cleanDstName;
|
|
|
|
#endif
|
|
|
|
if(!QFile::exists(cleanDstName) && !QDir().mkpath(cleanDstName)) {
|
|
|
|
qDebug() << "cpdir: Failure to create " << cleanDstName;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool result = true;
|
|
|
|
QDir dir = QDir(cleanSrcName);
|
|
|
|
QFileInfoList allEntries = dir.entryInfoList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
|
|
|
|
for (int i = 0; result && (i < allEntries.count()); ++i) {
|
|
|
|
QFileInfo entry = allEntries.at(i);
|
|
|
|
bool intermediate = true;
|
|
|
|
if (entry.isDir()) {
|
|
|
|
intermediate = cpdir(QString("%1/%2").arg(cleanSrcName).arg(entry.fileName()),
|
2012-04-20 15:58:24 +00:00
|
|
|
QString("%1/%2").arg(cleanDstName).arg(entry.fileName()));
|
2011-04-27 10:05:43 +00:00
|
|
|
} else {
|
|
|
|
QString destFile = QString("%1/%2").arg(cleanDstName).arg(entry.fileName());
|
|
|
|
#ifdef CONFIGURE_DEBUG_CP_DIR
|
|
|
|
qDebug() << "About to cp (file)" << entry.absoluteFilePath() << "->" << destFile;
|
|
|
|
#endif
|
|
|
|
QFile::remove(destFile);
|
2012-04-20 15:58:24 +00:00
|
|
|
intermediate = QFile::copy(entry.absoluteFilePath(), destFile);
|
|
|
|
SetFileAttributes((wchar_t*)destFile.utf16(), FILE_ATTRIBUTE_NORMAL);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
if(!intermediate) {
|
|
|
|
qDebug() << "cpdir: Failure for " << entry.fileName() << entry.isDir();
|
|
|
|
result = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Environment::rmdir(const QString &name)
|
|
|
|
{
|
|
|
|
bool result = true;
|
|
|
|
QString cleanName = QDir::cleanPath(name);
|
|
|
|
|
|
|
|
QDir dir = QDir(cleanName);
|
|
|
|
QFileInfoList allEntries = dir.entryInfoList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
|
|
|
|
for (int i = 0; result && (i < allEntries.count()); ++i) {
|
|
|
|
QFileInfo entry = allEntries.at(i);
|
|
|
|
if (entry.isDir()) {
|
|
|
|
result &= rmdir(entry.absoluteFilePath());
|
|
|
|
} else {
|
|
|
|
result &= QFile::remove(entry.absoluteFilePath());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result &= dir.rmdir(cleanName);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
QT_END_NAMESPACE
|