Changeset 561 for trunk/tools/macdeployqt/shared
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/tools/macdeployqt/shared/shared.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information ([email protected]) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation ([email protected]) 5 6 ** 6 7 ** This file is part of the tools applications of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you 37 ** @nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 51 51 52 52 bool runStripEnabled = true; 53 53 54 54 55 using std::cout; … … 62 63 QDebug operator<<(QDebug debug, const FrameworkInfo &info) 63 64 { 65 64 66 debug << "Framework directory" << info.frameworkDirectory << "\n"; 65 debug << "Framework name" << info.frameworkName << "\n";66 67 debug << "Framework path" << info.frameworkPath << "\n"; 67 68 debug << "Binary directory" << info.binaryDirectory << "\n"; … … 72 73 debug << "Deployed install name" << info.deployedInstallName << "\n"; 73 74 debug << "Source file Path" << info.sourceFilePath << "\n"; 74 debug << "Deployed Direct tory (relative to bundle)" << info.destinationDirectory << "\n";75 75 debug << "Deployed Directory (relative to bundle)" << info.destinationDirectory << "\n"; 76 76 77 return debug; 77 78 } … … 90 91 { 91 92 if (QFile::copy(from, to)) { 92 qDebug() << "copied" << from << "to" << to; 93 LogNormal() << " copied:" << from; 94 LogNormal() << " to" << to; 93 95 return true; 94 96 } else { 95 qDebug() << "ERROR: file copy failed from" << from << "to" << to; 97 LogError() << "file copy failed from" << from; 98 LogError() << " to" << to; 96 99 return false; 97 100 } 98 101 } 99 102 100 101 FrameworkInfo parseOtoolLibraryLine(const QString &line) 103 FrameworkInfo parseOtoolLibraryLine(const QString &line, bool useDebugLibs) 102 104 { 103 105 FrameworkInfo info; … … 106 108 if (trimmed.isEmpty()) 107 109 return info; 108 110 109 111 // Don't deploy system libraries. 110 112 if (trimmed.startsWith("/System/Library/") || … … 112 114 || trimmed.startsWith("@executable_path")) 113 115 return info; 114 116 115 117 enum State {QtPath, FrameworkName, DylibName, Version, End}; 116 118 State state = QtPath; … … 118 120 QString name; 119 121 QString qtPath; 122 120 123 121 124 // Split the line into [Qt-path]/lib/qt[Module].framework/Versions/[Version]/ … … 123 126 while (part < parts.count()) { 124 127 const QString currentPart = parts.at(part).simplified() ; 125 // qDebug() << "currentPart" << currentPart;126 128 ++part; 127 129 if (currentPart == "") … … 149 151 state = DylibName; 150 152 } 151 153 152 154 --part; 153 155 continue; 154 156 } 155 157 qtPath += (currentPart + "/"); 156 157 } if (state == FrameworkName) { 158 159 } if (state == FrameworkName) { 158 160 // remove ".framework" 159 161 name = currentPart; … … 164 166 continue; 165 167 } if (state == DylibName) { 166 name = 168 name = currentPart.split(" (compatibility").at(0); 167 169 info.frameworkName = name; 168 info. installName += info.frameworkName;169 info. deployedInstallName = "@executable_path/../Frameworks/" + info.frameworkName;170 info. binaryName = name;171 info.frameworkPath = info.frameworkDirectory + info. frameworkName;170 info.; 171 info.ame; 172 info.ame; 173 info.frameworkPath = info.frameworkDirectory + info.Name; 172 174 info.sourceFilePath = info.frameworkPath; 173 175 info.destinationDirectory = bundleFrameworkDirectory + "/"; 176 177 174 178 state = End; 175 179 ++part; … … 177 181 } else if (state == Version) { 178 182 info.version = currentPart; 179 info.binaryDirectory = "Versions/" + info.version; 180 info.binaryName = name ;183 info.binaryDirectory = "Versions/" + info.version; 184 info.binaryName = name; 181 185 info.binaryPath = "/" + info.binaryDirectory + "/" + info.binaryName; 182 info.installName += info.frameworkName + info.binaryPath;186 info.installName += info.frameworkName + ; 183 187 info.deployedInstallName = "@executable_path/../Frameworks/" + info.frameworkName + info.binaryPath; 184 188 info.frameworkPath = info.frameworkDirectory + info.frameworkName; 185 189 info.sourceFilePath = info.frameworkPath + info.binaryPath; 186 190 info.destinationDirectory = bundleFrameworkDirectory + "/" + info.frameworkName + "/" + info.binaryDirectory; 187 188 191 state = End; 189 192 } else if (state == End) { … … 199 202 QString appName = QFileInfo(appBundlePath).completeBaseName(); 200 203 QString binaryPath = appBundlePath + "/Contents/MacOS/" + appName; 201 204 202 205 if (QFile::exists(binaryPath)) 203 206 return binaryPath; 204 qDebug() << "Error:Could not find bundle binary for" << appBundlePath;207 Could not find bundle binary for" << appBundlePath; 205 208 return QString(); 206 209 } 207 210 208 QList<FrameworkInfo> getQtFrameworks(const QStringList &otoolLines )209 { 210 QList<FrameworkInfo> libraries; 211 QList<FrameworkInfo> getQtFrameworks(const QStringList &otoolLines) 212 { 213 QList<FrameworkInfo> libraries; 211 214 foreach(const QString line, otoolLines) { 212 FrameworkInfo info = parseOtoolLibraryLine(line );215 FrameworkInfo info = parseOtoolLibraryLine(line); 213 216 if (info.frameworkName.isEmpty() == false) { 217 218 214 219 libraries.append(info); 215 220 } … … 218 223 } 219 224 220 QList<FrameworkInfo> getQtFrameworks(const QString &path) 221 { 225 QList<FrameworkInfo> getQtFrameworks(const QString &path, bool useDebugLibs) 226 { 227 LogDebug() << "Using otool:"; 228 LogDebug() << " inspecting" << path; 222 229 QProcess otool; 223 230 otool.start("otool", QStringList() << "-L" << path); 224 231 otool.waitForFinished(); 225 232 226 233 if (otool.exitCode() != 0) { 227 qDebug() << otool.readAllStandardError();228 } 229 234 () << otool.readAllStandardError(); 235 } 236 230 237 QString output = otool.readAllStandardOutput(); 231 238 QStringList outputLines = output.split("\n"); … … 234 241 outputLines.removeFirst(); // frameworks and dylibs lists themselves as a dependency. 235 242 236 return getQtFrameworks(outputLines );243 return getQtFrameworks(outputLines); 237 244 } 238 245 … … 257 264 QString copyFramework(const FrameworkInfo &framework, const QString path) 258 265 { 259 constQString from = framework.sourceFilePath;260 constQString toDir = path + "/" + framework.destinationDirectory;261 constQString to = toDir + "/" + framework.binaryName;266 QString from = framework.sourceFilePath; 267 QString toDir = path + "/" + framework.destinationDirectory; 268 QString to = toDir + "/" + framework.binaryName; 262 269 263 270 if (QFile::exists(from) == false) { 264 qDebug() << "ERROR:no file at" << from;271 no file at" << from; 265 272 return QString(); 266 273 } … … 269 276 QDir dir; 270 277 if (dir.mkpath(toDir) == false) { 271 qDebug() << "ERROR:could not create destination directory" << to;278 could not create destination directory" << to; 272 279 return QString(); 273 280 } 274 281 275 282 276 283 if (QFile::exists(to)) { 277 // qDebug() << framework.frameworkName << "already deployed, skip";278 284 return QString(); 279 285 } 280 286 281 287 copyFilePrintStatus(from, to); 282 288 283 const QString resourcesSourcePath = framework.frameworkPath + "/Resources"; 284 const QString resourcesDestianationPath = path + "/Contents/Frameworks/" + framework.frameworkName + "/Resources"; 289 const QString resourcesSourcePath = framework.frameworkPath + "/Resources"; 290 const QString resourcesDestianationPath = path + "/Contents/Frameworks/" + framework.frameworkName + "/Resources"; 285 291 recursiveCopy(resourcesSourcePath, resourcesDestianationPath); 286 292 … … 294 300 installNametool.waitForFinished(); 295 301 if (installNametool.exitCode() != 0) { 296 qDebug() << installNametool.readAllStandardError();297 qDebug() << installNametool.readAllStandardOutput();302 () << installNametool.readAllStandardError(); 303 () << installNametool.readAllStandardOutput(); 298 304 } 299 305 } … … 301 307 void changeIdentification(const QString &id, const QString &binaryPath) 302 308 { 303 // qDebug() << "change identification on" << binaryPath << id; 309 LogDebug() << "Using install_name_tool:"; 310 LogDebug() << " change identification in" << binaryPath; 311 LogDebug() << " to" << id; 304 312 runInstallNameTool(QStringList() << "-id" << id << binaryPath); 305 313 } … … 307 315 void changeInstallName(const QString &oldName, const QString &newName, const QString &binaryPath) 308 316 { 309 // qDebug() << "change install name on" << binaryPath << oldName << newName; 317 LogDebug() << "Using install_name_tool:"; 318 LogDebug() << " in" << binaryPath; 319 LogDebug() << " change reference" << oldName; 320 LogDebug() << " to" << newName; 310 321 runInstallNameTool(QStringList() << "-change" << oldName << newName << binaryPath); 311 322 } … … 316 327 return; 317 328 329 330 318 331 QProcess strip; 319 332 strip.start("strip", QStringList() << "-x" << binaryPath); 320 333 strip.waitForFinished(); 321 334 if (strip.exitCode() != 0) { 322 qDebug() << strip.readAllStandardError(); 323 qDebug() << strip.readAllStandardOutput(); 324 } else { 325 qDebug() << "stripped" << binaryPath; 335 LogError() << strip.readAllStandardError(); 336 LogError() << strip.readAllStandardOutput(); 326 337 } 327 338 } … … 334 345 a list of actually deployed frameworks. 335 346 */ 336 DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks, const QString &bundlePath, const QString &binaryPath) 337 { 347 DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks, 348 const QString &bundlePath, const QString &binaryPath, bool useDebugLibs) 349 { 350 LogNormal(); 351 LogNormal() << "Deploying Qt frameworks found inside:" << binaryPath; 338 352 QStringList copiedFrameworks; 339 353 DeploymentInfo deploymenInfo; 340 354 341 355 while (frameworks.isEmpty() == false) { 342 356 const FrameworkInfo framework = frameworks.takeFirst(); 343 357 copiedFrameworks.append(framework.frameworkName); 344 358 345 359 // Get the qt path from one of the Qt frameworks; 346 if (deploymenInfo.qtPath == QString() && framework.frameworkName.contains("Qt")360 if (deploymenInfo.qtPath() && framework.frameworkName.contains("Qt") 347 361 && framework.frameworkDirectory.contains("/lib")) 348 362 { … … 351 365 } 352 366 353 // qDebug() << "";354 // qDebug() << "deploy" << framework.frameworkName;355 356 367 if (framework.installName.startsWith("/@executable_path/")) { 357 qDebug() << framework.frameworkName << "already deployed, skipping.";368 () << framework.frameworkName << "already deployed, skipping."; 358 369 continue; 359 370 } 360 371 361 372 // Install_name_tool the new id into the binary 362 373 changeInstallName(framework.installName, framework.deployedInstallName, binaryPath); … … 365 376 const QString deployedBinaryPath = copyFramework(framework, bundlePath); 366 377 // Skip the rest if already was deployed. 367 if (deployedBinaryPath == QString())378 if (deployedBinaryPath()) 368 379 continue; 369 380 370 381 runStrip(deployedBinaryPath); 371 382 … … 373 384 changeIdentification(framework.deployedInstallName, deployedBinaryPath); 374 385 // Check for framework dependencies 375 QList<FrameworkInfo> dependencies = getQtFrameworks(deployedBinaryPath );386 QList<FrameworkInfo> dependencies = getQtFrameworks(deployedBinaryPath); 376 387 377 388 foreach (FrameworkInfo dependency, dependencies) { 378 // qDebug() << "dependent framework" << dependency.installName << deployedBinaryPath;379 389 changeInstallName(dependency.installName, dependency.deployedInstallName, deployedBinaryPath); 380 390 381 391 // Deploy framework if neccesary. 382 392 if (copiedFrameworks.contains(dependency.frameworkName) == false && frameworks.contains(dependency) == false) { … … 389 399 } 390 400 391 DeploymentInfo deployQtFrameworks(const QString &appBundlePath )401 DeploymentInfo deployQtFrameworks(const QString &appBundlePath) 392 402 { 393 403 ApplicationBundleInfo applicationBundle; 394 404 applicationBundle.path = appBundlePath; 395 405 applicationBundle.binaryPath = findAppBinary(appBundlePath); 396 return deployQtFrameworks(getQtFrameworks(applicationBundle.binaryPath), applicationBundle.path, applicationBundle.binaryPath); 397 } 398 399 void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pluginSourcePath, const QString pluginDestinationPath, DeploymentInfo deploymentInfo) 400 { 406 QList<FrameworkInfo> frameworks = getQtFrameworks(applicationBundle.binaryPath, useDebugLibs); 407 if (frameworks.isEmpty()) { 408 LogWarning(); 409 LogWarning() << "Could not find any external Qt frameworks to deploy in" << appBundlePath; 410 LogWarning() << "Perhaps macdeployqt was already used on" << appBundlePath << "?"; 411 LogWarning() << "If so, you will need to rebuild" << appBundlePath << "before trying again."; 412 return DeploymentInfo(); 413 } else { 414 return deployQtFrameworks(frameworks, applicationBundle.path, applicationBundle.binaryPath, useDebugLibs); 415 } 416 } 417 418 void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pluginSourcePath, 419 const QString pluginDestinationPath, DeploymentInfo deploymentInfo, bool useDebugLibs) 420 { 421 LogNormal() << "Deploying plugins from" << pluginSourcePath; 401 422 QStringList plugins = QDir(pluginSourcePath).entryList(QStringList() << "*.dylib"); 402 423 403 424 foreach (QString pluginName, plugins) { 404 405 // Skip some Qt plugins based on what frameworks were deployed:406 //qDebug() << pluginSourcePath << deploymentInfo.pluginPath;407 408 425 if (pluginSourcePath.contains(deploymentInfo.pluginPath)) { 409 426 QStringList deployedFrameworks = deploymentInfo.deployedFrameworks; 410 427 411 // Skip the debug versions of the plugins 412 if (pluginName.endsWith("_debug.dylib")) 428 // Skip the debug versions of the plugins, unless specified otherwise. 429 if (!useDebugLibs && pluginName.endsWith("_debug.dylib")) 430 continue; 431 432 // Skip the release versions of the plugins, unless specified otherwise. 433 if (useDebugLibs && !pluginName.endsWith("_debug.dylib")) 413 434 continue; 414 435 … … 421 442 if (pluginName.contains("libqglgraphicssystem")) 422 443 continue; 423 #endif 444 #endif 424 445 // Deploy accessibility for Qt3Support only if the Qt3Support.framework is in use 425 446 if (deployedFrameworks.indexOf("Qt3Support.framework") == -1 && pluginName.contains("accessiblecompatwidgets")) … … 449 470 const QString destinationPath = pluginDestinationPath + "/" + pluginName; 450 471 if (copyFilePrintStatus(sourcePath, destinationPath)) { 451 452 runStrip(destinationPath); 453 454 // Special case for the phonon plugin: CoreVideo is not available as a separate framework 455 // on panther, link against the QuartzCore framework instead. (QuartzCore contians CoreVideo.) 456 if (pluginName.contains("libphonon_qt7")) { 457 changeInstallName("/System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo", 458 "/System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore", 459 destinationPath); 460 } 461 462 // qDebug() << "deploy plugin depedencies:"; 463 QList<FrameworkInfo> frameworks = getQtFrameworks(destinationPath); 464 // qDebug() << frameworks; 465 deployQtFrameworks(frameworks, appBundleInfo.path, destinationPath); 466 // qDebug() << "deploy plugin depedencies done"; 472 473 runStrip(destinationPath); 474 475 // Special case for the phonon plugin: CoreVideo is not available as a separate framework 476 // on panther, link against the QuartzCore framework instead. (QuartzCore contians CoreVideo.) 477 if (pluginName.contains("libphonon_qt7")) { 478 changeInstallName("/System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo", 479 "/System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore", 480 destinationPath); 481 } 482 483 QList<FrameworkInfo> frameworks = getQtFrameworks(destinationPath, useDebugLibs); 484 deployQtFrameworks(frameworks, appBundleInfo.path, destinationPath, useDebugLibs); 467 485 } 468 486 } // foreach plugins … … 470 488 QStringList subdirs = QDir(pluginSourcePath).entryList(QStringList() << "*", QDir::Dirs | QDir::NoDotAndDotDot); 471 489 foreach (const QString &subdir, subdirs) 472 deployPlugins(appBundleInfo, pluginSourcePath + "/" + subdir, pluginDestinationPath + "/" + subdir, deploymentInfo );490 deployPlugins(appBundleInfo, pluginSourcePath + "/" + subdir, pluginDestinationPath + "/" + subdir, deploymentInfo); 473 491 } 474 492 … … 480 498 481 499 QDir().mkpath(filePath); 482 500 483 501 QFile qtconf(fileName); 484 502 if (qtconf.exists()) { 485 qDebug() << "";486 qDebug() << "Warning:"<< fileName << "already exists, will not overwrite.";487 qDebug() << "To make sure the plugins are loaded from the correct location,";488 qDebug() << "please make sure qt.conf contains the following lines:";489 qDebug() << contents;490 qDebug() << "";503 ; 504 << fileName << "already exists, will not overwrite."; 505 g() << "To make sure the plugins are loaded from the correct location,"; 506 g() << "please make sure qt.conf contains the following lines:"; 507 ; 508 "; 491 509 return; 492 510 } … … 494 512 qtconf.open(QIODevice::WriteOnly); 495 513 if (qtconf.write(contents) != -1) { 496 qDebug() << ""; 497 qDebug() << "Created configuration file:" << fileName; 498 qDebug() << "This file sets the plugin search path to" << appBundlePath + "/Contents/PlugIns"; 499 qDebug() << ""; 500 } 501 } 502 503 void deployPlugins(const QString &appBundlePath, DeploymentInfo deploymentInfo) 514 LogNormal() << "Created configuration file:" << fileName; 515 LogNormal() << "This file sets the plugin search path to" << appBundlePath + "/Contents/PlugIns"; 516 } 517 } 518 519 void deployPlugins(const QString &appBundlePath, DeploymentInfo deploymentInfo, bool useDebugLibs) 504 520 { 505 521 ApplicationBundleInfo applicationBundle; 506 522 applicationBundle.path = appBundlePath; 507 523 applicationBundle.binaryPath = findAppBinary(appBundlePath); 508 524 509 525 const QString pluginDestinationPath = appBundlePath + "/" + "Contents/PlugIns"; 510 511 // qDebug() << ""; 512 // qDebug() << "recursively copying plugins from" << deploymentInfo.pluginPath << "to" << pluginDestinationPath; 513 deployPlugins(applicationBundle, deploymentInfo.pluginPath, pluginDestinationPath, deploymentInfo); 526 deployPlugins(applicationBundle, deploymentInfo.pluginPath, pluginDestinationPath, deploymentInfo, useDebugLibs); 514 527 } 515 528 … … 517 530 void changeQtFrameworks(const QList<FrameworkInfo> frameworks, const QString &appBinaryPath, const QString &absoluteQtPath) 518 531 { 519 qDebug() << "Changing" << appBinaryPath << "to link against Qt in" << absoluteQtPath; 532 LogNormal() << "Changing" << appBinaryPath << "to link against"; 533 LogNormal() << "Qt in" << absoluteQtPath; 520 534 QString finalQtPath = absoluteQtPath; 521 535 522 if ( absoluteQtPath.startsWith("/Library/Frameworks") == false)536 if () 523 537 finalQtPath += "/lib/"; 524 538 … … 526 540 const QString oldBinaryId = framework.installName; 527 541 const QString newBinaryId = finalQtPath + framework.frameworkName + framework.binaryPath; 528 qDebug() << "Changing" << oldBinaryId << "to" << newBinaryId;529 542 changeInstallName(oldBinaryId, newBinaryId, appBinaryPath); 530 543 } 531 544 } 532 545 533 void changeQtFrameworks(const QString appPath, const QString &qtPath )546 void changeQtFrameworks(const QString appPath, const QString &qtPath) 534 547 { 535 548 const QString appBinaryPath = findAppBinary(appPath); 536 const QList<FrameworkInfo> qtFrameworks = getQtFrameworks(appBinaryPath); 537 const QString absoluteQtPath = QDir(qtPath).absolutePath(); 538 changeQtFrameworks(qtFrameworks, appBinaryPath, absoluteQtPath); 549 const QList<FrameworkInfo> frameworks = getQtFrameworks(appBinaryPath, useDebugLibs); 550 if (frameworks.isEmpty()) { 551 LogWarning(); 552 LogWarning() << "Could not find any _external_ Qt frameworks to change in" << appPath; 553 return; 554 } else { 555 const QString absoluteQtPath = QDir(qtPath).absolutePath(); 556 changeQtFrameworks(frameworks, appBinaryPath, absoluteQtPath); 557 } 539 558 } 540 559 …