make QMakeMetaInfo a little less inefficient with libtool .la files
[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 /* 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).
63 */
64 static QString pwd;
65 QString qmake_getpwd()
66 {
67     if(pwd.isNull())
68         pwd = QDir::currentPath();
69     return pwd;
70 }
71 bool qmake_setpwd(const QString &p)
72 {
73     if(QDir::setCurrent(p)) {
74         pwd = QDir::currentPath();
75         return true;
76     }
77     return false;
78 }
79
80 int runQMake(int argc, char **argv)
81 {
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);
87
88     // parse command line
89     int ret = Option::init(argc, argv);
90     if(ret != Option::QMAKE_CMDLINE_SUCCESS) {
91         if ((ret & Option::QMAKE_CMDLINE_ERROR) != 0)
92             return 1;
93         return 0;
94     }
95
96     QString oldpwd = qmake_getpwd();
97 #ifdef Q_OS_WIN
98     if(!(oldpwd.length() == 3 && oldpwd[0].isLetter() && oldpwd.endsWith(":/")))
99 #endif
100     {
101         if(!oldpwd.endsWith(QLatin1Char('/')))
102             oldpwd += QLatin1Char('/');
103     }
104     Option::output_dir = oldpwd; //for now this is the output dir
105
106     if(Option::output.fileName() != "-") {
107         QFileInfo fi(Option::output);
108         QString dir;
109         if(fi.isDir()) {
110             dir = fi.filePath();
111         } else {
112             QString tmp_dir = fi.path();
113             if(!tmp_dir.isEmpty() && QFile::exists(tmp_dir))
114                 dir = tmp_dir;
115         }
116         if(!dir.isNull() && dir != ".")
117             Option::output_dir = dir;
118         if(QDir::isRelativePath(Option::output_dir))
119             Option::output_dir.prepend(oldpwd);
120         Option::output_dir = QDir::cleanPath(Option::output_dir);
121     }
122
123     QMakeProperty prop;
124     if(Option::qmake_mode == Option::QMAKE_QUERY_PROPERTY ||
125        Option::qmake_mode == Option::QMAKE_SET_PROPERTY ||
126        Option::qmake_mode == Option::QMAKE_UNSET_PROPERTY)
127         return prop.exec() ? 0 : 101;
128
129     QMakeProject project(&prop);
130     int exit_val = 0;
131     QStringList files;
132     if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
133         files << "(*hack*)"; //we don't even use files, but we do the for() body once
134     else
135         files = Option::mkfile::project_files;
136     for(QStringList::Iterator pfile = files.begin(); pfile != files.end(); pfile++) {
137         if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
138            Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
139             QString fn = Option::normalizePath(*pfile);
140             if(!QFile::exists(fn)) {
141                 fprintf(stderr, "Cannot find file: %s.\n",
142                         QDir::toNativeSeparators(fn).toLatin1().constData());
143                 exit_val = 2;
144                 continue;
145             }
146
147             //setup pwd properly
148             debug_msg(1, "Resetting dir to: %s",
149                       QDir::toNativeSeparators(oldpwd).toLatin1().constData());
150             qmake_setpwd(oldpwd); //reset the old pwd
151             int di = fn.lastIndexOf(QLatin1Char('/'));
152             if(di != -1) {
153                 debug_msg(1, "Changing dir to: %s",
154                           QDir::toNativeSeparators(fn.left(di)).toLatin1().constData());
155                 if(!qmake_setpwd(fn.left(di)))
156                     fprintf(stderr, "Cannot find directory: %s\n",
157                             QDir::toNativeSeparators(fn.left(di)).toLatin1().constData());
158                 fn = fn.right(fn.length() - di - 1);
159             }
160
161             Option::prepareProject(fn);
162
163             // read project..
164             if(!project.read(fn)) {
165                 fprintf(stderr, "Error processing project file: %s\n",
166                         fn == QLatin1String("-") ?
167                             "(stdin)" : QDir::toNativeSeparators(*pfile).toLatin1().constData());
168                 exit_val = 3;
169                 continue;
170             }
171             if (Option::mkfile::do_preprocess) {
172                 project.dump();
173                 continue; //no need to create makefile
174             }
175         }
176
177         bool success = true;
178         MetaMakefileGenerator *mkfile = MetaMakefileGenerator::createMetaGenerator(&project, QString(), false, &success);
179         if (!success)
180             exit_val = 3;
181
182         if(mkfile && !mkfile->write(oldpwd)) {
183             if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
184                 fprintf(stderr, "Unable to generate project file.\n");
185             else
186                 fprintf(stderr, "Unable to generate makefile for: %s\n",
187                         QDir::toNativeSeparators(*pfile).toLatin1().constData());
188             exit_val = 5;
189         }
190         delete mkfile;
191         mkfile = NULL;
192     }
193     qmakeClearCaches();
194     return exit_val;
195 }
196
197 QT_END_NAMESPACE
198
199 int main(int argc, char **argv)
200 {
201     return QT_PREPEND_NAMESPACE(runQMake)(argc, argv);
202 }