⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 project.cpp

📁 qtmake 文件的代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
**
** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
**
** This file is part of the qmake application of the Qt Toolkit.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.trolltech.com/products/qt/opensource.html
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://www.trolltech.com/products/qt/licensing.html or contact the
** sales department at sales@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

#include "project.h"
#include "property.h"
#include "option.h"
#include "cachekeys.h"

#include <qdatetime.h>
#include <qfile.h>
#include <qfileinfo.h>
#include <qdir.h>
#include <qregexp.h>
#include <qtextstream.h>
#include <qstack.h>
#include <qhash.h>
#ifdef Q_OS_UNIX
# include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>

#ifdef Q_OS_WIN32
#define QT_POPEN _popen
#else
#define QT_POPEN popen
#endif

struct parser_info {
    QString file;
    int line_no;
    bool from_file;
} parser;

static QString remove_quotes(const QString &arg)
{
    static bool symbols_init = false;
    enum { SINGLEQUOTE, DOUBLEQUOTE };
    static ushort symbols[2];
    if(!symbols_init) {
        symbols_init = true;
        symbols[SINGLEQUOTE] = QChar('\'').unicode();
        symbols[DOUBLEQUOTE] = QChar('"').unicode();
    }

    const QChar *arg_data = arg.data();
    const ushort first = arg_data->unicode();
    const int arg_len = arg.length();
    if(first == symbols[SINGLEQUOTE] || first == symbols[DOUBLEQUOTE]) {
        const ushort last = (arg_data+arg_len-1)->unicode();
        if(last == first)
            return arg.mid(1, arg_len-2);
    }
    return arg;
}

//just a parsable entity
struct ParsableBlock
{
    ParsableBlock() { }
    virtual ~ParsableBlock() { }

    struct Parse {
        QString text;
        parser_info pi;
        Parse(const QString &t) : text(t){ pi = ::parser; }
    };
    QList<Parse> parser;

protected:
    virtual bool continueBlock() = 0;
    bool eval(QMakeProject *p, QMap<QString, QStringList> &place);
};

bool ParsableBlock::eval(QMakeProject *p, QMap<QString, QStringList> &place)
{
    //save state
    parser_info pi = ::parser;
    const int block_count = p->scope_blocks.count();

    //execute
    bool ret = true;
    for(int i = 0; i < parser.count(); i++) {
        ::parser = parser.at(i).pi;
        if(!(ret = p->parse(parser.at(i).text, place)) || !continueBlock())
            break;
    }

    //restore state
    ::parser = pi;
    while(p->scope_blocks.count() > block_count)
        p->scope_blocks.pop();
    return ret;
}

//defined functions
struct FunctionBlock : public ParsableBlock
{
    FunctionBlock() : calling_place(0), scope_level(1), cause_return(false) { }

    QMap<QString, QStringList> vars;
    QMap<QString, QStringList> *calling_place;
    QString return_value;
    int scope_level;
    bool cause_return;

    bool exec(const QStringList &args,
              QMakeProject *p, QMap<QString, QStringList> &place, QString &functionReturn);
    virtual bool continueBlock() { return !cause_return; }
};

bool FunctionBlock::exec(const QStringList &args,
                         QMakeProject *proj, QMap<QString, QStringList> &place, QString &functionReturn)
{
    //save state
#if 1
    calling_place = &place;
#else
    calling_place = &proj->variables();
#endif
    return_value = "";
    cause_return = false;

    //execute
#if 0
    vars = proj->variables();
#else
    vars = place;
#endif
    vars["ARGS"] = args;
    for(int i = 0; i < args.count(); i++)
        vars[QString::number(i+1)] = QStringList(args[i]);
    bool ret = ParsableBlock::eval(proj, vars);
    functionReturn = return_value;

    //restore state
    calling_place = 0;
    return_value.clear();
    vars.clear();
    return ret;
}

//loops
struct IteratorBlock : public ParsableBlock
{
    IteratorBlock() : scope_level(1), loop_forever(false), cause_break(false), cause_next(false) { }

    int scope_level;

    struct Test {
        QString func;
        QStringList args;
        bool invert;
        parser_info pi;
        Test(const QString &f, QStringList &a, bool i) : func(f), args(a), invert(i) { pi = ::parser; }
    };
    QList<Test> test;

    QString variable;

    bool loop_forever, cause_break, cause_next;
    QStringList list;

