1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the qmake application of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
45 #include "cachekeys.h"
46 #include "metamakefile.h"
47 #include <qnamespace.h>
55 #include <sys/types.h>
60 /* This is to work around lame implementation on Darwin. It has been noted that the getpwd(3) function
61 is much too slow, and called much too often inside of Qt (every fileFixify). With this we use a locally
62 cached copy because I can control all the times it is set (because Qt never sets the pwd under me).
65 QString qmake_getpwd()
68 pwd = QDir::currentPath();
71 bool qmake_setpwd(const QString &p)
73 if(QDir::setCurrent(p)) {
74 pwd = QDir::currentPath();
80 int runQMake(int argc, char **argv)
82 // stderr is unbuffered by default, but stdout buffering depends on whether
83 // there is a terminal attached. Buffering can make output from stderr and stdout
84 // appear out of sync, so force stdout to be unbuffered as well.
85 // This is particularly important for things like QtCreator and scripted builds.
86 setvbuf(stdout, (char *)NULL, _IONBF, 0);
89 Option::globals = &globals;
92 int ret = Option::init(argc, argv);
93 if(ret != Option::QMAKE_CMDLINE_SUCCESS) {
94 if ((ret & Option::QMAKE_CMDLINE_ERROR) != 0)
99 QString oldpwd = qmake_getpwd();
101 if(!(oldpwd.length() == 3 && oldpwd[0].isLetter() && oldpwd.endsWith(":/")))
104 if(!oldpwd.endsWith(QLatin1Char('/')))
105 oldpwd += QLatin1Char('/');
107 Option::output_dir = oldpwd; //for now this is the output dir
109 if(Option::output.fileName() != "-") {
110 QFileInfo fi(Option::output);
115 QString tmp_dir = fi.path();
116 if(!tmp_dir.isEmpty() && QFile::exists(tmp_dir))
119 if(!dir.isNull() && dir != ".")
120 Option::output_dir = dir;
121 if(QDir::isRelativePath(Option::output_dir))
122 Option::output_dir.prepend(oldpwd);
123 Option::output_dir = QDir::cleanPath(Option::output_dir);
127 if(Option::qmake_mode == Option::QMAKE_QUERY_PROPERTY ||
128 Option::qmake_mode == Option::QMAKE_SET_PROPERTY ||
129 Option::qmake_mode == Option::QMAKE_UNSET_PROPERTY)
130 return prop.exec() ? 0 : 101;
131 globals.setQMakeProperty(&prop);
133 ProFileCache proFileCache;
134 Option::proFileCache = &proFileCache;
135 QMakeParser parser(&proFileCache, &Option::evalHandler);
136 Option::parser = &parser;
138 QMakeProject project;
141 if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
142 files << "(*hack*)"; //we don't even use files, but we do the for() body once
144 files = Option::mkfile::project_files;
145 for(QStringList::Iterator pfile = files.begin(); pfile != files.end(); pfile++) {
146 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
147 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
148 QString fn = Option::normalizePath(*pfile);
149 if(!QFile::exists(fn)) {
150 fprintf(stderr, "Cannot find file: %s.\n",
151 QDir::toNativeSeparators(fn).toLatin1().constData());
157 debug_msg(1, "Resetting dir to: %s",
158 QDir::toNativeSeparators(oldpwd).toLatin1().constData());
159 qmake_setpwd(oldpwd); //reset the old pwd
160 int di = fn.lastIndexOf(QLatin1Char('/'));
162 debug_msg(1, "Changing dir to: %s",
163 QDir::toNativeSeparators(fn.left(di)).toLatin1().constData());
164 if(!qmake_setpwd(fn.left(di)))
165 fprintf(stderr, "Cannot find directory: %s\n",
166 QDir::toNativeSeparators(fn.left(di)).toLatin1().constData());
167 fn = fn.right(fn.length() - di - 1);
170 Option::prepareProject(fn);
173 if(!project.read(fn)) {
174 fprintf(stderr, "Error processing project file: %s\n",
175 QDir::toNativeSeparators(*pfile).toLatin1().constData());
179 if (Option::mkfile::do_preprocess) {
181 continue; //no need to create makefile
186 MetaMakefileGenerator *mkfile = MetaMakefileGenerator::createMetaGenerator(&project, QString(), false, &success);
190 if(mkfile && !mkfile->write(oldpwd)) {
191 if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
192 fprintf(stderr, "Unable to generate project file.\n");
194 fprintf(stderr, "Unable to generate makefile for: %s\n",
195 QDir::toNativeSeparators(*pfile).toLatin1().constData());
207 int main(int argc, char **argv)
209 return QT_PREPEND_NAMESPACE(runQMake)(argc, argv);