112 QCoreApplication app(argc, argv);
113 QCoreApplication::setApplicationVersion(
QStringLiteral(QT_VERSION_STR));
118 parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
119 parser.setApplicationDescription(
"Qt Resource Compiler version " QT_VERSION_STR
""_L1);
120 parser.addHelpOption();
121 parser.addVersionOption();
124 outputOption.setDescription(
QStringLiteral(
"Write output to <file> rather than stdout."));
126 parser.addOption(outputOption);
129 tempOption.setDescription(
QStringLiteral(
"Use temporary <file> for big resources."));
131 parser.addOption(tempOption);
134 parser.addOption(nameOption);
137 parser.addOption(rootOption);
139#if QT_CONFIG(zstd) && !defined(QT_NO_COMPRESS)
140# define ALGOS "[zstd], zlib, none"
142# define ALGOS "[zstd], none"
143#elif !defined(QT_NO_COMPRESS)
144# define ALGOS "[zlib], none"
146# define ALGOS "[none]"
148 const QString &algoDescription =
151 parser.addOption(compressionAlgoOption);
155 parser.addOption(compressOption);
158 parser.addOption(nocompressOption);
161 parser.addOption(noZstdOption);
164 parser.addOption(thresholdOption);
167 parser.addOption(binaryOption);
170 generatorOption.setDescription(
QStringLiteral(
"Select generator."));
171 generatorOption.setValueName(
QStringLiteral(
"cpp|python|python2"));
172 parser.addOption(generatorOption);
175 parser.addOption(passOption);
178 parser.addOption(namespaceOption);
181 parser.addOption(verboseOption);
184 parser.addOption(listOption);
187 QStringLiteral(
"Only output a mapping of resource paths to file system paths defined in the .qrc file, do not generate code."));
188 parser.addOption(mapOption);
192 parser.addOption(depFileOption);
195 parser.addOption(projectOption);
198 parser.addOption(formatVersionOption);
208 quint8 formatVersion = 3;
209 if (parser.isSet(formatVersionOption)) {
211 formatVersion = parser.value(formatVersionOption).toUInt(&ok);
213 errorMsg =
"Invalid format version specified"_L1;
214 }
else if (formatVersion < 1 || formatVersion > 3) {
215 errorMsg =
"Unsupported format version specified"_L1;
220 if (parser.isSet(nameOption))
221 library.setInitName(parser.value(nameOption));
222 if (parser.isSet(rootOption)) {
223 library.setResourceRoot(QDir::cleanPath(parser.value(rootOption)));
224 if (library.resourceRoot().isEmpty() || library.resourceRoot().at(0) != u'/')
225 errorMsg =
"Root must start with a /"_L1;
228 if (parser.isSet(compressionAlgoOption))
229 library.setCompressionAlgorithm(RCCResourceLibrary::parseCompressionAlgorithm(parser.value(compressionAlgoOption), &errorMsg));
230 if (parser.isSet(noZstdOption))
233 if (formatVersion < 3)
234 errorMsg =
"Zstandard compression requires format version 3 or higher"_L1;
235 if (library.noZstd())
236 errorMsg =
"--compression-algo=zstd and --no-zstd both specified."_L1;
238 if (parser.isSet(nocompressOption))
240 if (parser.isSet(compressOption) && errorMsg.isEmpty()) {
241 int level = library.parseCompressionLevel(library.compressionAlgorithm(), parser.value(compressOption), &errorMsg);
244 if (parser.isSet(thresholdOption))
245 library.setCompressThreshold(parser.value(thresholdOption).toInt());
246 if (parser.isSet(binaryOption))
248 if (parser.isSet(generatorOption)) {
249 auto value = parser.value(generatorOption);
250 if (value ==
"cpp"_L1) {
252 }
else if (value ==
"python"_L1) {
254 }
else if (value ==
"python2"_L1) {
255 qWarning(
"Format python2 is no longer supported, defaulting to python.");
258 errorMsg =
"Invalid generator: "_L1 + value;
262 if (parser.isSet(passOption)) {
263 if (parser.value(passOption) ==
"1"_L1)
265 else if (parser.value(passOption) ==
"2"_L1)
268 errorMsg =
"Pass number must be 1 or 2"_L1;
270 if (parser.isSet(namespaceOption))
272 if (parser.isSet(verboseOption))
275 const bool list = parser.isSet(listOption);
276 const bool map = parser.isSet(mapOption);
277 const bool projectRequested = parser.isSet(projectOption);
278 const QStringList filenamesIn = parser.positionalArguments();
280 for (
const QString &file : filenamesIn) {
283 else if (!QFile::exists(file)) {
284 qWarning(
"%s: File does not exist '%s'", argv[0],
qPrintable(file));
289 QString outFilename = parser.value(outputOption);
290 QString tempFilename = parser.value(tempOption);
291 QString depFilename = parser.value(depFileOption);
293 if (projectRequested) {
294 return createProject(outFilename);
297 if (filenamesIn.isEmpty())
300 if (!errorMsg.isEmpty()) {
301 fprintf(stderr,
"%s: %s\n", argv[0],
qPrintable(errorMsg));
306 if (!errorDevice.open(stderr, QIODevice::WriteOnly|QIODevice::Text))
309 if (library.verbose())
310 errorDevice.write(
"Qt resource compiler\n");
312 library.setInputFiles(filenamesIn);
314 if (!library.readFiles(list || map, errorDevice))
320 QIODevice::OpenMode mode = QIODevice::NotOpen;
322 case RCCResourceLibrary::C_Code:
323 case RCCResourceLibrary::Pass1:
324 case RCCResourceLibrary::Python_Code:
325 mode = QIODevice::WriteOnly | QIODevice::Text;
327 case RCCResourceLibrary::Pass2:
328 case RCCResourceLibrary::Binary:
329 mode = QIODevice::WriteOnly;
334 if (outFilename.isEmpty() || outFilename ==
"-"_L1) {
337 if (library.format() == RCCResourceLibrary::Binary)
338 _setmode(_fileno(stdout), _O_BINARY);
342 mode &= ~QIODevice::Text;
345 if (!out.open(stdout, mode)) {
346 const QString msg = QString::fromLatin1(
"Unable to open standard output for writing: %1\n")
347 .arg(out.errorString());
348 errorDevice.write(msg.toUtf8());
352 out.setFileName(outFilename);
353 if (!out.open(mode)) {
354 const QString msg = QString::fromLatin1(
"Unable to open %1 for writing: %2\n")
355 .arg(outFilename, out.errorString());
356 errorDevice.write(msg.toUtf8());
363 const QStringList data = library.dataFiles();
364 for (
int i = 0; i < data.size(); ++i) {
365 out.write(
qPrintable(QDir::cleanPath(data.at(i))));
373 for (
auto it = data.begin(), end = data.end(); it != end; ++it) {
376 out.write(
qPrintable(QDir::cleanPath(it.value())));
383 if (!depFilename.isEmpty()) {
385 depout.setFileName(depFilename);
387 if (outFilename.isEmpty() || outFilename ==
"-"_L1) {
388 const QString msg = QString::fromUtf8(
"Unable to write depfile when outputting to stdout!\n");
389 errorDevice.write(msg.toUtf8());
393 if (!depout.open(QIODevice::WriteOnly | QIODevice::Text)) {
394 const QString msg = QString::fromUtf8(
"Unable to open depfile %1 for writing: %2\n")
395 .arg(depout.fileName(), depout.errorString());
396 errorDevice.write(msg.toUtf8());
400 writeDepFile(depout, library.dataFiles(), outFilename);
405 if (!tempFilename.isEmpty()) {
406 temp.setFileName(tempFilename);
407 if (!temp.open(QIODevice::ReadOnly)) {
408 const QString msg = QString::fromUtf8(
"Unable to open temporary file %1 for reading: %2\n")
409 .arg(tempFilename, out.errorString());
410 errorDevice.write(msg.toUtf8());
414 bool success = library.output(out, temp, errorDevice);