1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** All rights reserved.
|
---|
5 | ** Contact: Nokia Corporation ([email protected])
|
---|
6 | **
|
---|
7 | ** This file is part of the tools applications of the Qt Toolkit.
|
---|
8 | **
|
---|
9 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
10 | ** Commercial Usage
|
---|
11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
14 | ** a written agreement between you and Nokia.
|
---|
15 | **
|
---|
16 | ** GNU Lesser General Public License Usage
|
---|
17 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
18 | ** General Public License version 2.1 as published by the Free Software
|
---|
19 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
20 | ** packaging of this file. Please review the following information to
|
---|
21 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
23 | **
|
---|
24 | ** In addition, as a special exception, Nokia gives you certain additional
|
---|
25 | ** rights. These rights are described in the Nokia Qt LGPL Exception
|
---|
26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
---|
27 | **
|
---|
28 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you have questions regarding the use of this file, please contact
|
---|
37 | ** Nokia at [email protected].
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | #include "deployment.h"
|
---|
43 | #include "remoteconnection.h"
|
---|
44 | #include <option.h>
|
---|
45 | #include <qdir.h>
|
---|
46 | #include <qfile.h>
|
---|
47 | #include <qstring.h>
|
---|
48 |
|
---|
49 | extern void debugOutput(const QString& text, int level);
|
---|
50 |
|
---|
51 | bool DeploymentHandler::deviceCopy(const DeploymentList &deploymentList)
|
---|
52 | {
|
---|
53 | for (int i=0; i<deploymentList.size(); ++i) {
|
---|
54 | CopyItem item = deploymentList.at(i);
|
---|
55 | m_connection->createDirectory(item.to.left(item.to.lastIndexOf(QLatin1Char('\\'))));
|
---|
56 | if (!m_connection->copyFileToDevice(item.from , item.to)) {
|
---|
57 | debugOutput(QString::fromLatin1("Error while copy: %1 -> %2").arg(item.from).arg(item.to),0);
|
---|
58 | return false;
|
---|
59 | }
|
---|
60 | }
|
---|
61 | return true;
|
---|
62 | }
|
---|
63 |
|
---|
64 | bool DeploymentHandler::deviceDeploy(const DeploymentList &deploymentList)
|
---|
65 | {
|
---|
66 | DeploymentList copyList;
|
---|
67 | for (int i=0; i<deploymentList.size(); ++i) {
|
---|
68 | #if defined(Q_OS_WIN)
|
---|
69 | HANDLE localHandle = CreateFile(deploymentList.at(i).from.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
|
---|
70 | if (localHandle == INVALID_HANDLE_VALUE) {
|
---|
71 | copyList.append(deploymentList.at(i));
|
---|
72 | continue;
|
---|
73 | }
|
---|
74 | FILETIME localCreationTime;
|
---|
75 | if (!GetFileTime(localHandle, NULL, NULL, &localCreationTime) || !m_connection->timeStampForLocalFileTime(&localCreationTime)) {
|
---|
76 | copyList.append(deploymentList.at(i));
|
---|
77 | CloseHandle(localHandle);
|
---|
78 | continue;
|
---|
79 | }
|
---|
80 | CloseHandle(localHandle);
|
---|
81 |
|
---|
82 | FILETIME deviceCreationTime;
|
---|
83 | if (!m_connection->fileCreationTime(deploymentList.at(i).to , &deviceCreationTime)) {
|
---|
84 | copyList.append(deploymentList.at(i));
|
---|
85 | continue;
|
---|
86 | }
|
---|
87 |
|
---|
88 | int res = CompareFileTime(&localCreationTime, &deviceCreationTime);
|
---|
89 | if (res != 0)
|
---|
90 | copyList.append(deploymentList.at(i));
|
---|
91 | else
|
---|
92 | debugOutput(QString::fromLatin1("Skipping File %1, already latest version").arg(deploymentList.at(i).from),0);
|
---|
93 | #else
|
---|
94 | copyList.append(deploymentList.at(i));
|
---|
95 | #endif
|
---|
96 | }
|
---|
97 | return deviceCopy(copyList);
|
---|
98 | }
|
---|
99 |
|
---|
100 | void DeploymentHandler::cleanup(const DeploymentList &deploymentList)
|
---|
101 | {
|
---|
102 | for (int i=0; i<deploymentList.size(); ++i) {
|
---|
103 | m_connection->deleteFile(deploymentList.at(i).to);
|
---|
104 | #ifdef Q_OS_WIN
|
---|
105 | QString path = deploymentList.at(i).to;
|
---|
106 | int pos;
|
---|
107 | while ( (pos = path.lastIndexOf(QLatin1Char('\\'))) > 0) {
|
---|
108 | path = path.left(pos);
|
---|
109 | if (!m_connection->deleteDirectory(path, false, true))
|
---|
110 | break;
|
---|
111 | }
|
---|
112 | #endif
|
---|
113 | }
|
---|
114 | }
|
---|
115 |
|
---|
116 | void DeploymentHandler::initQtDeploy(QMakeProject *project, DeploymentList &deploymentList, const QString &testPath)
|
---|
117 | {
|
---|
118 | QString targetPath = project->values("deploy.path").join(" ");
|
---|
119 | if (targetPath.isEmpty())
|
---|
120 | targetPath = testPath;
|
---|
121 | if (targetPath.endsWith("/") || targetPath.endsWith("\\"))
|
---|
122 | targetPath = targetPath.mid(0,targetPath.size()-1);
|
---|
123 |
|
---|
124 | // Only deploy Qt libs for shared build
|
---|
125 | if (!project->values("QMAKE_QT_DLL").isEmpty() && !project->values("QMAKE_LIBDIR").isEmpty()) {
|
---|
126 | QStringList libs = project->values("LIBS");
|
---|
127 | QStringList qtLibs;
|
---|
128 | QStringList libPaths;
|
---|
129 | foreach (QString item, libs) {
|
---|
130 |
|
---|
131 | if (item.startsWith("-L")) {
|
---|
132 | // -L -> a directory containing DLLs
|
---|
133 | libPaths << item.mid(2);
|
---|
134 | continue;
|
---|
135 | }
|
---|
136 |
|
---|
137 | QStringList libCandidates;
|
---|
138 |
|
---|
139 | if (item.startsWith("-l")) {
|
---|
140 | // -l -> a library located within one of the standard library paths
|
---|
141 | QString lib = item.mid(2);
|
---|
142 |
|
---|
143 | // Check if it's a Qt library first, then check in all paths given with -L.
|
---|
144 | // Note Qt libraries get a `4' appended to them, others don't.
|
---|
145 | libCandidates << project->values("QMAKE_LIBDIR").at(0) + QDir::separator() + lib + QLatin1String("4.dll");
|
---|
146 | foreach (QString const& libPath, libPaths) {
|
---|
147 | libCandidates << libPath + QDir::separator() + lib + QLatin1String(".dll");
|
---|
148 | }
|
---|
149 | } else {
|
---|
150 | libCandidates << item.replace(".lib",".dll");
|
---|
151 | }
|
---|
152 |
|
---|
153 | foreach (QString const& file, libCandidates) {
|
---|
154 | QFileInfo info(file);
|
---|
155 | if (info.exists()) {
|
---|
156 | qtLibs += info.dir().absoluteFilePath(info.fileName());
|
---|
157 | break;
|
---|
158 | }
|
---|
159 | }
|
---|
160 | }
|
---|
161 | for (QStringList::ConstIterator it = qtLibs.constBegin(); it != qtLibs.constEnd(); ++it) {
|
---|
162 | QString dllName = *it;
|
---|
163 | QFileInfo info(dllName);
|
---|
164 | if (!info.exists())
|
---|
165 | continue;
|
---|
166 | deploymentList.append(CopyItem(Option::fixPathToLocalOS(info.absoluteFilePath()) ,
|
---|
167 | Option::fixPathToLocalOS(targetPath + "/" + info.fileName())));
|
---|
168 | }
|
---|
169 | }
|
---|
170 |
|
---|
171 | #ifndef QT_CETEST_NO_ACTIVESYNC
|
---|
172 | // QtRemote deployment. We always deploy to \Windows
|
---|
173 | if (!project->values("QMAKE_LIBDIR").isEmpty()) {
|
---|
174 | QString remoteLibName = QLatin1String("QtRemote.dll");
|
---|
175 | QString remoteLib = Option::fixPathToLocalOS(project->values("QMAKE_LIBDIR").at(0) + QDir::separator() + remoteLibName);
|
---|
176 | if (QFile::exists(remoteLib))
|
---|
177 | deploymentList.append(CopyItem(remoteLib, QString::fromLatin1("\\Windows\\") + remoteLibName));
|
---|
178 | else
|
---|
179 | debugOutput(QString::fromLatin1("Could not find QtRemote. Might not be able to launch target executable"),0);
|
---|
180 | }
|
---|
181 | #endif
|
---|
182 |
|
---|
183 | // C-runtime deployment
|
---|
184 | QString runtime = project->values("QT_CE_C_RUNTIME").join(QLatin1String(" "));
|
---|
185 | debugOutput(QString::fromLatin1("Runtime:%1").arg(runtime), 2);
|
---|
186 | if (!runtime.isEmpty() && (runtime != QLatin1String("no"))) {
|
---|
187 | QString runtimeVersion = QLatin1String("msvcr");
|
---|
188 | const QString mkspec = project->values("QMAKESPEC").first();
|
---|
189 | if (mkspec.endsWith("2008"))
|
---|
190 | runtimeVersion.append("90");
|
---|
191 | else
|
---|
192 | runtimeVersion.append("80");
|
---|
193 | if (project->isActiveConfig("debug"))
|
---|
194 | runtimeVersion.append("d");
|
---|
195 | runtimeVersion.append(".dll");
|
---|
196 |
|
---|
197 | if (runtime == "yes") {
|
---|
198 | // Auto-find C-runtime
|
---|
199 | QString vcInstallDir = qgetenv("VCINSTALLDIR");
|
---|
200 | if (!vcInstallDir.isEmpty()) {
|
---|
201 | vcInstallDir += "\\ce\\dll\\";
|
---|
202 | vcInstallDir += project->values("CE_ARCH").join(QLatin1String(" "));
|
---|
203 | if (!QFileInfo(vcInstallDir + QDir::separator() + runtimeVersion).exists())
|
---|
204 | runtime.clear();
|
---|
205 | else
|
---|
206 | runtime = vcInstallDir;
|
---|
207 | }
|
---|
208 | }
|
---|
209 |
|
---|
210 | if (!runtime.isEmpty()) {
|
---|
211 | deploymentList.append(CopyItem(Option::fixPathToLocalOS(runtime + "/" + runtimeVersion ) ,
|
---|
212 | Option::fixPathToLocalOS(targetPath + "/" + runtimeVersion)));
|
---|
213 | }
|
---|
214 | }
|
---|
215 | }
|
---|
216 |
|
---|
217 | void DeploymentHandler::initProjectDeploy(QMakeProject* project, DeploymentList &deploymentList, const QString &testPath)
|
---|
218 | {
|
---|
219 | QString targetPath = project->values("deploy.path").join(" ");
|
---|
220 | if (targetPath.isEmpty())
|
---|
221 | targetPath = testPath;
|
---|
222 | if (targetPath.endsWith("/") || targetPath.endsWith("\\"))
|
---|
223 | targetPath = targetPath.mid(0,targetPath.size()-1);
|
---|
224 |
|
---|
225 | QStringList& list = project->values("DEPLOYMENT");
|
---|
226 | if (list.isEmpty())
|
---|
227 | return;
|
---|
228 |
|
---|
229 | for (int it = 0; it < list.size(); ++it) {
|
---|
230 | QString argSource = list.at(it) + QString(".sources");
|
---|
231 | QString argPath = list.at(it) + QString(".path");
|
---|
232 | if ((project->values(argSource).isEmpty() || project->values(argPath).isEmpty()) && list.at(it) != "deploy") {
|
---|
233 | debugOutput(QString::fromLatin1("cannot deploy \"%1\" because of missing data.").arg(list.at(it)), 0);
|
---|
234 | continue;
|
---|
235 | }
|
---|
236 |
|
---|
237 | QString addPath = project->values(argPath).join(QLatin1String(" "));
|
---|
238 | if (addPath == QLatin1String("."))
|
---|
239 | addPath.clear();
|
---|
240 | if (!addPath.startsWith("/") && !addPath.startsWith(QLatin1String("\\")))
|
---|
241 | addPath = targetPath + "/" + addPath;
|
---|
242 |
|
---|
243 | QStringList addSources = project->values(argSource);
|
---|
244 | addSources.replaceInStrings(QLatin1String("/"), QLatin1String("\\"));
|
---|
245 | for(int index=0; index < addSources.size(); ++index) {
|
---|
246 | QString dirstr = qmake_getpwd();
|
---|
247 | QString filestr = Option::fixPathToLocalOS(addSources.at(index), false, false);
|
---|
248 | int slsh = filestr.lastIndexOf(Option::dir_sep);
|
---|
249 | if(slsh != -1) {
|
---|
250 | dirstr = filestr.left(slsh+1);
|
---|
251 | filestr = filestr.right(filestr.length() - slsh - 1);
|
---|
252 | }
|
---|
253 | if(dirstr.right(Option::dir_sep.length()) != Option::dir_sep)
|
---|
254 | dirstr += Option::dir_sep;
|
---|
255 | QFileInfo info(dirstr + filestr);
|
---|
256 |
|
---|
257 | static int addQMakeDeployCounter = 0;
|
---|
258 | QStringList entryList = info.absoluteDir().entryList(QStringList() << info.fileName());
|
---|
259 | if (entryList.size() > 1) {
|
---|
260 | foreach(QString s, entryList) {
|
---|
261 | // We do not include directories when using wildcards
|
---|
262 | QFileInfo wildInfo(info.absolutePath() + "/" + s);
|
---|
263 | if (wildInfo.isDir()) {
|
---|
264 | continue;
|
---|
265 | }
|
---|
266 | QString appendedQmakeDeploy = QString::fromLatin1("_q_make_additional_deploy_%1").arg(addQMakeDeployCounter++);
|
---|
267 | project->parse(appendedQmakeDeploy + QLatin1String(".sources = \"") + wildInfo.absoluteFilePath());
|
---|
268 | project->parse(appendedQmakeDeploy + QLatin1String(".path = \"") + addPath);
|
---|
269 | list.append(appendedQmakeDeploy);
|
---|
270 | }
|
---|
271 | continue;
|
---|
272 | }
|
---|
273 |
|
---|
274 | if (info.isDir()) {
|
---|
275 | QDir additionalDir(dirstr + filestr);
|
---|
276 | QStringList additionalEntries = additionalDir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::NoSymLinks);
|
---|
277 | foreach(QString item, additionalEntries) {
|
---|
278 | QString appendedDeploy = QString::fromLatin1("_q_make_additional_deploy_%1").arg(addQMakeDeployCounter++);
|
---|
279 | project->parse(appendedDeploy + QLatin1String(".sources = \"") + Option::fixPathToLocalOS(additionalDir.absoluteFilePath(item)) + QLatin1String("\""));
|
---|
280 | QString appendTargetPath = project->values(argPath).join(QLatin1String(" "));
|
---|
281 | if (appendTargetPath == QLatin1String("."))
|
---|
282 | appendTargetPath = filestr;
|
---|
283 | else
|
---|
284 | appendTargetPath.append(QLatin1String("\\") + filestr);
|
---|
285 | project->parse(appendedDeploy + QLatin1String(".path = ") + appendTargetPath);
|
---|
286 | list.append(appendedDeploy);
|
---|
287 | }
|
---|
288 | } else if (entryList.size() == 1)
|
---|
289 | deploymentList.append(CopyItem(Option::fixPathToLocalOS(info.absolutePath() + "/" + entryList.at(0)) ,
|
---|
290 | Option::fixPathToLocalOS(addPath + "/" + entryList.at(0))));
|
---|
291 | }
|
---|
292 | }
|
---|
293 | }
|
---|