repurpose deprecated -E switch
[profile/ivi/qtbase.git] / qmake / main.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the qmake application of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "project.h"
43 #include "property.h"
44 #include "option.h"
45 #include "cachekeys.h"
46 #include "metamakefile.h"
47 #include <qnamespace.h>
48 #include <qdebug.h>
49 #include <qregexp.h>
50 #include <qdir.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <ctype.h>
54 #include <fcntl.h>
55 #include <sys/types.h>
56 #include <sys/stat.h>
57
58 QT_BEGIN_NAMESPACE
59
60 // for Borland, main is defined to qMain which breaks qmake
61 #undef main
62 #ifdef Q_OS_MAC
63 #endif
64
65 /* This is to work around lame implementation on Darwin. It has been noted that the getpwd(3) function
66    is much too slow, and called much too often inside of Qt (every fileFixify). With this we use a locally
67    cached copy because I can control all the times it is set (because Qt never sets the pwd under me).
68 */
69 static QString pwd;
70 QString qmake_getpwd()
71 {
72     if(pwd.isNull())
73         pwd = QDir::currentPath();
74     return pwd;
75 }
76 bool qmake_setpwd(const QString &p)
77 {
78     if(QDir::setCurrent(p)) {
79         pwd = QDir::currentPath();
80         return true;
81     }
82     return false;
83 }
84
85 int runQMake(int argc, char **argv)
86 {
87     // stderr is unbuffered by default, but stdout buffering depends on whether
88     // there is a terminal attached. Buffering can make output from stderr and stdout
89     // appear out of sync, so force stdout to be unbuffered as well.
90     // This is particularly important for things like QtCreator and scripted builds.
91     setvbuf(stdout, (char *)NULL, _IONBF, 0);
92
93     // parse command line
94     int ret = Option::init(argc, argv);
95     if(ret != Option::QMAKE_CMDLINE_SUCCESS) {
96         if ((ret & Option::QMAKE_CMDLINE_ERROR) != 0)
97             return 1;
98         return 0;
99     }
100
101     QString oldpwd = qmake_getpwd();
102 #ifdef Q_OS_WIN
103     if(!(oldpwd.length() == 3 && oldpwd[0].isLetter() && oldpwd.endsWith(":/")))
104 #endif
105     {
106         if(!oldpwd.endsWith(QLatin1Char('/')))
107             oldpwd += QLatin1Char('/');
108     }
109     Option::output_dir = oldpwd; //for now this is the output dir
110
111     if(Option::output.fileName() != "-") {
112         QFileInfo fi(Option::output);
113         QString dir;
114         if(fi.isDir()) {
115             dir = fi.filePath();
116         } else {
117             QString tmp_dir = fi.path();
118             if(!tmp_dir.isEmpty() && QFile::exists(tmp_dir))
119                 dir = tmp_dir;
120         }
121         if(!dir.isNull() && dir != ".")
122             Option::output_dir = dir;
123         if(QDir::isRelativePath(Option::output_dir))
124             Option::output_dir.prepend(oldpwd);
125         Option::output_dir = QDir::cleanPath(Option::output_dir);
126     }
127
128     QMakeProperty prop;
129     if(Option::qmake_mode == Option::QMAKE_QUERY_PROPERTY ||
130        Option::qmake_mode == Option::QMAKE_SET_PROPERTY ||
131        Option::qmake_mode == Option::QMAKE_UNSET_PROPERTY)
132         return prop.exec() ? 0 : 101;
133
134     QMakeProject project(&prop);
135     int exit_val = 0;
136     QStringList files;
137     if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
138         files << "(*hack*)"; //we don't even use files, but we do the for() body once
139     else
140         files = Option::mkfile::project_files;
141     for(QStringList::Iterator pfile = files.begin(); pfile != files.end(); pfile++) {
142         if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
143            Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
144             QString fn = Option::normalizePath(*pfile);
145             if(!QFile::exists(fn)) {
146                 fprintf(stderr, "Cannot find file: %s.\n",
147                         QDir::toNativeSeparators(fn).toLatin1().constData());
148                 exit_val = 2;
149                 continue;
150             }
151
152             //setup pwd properly
153             debug_msg(1, "Resetting dir to: %s",
154                       QDir::toNativeSeparators(oldpwd).toLatin1().constData());
155             qmake_setpwd(oldpwd); //reset the old pwd
156             int di = fn.lastIndexOf(QLatin1Char('/'));
157             if(di != -1) {
158                 debug_msg(1, "Changing dir to: %s",
159                           QDir::toNativeSeparators(fn.left(di)).toLatin1().constData());
160                 if(!qmake_setpwd(fn.left(di)))
161                     fprintf(stderr, "Cannot find directory: %s\n",
162                             QDir::toNativeSeparators(fn.left(di)).toLatin1().constData());
163                 fn = fn.right(fn.length() - di - 1);
164             }
165
166             Option::prepareProject(fn);
167
168             // read project..
169             if(!project.read(fn)) {
170                 fprintf(stderr, "Error processing project file: %s\n",
171                         fn == QLatin1String("-") ?
172                             "(stdin)" : QDir::toNativeSeparators(*pfile).toLatin1().constData());
173                 exit_val = 3;
174                 continue;
175             }
176             if (Option::mkfile::do_preprocess) {
177                 project.dump();
178                 continue; //no need to create makefile
179             }
180         }
181
182         bool success = true;
183         MetaMakefileGenerator *mkfile = MetaMakefileGenerator::createMetaGenerator(&project, QString(), false, &success);
184         if (!success)
185             exit_val = 3;
186
187         if(mkfile && !mkfile->write(oldpwd)) {
188             if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
189                 fprintf(stderr, "Unable to generate project file.\n");
190             else
191                 fprintf(stderr, "Unable to generate makefile for: %s\n",
192                         QDir::toNativeSeparators(*pfile).toLatin1().constData());
193             exit_val = 5;
194         }
195         delete mkfile;
196         mkfile = NULL;
197     }
198     qmakeClearCaches();
199     return exit_val;
200 }
201
202 QT_END_NAMESPACE
203
204 int main(int argc, char **argv)
205 {
206     return QT_PREPEND_NAMESPACE(runQMake)(argc, argv);
207 }