1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954 |
- #include <QCoreApplication>
- #include <QStringList>
- #include <QDir>
- #include <QJsonDocument>
- #include <QJsonObject>
- #include <QJsonArray>
- #include <QJsonValue>
- #include <QSet>
- #include <QXmlStreamReader>
- #include <QDateTime>
- #include <QStandardPaths>
- #include <QUuid>
- #include <QDirIterator>
- #include <algorithm>
- static const bool mustReadOutputAnyway = true;
- void deleteRecursively(const QString &dirName)
- {
- QDir dir(dirName);
- if (!dir.exists())
- return;
- QFileInfoList entries = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
- foreach (QFileInfo entry, entries) {
- if (entry.isDir())
- deleteRecursively(entry.absoluteFilePath());
- else
- QFile::remove(entry.absoluteFilePath());
- }
- QDir().rmdir(dirName);
- }
- FILE *openProcess(const QString &command)
- {
- #if defined(Q_OS_WIN32)
- QString processedCommand = QLatin1Char('\"') + command + QLatin1Char('\"');
- #else
- QString processedCommand = command;
- #endif
- return popen(processedCommand.toLocal8Bit().constData(), "r");
- }
- struct QtDependency
- {
- QtDependency(QString rpath, QString apath) : relativePath(rpath), absolutePath(apath) {}
- bool operator==(const QtDependency &other) const
- {
- return relativePath == other.relativePath && absolutePath == other.absolutePath;
- }
- QString relativePath;
- QString absolutePath;
- };
- struct Options
- {
- Options()
- : helpRequested(false)
- , verbose(false)
- , timing(false)
- , build(true)
- , deploymentMechanism(Bundled)
- , releasePackage(false)
- , authorPass("")
- , tizenDistributor2SignerFile("")
- , tizenDistributor2SignerPassword("")
- , tizenDistributor2CaCerFile("")
- , tizenDistributor2RootPath("")
- , installTpk(false)
- , unInstallTpk(false)
- , fetchedRemoteModificationDates(false)
- {}
- ~Options()
- {
- if (!temporaryDirectoryName.isEmpty())
- deleteRecursively(temporaryDirectoryName);
- }
- enum DeploymentMechanism
- {
- Bundled,
- Target,
- Debug
- };
- bool helpRequested;
- bool verbose;
- bool timing;
- bool build;
- QTime timer;
-
- QString tizenSdkDirectory;
- QString sdbBinary;
- QString nativeSigningBinary;
-
- QString qtInstallDirectory;
- QString qtInstallLibDirectory;
- QString qtInstallBinDirectory;
- QString outputDirectory;
- QString applicationBinary;
- QString rootPath;
- QStringList qmlImportPaths;
-
- QString tizenPlatform;
- QString architecture;
- QString toolchainBinDirectory;
- QString toolchainVersion;
- QString toolchainPrefix;
- QString qtPlatformPluginName;
-
- DeploymentMechanism deploymentMechanism;
- QString packageName;
- QString packageVersion;
- QStringList extraLibs;
- QStringList extraPlugins;
-
- bool releasePackage;
- QString authorKey;
- QString authorPass;
- QString tizenDeveloperCaCerFile;
- QString tizenDistributorSignerFile;
- QString tizenDistributorSignerPassword;
- QString tizenDistributorCaCerFile;
- QString tizenDistributor2SignerFile;
- QString tizenDistributor2SignerPassword;
- QString tizenDistributor2CaCerFile;
- QString tizenDistributor2RootPath;
-
- bool installTpk;
- bool unInstallTpk;
- QString installLocation;
-
- typedef QPair<QString, QString> BundledFile;
- QList<BundledFile> bundledFiles;
- QList<QtDependency> qtDependencies;
- QStringList localLibs;
- QString temporaryDirectoryName;
- bool fetchedRemoteModificationDates;
- QDateTime remoteModificationDate;
- QStringList permissions;
- QStringList features;
- };
- inline static bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16])
- {
- for (int x = arg.length() - 1; x >= 0; --x) {
- ushort c = arg.unicode()[x].unicode();
- if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))))
- return true;
- }
- return false;
- }
- static QString shellQuoteUnix(const QString &arg)
- {
-
- static const uchar iqm[] = {
- 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
- 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
- };
- if (!arg.length())
- return QString::fromLatin1("\"\"");
- QString ret(arg);
- if (hasSpecialChars(ret, iqm)) {
- ret.replace(QLatin1Char('\''), QLatin1String("'\\''"));
- ret.prepend(QLatin1Char('\''));
- ret.append(QLatin1Char('\''));
- }
- return ret;
- }
- static QString shellQuoteWin(const QString &arg)
- {
-
-
-
-
- static const uchar iqm[] = {
- 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10
- };
- if (!arg.length())
- return QString::fromLatin1("\"\"");
- QString ret(arg);
- if (hasSpecialChars(ret, iqm)) {
-
-
-
- ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\"\\1\\1\\^\"\""));
-
-
-
- int i = ret.length();
- while (i > 0 && ret.at(i - 1) == QLatin1Char('\\'))
- --i;
- ret.insert(i, QLatin1Char('"'));
- ret.prepend(QLatin1Char('"'));
- }
- return ret;
- }
- static QString shellQuote(const QString &arg)
- {
- if (QDir::separator() == QLatin1Char('\\'))
- return shellQuoteWin(arg);
- else
- return shellQuoteUnix(arg);
- }
- void deleteMissingFiles(const Options &options, const QDir &srcDir, const QDir &dstDir)
- {
- if (options.verbose)
- fprintf(stdout, "Delete missing files %s %s\n", qPrintable(srcDir.absolutePath()), qPrintable(dstDir.absolutePath()));
- QFileInfoList srcEntries = srcDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
- QFileInfoList dstEntries = dstDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
- foreach (const QFileInfo &dst, dstEntries) {
- bool found = false;
- foreach (const QFileInfo &src, srcEntries)
- if (dst.fileName() == src.fileName()) {
- if (dst.isDir())
- deleteMissingFiles(options, src.absoluteFilePath(), dst.absoluteFilePath());
- found = true;
- break;
- }
- if (!found) {
- if (options.verbose)
- fprintf(stdout, "%s not found in %s, removing it.\n", qPrintable(dst.fileName()), qPrintable(srcDir.absolutePath()));
- if (dst.isDir())
- deleteRecursively(dst.absolutePath());
- else
- QFile::remove(dst.absoluteFilePath());
- }
- }
- fflush(stdout);
- }
- QString cleanPackageName(QString packageName)
- {
- QRegExp legalChars(QLatin1String("[a-zA-Z0-9_\\.]"));
- packageName.replace(QLatin1Char('.'),QLatin1String("_"));
- static QStringList keywords;
- if (keywords.isEmpty()) {
- keywords << QLatin1String("abstract") << QLatin1String("continue") << QLatin1String("for")
- << QLatin1String("new") << QLatin1String("switch") << QLatin1String("assert")
- << QLatin1String("default") << QLatin1String("if") << QLatin1String("package")
- << QLatin1String("synchronized") << QLatin1String("boolean") << QLatin1String("do")
- << QLatin1String("goto") << QLatin1String("private") << QLatin1String("this")
- << QLatin1String("break") << QLatin1String("double") << QLatin1String("implements")
- << QLatin1String("protected") << QLatin1String("throw") << QLatin1String("byte")
- << QLatin1String("else") << QLatin1String("import") << QLatin1String("public")
- << QLatin1String("throws") << QLatin1String("case") << QLatin1String("enum")
- << QLatin1String("instanceof") << QLatin1String("return") << QLatin1String("transient")
- << QLatin1String("catch") << QLatin1String("extends") << QLatin1String("int")
- << QLatin1String("short") << QLatin1String("try") << QLatin1String("char")
- << QLatin1String("final") << QLatin1String("interface") << QLatin1String("static")
- << QLatin1String("void") << QLatin1String("class") << QLatin1String("finally")
- << QLatin1String("long") << QLatin1String("strictfp") << QLatin1String("volatile")
- << QLatin1String("const") << QLatin1String("float") << QLatin1String("native")
- << QLatin1String("super") << QLatin1String("while");
- }
-
- int index = -1;
- while (index < packageName.length()) {
- int next = packageName.indexOf(QLatin1Char('.'), index + 1);
- if (next == -1)
- next = packageName.length();
- QString word = packageName.mid(index + 1, next - index - 1);
- if (!word.isEmpty()) {
- QChar c = word[0];
- if ((c >= QChar(QLatin1Char('0')) && c<= QChar(QLatin1Char('9')))
- || c == QLatin1Char('_')) {
- packageName.insert(index + 1, QLatin1Char('a'));
- index = next + 1;
- continue;
- }
- }
- if (keywords.contains(word)) {
- packageName.insert(next, QLatin1String("_"));
- index = next + 1;
- } else {
- index = next;
- }
- }
- return packageName;
- }
- Options parseOptions()
- {
- Options options;
- QStringList arguments = QCoreApplication::arguments();
- for (int i=0; i<arguments.size(); ++i) {
- const QString &argument = arguments.at(i);
- if (argument.compare(QLatin1String("--output"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.outputDirectory = arguments.at(++i).trimmed();
- } else if (argument.compare(QLatin1String("--no-build"), Qt::CaseInsensitive) == 0) {
- options.build = false;
- } else if (argument.compare(QLatin1String("--install"), Qt::CaseInsensitive) == 0) {
- options.installTpk = true;
- options.unInstallTpk = true;
- } else if (argument.compare(QLatin1String("--reinstall"), Qt::CaseInsensitive) == 0) {
- options.installTpk = true;
- options.unInstallTpk = false;
- } else if (argument.compare(QLatin1String("--help"), Qt::CaseInsensitive) == 0) {
- options.helpRequested = true;
- } else if (argument.compare(QLatin1String("--verbose"), Qt::CaseInsensitive) == 0) {
- options.verbose = true;
- } else if (argument.compare(QLatin1String("--deployment"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size()) {
- options.helpRequested = true;
- } else {
- QString deploymentMechanism = arguments.at(++i);
- if (deploymentMechanism.compare(QLatin1String("target"), Qt::CaseInsensitive) == 0) {
- options.deploymentMechanism = Options::Target;
- } else if (deploymentMechanism.compare(QLatin1String("debug"), Qt::CaseInsensitive) == 0) {
- options.deploymentMechanism = Options::Debug;
- QString temporaryDirectoryName = QStandardPaths::standardLocations(QStandardPaths::TempLocation).at(0)
- + QLatin1String("/tizen-build-")
- + QUuid::createUuid().toString();
- if (QFileInfo(temporaryDirectoryName).exists()) {
- fprintf(stderr, "Temporary directory '%s' already exists. Bailing out.\n",
- qPrintable(temporaryDirectoryName));
- options.helpRequested = true;
- } else {
- QDir().mkpath(temporaryDirectoryName);
- options.temporaryDirectoryName = temporaryDirectoryName;
- }
- } else if (deploymentMechanism.compare(QLatin1String("bundled"), Qt::CaseInsensitive) == 0) {
- options.deploymentMechanism = Options::Bundled;
- } else {
- fprintf(stderr, "Unrecognized deployment mechanism: %s\n", qPrintable(deploymentMechanism));
- options.helpRequested = true;
- }
- }
- } else if (argument.compare(QLatin1String("--device"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.installLocation = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--release"), Qt::CaseInsensitive) == 0) {
- options.releasePackage = true;
- } else if (argument.compare(QLatin1String("--tizen-sdk-directory"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.tizenSdkDirectory = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--author-password"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.authorPass = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--author-key"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.authorKey = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--distributor-password"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.tizenDistributorSignerPassword= arguments.at(++i);
- } else if (argument.compare(QLatin1String("--distributor-key"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.tizenDistributorSignerFile= arguments.at(++i);
- } else if (argument.compare(QLatin1String("--qt-install-directory"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.qtInstallDirectory = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--qt-install-lib-directory"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.qtInstallLibDirectory = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--qt-install-bin-directory"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.qtInstallBinDirectory = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--toolchain-bin-directory"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.toolchainBinDirectory = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--toolchain-prefix"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.toolchainPrefix = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--sdb-binary"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.sdbBinary = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--application-binary"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.applicationBinary = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--package-name"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.packageName= arguments.at(++i);
- } else if (argument.compare(QLatin1String("--package-version"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.packageVersion= arguments.at(++i);
- } else if (argument.compare(QLatin1String("--architecture"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.architecture = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--qml-root-path"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.rootPath = arguments.at(++i);
- } else if (argument.compare(QLatin1String("--qt-platform-plugin-name"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.qtPlatformPluginName = arguments.at(++i);
- }
- }
- if (options.architecture.isEmpty()) {
- fprintf(stderr, "Error no architecture set.\n");
- options.helpRequested = true;
- }
- if (options.packageName.isEmpty()) {
- options.packageName = QString("org.qtproject.example.%1").arg(QFileInfo(options.applicationBinary).fileName());
- }
- if (options.packageVersion.isEmpty()) {
- options.packageVersion = QLatin1Literal("1.0.0");
- }
- if (options.toolchainBinDirectory.isEmpty()) {
- fprintf(stderr, "Error no toolchain-bin-directory.\n");
- options.helpRequested = true;
- }
- if (options.toolchainPrefix.isEmpty()) {
- fprintf(stderr, "Error no toolchain-prefix\n");
- options.helpRequested = true;
- }
- if (options.applicationBinary.isEmpty()) {
- fprintf(stderr, "Error application-binary was not set\n");
- options.helpRequested = true;
- }
- if (!options.authorKey.isEmpty())
- options.build = true;
- if (options.qtInstallLibDirectory.isEmpty())
- options.qtInstallLibDirectory = QDir(options.qtInstallDirectory).absoluteFilePath("lib");
- if (options.qtInstallBinDirectory.isEmpty())
- options.qtInstallBinDirectory = QDir(options.qtInstallDirectory).absoluteFilePath("bin");
- if (options.tizenSdkDirectory.isEmpty())
- options.tizenSdkDirectory = QDir::home().absoluteFilePath("tizen-sdk");
- if (options.sdbBinary.isEmpty())
- options.sdbBinary = QDir(options.tizenSdkDirectory).absoluteFilePath("tools/sdb");
- if (options.nativeSigningBinary.isEmpty())
- options.nativeSigningBinary = QDir(options.tizenSdkDirectory).absoluteFilePath("tools/ide/bin/native-signing");
- if (options.tizenDistributorSignerFile.isEmpty())
- options.tizenDistributorSignerFile = QDir(options.tizenSdkDirectory).absoluteFilePath("tools/certificate-generator/certificates/distributor/tizen-distributor-signer.p12");
- if (options.tizenDistributorSignerPassword.isEmpty())
- options.tizenDistributorSignerPassword = "tizenpkcs12passfordsigner";
- if (options.qtPlatformPluginName.isEmpty())
- options.qtPlatformPluginName = "xcb";
- options.timing = qEnvironmentVariableIsSet("TIZENDEPLOYQT_TIMING_OUTPUT");
- if (!QDir::current().mkpath(options.outputDirectory)) {
- fprintf(stderr, "Invalid output directory: %s\n", qPrintable(options.outputDirectory));
- options.outputDirectory.clear();
- } else {
- options.outputDirectory = QFileInfo(options.outputDirectory).canonicalFilePath();
- if (!options.outputDirectory.endsWith(QLatin1Char('/')))
- options.outputDirectory += QLatin1Char('/');
- }
- return options;
- }
- void printHelp()
- {
- fprintf(stderr, "Syntax: %s PARAMETERS [options]\n"
- "\n"
- " Creates an Tizen package in the build directory <destination> and\n"
- " builds it into an .tpk file.\n\n"
- " PARAMETERS:\n"
- " --output <destination>"
- " --application-binary <path/to/application/binary>"
- " Optional arguments:\n"
- " --deployment <mechanism>: Supported deployment mechanisms:\n"
- " bundled (default): Include Qt files in stand-alone package.\n"
- " ministro: Use the Ministro service to manage Qt files.\n"
- " debug: Copy Qt files to device for quick debugging.\n"
- " --no-build: Do not build the package, it is useful to just install\n"
- " a package previously built.\n"
- " --install: Installs apk to device/emulator. By default this step is\n"
- " not taken. If the application has previously been installed on\n"
- " the device, it will be uninstalled first.\n"
- " --reinstall: Installs apk to device/emulator. By default this step\n"
- " is not taken. If the application has previously been installed on\n"
- " the device, it will be overwritten, but its data will be left\n"
- " intact.\n"
- " --device [device ID]: Use specified device for deployment. Default\n"
- " is the device selected by default by adb.\n"
- " --release: Builds a package ready for release. By default, the\n"
- " package will be signed with a debug key.\n"
- " --sdb-binary <path/to/sdb/binary/sdb> By default it is set to\n"
- " <tizen0sdk-directory>/tools/sdb\n"
- " --author-key <paths/to/author.p12> Also implies the\n"
- " --release option.\n"
- " Optional arguments for use with signing:\n"
- " --author-password <password>: author key password.\n"
- " --distributor-key <path/to/distributor.p12>\n"
- " Optional arguments for use with signing:\n"
- " --distributor-password <password>: distributor key password.\n"
- " --tizen-sdk-directory <path/to/tizensdk> Also implies the\n"
- " --qt-install-bin-directory <path>: path to host bin directory. By\n"
- " default it is set to <qt-install-directory>/bin\n"
- " --qt-install-lib-directory <path>: path to target lib directory.\n"
- " By default it is set to <qt-install-directory>/lib\n"
- " --qt-install-directory <path>: path to target qt install directory.\n"
- " By default it is set to <qt-install-directory>/lib\n"
- " --qml-root-path <path>: path to target qml directory.\n"
- " By default it is set to <qt-install-directory>/lib\n"
- " --verbose: Prints out information during processing.\n"
- " --help: Displays this information.\n\n",
- qPrintable(QCoreApplication::arguments().at(0))
- );
- }
- bool quasiLexicographicalReverseLessThan(const QFileInfo &fi1, const QFileInfo &fi2)
- {
- QString s1 = fi1.baseName();
- QString s2 = fi2.baseName();
- if (s1.length() == s2.length())
- return s1 > s2;
- else
- return s1.length() > s2.length();
- }
- bool alwaysOverwritableFile(const QString &)
- {
- return false;
- }
- bool copyFileIfNewer(const QString &sourceFileName,
- const QString &destinationFileName,
- bool verbose,
- bool forceOverwrite = false)
- {
- if (QFile::exists(destinationFileName)) {
- QFileInfo destinationFileInfo(destinationFileName);
- QFileInfo sourceFileInfo(sourceFileName);
- if (!forceOverwrite
- && sourceFileInfo.lastModified() <= destinationFileInfo.lastModified()
- && !alwaysOverwritableFile(destinationFileName)) {
- if (verbose)
- fprintf(stdout, " -- Skipping file %s. Same or newer file already in place.\n", qPrintable(sourceFileName));
- return true;
- } else {
- if (!QFile(destinationFileName).remove()) {
- fprintf(stderr, "Can't remove old file: %s\n", qPrintable(destinationFileName));
- return false;
- }
- }
- }
- if (!QDir().mkpath(QFileInfo(destinationFileName).path())) {
- fprintf(stderr, "Cannot make output directory for %s.\n", qPrintable(destinationFileName));
- return false;
- }
- if (!QFile::exists(destinationFileName) && !QFile::copy(sourceFileName, destinationFileName)) {
- fprintf(stderr, "Failed to copy %s to %s.\n", qPrintable(sourceFileName), qPrintable(destinationFileName));
- return false;
- } else {
- if (verbose) {
- fprintf(stdout, " -- Copied %s\n", qPrintable(destinationFileName));
- fflush(stdout);
- }
- }
- return true;
- }
- bool copyFiles(const QDir &sourceDirectory, const QDir &destinationDirectory, bool verbose, bool forceOverwrite = false)
- {
- QFileInfoList entries = sourceDirectory.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
- foreach (QFileInfo entry, entries) {
- if (entry.isDir()) {
- QDir dir(entry.absoluteFilePath());
- if (!destinationDirectory.mkpath(dir.dirName())) {
- fprintf(stderr, "Cannot make directory %s in %s\n", qPrintable(dir.dirName()), qPrintable(destinationDirectory.path()));
- return false;
- }
- if (!copyFiles(dir, QDir(destinationDirectory.path() + QLatin1String("/") + dir.dirName()), verbose, forceOverwrite))
- return false;
- } else {
- QString destination = destinationDirectory.absoluteFilePath(entry.fileName());
- if (!copyFileIfNewer(entry.absoluteFilePath(), destination, verbose, forceOverwrite))
- return false;
- }
- }
- return true;
- }
- void cleanTopFolders(const Options &options, const QDir &srcDir, const QString &dstDir)
- {
- foreach (const QFileInfo &dir, srcDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs)) {
- if (dir.fileName() != QLatin1String("libs"))
- deleteMissingFiles(options, dir.absoluteFilePath(), dstDir + dir.fileName());
- }
- }
- QStringList allFilesInside(const QDir& current, const QDir& rootDir)
- {
- QStringList files;
- foreach (QString dir, current.entryList(QDir::Dirs|QDir::NoDotAndDotDot)) {
- files += allFilesInside(QDir(current.filePath(dir)), rootDir);
- }
- foreach (QString file, current.entryList(QDir::Files)) {
- files += rootDir.relativeFilePath(current.filePath(file));
- }
- return files;
- }
- bool updateFile(const QString &fileName, const QHash<QString, QString> &replacements)
- {
- QFile inputFile(fileName);
- if (!inputFile.open(QIODevice::ReadOnly)) {
- fprintf(stderr, "Cannot open %s for reading.\n", qPrintable(fileName));
- return false;
- }
-
-
- QByteArray contents = inputFile.readAll();
- bool hasReplacements = false;
- QHash<QString, QString>::const_iterator it;
- for (it = replacements.constBegin(); it != replacements.constEnd(); ++it) {
- forever {
- int index = contents.indexOf(it.key().toUtf8());
- if (index >= 0) {
- contents.replace(index, it.key().length(), it.value().toUtf8());
- hasReplacements = true;
- } else {
- break;
- }
- }
- }
- if (hasReplacements) {
- inputFile.close();
- if (!inputFile.open(QIODevice::WriteOnly)) {
- fprintf(stderr, "Cannot open %s for writing.\n", qPrintable(fileName));
- return false;
- }
- inputFile.write(contents);
- }
- return true;
- }
- bool updateStringsXml(const Options &options)
- {
- if (options.verbose)
- fprintf(stdout, " -- res/values/strings.xml\n");
- QHash<QString, QString> replacements;
- replacements["<!-- %%INSERT_APP_NAME%% -->"] = QFileInfo(options.applicationBinary).baseName().mid(sizeof("lib") - 1);
- QString fileName = options.outputDirectory + QLatin1String("/res/values/strings.xml");
- if (!QFile::exists(fileName)) {
- if (options.verbose)
- fprintf(stdout, " -- Create strings.xml since it's missing.\n");
- QFile file(fileName);
- if (!file.open(QIODevice::WriteOnly)) {
- fprintf(stderr, "Can't open %s for writing.\n", qPrintable(fileName));
- return false;
- }
- file.write(QByteArray("<?xml version='1.0' encoding='utf-8'?><resources><string name=\"app_name\">")
- .append(QFileInfo(options.applicationBinary).baseName().mid(sizeof("lib") - 1).toLatin1())
- .append("</string></resources>\n"));
- return true;
- }
- if (!updateFile(fileName, replacements))
- return false;
-
-
-
- QFile stringsXml(fileName);
- if (!stringsXml.open(QIODevice::ReadOnly)) {
- fprintf(stderr, "Cannot open %s for reading.\n", qPrintable(fileName));
- return false;
- }
- QXmlStreamReader reader(&stringsXml);
- while (!reader.atEnd()) {
- reader.readNext();
- if (reader.isStartElement() &&
- reader.name() == QLatin1String("string") &&
- reader.attributes().hasAttribute(QLatin1String("name")) &&
- reader.attributes().value(QLatin1String("name")) == QLatin1String("app_name")) {
- return true;
- }
- }
- replacements.clear();
- replacements["<!-- %%INSERT_STRINGS -->"] = QString(QLatin1String("<string name=\"app_name\">%1</string>\n"))
- .arg(QFileInfo(options.applicationBinary).baseName().mid(sizeof("lib") - 1));
- if (!updateFile(fileName, replacements))
- return false;
- return true;
- }
- QList<QtDependency> findFilesRecursively(const Options &options, const QFileInfo &info, const QString &rootPath)
- {
- if (!info.exists())
- return QList<QtDependency>();
- if (info.isDir()) {
- QList<QtDependency> ret;
- QDir dir(info.filePath());
- QStringList entries = dir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
- foreach (QString entry, entries) {
- QString s = info.absoluteFilePath() + QLatin1Char('/') + entry;
- ret += findFilesRecursively(options, s, rootPath);
- }
- return ret;
- } else {
- return QList<QtDependency>() << QtDependency(info.absoluteFilePath().mid(rootPath.length()), info.absoluteFilePath());
- }
- }
- QList<QtDependency> findFilesRecursively(const Options &options, const QString &fileName)
- {
- QFileInfo info(options.qtInstallDirectory + QLatin1Char('/') + fileName);
- return findFilesRecursively(options, info, options.qtInstallDirectory + QLatin1Char('/'));
- }
- QStringList getQtLibsFromElf(const Options &options, const QString &fileName)
- {
- QString readElf = QDir(options.toolchainBinDirectory)
- .absoluteFilePath(options.toolchainPrefix)
- + QLatin1String("-readelf");
- #if defined(Q_OS_WIN32)
- readElf += QLatin1String(".exe");
- #endif
- if (!QFile::exists(readElf)) {
- fprintf(stderr, "Command does not exist: %s\n", qPrintable(readElf));
- return QStringList();
- }
- readElf = QString::fromLatin1("%1 -d -W %2").arg(shellQuote(readElf)).arg(shellQuote(fileName));
- FILE *readElfCommand = openProcess(readElf);
- if (readElfCommand == 0) {
- fprintf(stderr, "Cannot execute command %s", qPrintable(readElf));
- return QStringList();
- }
- QStringList ret;
- char buffer[512];
- while (fgets(buffer, sizeof(buffer), readElfCommand) != 0) {
- QByteArray line = QByteArray::fromRawData(buffer, qstrlen(buffer));
- if (line.contains("(NEEDED)") && line.contains("Shared library:") ) {
- const int pos = line.lastIndexOf('[') + 1;
- QString libraryName = QString::fromLatin1(line.mid(pos, line.length() - pos - 2));
- if (! libraryName.startsWith("libQt"))
- continue;
- if (QFile::exists(options.qtInstallLibDirectory + QLatin1Char('/') + libraryName)) {
- ret += QString("lib/") + libraryName;
- }
- }
- }
- pclose(readElfCommand);
- return ret;
- }
- bool readDependenciesFromElf(Options *options,
- const QString &fileName,
- QSet<QString> *usedDependencies,
- QSet<QString> *remainingDependencies)
- {
-
- QStringList dependencies = getQtLibsFromElf(*options, fileName);
- if (options->verbose) {
- fprintf(stdout, "Reading dependencies from %s\n", qPrintable(fileName));
- foreach (QString dep, dependencies)
- fprintf(stdout, " %s\n", qPrintable(dep));
- }
-
- foreach (QString dependency, dependencies) {
- if (usedDependencies->contains(dependency))
- continue;
- QString absoluteDependencyPath(options->qtInstallLibDirectory + QLatin1Char('/') + QString(dependency).remove("lib/"));
- usedDependencies->insert(dependency);
- if (!readDependenciesFromElf(options,
- absoluteDependencyPath,
- usedDependencies,
- remainingDependencies)) {
- return false;
- }
- options->qtDependencies.append(QtDependency(dependency, absoluteDependencyPath));
- if (options->verbose)
- fprintf(stdout, "Appending dependency: %s\n", qPrintable(dependency));
- }
- return true;
- }
- bool goodToCopy(const Options *options, const QString &file, QStringList *unmetDependencies);
- bool scanImports(Options *options, QSet<QString> *usedDependencies)
- {
- if (options->verbose)
- fprintf(stdout, "Scanning for QML imports.\n");
- QString qmlImportScanner = QCoreApplication::applicationDirPath() + QLatin1String("/qmlimportscanner");
- #if defined(Q_OS_WIN32)
- qmlImportScanner += QLatin1String(".exe");
- #endif
- if (!QFile::exists(qmlImportScanner)) {
- fprintf(stderr, "qmlimportscanner not found: %s\n", qPrintable(qmlImportScanner));
- return false;
- }
- QString rootPath = options->rootPath;
- QStringList importPaths;
- importPaths += shellQuote(options->qtInstallDirectory + QLatin1String("/qml"));
- importPaths += QFileInfo(rootPath).absoluteFilePath();
- foreach (QString qmlImportPath, options->qmlImportPaths)
- importPaths += shellQuote(qmlImportPath);
- qmlImportScanner += QString::fromLatin1(" -rootPath %1 -importPath %2")
- .arg(shellQuote(rootPath))
- .arg(importPaths.join(QLatin1Char(' ')));
- if (options->verbose) {
- fprintf(stdout, "Running qmlimportscanner: %s.\n", qPrintable(qmlImportScanner));
- }
- FILE *qmlImportScannerCommand = popen(qmlImportScanner.toLocal8Bit().constData(), "r");
- if (qmlImportScannerCommand == 0) {
- fprintf(stderr, "Couldn't run qmlimportscanner.\n");
- return false;
- }
- QByteArray output;
- char buffer[512];
- while (fgets(buffer, sizeof(buffer), qmlImportScannerCommand) != 0)
- output += QByteArray(buffer, qstrlen(buffer));
- QJsonDocument jsonDocument = QJsonDocument::fromJson(output);
- if (jsonDocument.isNull()) {
- fprintf(stderr, "Invalid json output from qmlimportscanner.\n");
- return false;
- }
- QString absoluteOutputPath = QFileInfo(options->outputDirectory).absoluteFilePath();
- QJsonArray jsonArray = jsonDocument.array();
- for (int i=0; i<jsonArray.count(); ++i) {
- QJsonValue value = jsonArray.at(i);
- if (!value.isObject()) {
- fprintf(stderr, "Invalid format of qmlimportscanner output.\n");
- return false;
- }
- QJsonObject object = value.toObject();
- QString path = object.value(QLatin1String("path")).toString();
- if (path.isEmpty()) {
- fprintf(stderr, "Warning: QML import could not be resolved in any of the import paths: %s\n",
- qPrintable(object.value(QLatin1String("name")).toString()));
- } else {
- if (options->verbose)
- fprintf(stdout, " -- Adding '%s' as QML dependency\n", path.toLocal8Bit().constData());
- QFileInfo info(path);
-
- if (!info.exists()) {
- if (options->verbose)
- fprintf(stdout, " -- Skipping because file does not exist.\n");
- continue;
- }
- QString importPathOfThisImport;
- foreach (QString importPath, importPaths) {
- #if defined(Q_OS_WIN32)
- Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive;
- #else
- Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive;
- #endif
- QString cleanImportPath = QDir::cleanPath(importPath);
- if (info.absoluteFilePath().startsWith(cleanImportPath, caseSensitivity)) {
- importPathOfThisImport = importPath;
- break;
- }
- }
- if (importPathOfThisImport.isEmpty()) {
- fprintf(stderr, "Import found outside of import paths: %s.\n", qPrintable(info.absoluteFilePath()));
- return false;
- }
- QDir dir(importPathOfThisImport);
- importPathOfThisImport = dir.absolutePath() + QLatin1Char('/');
- QList<QtDependency> fileNames = findFilesRecursively(*options, info, importPathOfThisImport);
- foreach (QtDependency fileName, fileNames) {
- if (usedDependencies->contains(fileName.absolutePath))
- continue;
- usedDependencies->insert(fileName.absolutePath);
- if (options->verbose)
- fprintf(stdout, " -- Appending dependency found by qmlimportscanner: %s\n", qPrintable(fileName.absolutePath));
-
- fileName.relativePath.prepend("qml/");
- options->qtDependencies.append(fileName);
- if (fileName.absolutePath.endsWith(QLatin1String(".so"))) {
- QSet<QString> remainingDependencies;
- if (!readDependenciesFromElf(options, fileName.absolutePath, usedDependencies, &remainingDependencies))
- return false;
- }
- }
- }
- }
- return true;
- }
- bool readDependencies(Options *options)
- {
- if (options->verbose)
- fprintf(stdout, "Detecting dependencies of application.\n");
-
- if (!options->qtDependencies.isEmpty()) {
- if (options->verbose)
- fprintf(stdout, "\tDependencies explicitly overridden in .pro file. No detection needed.\n");
- return true;
- }
- if (options->deploymentMechanism == Options::Target)
- return true;
- QSet<QString> usedDependencies;
- QSet<QString> remainingDependencies;
-
- if (!readDependenciesFromElf(options, options->applicationBinary, &usedDependencies, &remainingDependencies))
- return false;
- QString qtDir = options->qtInstallDirectory + QLatin1Char('/');
-
- if (!options->qtPlatformPluginName.isEmpty()) {
-
- QString relativePluginPath = QString("plugins/platforms/libq%1.so").arg(options->qtPlatformPluginName);
- QString absolutePluginPath = qtDir + relativePluginPath;
- options->qtDependencies.append(QtDependency(relativePluginPath, absolutePluginPath));
- if (!readDependenciesFromElf(options, absolutePluginPath, &usedDependencies, &remainingDependencies))
- return false;
- }
- while (!remainingDependencies.isEmpty()) {
- QSet<QString>::iterator start = remainingDependencies.begin();
- QString fileName = qtDir + *start;
- remainingDependencies.erase(start);
- QStringList unmetDependencies;
- if (goodToCopy(options, fileName, &unmetDependencies)) {
- bool ok = readDependenciesFromElf(options, fileName, &usedDependencies, &remainingDependencies);
- if (!ok)
- return false;
- } else if (options->verbose) {
- fprintf(stdout, "Skipping %s due to unmet dependencies: %s\n",
- qPrintable(fileName),
- qPrintable(unmetDependencies.join(QLatin1Char(','))));
- }
- }
- QStringList::iterator it = options->localLibs.begin();
- while (it != options->localLibs.end()) {
- QStringList unmetDependencies;
- if (!goodToCopy(options, qtDir + *it, &unmetDependencies)) {
- if (options->verbose) {
- fprintf(stdout, "Skipping %s due to unmet dependencies: %s\n",
- qPrintable(*it),
- qPrintable(unmetDependencies.join(QLatin1Char(','))));
- }
- it = options->localLibs.erase(it);
- } else {
- ++it;
- }
- }
- if (!options->rootPath.isEmpty() && !scanImports(options, &usedDependencies))
- return false;
- return true;
- }
- bool stripFile(const Options &options, const QString &fileName)
- {
- QString strip = QDir(options.toolchainBinDirectory)
- .absoluteFilePath(options.toolchainPrefix)
- + QLatin1String("-strip");
- #if defined(Q_OS_WIN32)
- strip += QLatin1String(".exe");
- #endif
- if (!QFile::exists(strip)) {
- fprintf(stderr, "Command does not exist: %s\n", qPrintable(strip));
- return false;
- }
- strip = QString::fromLatin1("%1 %2").arg(shellQuote(strip)).arg(shellQuote(fileName));
- FILE *stripCommand = openProcess(strip);
- if (stripCommand == 0) {
- fprintf(stderr, "Cannot execute command %s", qPrintable(strip));
- return false;
- }
- pclose(stripCommand);
- return true;
- }
- bool stripLibraries(const Options &options)
- {
- if (options.verbose)
- fprintf(stdout, "Stripping libraries to minimize size.\n");
- QString libraryPath = options.outputDirectory
- + QLatin1String("/lib/");
- QStringList libraries = QDir(libraryPath).entryList(QDir::Files);
- foreach (QString library, libraries) {
- if (library.endsWith(".so")) {
- if (!stripFile(options, libraryPath + QLatin1Char('/') + library))
- return false;
- }
- }
- return true;
- }
- bool containsApplicationBinary(const Options &options)
- {
- if (options.verbose)
- fprintf(stdout, "Checking if application binary is in package.\n");
- QFileInfo applicationBinary(options.applicationBinary);
- if (!QFile::exists(options.applicationBinary)) {
- #if defined(Q_OS_WIN32)
- QLatin1String makeTool("mingw32-make");
- #else
- QLatin1String makeTool("make");
- #endif
- fprintf(stderr, "Application binary is not in output directory: %s. Please run '%s install INSTALL_ROOT=%s' first.\n",
- qPrintable(options.applicationBinary),
- qPrintable(makeTool),
- qPrintable(options.outputDirectory));
- return false;
- }
- return true;
- }
- FILE *runSdb(const Options &options, const QString &arguments)
- {
- if (!QFile::exists(options.sdbBinary)) {
- fprintf(stderr, "Cannot find sdb tool: %s\n", qPrintable(options.sdbBinary));
- return 0;
- }
- QString installOption;
- if (!options.installLocation.isEmpty())
- installOption = QLatin1String(" -s ") + shellQuote(options.installLocation);
- QString sdb = QString::fromLatin1("%1%2 %3").arg(shellQuote(options.sdbBinary)).arg(installOption).arg(arguments);
- if (options.verbose)
- fprintf(stdout, "Running command \"%s\"\n", sdb.toLocal8Bit().constData());
- FILE *sdbCommand = openProcess(sdb);
- if (sdbCommand == 0) {
- fprintf(stderr, "Cannot start sdb: %s\n", qPrintable(sdb));
- return 0;
- }
- return sdbCommand;
- }
- bool fetchRemoteModifications(Options *options, const QString &directory)
- {
- options->fetchedRemoteModificationDates = true;
- QString modificationFileName = directory + QLatin1String("/modification.txt");
- FILE *sdbCommand = runSdb(*options, QLatin1String("shell ") + shellQuote(QString(" [ -e %1 ] && cat %1").arg(modificationFileName)));
- if (sdbCommand == 0)
- return false;
- char buffer[2048];
- QStringList qtPaths;
- while(fgets(buffer, sizeof(buffer), sdbCommand) != 0)
- qtPaths << QString::fromUtf8(buffer,qstrlen(buffer)).trimmed();
- pclose(sdbCommand);
- if (qtPaths.size() < 2 || options->qtInstallDirectory != qtPaths.at(0) || options->qtInstallLibDirectory != qtPaths.at(1)) {
- sdbCommand = runSdb(*options, QLatin1String(" shell rm -rf ") + shellQuote(directory));
- if (options->verbose) {
- fprintf(stdout, " -- Removing old Qt libs.\n");
- while (fgets(buffer, sizeof(buffer), sdbCommand) != 0)
- fprintf(stdout, "%s", buffer);
- }
- pclose(sdbCommand);
- }
- sdbCommand = runSdb(*options, QLatin1String("shell ") + shellQuote(QString(" [ -e %1 ] && stat -c %Y %1").arg(modificationFileName)));
- if (sdbCommand == 0)
- return false;
- QByteArray result;
- while (fgets(buffer, sizeof(buffer), sdbCommand) != 0)
- result += QByteArray::fromRawData(buffer, qstrlen(buffer)).trimmed();
- pclose(sdbCommand);
- bool ok = true;
- quint64 msecsSinceEpoch = result.isEmpty() ? 0 : result.toULongLong(&ok) * 1000;
- if (!ok)
- fprintf(stderr, "wrong date format of modification file. Output: %s", qPrintable(result));
- options->remoteModificationDate = QDateTime::fromMSecsSinceEpoch(msecsSinceEpoch);
- {
- QFile file(options->temporaryDirectoryName + "/modification.txt");
- if (!file.open(QIODevice::WriteOnly)) {
- fprintf(stderr, "Cannot create modification timestamp in file %s. Error: %s.\n", qPrintable(file.fileName()),qPrintable(file.errorString()));
- return false;
- }
- file.write(options->qtInstallDirectory.toUtf8()+"\n"+options->qtInstallLibDirectory.toUtf8());
- }
- return true;
- }
- bool goodToCopy(const Options *options, const QString &file, QStringList *unmetDependencies)
- {
- if (!file.endsWith(QLatin1String(".so")))
- return true;
- bool ret = true;
- foreach (const QString &lib, getQtLibsFromElf(*options, file)) {
- if (!options->qtDependencies.contains(QtDependency(lib, options->qtInstallLibDirectory + QLatin1Char('/') + QString(lib).remove("lib/")))) {
- ret = false;
- unmetDependencies->append(lib);
- }
- }
- return ret;
- }
- bool deployToLocalTmp(Options *options,
- const QString &qtDependency, bool &wasCopiedOrUpdated)
- {
- if (!options->installTpk)
- return true;
- if (!options->fetchedRemoteModificationDates)
- fetchRemoteModifications(options, QLatin1String("/tmp/qt"));
- QString absFileName;
- if (qtDependency.startsWith("lib/"))
- absFileName = QString(options->qtInstallLibDirectory + QLatin1Char('/') + QString(qtDependency).remove(0,4));
- else
- absFileName = QString(options->qtInstallDirectory + QLatin1Char('/') + qtDependency);
- QFileInfo fileInfo(absFileName);
-
- QDateTime sourceModified = QDateTime::fromTime_t(fileInfo.lastModified().toTime_t());
- if (options->remoteModificationDate.isNull() || options->remoteModificationDate < sourceModified) {
- if (!copyFileIfNewer(absFileName,
- options->temporaryDirectoryName + QLatin1Char('/') + qtDependency,
- options->verbose)) {
- return false;
- }
- if (qtDependency.endsWith(QLatin1String(".so"))
- && !stripFile(*options, options->temporaryDirectoryName + QLatin1Char('/') + qtDependency)) {
- return false;
- }
- wasCopiedOrUpdated = true;
- } else
- wasCopiedOrUpdated = false;
- return true;
- }
- bool chrpath(const QString &rpath, const QStringList &files, Options *options, const QRegExp &paddingPatternToReplace = QRegExp())
- {
- if (files.isEmpty())
- return true;
- QString chrpathCommandStr;
- FILE *chrpathCommand;
- QHash<QString, QStringList> rpathsAndFiles;
- if (!paddingPatternToReplace.isEmpty()) {
- chrpathCommandStr = QLatin1String("chrpath -l ");
- if (options->verbose) {
- fprintf(stdout, "Running: %s\n", qPrintable(chrpathCommandStr + files.join(" ")));
- }
- chrpathCommand = openProcess(chrpathCommandStr + files.join(" "));
- if (chrpathCommand == 0) {
- fprintf(stderr, "Cannot execute command %s", qPrintable(files.join(" ")));
- return false;
- }
- size_t bufferSize = 0;
- char *rawLine = 0;
- QRegExp rpathRunPathRegExp("RPATH=|RUNTPATH=");
- QString line;
- int lineLength = 0;
- while ((lineLength = getline(&rawLine, &bufferSize, chrpathCommand)) != -1) {
- line = QString::fromLatin1(rawLine, lineLength);
- if (line.contains(paddingPatternToReplace)) {
- rpathsAndFiles[line.mid(line.indexOf(QLatin1Char(':'))+1)
- .replace(rpathRunPathRegExp,QString::null)
- .replace(paddingPatternToReplace,rpath).trimmed()] << (line.left(line.indexOf(QLatin1Char(':'))).trimmed());
- }
- }
- delete rawLine;
- int returnCode = pclose(chrpathCommand);
- if (returnCode != 0) {
- fprintf(stderr, "Warning: chrpath failed!\n");
- if (!options->verbose)
- fprintf(stderr, " -- Run with --verbose for more information.\n");
- return false;
- }
- } else {
- rpathsAndFiles[rpath] = files;
- }
- foreach(const QString &fileRpath, rpathsAndFiles.keys()) {
- chrpathCommandStr = QString::fromLatin1("chrpath -c -r %1 %2")
- .arg(shellQuote(fileRpath))
- .arg(rpathsAndFiles.value(fileRpath).join(QLatin1Char(' ')));
- if (options->verbose)
- fprintf(stdout, "Running: %s\n", qPrintable(chrpathCommandStr));
- chrpathCommand = openProcess(chrpathCommandStr);
- if (chrpathCommand == 0) {
- fprintf(stderr, "Cannot execute command %s\n", qPrintable(chrpathCommandStr));
- return false;
- }
- char buffer[512];
- while (fgets(buffer, sizeof(buffer), chrpathCommand) != 0)
- if (options->verbose)
- fprintf(stdout, "%s", buffer);
- int returnCode = pclose(chrpathCommand);
- if (returnCode != 0) {
- fprintf(stderr, "Warning: chrpath failed!\n");
- if (!options->verbose)
- fprintf(stderr, " -- Run with --verbose for more information.\n");
- return false;
- }
- }
- return true;
- }
- bool copyQtFiles(Options *options)
- {
- if (options->verbose) {
- switch (options->deploymentMechanism) {
- case Options::Bundled:
- fprintf(stdout, "Copying %d dependencies from Qt into package.\n", options->qtDependencies.size());
- break;
- case Options::Target:
- fprintf(stdout, "Setting %d dependencies from Qt in package.\n", options->qtDependencies.size());
- break;
- case Options::Debug:
- fprintf(stdout, "Copying %d dependencies from Qt to device.\n", options->qtDependencies.size());
- break;
- };
- }
- QStringList chrpathFiles;
- QString rpath(QString::fromLatin1("/opt/usr/apps/%1/lib").arg(options->packageName));
- {
- QFileInfo fInfo(options->applicationBinary);
- QString correspondingBinaryName;
- QString absolutePath = fInfo.absolutePath().append(QLatin1Char('/'));
- if (fInfo.fileName().endsWith(".so")) {
- correspondingBinaryName = absolutePath + fInfo.fileName()
- .replace(QRegExp("^lib"),"")
- .replace(QRegExp(".so$"),"");
- } else {
- correspondingBinaryName = absolutePath + fInfo.fileName()
- .prepend(QLatin1String("lib"))
- .prepend(".so");
- }
- chrpathFiles << fInfo.absoluteFilePath();
- if (QFile::exists(correspondingBinaryName))
- chrpathFiles << correspondingBinaryName;
- }
- if (options->deploymentMechanism == Options::Debug) {
-
- rpath.append(":/tmp/qt/lib");
- QDirIterator installDirIterator(options->qtInstallDirectory, QDirIterator::Subdirectories);
- QDirIterator installLibDirIterator(options->qtInstallLibDirectory, QDirIterator::Subdirectories);
- QDirIterator *dirIterator;
- QString relativePathPrefix;
- if (installDirIterator.hasNext())
- dirIterator = &installDirIterator;
- else {
- dirIterator = &installLibDirIterator;
- relativePathPrefix = QString("lib/");
- }
- bool wasCopiedOrUpdated;
- while (dirIterator->hasNext()) {
- dirIterator->next();
- QFileInfo info = dirIterator->fileInfo();
- if (!info.isDir()) {
- QString relativePath = info.absoluteFilePath().mid(dirIterator->path().length());
- if (relativePath.startsWith(QLatin1Char('/')))
- relativePath.remove(0, 1);
- relativePath = relativePathPrefix + relativePath;
- if ((relativePath.startsWith("lib/libQt") && relativePath.endsWith(".so.5"))
- || relativePath.startsWith("plugins/")
- || relativePath.startsWith("imports/")
- || relativePath.startsWith("qml/")) {
- wasCopiedOrUpdated = false;
- if (!deployToLocalTmp(options, relativePath, wasCopiedOrUpdated))
- return false;
- if(wasCopiedOrUpdated)
- options->bundledFiles += qMakePair(options->temporaryDirectoryName + QLatin1Char('/') + relativePath, relativePath);
- }
- }
- if (!dirIterator->hasNext() && dirIterator == &installDirIterator) {
- dirIterator = &installLibDirIterator;
- relativePathPrefix = QString("lib/");
- }
- }
- } else if (options->deploymentMechanism == Options::Bundled) {
- if (!options->build)
- return true;
- QString libDestinationDirectory = "lib/qt/";
- rpath.append(":/opt/usr/apps/%1/lib");
-
- foreach (QtDependency qtDependency, options->qtDependencies) {
- QString sourceFileName = qtDependency.absolutePath;
- QString destinationFileName;
- destinationFileName = libDestinationDirectory + qtDependency.relativePath;
- if (!QFile::exists(sourceFileName)) {
- fprintf(stderr, "Source Qt file does not exist: %s.\n", qPrintable(sourceFileName));
- return false;
- }
- QStringList unmetDependencies;
- if (!goodToCopy(options, sourceFileName, &unmetDependencies)) {
- if (options->verbose) {
- fprintf(stdout, " -- Skipping %s. It has unmet dependencies: %s.\n",
- qPrintable(sourceFileName),
- qPrintable(unmetDependencies.join(QLatin1Char(','))));
- }
- continue;
- }
- if (options->deploymentMechanism == Options::Bundled
- && !copyFileIfNewer(sourceFileName,
- options->outputDirectory + QLatin1Char('/') + destinationFileName,
- options->verbose)) {
- return false;
- }
- options->bundledFiles += qMakePair(options->outputDirectory + QLatin1Char('/') + destinationFileName, qtDependency.relativePath);
- }
- }
- foreach (Options::BundledFile bundled, options->bundledFiles) {
- if (bundled.first.endsWith(".so") || bundled.first.endsWith(".so.5"))
- chrpathFiles << shellQuote(bundled.first);
- }
- return chrpath(rpath, chrpathFiles, options, QRegExp("@_+PADDING_+@"));
- }
- QString findInPath(const QString &fileName)
- {
- QString path = qgetenv("PATH");
- #if defined(Q_OS_WIN32)
- QLatin1Char separator(';');
- #else
- QLatin1Char separator(':');
- #endif
- QStringList paths = path.split(separator);
- foreach (QString path, paths) {
- QFileInfo fileInfo(path + QLatin1Char('/') + fileName);
- if (fileInfo.exists() && fileInfo.isFile() && fileInfo.isExecutable())
- return path + QLatin1Char('/') + fileName;
- }
- return QString();
- }
- bool uninstallTpk(const Options &options)
- {
- if (options.verbose)
- fprintf(stdout, "Uninstalling old Tizen package %s if present.\n", qPrintable(options.packageName));
- FILE *sdbCommand = runSdb(options, QLatin1String(" shell pkgcmd -u -n") + shellQuote(options.packageName));
- if (sdbCommand == 0)
- return false;
- if (options.verbose || mustReadOutputAnyway) {
- char buffer[512];
- while (fgets(buffer, sizeof(buffer), sdbCommand) != 0)
- if (options.verbose)
- fprintf(stdout, "%s", buffer);
- }
- int returnCode = pclose(sdbCommand);
- if (returnCode != 0) {
- fprintf(stderr, "Warning: Uninstall failed!\n");
- if (!options.verbose)
- fprintf(stderr, " -- Run with --verbose for more information.\n");
- return false;
- }
- return true;
- }
- enum PackageType {
- UnsignedAPK,
- SignedAPK
- };
- QString tpkPath(const Options &options)
- {
- QString path(options.outputDirectory);
- QString tpkName = QString("%1_%2_%3.tpk")
- .arg(cleanPackageName(options.packageName))
- .arg(QString(options.packageVersion).replace(QLatin1Char('.'),QLatin1Char('_')))
- .arg(options.architecture);
- return shellQuote(QDir(path).absoluteFilePath(tpkName));
- }
- bool installTpk(const Options &options)
- {
- fflush(stdout);
-
- if (options.unInstallTpk)
- uninstallTpk(options);
- if (options.verbose)
- fprintf(stdout, "Installing Tizen package to device.\n");
- FILE *sdbCommand = runSdb(options,
- QLatin1String(" install ")
- + tpkPath(options));
- if (sdbCommand == 0)
- return false;
- if (options.verbose || mustReadOutputAnyway) {
- char buffer[512];
- while (fgets(buffer, sizeof(buffer), sdbCommand) != 0)
- if (options.verbose)
- fprintf(stdout, "%s", buffer);
- }
- int returnCode = pclose(sdbCommand);
- if (returnCode != 0) {
- fprintf(stderr, "Installing to device failed!\n");
- if (!options.verbose)
- fprintf(stderr, " -- Run with --verbose for more information.\n");
- return false;
- }
- return true;
- }
- bool copyGnuStl(Options *options)
- {
- if (options->deploymentMechanism == Options::Debug && !options->installTpk)
- return true;
- if (options->verbose)
- fprintf(stdout, "Copying GNU STL library\n");
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- return true;
- }
- bool signPackage(const Options &options)
- {
- if (options.verbose)
- fprintf(stdout, "Signing Tizen package.\n");
- if (!QFile::exists(options.nativeSigningBinary)) {
- fprintf(stderr, "Cannot find native-signing: %s.\n", qPrintable(options.nativeSigningBinary));
- return false;
- }
- QString nativeSigningTool = QString::fromLatin1("%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12")
- .arg(shellQuote(options.nativeSigningBinary))
- .arg(shellQuote(options.outputDirectory))
- .arg(shellQuote(options.tizenDeveloperCaCerFile))
- .arg(shellQuote(options.authorKey))
- .arg(shellQuote(options.authorPass))
- .arg(shellQuote(options.tizenDistributorSignerFile))
- .arg(shellQuote(options.tizenDistributorSignerPassword))
- .arg(shellQuote(options.tizenDistributorCaCerFile))
- .arg(shellQuote(options.tizenDistributor2SignerFile))
- .arg(shellQuote(options.tizenDistributor2SignerPassword))
- .arg(shellQuote(options.tizenDistributor2CaCerFile))
- .arg(shellQuote(options.tizenDistributor2RootPath));
- QStringList tpkFilesToRemove = QDir(options.outputDirectory).entryList(QStringList() << "*.tpk");
- tpkFilesToRemove << tpkPath(options);
- foreach (QString tpkFile, tpkFilesToRemove)
- QFile::remove(tpkFile);
- if (QFile::exists(tpkPath(options)) && !QFile::remove(tpkPath(options)))
- return false;
- QString qtConfFileName = options.outputDirectory+"bin/qt.conf";
- if(options.deploymentMechanism == Options::Debug) {
- QFile qtConfFile(qtConfFileName);
- if (!qtConfFile.open(QIODevice::WriteOnly)) {
- fprintf(stderr, "Cannot open %s for write.\n", qPrintable(qtConfFile.fileName()));
- return false;
- }
- qtConfFile.write(QByteArray("[Paths]\nPrefix = /tmp/qt"));
- } else if (options.deploymentMechanism == Options::Bundled) {
- QFile qtConfFile(qtConfFileName);
- if (!qtConfFile.open(QIODevice::WriteOnly)) {
- fprintf(stderr, "Cannot open %s for write.\n", qPrintable(qtConfFile.fileName()));
- return false;
- }
- qtConfFile.write(QByteArray("[Paths]\nPrefix = ../lib/qt"));
- }
- if (options.verbose)
- fprintf(stdout, "Running: %s\n", qPrintable(nativeSigningTool));
- FILE *nativeSigningCommand = openProcess(nativeSigningTool);
- if (nativeSigningCommand == 0) {
- fprintf(stderr, "Couldn't run native-signing.\n");
- if (options.deploymentMechanism == Options::Debug)
- QFile::remove(qtConfFileName);
- return false;
- }
- if (options.verbose) {
- char buffer[512];
- while (fgets(buffer, sizeof(buffer), nativeSigningCommand) != 0)
- fprintf(stdout, "%s", buffer);
- }
- int errorCode = pclose(nativeSigningCommand);
- if (errorCode != 0) {
- fprintf(stderr, "native signing command failed.\n");
- if (!options.verbose)
- fprintf(stderr, " -- Run with --verbose for more information.\n");
- return false;
- }
- QString zipTool = "zip";
- #if defined(Q_OS_WIN32)
- zipTool += QLatin1String(".exe");
- #endif
- zipTool = QStandardPaths::findExecutable(zipTool);
- if (zipTool.isEmpty()) {
- fprintf(stderr, "zip tool not found: %s\n", qPrintable(zipTool));
- return false;
- }
- QDir::setCurrent(options.outputDirectory);
- zipTool = QString::fromLatin1("%1%2 -r %3 .")
- .arg(shellQuote(zipTool))
- .arg(options.verbose ? QString::fromLatin1(" -v") : QString())
- .arg(tpkPath(options));
- if (options.verbose)
- fprintf(stdout, "Running:%s\n", qPrintable(zipTool));
- FILE *zipToolCommand = openProcess(zipTool);
- if (zipToolCommand == 0) {
- fprintf(stderr, "Couldn't run zip.\n");
- return false;
- }
- char buffer[512];
- while (fgets(buffer, sizeof(buffer), zipToolCommand) != 0)
- fprintf(stdout, "%s", buffer);
- errorCode = pclose(zipToolCommand);
- if (errorCode != 0) {
- fprintf(stderr, "zip command failed.\n");
- if (!options.verbose)
- fprintf(stderr, " -- Run with --verbose for more information.\n");
- return false;
- }
- return true;
- }
- bool copyGdbServer(const Options &options)
- {
- if (options.verbose)
- fprintf(stdout, "Copying gdbserver into package.\n");
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- return true;
- }
- bool deployAllToLocalTmp(const Options &options)
- {
- FILE *sdbCommand = runSdb(options,
- QString::fromLatin1(" push %1 /tmp/qt")
- .arg(shellQuote(options.temporaryDirectoryName)));
- if (sdbCommand == 0)
- return false;
- if (options.verbose) {
- fprintf(stdout, " -- Deploying Qt files to device.\n");
- char buffer[512];
- while (fgets(buffer, sizeof(buffer), sdbCommand) != 0)
- fprintf(stdout, "%s", buffer);
- }
- int errorCode = pclose(sdbCommand);
- if (errorCode != 0) {
- fprintf(stderr, "Copying files to device failed!\n");
- return false;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- return true;
- }
- enum ErrorCode
- {
- Success,
- SyntaxErrorOrHelpRequested = 1,
- CannotReadDependencies,
- CannotCopyGnuStl,
- CannotCopyQtFiles,
- CannotFindApplicationBinary,
- CannotCopyGdbServer,
- CannotStripLibraries,
- CannotSignPackage,
- CannotInstallTpk,
- CannotDeployAllToLocalTmp
- };
- int main(int argc, char *argv[])
- {
- QCoreApplication a(argc, argv);
- Options options = parseOptions();
- if (options.helpRequested || options.outputDirectory.isEmpty()) {
- printHelp();
- return SyntaxErrorOrHelpRequested;
- }
- options.timer.start();
- if (Q_UNLIKELY(options.timing))
- fprintf(stdout, "[TIMING] %d ms: Read input file\n", options.timer.elapsed());
- fprintf(stdout,
-
- "Generating Tizen Package\n"
- " Output directory: %s\n"
- " Application binary: %s\n"
- " Tizen build platform: %s\n"
- " Install to device: %s\n",
- qPrintable(options.outputDirectory),
- qPrintable(options.applicationBinary),
- qPrintable(options.tizenPlatform),
- options.installTpk
- ? (options.installLocation.isEmpty() ? "Default device" : qPrintable(options.installLocation))
- : "No"
- );
- if (!readDependencies(&options))
- return CannotReadDependencies;
- if (Q_UNLIKELY(options.timing))
- fprintf(stdout, "[TIMING] %d ms: Read dependencies\n", options.timer.elapsed());
- if (options.deploymentMechanism != Options::Target && !copyGnuStl(&options))
- return CannotCopyGnuStl;
- if (Q_UNLIKELY(options.timing))
- fprintf(stdout, "[TIMING] %d ms: Copied GNU STL\n", options.timer.elapsed());
- if (!copyQtFiles(&options))
- return CannotCopyQtFiles;
- if (options.installTpk && options.deploymentMechanism == Options::Debug && !deployAllToLocalTmp(options))
- return CannotDeployAllToLocalTmp;
- if (options.build) {
- if (Q_UNLIKELY(options.timing))
- fprintf(stdout, "[TIMING] %d ms: Copied Qt files\n", options.timer.elapsed());
- if (!containsApplicationBinary(options))
- return CannotFindApplicationBinary;
- if (Q_UNLIKELY(options.timing))
- fprintf(stdout, "[TIMING] %d ms: Checked for application binary\n", options.timer.elapsed());
- if (!options.releasePackage && !copyGdbServer(options))
- return CannotCopyGdbServer;
- if (Q_UNLIKELY(options.timing))
- fprintf(stdout, "[TIMING] %d ms: Copied GDB server\n", options.timer.elapsed());
- if (!stripLibraries(options))
- return CannotStripLibraries;
- if (Q_UNLIKELY(options.timing))
- fprintf(stdout, "[TIMING] %d ms: Stripped libraries\n", options.timer.elapsed());
- if (!options.authorKey.isEmpty() && !signPackage(options))
- return CannotSignPackage;
- if (Q_UNLIKELY(options.timing))
- fprintf(stdout, "[TIMING] %d ms: Signed package\n", options.timer.elapsed());
- }
- if (options.installTpk && !installTpk(options))
- return CannotInstallTpk;
- if (Q_UNLIKELY(options.timing))
- fprintf(stdout, "[TIMING] %d ms: Installed APK\n", options.timer.elapsed());
- fprintf(stdout, "Tizen package built successfully in %.3f ms.\n", options.timer.elapsed() / 1000.);
- if (options.installTpk)
- fprintf(stdout, " -- It can now be run from the selected device/emulator.\n");
- fprintf(stdout, " -- File: %s\n", qPrintable(tpkPath(options)));
- fflush(stdout);
- return 0;
- }
|