    bool exec(QMakeProject *p, QMap<QString, QStringList> &place);
    virtual bool continueBlock() { return !cause_next && !cause_break; }
};
bool IteratorBlock::exec(QMakeProject *p, QMap<QString, QStringList> &place)
{
    bool ret = true;
    QStringList::Iterator it;
    if(!loop_forever)
        it = list.begin();
    int iterate_count = 0;
    //save state
    IteratorBlock *saved_iterator = p->iterator;
    p->iterator = this;

    //do the loop
    while(loop_forever || it != list.end()) {
        cause_next = cause_break = false;
        if(!loop_forever && (*it).isEmpty()) { //ignore empty items
            ++it;
            continue;
        }

        //set up the loop variable
        QStringList va;
        if(!variable.isEmpty()) {
            va = place[variable];
            if(loop_forever)
                place[variable] = QStringList(QString::number(iterate_count));
            else
                place[variable] = QStringList(*it);
        }
        //do the iterations
        bool succeed = true;
        for(QList<Test>::Iterator test_it = test.begin(); test_it != test.end(); ++test_it) {
            ::parser = (*test_it).pi;
            succeed = p->doProjectTest((*test_it).func, (*test_it).args, place);
            if((*test_it).invert)
                succeed = !succeed;
            if(!succeed)
                break;
        }
        if(succeed)
            ret = ParsableBlock::eval(p, place);
        //restore the variable in the map
        if(!variable.isEmpty())
            place[variable] = va;
        //loop counters
        if(!loop_forever)
            ++it;
        iterate_count++;
        if(!ret || cause_break)
            break;
    }

    //restore state
    p->iterator = saved_iterator;
    return ret;
}

QMakeProject::ScopeBlock::~ScopeBlock()
{
#if 0
    if(iterate)
        delete iterate;
#endif
}

static void qmake_error_msg(const QString &msg)
{
    fprintf(stderr, "%s:%d: %s\n", parser.file.toLatin1().constData(), parser.line_no,
            msg.toLatin1().constData());
}

/*
   1) environment variable QMAKEFEATURES (as separated by colons)
   2) property variable QMAKEFEATURES (as separated by colons)
   3) <project_root> (where .qmake.cache lives) + FEATURES_DIR
   4) environment variable QMAKEPATH (as separated by colons) + /mkspecs/FEATURES_DIR
   5) your QMAKESPEC/features dir
   6) your data_install/mkspecs/FEATURES_DIR
   7) your QMAKESPEC/../FEATURES_DIR dir

   FEATURES_DIR is defined as:

   1) features/(unix|win32|macx)/
   2) features/
*/
QStringList qmake_feature_paths(QMakeProperty *prop=0)
{
    QStringList concat;
    {
        const QString base_concat = QDir::separator() + QString("features");
        switch(Option::target_mode) {
        case Option::TARG_MACX_MODE:                     //also a unix
            concat << base_concat + QDir::separator() + "mac";
            concat << base_concat + QDir::separator() + "macx";
            concat << base_concat + QDir::separator() + "unix";
            break;
        case Option::TARG_UNIX_MODE:
            concat << base_concat + QDir::separator() + "unix";
            break;
        case Option::TARG_WIN_MODE:
            concat << base_concat + QDir::separator() + "win32";
            break;
        case Option::TARG_MAC9_MODE:
            concat << base_concat + QDir::separator() + "mac";
            concat << base_concat + QDir::separator() + "mac9";
            break;
        case Option::TARG_QNX6_MODE: //also a unix
            concat << base_concat + QDir::separator() + "qnx6";
            concat << base_concat + QDir::separator() + "unix";
            break;
        }
        concat << base_concat;
    }
    const QString mkspecs_concat = QDir::separator() + QString("mkspecs");
    QStringList feature_roots;
    QByteArray mkspec_path = qgetenv("QMAKEFEATURES");
    if(!mkspec_path.isNull())
        feature_roots += splitPathList(QString::fromLocal8Bit(mkspec_path));
    if(prop)
        feature_roots += splitPathList(prop->value("QMAKEFEATURES"));
    if(!Option::mkfile::cachefile.isEmpty()) {
        QString path;
        int last_slash = Option::mkfile::cachefile.lastIndexOf(Option::dir_sep);
        if(last_slash != -1)
            path = Option::fixPathToLocalOS(Option::mkfile::cachefile.left(last_slash));
        for(QStringList::Iterator concat_it = concat.begin();
            concat_it != concat.end(); ++concat_it)
            feature_roots << (path + (*concat_it));
    }
    QByteArray qmakepath = qgetenv("QMAKEPATH");
    if (!qmakepath.isNull()) {
        const QStringList lst = splitPathList(QString::fromLocal8Bit(qmakepath));
        for(QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) {
            for(QStringList::Iterator concat_it = concat.begin();
                concat_it != concat.end(); ++concat_it)
                    feature_roots << ((*it) + mkspecs_concat + (*concat_it));
        }
    }
    if(!Option::mkfile::qmakespec.isEmpty())
        feature_roots << Option::mkfile::qmakespec + QDir::separator() + "features";
    if(!Option::mkfile::qmakespec.isEmpty()) {
        QFileInfo specfi(Option::mkfile::qmakespec);
        QDir specdir(specfi.absoluteFilePath());
        while(!specdir.isRoot()) {
            if(!specdir.cdUp() || specdir.isRoot())
                break;
            if(QFile::exists(specdir.path() + QDir::separator() + "features")) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -