2016-12-30 15:11:20 +00:00
/****************************************************************************
* *
* * Copyright ( C ) 2016 The Qt Company Ltd .
* * Contact : https : //www.qt.io/licensing/
* *
* * This file is part of the QtQml module of the Qt Toolkit .
* *
* * $ QT_BEGIN_LICENSE : GPL - EXCEPT $
* * Commercial License Usage
* * Licensees holding valid commercial Qt licenses may use this file in
* * accordance with the commercial license agreement provided with the
* * Software or , alternatively , in accordance with the terms contained in
* * a written agreement between you and The Qt Company . For licensing terms
* * and conditions see https : //www.qt.io/terms-conditions. For further
* * information use the contact form at https : //www.qt.io/contact-us.
* *
* * GNU General Public License Usage
* * Alternatively , this file may be used under the terms of the GNU
* * General Public License version 3 as published by the Free Software
* * Foundation with exceptions as appearing in the file LICENSE . GPL3 - EXCEPT
* * included in the packaging of this file . Please review the following
* * information to ensure the GNU General Public License requirements will
* * be met : https : //www.gnu.org/licenses/gpl-3.0.html.
* *
* * $ QT_END_LICENSE $
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <QCoreApplication>
# include <QStringList>
# include <QCommandLineParser>
# include <QFile>
# include <QFileInfo>
# include <QDateTime>
2017-03-14 18:26:14 +00:00
# include <QHashFunctions>
2018-01-22 15:46:03 +00:00
# include <QSaveFile>
2016-12-30 15:11:20 +00:00
# include <private/qqmlirbuilder_p.h>
# include <private/qqmljsparser_p.h>
2018-02-12 13:03:13 +00:00
# include <private/qqmljslexer_p.h>
2016-12-30 15:11:20 +00:00
2018-01-22 15:46:03 +00:00
# include "resourcefilemapper.h"
int filterResourceFile ( const QString & input , const QString & output ) ;
bool generateLoader ( const QStringList & compiledFiles , const QString & output , const QStringList & resourceFileMappings , QString * errorString ) ;
QString symbolNamespaceForPath ( const QString & relativePath ) ;
2018-01-15 14:36:25 +00:00
QSet < QString > illegalNames ;
void setupIllegalNames ( )
{
// #### this in incomplete
illegalNames . insert ( QStringLiteral ( " Math " ) ) ;
illegalNames . insert ( QStringLiteral ( " Array " ) ) ;
illegalNames . insert ( QStringLiteral ( " String " ) ) ;
illegalNames . insert ( QStringLiteral ( " Function " ) ) ;
illegalNames . insert ( QStringLiteral ( " Boolean " ) ) ;
illegalNames . insert ( QStringLiteral ( " Number " ) ) ;
illegalNames . insert ( QStringLiteral ( " Date " ) ) ;
illegalNames . insert ( QStringLiteral ( " RegExp " ) ) ;
illegalNames . insert ( QStringLiteral ( " Error " ) ) ;
illegalNames . insert ( QStringLiteral ( " Object " ) ) ;
}
2016-12-30 15:11:20 +00:00
struct Error
{
QString message ;
void print ( ) ;
Error augment ( const QString & contextErrorMessage ) const ;
} ;
void Error : : print ( )
{
fprintf ( stderr , " %s \n " , qPrintable ( message ) ) ;
}
Error Error : : augment ( const QString & contextErrorMessage ) const
{
Error augmented ;
augmented . message = contextErrorMessage + message ;
return augmented ;
}
QString diagnosticErrorMessage ( const QString & fileName , const QQmlJS : : DiagnosticMessage & m )
{
QString message ;
message = fileName + QLatin1Char ( ' : ' ) + QString : : number ( m . loc . startLine ) + QLatin1Char ( ' : ' ) ;
if ( m . loc . startColumn > 0 )
message + = QString : : number ( m . loc . startColumn ) + QLatin1Char ( ' : ' ) ;
if ( m . isError ( ) )
message + = QLatin1String ( " error: " ) ;
else
message + = QLatin1String ( " warning: " ) ;
message + = m . message ;
return message ;
}
2017-03-10 08:17:35 +00:00
// Ensure that ListElement objects keep all property assignments in their string form
static void annotateListElements ( QmlIR : : Document * document )
{
QStringList listElementNames ;
foreach ( const QV4 : : CompiledData : : Import * import , document - > imports ) {
const QString uri = document - > stringAt ( import - > uriIndex ) ;
if ( uri ! = QStringLiteral ( " QtQml.Models " ) & & uri ! = QStringLiteral ( " QtQuick " ) )
continue ;
QString listElementName = QStringLiteral ( " ListElement " ) ;
const QString qualifier = document - > stringAt ( import - > qualifierIndex ) ;
if ( ! qualifier . isEmpty ( ) ) {
listElementName . prepend ( QLatin1Char ( ' . ' ) ) ;
listElementName . prepend ( qualifier ) ;
}
listElementNames . append ( listElementName ) ;
}
if ( listElementNames . isEmpty ( ) )
return ;
foreach ( QmlIR : : Object * object , document - > objects ) {
if ( ! listElementNames . contains ( document - > stringAt ( object - > inheritedTypeNameIndex ) ) )
continue ;
for ( QmlIR : : Binding * binding = object - > firstBinding ( ) ; binding ; binding = binding - > next ) {
if ( binding - > type ! = QV4 : : CompiledData : : Binding : : Type_Script )
continue ;
binding - > stringIndex = document - > registerString ( object - > bindingAsString ( document , binding - > value . compiledScriptIndex ) ) ;
}
}
}
2017-09-12 15:20:47 +00:00
static bool checkArgumentsObjectUseInSignalHandlers ( const QmlIR : : Document & doc , Error * error )
{
for ( QmlIR : : Object * object : qAsConst ( doc . objects ) ) {
for ( auto binding = object - > bindingsBegin ( ) ; binding ! = object - > bindingsEnd ( ) ; + + binding ) {
if ( binding - > type ! = QV4 : : CompiledData : : Binding : : Type_Script )
continue ;
const QString propName = doc . stringAt ( binding - > propertyNameIndex ) ;
if ( ! propName . startsWith ( QLatin1String ( " on " ) )
| | propName . length ( ) < 3
| | ! propName . at ( 2 ) . isUpper ( ) )
continue ;
auto compiledFunction = doc . jsModule . functions . value ( object - > runtimeFunctionIndices . at ( binding - > value . compiledScriptIndex ) ) ;
if ( ! compiledFunction )
continue ;
2017-10-22 10:05:18 +00:00
if ( compiledFunction - > usesArgumentsObject = = QV4 : : Compiler : : Context : : ArgumentsObjectUsed ) {
2017-09-12 15:20:47 +00:00
error - > message = QLatin1Char ( ' : ' ) + QString : : number ( compiledFunction - > line ) + QLatin1Char ( ' : ' ) ;
if ( compiledFunction - > column > 0 )
error - > message + = QString : : number ( compiledFunction - > column ) + QLatin1Char ( ' : ' ) ;
error - > message + = QLatin1String ( " error: The use of the arguments object in signal handlers is \n "
" not supported when compiling qml files ahead of time, because it may be ambiguous if \n "
" any signal parameter is called \" arguments \" . Unfortunately we cannot distinguish \n "
" between it being a parameter or the JavaScript arguments object at this point. \n "
" Consider renaming the parameter of the signal if applicable. " ) ;
return false ;
}
}
}
return true ;
}
2018-01-22 15:46:03 +00:00
using SaveFunction = std : : function < bool ( QV4 : : CompiledData : : CompilationUnit * , QString * ) > ;
static bool compileQmlFile ( const QString & inputFileName , SaveFunction saveFunction , Error * error )
2016-12-30 15:11:20 +00:00
{
QmlIR : : Document irDocument ( /*debugMode*/ false ) ;
QString sourceCode ;
{
QFile f ( inputFileName ) ;
if ( ! f . open ( QIODevice : : ReadOnly ) ) {
error - > message = QLatin1String ( " Error opening " ) + inputFileName + QLatin1Char ( ' : ' ) + f . errorString ( ) ;
return false ;
}
sourceCode = QString : : fromUtf8 ( f . readAll ( ) ) ;
if ( f . error ( ) ! = QFileDevice : : NoError ) {
error - > message = QLatin1String ( " Error reading from " ) + inputFileName + QLatin1Char ( ' : ' ) + f . errorString ( ) ;
return false ;
}
}
{
QmlIR : : IRBuilder irBuilder ( illegalNames ) ;
if ( ! irBuilder . generateFromQml ( sourceCode , inputFileName , & irDocument ) ) {
for ( const QQmlJS : : DiagnosticMessage & parseError : qAsConst ( irBuilder . errors ) ) {
if ( ! error - > message . isEmpty ( ) )
error - > message + = QLatin1Char ( ' \n ' ) ;
error - > message + = diagnosticErrorMessage ( inputFileName , parseError ) ;
}
return false ;
}
}
2017-03-10 08:17:35 +00:00
annotateListElements ( & irDocument ) ;
2016-12-30 15:11:20 +00:00
{
2017-06-22 08:01:17 +00:00
QmlIR : : JSCodeGen v4CodeGen ( irDocument . code ,
2017-06-12 08:27:54 +00:00
& irDocument . jsGenerator , & irDocument . jsModule ,
& irDocument . jsParserEngine , irDocument . program ,
2018-02-21 09:41:54 +00:00
/*import cache*/ nullptr , & irDocument . jsGenerator . stringTable , illegalNames ) ;
2017-07-07 09:40:30 +00:00
v4CodeGen . setUseFastLookups ( false ) ; // Disable lookups in non-standalone (aka QML) mode
2016-12-30 15:11:20 +00:00
for ( QmlIR : : Object * object : qAsConst ( irDocument . objects ) ) {
if ( object - > functionsAndExpressions - > count = = 0 )
continue ;
QList < QmlIR : : CompiledFunctionOrExpression > functionsToCompile ;
for ( QmlIR : : CompiledFunctionOrExpression * foe = object - > functionsAndExpressions - > first ; foe ; foe = foe - > next ) {
foe - > disableAcceleratedLookups = true ;
functionsToCompile < < * foe ;
}
const QVector < int > runtimeFunctionIndices = v4CodeGen . generateJSCodeForFunctionsAndBindings ( functionsToCompile ) ;
QList < QQmlJS : : DiagnosticMessage > jsErrors = v4CodeGen . errors ( ) ;
if ( ! jsErrors . isEmpty ( ) ) {
for ( const QQmlJS : : DiagnosticMessage & e : qAsConst ( jsErrors ) ) {
if ( ! error - > message . isEmpty ( ) )
error - > message + = QLatin1Char ( ' \n ' ) ;
error - > message + = diagnosticErrorMessage ( inputFileName , e ) ;
}
return false ;
}
QQmlJS : : MemoryPool * pool = irDocument . jsParserEngine . pool ( ) ;
object - > runtimeFunctionIndices . allocate ( pool , runtimeFunctionIndices ) ;
}
2017-09-12 15:20:47 +00:00
if ( ! checkArgumentsObjectUseInSignalHandlers ( irDocument , error ) ) {
* error = error - > augment ( inputFileName ) ;
return false ;
}
2016-12-30 15:11:20 +00:00
QmlIR : : QmlUnitGenerator generator ;
2017-06-22 08:01:17 +00:00
irDocument . javaScriptCompilationUnit = v4CodeGen . generateCompilationUnit ( /*generate unit*/ false ) ;
2017-03-15 09:09:54 +00:00
QV4 : : CompiledData : : Unit * unit = generator . generate ( irDocument ) ;
2016-12-30 15:11:20 +00:00
unit - > flags | = QV4 : : CompiledData : : Unit : : StaticData ;
2017-01-03 12:19:15 +00:00
unit - > flags | = QV4 : : CompiledData : : Unit : : PendingTypeCompilation ;
2016-12-30 15:11:20 +00:00
irDocument . javaScriptCompilationUnit - > data = unit ;
2018-01-22 15:46:03 +00:00
if ( ! saveFunction ( irDocument . javaScriptCompilationUnit , & error - > message ) )
2016-12-30 15:11:20 +00:00
return false ;
free ( unit ) ;
}
return true ;
}
2018-01-22 15:46:03 +00:00
static bool compileJSFile ( const QString & inputFileName , const QString & inputFileUrl , SaveFunction saveFunction , Error * error )
2016-12-30 15:11:20 +00:00
{
QmlIR : : Document irDocument ( /*debugMode*/ false ) ;
QString sourceCode ;
{
QFile f ( inputFileName ) ;
if ( ! f . open ( QIODevice : : ReadOnly ) ) {
error - > message = QLatin1String ( " Error opening " ) + inputFileName + QLatin1Char ( ' : ' ) + f . errorString ( ) ;
return false ;
}
sourceCode = QString : : fromUtf8 ( f . readAll ( ) ) ;
if ( f . error ( ) ! = QFileDevice : : NoError ) {
error - > message = QLatin1String ( " Error reading from " ) + inputFileName + QLatin1Char ( ' : ' ) + f . errorString ( ) ;
return false ;
}
}
QQmlJS : : Engine * engine = & irDocument . jsParserEngine ;
QmlIR : : ScriptDirectivesCollector directivesCollector ( engine , & irDocument . jsGenerator ) ;
QQmlJS : : Directives * oldDirs = engine - > directives ( ) ;
engine - > setDirectives ( & directivesCollector ) ;
QQmlJS : : AST : : Program * program = nullptr ;
{
QQmlJS : : Lexer lexer ( engine ) ;
lexer . setCode ( sourceCode , /*line*/ 1 , /*parseAsBinding*/ false ) ;
QQmlJS : : Parser parser ( engine ) ;
bool parsed = parser . parseProgram ( ) ;
for ( const QQmlJS : : DiagnosticMessage & parseError : parser . diagnosticMessages ( ) ) {
if ( ! error - > message . isEmpty ( ) )
error - > message + = QLatin1Char ( ' \n ' ) ;
error - > message + = diagnosticErrorMessage ( inputFileName , parseError ) ;
}
if ( ! parsed ) {
engine - > setDirectives ( oldDirs ) ;
return false ;
}
program = QQmlJS : : AST : : cast < QQmlJS : : AST : : Program * > ( parser . rootNode ( ) ) ;
if ( ! program ) {
lexer . setCode ( QStringLiteral ( " undefined; " ) , 1 , false ) ;
parsed = parser . parseProgram ( ) ;
Q_ASSERT ( parsed ) ;
program = QQmlJS : : AST : : cast < QQmlJS : : AST : : Program * > ( parser . rootNode ( ) ) ;
Q_ASSERT ( program ) ;
}
}
{
2017-06-22 08:01:17 +00:00
QmlIR : : JSCodeGen v4CodeGen ( irDocument . code , & irDocument . jsGenerator ,
2017-06-12 08:27:54 +00:00
& irDocument . jsModule , & irDocument . jsParserEngine ,
2018-02-21 09:41:54 +00:00
irDocument . program , /*import cache*/ nullptr ,
2018-01-30 09:42:34 +00:00
& irDocument . jsGenerator . stringTable , illegalNames ) ;
2017-07-07 09:40:30 +00:00
v4CodeGen . setUseFastLookups ( false ) ; // Disable lookups in non-standalone (aka QML) mode
2018-01-30 09:42:34 +00:00
v4CodeGen . generateFromProgram ( inputFileName , inputFileUrl , sourceCode , program ,
& irDocument . jsModule , QV4 : : Compiler : : GlobalCode ) ;
2016-12-30 15:11:20 +00:00
QList < QQmlJS : : DiagnosticMessage > jsErrors = v4CodeGen . errors ( ) ;
if ( ! jsErrors . isEmpty ( ) ) {
for ( const QQmlJS : : DiagnosticMessage & e : qAsConst ( jsErrors ) ) {
if ( ! error - > message . isEmpty ( ) )
error - > message + = QLatin1Char ( ' \n ' ) ;
error - > message + = diagnosticErrorMessage ( inputFileName , e ) ;
}
engine - > setDirectives ( oldDirs ) ;
return false ;
}
QmlIR : : QmlUnitGenerator generator ;
2017-06-22 08:01:17 +00:00
irDocument . javaScriptCompilationUnit = v4CodeGen . generateCompilationUnit ( /*generate unit*/ false ) ;
2017-03-15 09:09:54 +00:00
QV4 : : CompiledData : : Unit * unit = generator . generate ( irDocument ) ;
2016-12-30 15:11:20 +00:00
unit - > flags | = QV4 : : CompiledData : : Unit : : StaticData ;
irDocument . javaScriptCompilationUnit - > data = unit ;
2018-01-22 15:46:03 +00:00
if ( ! saveFunction ( irDocument . javaScriptCompilationUnit , & error - > message ) ) {
2016-12-30 15:11:20 +00:00
engine - > setDirectives ( oldDirs ) ;
return false ;
}
free ( unit ) ;
}
engine - > setDirectives ( oldDirs ) ;
return true ;
}
2018-01-22 15:46:03 +00:00
static bool saveUnitAsCpp ( const QString & inputFileName , const QString & outputFileName , QV4 : : CompiledData : : CompilationUnit * unit , QString * errorString )
{
QSaveFile f ( outputFileName ) ;
if ( ! f . open ( QIODevice : : WriteOnly | QIODevice : : Truncate ) ) {
* errorString = f . errorString ( ) ;
return false ;
}
auto writeStr = [ & f , errorString ] ( const QByteArray & data ) {
if ( f . write ( data ) ! = data . size ( ) ) {
* errorString = f . errorString ( ) ;
return false ;
}
return true ;
} ;
if ( ! writeStr ( " // " ) )
return false ;
if ( ! writeStr ( inputFileName . toUtf8 ( ) ) )
return false ;
if ( ! writeStr ( " \n " ) )
return false ;
if ( ! writeStr ( QByteArrayLiteral ( " namespace QmlCacheGeneratedCode { \n namespace " ) ) )
return false ;
if ( ! writeStr ( symbolNamespaceForPath ( inputFileName ) . toUtf8 ( ) ) )
return false ;
if ( ! writeStr ( QByteArrayLiteral ( " { \n extern const unsigned char qmlData alignas(16) [] = { \n " ) ) )
return false ;
QByteArray hexifiedData ;
{
QByteArray modifiedUnit ;
modifiedUnit . resize ( unit - > data - > unitSize ) ;
memcpy ( modifiedUnit . data ( ) , unit - > data , unit - > data - > unitSize ) ;
const char * dataPtr = modifiedUnit . data ( ) ;
QV4 : : CompiledData : : Unit * unitPtr ;
memcpy ( & unitPtr , & dataPtr , sizeof ( unitPtr ) ) ;
unitPtr - > flags | = QV4 : : CompiledData : : Unit : : StaticData ;
QTextStream stream ( & hexifiedData ) ;
const uchar * begin = reinterpret_cast < const uchar * > ( modifiedUnit . constData ( ) ) ;
const uchar * end = begin + unit - > data - > unitSize ;
stream < < hex ;
int col = 0 ;
for ( const uchar * data = begin ; data < end ; + + data , + + col ) {
if ( data > begin )
stream < < ' , ' ;
if ( col % 8 = = 0 ) {
stream < < ' \n ' ;
col = 0 ;
}
stream < < " 0x " < < * data ;
}
stream < < ' \n ' ;
} ;
if ( ! writeStr ( hexifiedData ) )
return false ;
if ( ! writeStr ( " }; \n } \n } \n " ) )
return false ;
if ( ! f . commit ( ) ) {
* errorString = f . errorString ( ) ;
return false ;
}
return true ;
}
2016-12-30 15:11:20 +00:00
int main ( int argc , char * * argv )
{
// Produce reliably the same output for the same input by disabling QHash's random seeding.
2017-03-14 18:26:14 +00:00
qSetGlobalQHashSeed ( 0 ) ;
2016-12-30 15:11:20 +00:00
QCoreApplication app ( argc , argv ) ;
QCoreApplication : : setApplicationName ( QStringLiteral ( " qmlcachegen " ) ) ;
QCoreApplication : : setApplicationVersion ( QLatin1String ( QT_VERSION_STR ) ) ;
QCommandLineParser parser ;
parser . addHelpOption ( ) ;
parser . addVersionOption ( ) ;
2018-01-22 15:46:03 +00:00
QCommandLineOption filterResourceFileOption ( QStringLiteral ( " filter-resource-file " ) , QCoreApplication : : translate ( " main " , " Filter out QML/JS files from a resource file that can be cached ahead of time instead " ) ) ;
parser . addOption ( filterResourceFileOption ) ;
QCommandLineOption resourceFileMappingOption ( QStringLiteral ( " resource-file-mapping " ) , QCoreApplication : : translate ( " main " , " Path from original resource file to new one " ) , QCoreApplication : : translate ( " main " , " old-name:new-name " ) ) ;
parser . addOption ( resourceFileMappingOption ) ;
QCommandLineOption resourceOption ( QStringLiteral ( " resource " ) , QCoreApplication : : translate ( " main " , " Qt resource file that might later contain one of the compiled files " ) , QCoreApplication : : translate ( " main " , " resource-file-name " ) ) ;
parser . addOption ( resourceOption ) ;
QCommandLineOption resourcePathOption ( QStringLiteral ( " resource-path " ) , QCoreApplication : : translate ( " main " , " Qt resource file path corresponding to the file being compiled " ) , QCoreApplication : : translate ( " main " , " resource-path " ) ) ;
parser . addOption ( resourcePathOption ) ;
2017-03-02 14:52:38 +00:00
QCommandLineOption outputFileOption ( QStringLiteral ( " o " ) , QCoreApplication : : translate ( " main " , " Output file name " ) , QCoreApplication : : translate ( " main " , " file name " ) ) ;
parser . addOption ( outputFileOption ) ;
2017-03-03 09:35:13 +00:00
QCommandLineOption checkIfSupportedOption ( QStringLiteral ( " check-if-supported " ) , QCoreApplication : : translate ( " main " , " Check if cache generate is supported on the specified target architecture " ) ) ;
parser . addOption ( checkIfSupportedOption ) ;
2016-12-30 15:11:20 +00:00
parser . addPositionalArgument ( QStringLiteral ( " [qml file] " ) ,
QStringLiteral ( " QML source file to generate cache for. " ) ) ;
2018-01-22 15:46:03 +00:00
parser . setSingleDashWordOptionMode ( QCommandLineParser : : ParseAsLongOptions ) ;
2016-12-30 15:11:20 +00:00
parser . process ( app ) ;
2018-02-02 14:22:44 +00:00
enum Output {
GenerateCpp ,
GenerateCacheFile ,
GenerateLoader
} target = GenerateCacheFile ;
QString outputFileName ;
if ( parser . isSet ( outputFileOption ) )
outputFileName = parser . value ( outputFileOption ) ;
if ( outputFileName . endsWith ( QLatin1String ( " .cpp " ) ) ) {
target = GenerateCpp ;
if ( outputFileName . endsWith ( QLatin1String ( " qmlcache_loader.cpp " ) ) )
target = GenerateLoader ;
}
2017-03-03 09:35:13 +00:00
const QStringList sources = parser . positionalArguments ( ) ;
if ( sources . isEmpty ( ) ) {
parser . showHelp ( ) ;
2018-02-02 14:22:44 +00:00
} else if ( sources . count ( ) > 1 & & target ! = GenerateLoader ) {
2017-03-03 09:35:13 +00:00
fprintf ( stderr , " %s \n " , qPrintable ( QStringLiteral ( " Too many input files specified: ' " ) + sources . join ( QStringLiteral ( " ' ' " ) ) + QLatin1Char ( ' \' ' ) ) ) ;
return EXIT_FAILURE ;
}
2018-02-02 14:22:44 +00:00
const QString inputFile = sources . first ( ) ;
if ( outputFileName . isEmpty ( ) )
outputFileName = inputFile + QLatin1Char ( ' c ' ) ;
2017-03-02 14:52:38 +00:00
2018-01-22 15:46:03 +00:00
if ( parser . isSet ( filterResourceFileOption ) ) {
return filterResourceFile ( inputFile , outputFileName ) ;
}
2018-02-02 14:22:44 +00:00
if ( target = = GenerateLoader ) {
ResourceFileMapper mapper ( sources ) ;
2018-01-22 15:46:03 +00:00
2018-02-02 14:22:44 +00:00
Error error ;
2018-01-22 15:46:03 +00:00
if ( ! generateLoader ( mapper . qmlCompilerFiles ( ) , outputFileName , parser . values ( resourceFileMappingOption ) , & error . message ) ) {
error . augment ( QLatin1String ( " Error generating loader stub: " ) ) . print ( ) ;
return EXIT_FAILURE ;
}
return EXIT_SUCCESS ;
}
QString inputFileUrl = inputFile ;
SaveFunction saveFunction ;
2018-02-02 14:22:44 +00:00
if ( target = = GenerateCpp ) {
2018-01-22 15:46:03 +00:00
ResourceFileMapper fileMapper ( parser . values ( resourceOption ) ) ;
QString inputResourcePath = parser . value ( resourcePathOption ) ;
if ( ! inputResourcePath . isEmpty ( ) & & ! fileMapper . isEmpty ( ) ) {
fprintf ( stderr , " --%s and --%s are mutually exclusive. \n " ,
qPrintable ( resourcePathOption . names ( ) . first ( ) ) ,
qPrintable ( resourceOption . names ( ) . first ( ) ) ) ;
return EXIT_FAILURE ;
}
// If the user didn't specify the resource path corresponding to the file on disk being
// compiled, try to determine it from the resource file, if one was supplied.
if ( inputResourcePath . isEmpty ( ) ) {
const QStringList resourcePaths = fileMapper . resourcePaths ( inputFile ) ;
if ( resourcePaths . isEmpty ( ) ) {
fprintf ( stderr , " No resource path for file: %s \n " , qPrintable ( inputFile ) ) ;
return EXIT_FAILURE ;
}
if ( resourcePaths . size ( ) ! = 1 ) {
fprintf ( stderr , " Multiple resource paths for file %s. "
" Use the --%s option to disambiguate: \n " ,
qPrintable ( inputFile ) ,
qPrintable ( resourcePathOption . names ( ) . first ( ) ) ) ;
for ( const QString & resourcePath : resourcePaths )
fprintf ( stderr , " \t %s \n " , qPrintable ( resourcePath ) ) ;
return EXIT_FAILURE ;
}
inputResourcePath = resourcePaths . first ( ) ;
}
inputFileUrl = QStringLiteral ( " qrc:// " ) + inputResourcePath ;
saveFunction = [ inputResourcePath , outputFileName ] ( QV4 : : CompiledData : : CompilationUnit * unit , QString * errorString ) {
return saveUnitAsCpp ( inputResourcePath , outputFileName , unit , errorString ) ;
} ;
} else {
saveFunction = [ outputFileName ] ( QV4 : : CompiledData : : CompilationUnit * unit , QString * errorString ) {
return unit - > saveToDisk ( outputFileName , errorString ) ;
} ;
}
2018-01-18 09:31:08 +00:00
setupIllegalNames ( ) ;
2018-01-22 15:46:03 +00:00
2016-12-30 15:11:20 +00:00
if ( inputFile . endsWith ( QLatin1String ( " .qml " ) ) ) {
2018-02-02 14:22:44 +00:00
Error error ;
2018-01-22 15:46:03 +00:00
if ( ! compileQmlFile ( inputFile , saveFunction , & error ) ) {
2016-12-30 15:11:20 +00:00
error . augment ( QLatin1String ( " Error compiling qml file: " ) ) . print ( ) ;
return EXIT_FAILURE ;
}
} else if ( inputFile . endsWith ( QLatin1String ( " .js " ) ) ) {
2018-02-02 14:22:44 +00:00
Error error ;
2018-01-22 15:46:03 +00:00
if ( ! compileJSFile ( inputFile , inputFileUrl , saveFunction , & error ) ) {
2018-02-20 15:21:38 +00:00
error . augment ( QLatin1String ( " Error compiling js file: " ) ) . print ( ) ;
2016-12-30 15:11:20 +00:00
return EXIT_FAILURE ;
}
} else {
2018-02-02 14:22:44 +00:00
fprintf ( stderr , " Ignoring %s input file as it is not QML source code - maybe remove from QML_FILES? \n " , qPrintable ( inputFile ) ) ;
}
2016-12-30 15:11:20 +00:00
return EXIT_SUCCESS ;
}