| 1 | /**************************************************************************** | 
|---|
| 2 | ** | 
|---|
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | 
|---|
| 4 | ** Contact: https://www.qt.io/licensing/ | 
|---|
| 5 | ** | 
|---|
| 6 | ** This file is part of the qmake application of the Qt Toolkit. | 
|---|
| 7 | ** | 
|---|
| 8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ | 
|---|
| 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 The Qt Company. For licensing terms | 
|---|
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
|---|
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | 
|---|
| 16 | ** | 
|---|
| 17 | ** GNU General Public License Usage | 
|---|
| 18 | ** Alternatively, this file may be used under the terms of the GNU | 
|---|
| 19 | ** General Public License version 3 as published by the Free Software | 
|---|
| 20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | 
|---|
| 21 | ** included in the packaging of this file. Please review the following | 
|---|
| 22 | ** information to ensure the GNU General Public License requirements will | 
|---|
| 23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. | 
|---|
| 24 | ** | 
|---|
| 25 | ** $QT_END_LICENSE$ | 
|---|
| 26 | ** | 
|---|
| 27 | ****************************************************************************/ | 
|---|
| 28 |  | 
|---|
| 29 | #include "unixmake.h" | 
|---|
| 30 | #include "option.h" | 
|---|
| 31 | #include <qfile.h> | 
|---|
| 32 | #include <qhash.h> | 
|---|
| 33 | #include <qdir.h> | 
|---|
| 34 | #include <time.h> | 
|---|
| 35 | #include <qdebug.h> | 
|---|
| 36 |  | 
|---|
| 37 | QT_BEGIN_NAMESPACE | 
|---|
| 38 |  | 
|---|
| 39 | ProStringList UnixMakefileGenerator::libdirToFlags(const ProKey &key) | 
|---|
| 40 | { | 
|---|
| 41 | ProStringList results; | 
|---|
| 42 | for (const auto &libdir : qAsConst(project->values(key))) { | 
|---|
| 43 | if (!project->isEmpty( "QMAKE_LFLAGS_RPATH") && project->isActiveConfig( "rpath_libdirs")) | 
|---|
| 44 | project->values( "QMAKE_LFLAGS") += var( "QMAKE_LFLAGS_RPATH") + libdir; | 
|---|
| 45 | results.append( "-L"+ escapeFilePath(libdir)); | 
|---|
| 46 | } | 
|---|
| 47 | return results; | 
|---|
| 48 | } | 
|---|
| 49 |  | 
|---|
| 50 | void | 
|---|
| 51 | UnixMakefileGenerator::init() | 
|---|
| 52 | { | 
|---|
| 53 | ProStringList &configs = project->values( "CONFIG"); | 
|---|
| 54 | if(project->isEmpty( "ICON") && !project->isEmpty( "RC_FILE")) | 
|---|
| 55 | project->values( "ICON") = project->values( "RC_FILE"); | 
|---|
| 56 | if(project->isEmpty( "QMAKE_EXTENSION_PLUGIN")) | 
|---|
| 57 | project->values( "QMAKE_EXTENSION_PLUGIN").append(project->first( "QMAKE_EXTENSION_SHLIB")); | 
|---|
| 58 |  | 
|---|
| 59 | project->values( "QMAKE_ORIG_TARGET") = project->values( "TARGET"); | 
|---|
| 60 |  | 
|---|
| 61 | //version handling | 
|---|
| 62 | if (project->isEmpty( "VERSION")) { | 
|---|
| 63 | project->values( "VERSION").append( | 
|---|
| 64 | "1.0."+ (project->isEmpty( "VER_PAT") ? QString( "0") : project->first( "VER_PAT"))); | 
|---|
| 65 | } | 
|---|
| 66 | QStringList l = project->first( "VERSION").toQString().split('.'); | 
|---|
| 67 | l << "0"<< "0"; //make sure there are three | 
|---|
| 68 | project->values( "VER_MAJ").append(l[0]); | 
|---|
| 69 | project->values( "VER_MIN").append(l[1]); | 
|---|
| 70 | project->values( "VER_PAT").append(l[2]); | 
|---|
| 71 |  | 
|---|
| 72 | QString sroot = project->sourceRoot(); | 
|---|
| 73 | for (const ProString &iif : project->values( "QMAKE_INTERNAL_INCLUDED_FILES")) { | 
|---|
| 74 | if (iif == project->cacheFile()) | 
|---|
| 75 | continue; | 
|---|
| 76 | if (iif.startsWith(sroot) && iif.at(sroot.length()) == QLatin1Char('/')) | 
|---|
| 77 | project->values( "DISTFILES") += fileFixify(iif.toQString(), FileFixifyRelative); | 
|---|
| 78 | } | 
|---|
| 79 |  | 
|---|
| 80 | /* this should probably not be here, but I'm using it to wrap the .t files */ | 
|---|
| 81 | if(project->first( "TEMPLATE") == "app") | 
|---|
| 82 | project->values( "QMAKE_APP_FLAG").append( "1"); | 
|---|
| 83 | else if(project->first( "TEMPLATE") == "lib") | 
|---|
| 84 | project->values( "QMAKE_LIB_FLAG").append( "1"); | 
|---|
| 85 | else if(project->first( "TEMPLATE") == "subdirs") { | 
|---|
| 86 | MakefileGenerator::init(); | 
|---|
| 87 | if(project->isEmpty( "MAKEFILE")) | 
|---|
| 88 | project->values( "MAKEFILE").append( "Makefile"); | 
|---|
| 89 | return; /* subdirs is done */ | 
|---|
| 90 | } | 
|---|
| 91 |  | 
|---|
| 92 | project->values( "QMAKE_ORIG_DESTDIR") = project->values( "DESTDIR"); | 
|---|
| 93 | if((!project->isEmpty( "QMAKE_LIB_FLAG") && !project->isActiveConfig( "staticlib")) || | 
|---|
| 94 | (project->isActiveConfig( "qt") &&  project->isActiveConfig( "plugin"))) { | 
|---|
| 95 | if(configs.indexOf( "dll") == -1) configs.append( "dll"); | 
|---|
| 96 | } else if(!project->isEmpty( "QMAKE_APP_FLAG") || project->isActiveConfig( "dll")) { | 
|---|
| 97 | configs.removeAll( "staticlib"); | 
|---|
| 98 | } | 
|---|
| 99 | if(!project->isEmpty( "QMAKE_INCREMENTAL")) | 
|---|
| 100 | project->values( "QMAKE_LFLAGS") += project->values( "QMAKE_LFLAGS_INCREMENTAL"); | 
|---|
| 101 | else if(!project->isEmpty( "QMAKE_LFLAGS_PREBIND") && | 
|---|
| 102 | !project->values( "QMAKE_LIB_FLAG").isEmpty() && | 
|---|
| 103 | project->isActiveConfig( "dll")) | 
|---|
| 104 | project->values( "QMAKE_LFLAGS") += project->values( "QMAKE_LFLAGS_PREBIND"); | 
|---|
| 105 | project->values( "QMAKE_INCDIR") += project->values( "QMAKE_INCDIR_POST"); | 
|---|
| 106 | project->values( "QMAKE_RPATHDIR") += project->values( "QMAKE_RPATHDIR_POST"); | 
|---|
| 107 | project->values( "QMAKE_RPATHLINKDIR") += project->values( "QMAKE_RPATHLINKDIR_POST"); | 
|---|
| 108 | if(!project->isEmpty( "QMAKE_INCDIR")) | 
|---|
| 109 | project->values( "INCLUDEPATH") += project->values( "QMAKE_INCDIR"); | 
|---|
| 110 | // The order of the next two lines is relevant due to side effect on QMAKE_LFLAGS. | 
|---|
| 111 | ProStringList ldadd = project->values( "QMAKE_LIBDIR_FLAGS") + libdirToFlags( "QMAKE_LIBDIR"); | 
|---|
| 112 | ProStringList ldaddpost = libdirToFlags( "QMAKE_LIBDIR_POST"); | 
|---|
| 113 | if (project->isActiveConfig( "mac")) { | 
|---|
| 114 | if (!project->isEmpty( "QMAKE_FRAMEWORKPATH")) { | 
|---|
| 115 | const ProStringList &fwdirs = project->values( "QMAKE_FRAMEWORKPATH"); | 
|---|
| 116 | for (int i = 0; i < fwdirs.size(); ++i) | 
|---|
| 117 | project->values( "QMAKE_FRAMEWORKPATH_FLAGS") += "-F"+ escapeFilePath(fwdirs[i]); | 
|---|
| 118 | } | 
|---|
| 119 | ldadd += project->values( "QMAKE_FRAMEWORKPATH_FLAGS"); | 
|---|
| 120 | } | 
|---|
| 121 | ProStringList &qmklibs = project->values( "LIBS"); | 
|---|
| 122 | qmklibs = ldadd + qmklibs; | 
|---|
| 123 | ProStringList &qmklibspost = project->values( "QMAKE_LIBS"); | 
|---|
| 124 | qmklibspost = ldaddpost + qmklibspost; | 
|---|
| 125 | if (!project->isEmpty( "QMAKE_RPATHDIR") && !project->isEmpty( "QMAKE_LFLAGS_RPATH")) { | 
|---|
| 126 | const ProStringList &rpathdirs = project->values( "QMAKE_RPATHDIR"); | 
|---|
| 127 | for (int i = 0; i < rpathdirs.size(); ++i) { | 
|---|
| 128 | QString rpathdir = rpathdirs[i].toQString(); | 
|---|
| 129 | if (rpathdir.length() > 1 && rpathdir.at(0) == '$' && rpathdir.at(1) != '(') { | 
|---|
| 130 | rpathdir.replace(0, 1, "\\$$");  // Escape from make and the shell | 
|---|
| 131 | } else if (!rpathdir.startsWith('@') && fileInfo(rpathdir).isRelative()) { | 
|---|
| 132 | QString rpathbase = project->first( "QMAKE_REL_RPATH_BASE").toQString(); | 
|---|
| 133 | if (rpathbase.isEmpty()) { | 
|---|
| 134 | fprintf(stderr, "Error: This platform does not support relative paths in QMAKE_RPATHDIR (%s)\n", | 
|---|
| 135 | rpathdir.toLatin1().constData()); | 
|---|
| 136 | continue; | 
|---|
| 137 | } | 
|---|
| 138 | if (rpathbase.startsWith('$')) | 
|---|
| 139 | rpathbase.replace(0, 1, "\\$$");  // Escape from make and the shell | 
|---|
| 140 | if (rpathdir == ".") | 
|---|
| 141 | rpathdir = rpathbase; | 
|---|
| 142 | else | 
|---|
| 143 | rpathdir.prepend(rpathbase + '/'); | 
|---|
| 144 | project->values( "QMAKE_LFLAGS").insertUnique(project->values( "QMAKE_LFLAGS_REL_RPATH")); | 
|---|
| 145 | } | 
|---|
| 146 | project->values( "QMAKE_LFLAGS") += var( "QMAKE_LFLAGS_RPATH") + escapeFilePath(rpathdir); | 
|---|
| 147 | } | 
|---|
| 148 | } | 
|---|
| 149 | if (!project->isEmpty( "QMAKE_RPATHLINKDIR")) { | 
|---|
| 150 | const ProStringList &rpathdirs = project->values( "QMAKE_RPATHLINKDIR"); | 
|---|
| 151 | for (int i = 0; i < rpathdirs.size(); ++i) { | 
|---|
| 152 | if (!project->isEmpty( "QMAKE_LFLAGS_RPATHLINK")) | 
|---|
| 153 | project->values( "QMAKE_LFLAGS") += var( "QMAKE_LFLAGS_RPATHLINK") + escapeFilePath(QFileInfo(rpathdirs[i].toQString()).absoluteFilePath()); | 
|---|
| 154 | } | 
|---|
| 155 | } | 
|---|
| 156 |  | 
|---|
| 157 | if(project->isActiveConfig( "GNUmake") && !project->isEmpty( "QMAKE_CFLAGS_DEPS")) | 
|---|
| 158 | include_deps = true; //do not generate deps | 
|---|
| 159 |  | 
|---|
| 160 | MakefileGenerator::init(); | 
|---|
| 161 |  | 
|---|
| 162 | if (project->isActiveConfig( "objective_c")) | 
|---|
| 163 | project->values( "QMAKE_BUILTIN_COMPILERS") << "OBJC"<< "OBJCXX"; | 
|---|
| 164 |  | 
|---|
| 165 | for (const ProString &compiler : project->values( "QMAKE_BUILTIN_COMPILERS")) { | 
|---|
| 166 | QString compile_flag = var( "QMAKE_COMPILE_FLAG"); | 
|---|
| 167 | if(compile_flag.isEmpty()) | 
|---|
| 168 | compile_flag = "-c"; | 
|---|
| 169 |  | 
|---|
| 170 | if(doPrecompiledHeaders() && !project->isEmpty( "PRECOMPILED_HEADER")) { | 
|---|
| 171 | QString pchFlags = var(ProKey( "QMAKE_"+ compiler + "FLAGS_USE_PRECOMPILE")); | 
|---|
| 172 |  | 
|---|
| 173 | QString pchBaseName; | 
|---|
| 174 | if(!project->isEmpty( "PRECOMPILED_DIR")) { | 
|---|
| 175 | pchBaseName = Option::fixPathToTargetOS(project->first( "PRECOMPILED_DIR").toQString()); | 
|---|
| 176 | if(!pchBaseName.endsWith(Option::dir_sep)) | 
|---|
| 177 | pchBaseName += Option::dir_sep; | 
|---|
| 178 | } | 
|---|
| 179 | pchBaseName += project->first( "QMAKE_ORIG_TARGET").toQString(); | 
|---|
| 180 |  | 
|---|
| 181 | // replace place holders | 
|---|
| 182 | pchFlags.replace(QLatin1String( "${QMAKE_PCH_INPUT}"), | 
|---|
| 183 | escapeFilePath(project->first( "PRECOMPILED_HEADER").toQString())); | 
|---|
| 184 | pchFlags.replace(QLatin1String( "${QMAKE_PCH_OUTPUT_BASE}"), escapeFilePath(pchBaseName)); | 
|---|
| 185 | if (project->isActiveConfig( "icc_pch_style")) { | 
|---|
| 186 | // icc style | 
|---|
| 187 | pchFlags.replace(QLatin1String( "${QMAKE_PCH_OUTPUT}"), | 
|---|
| 188 | escapeFilePath(pchBaseName + project->first( "QMAKE_PCH_OUTPUT_EXT"))); | 
|---|
| 189 | const ProStringList pchArchs = project->values( "QMAKE_PCH_ARCHS"); | 
|---|
| 190 | for (const ProString &arch : pchArchs) { | 
|---|
| 191 | QString suffix = project->first( "QMAKE_PCH_OUTPUT_EXT").toQString(); | 
|---|
| 192 | suffix.replace(QLatin1String( "${QMAKE_PCH_ARCH}"), arch.toQString()); | 
|---|
| 193 | pchFlags.replace(QLatin1String( "${QMAKE_PCH_OUTPUT_") + arch + QLatin1Char('}'), | 
|---|
| 194 | escapeFilePath(pchBaseName + suffix)); | 
|---|
| 195 | } | 
|---|
| 196 | } else { | 
|---|
| 197 | // gcc style (including clang_pch_style) | 
|---|
| 198 | QString ; | 
|---|
| 199 | if (project->isActiveConfig( "clang_pch_style")) | 
|---|
| 200 | headerSuffix = project->first( "QMAKE_PCH_OUTPUT_EXT").toQString(); | 
|---|
| 201 |  | 
|---|
| 202 | pchBaseName += project->first( "QMAKE_PCH_OUTPUT_EXT").toQString(); | 
|---|
| 203 | pchBaseName += Option::dir_sep; | 
|---|
| 204 |  | 
|---|
| 205 | ProString language = project->first(ProKey( "QMAKE_LANGUAGE_"+ compiler)); | 
|---|
| 206 | if (!language.isEmpty()) { | 
|---|
| 207 | pchFlags.replace(QLatin1String( "${QMAKE_PCH_OUTPUT}"), | 
|---|
| 208 | escapeFilePath(pchBaseName + language + headerSuffix)); | 
|---|
| 209 | const ProStringList pchArchs = project->values( "QMAKE_PCH_ARCHS"); | 
|---|
| 210 | for (const ProString &arch : pchArchs) { | 
|---|
| 211 | QString file = pchBaseName + language + headerSuffix; | 
|---|
| 212 | file.replace(QLatin1String( "${QMAKE_PCH_ARCH}"), arch.toQString()); | 
|---|
| 213 | if (project->isActiveConfig( "clang_pch_style") | 
|---|
| 214 | && (file.endsWith(QLatin1String( ".pch")) | 
|---|
| 215 | || file.endsWith(QLatin1String( ".gch")))) { | 
|---|
| 216 | file.chop(4); // must omit header suffix for -include to recognize the PCH | 
|---|
| 217 | } | 
|---|
| 218 | pchFlags.replace(QLatin1String( "${QMAKE_PCH_OUTPUT_") + arch + QLatin1Char('}'), | 
|---|
| 219 | escapeFilePath(file)); | 
|---|
| 220 | } | 
|---|
| 221 | } | 
|---|
| 222 | } | 
|---|
| 223 |  | 
|---|
| 224 | if (!pchFlags.isEmpty()) | 
|---|
| 225 | compile_flag += " "+ pchFlags; | 
|---|
| 226 | } | 
|---|
| 227 |  | 
|---|
| 228 | QString compilerExecutable; | 
|---|
| 229 | if (compiler == "C"|| compiler == "OBJC") { | 
|---|
| 230 | compilerExecutable = "$(CC)"; | 
|---|
| 231 | compile_flag += " $(CFLAGS)"; | 
|---|
| 232 | } else { | 
|---|
| 233 | compilerExecutable = "$(CXX)"; | 
|---|
| 234 | compile_flag += " $(CXXFLAGS)"; | 
|---|
| 235 | } | 
|---|
| 236 |  | 
|---|
| 237 | compile_flag += " $(INCPATH)"; | 
|---|
| 238 |  | 
|---|
| 239 | ProString compilerVariable = compiler; | 
|---|
| 240 | if (compilerVariable == "C") | 
|---|
| 241 | compilerVariable = ProString( "CC"); | 
|---|
| 242 |  | 
|---|
| 243 | const ProKey runComp( "QMAKE_RUN_"+ compilerVariable); | 
|---|
| 244 | if(project->isEmpty(runComp)) | 
|---|
| 245 | project->values(runComp).append(compilerExecutable + " "+ compile_flag + " "+ var( "QMAKE_CC_O_FLAG") + "$obj $src"); | 
|---|
| 246 | const ProKey runCompImp( "QMAKE_RUN_"+ compilerVariable + "_IMP"); | 
|---|
| 247 | if(project->isEmpty(runCompImp)) | 
|---|
| 248 | project->values(runCompImp).append(compilerExecutable + " "+ compile_flag + " "+ var( "QMAKE_CC_O_FLAG") + "\"$@\" \"$<\""); | 
|---|
| 249 | } | 
|---|
| 250 |  | 
|---|
| 251 | if (project->isActiveConfig( "mac") && !project->isEmpty( "TARGET") && | 
|---|
| 252 | ((project->isActiveConfig( "build_pass") || project->isEmpty( "BUILDS")))) { | 
|---|
| 253 | ProString bundle; | 
|---|
| 254 | if(project->isActiveConfig( "bundle") && !project->isEmpty( "QMAKE_BUNDLE_EXTENSION")) { | 
|---|
| 255 | bundle = project->first( "TARGET"); | 
|---|
| 256 | if(!project->isEmpty( "QMAKE_BUNDLE_NAME")) | 
|---|
| 257 | bundle = project->first( "QMAKE_BUNDLE_NAME"); | 
|---|
| 258 | if(!bundle.endsWith(project->first( "QMAKE_BUNDLE_EXTENSION"))) | 
|---|
| 259 | bundle += project->first( "QMAKE_BUNDLE_EXTENSION"); | 
|---|
| 260 | } else if(project->first( "TEMPLATE") == "app"&& project->isActiveConfig( "app_bundle")) { | 
|---|
| 261 | bundle = project->first( "TARGET"); | 
|---|
| 262 | if(!project->isEmpty( "QMAKE_APPLICATION_BUNDLE_NAME")) | 
|---|
| 263 | bundle = project->first( "QMAKE_APPLICATION_BUNDLE_NAME"); | 
|---|
| 264 | if(!bundle.endsWith( ".app")) | 
|---|
| 265 | bundle += ".app"; | 
|---|
| 266 | if(project->isEmpty( "QMAKE_BUNDLE_LOCATION")) | 
|---|
| 267 | project->values( "QMAKE_BUNDLE_LOCATION").append( "Contents/MacOS"); | 
|---|
| 268 | project->values( "QMAKE_PKGINFO").append(project->first( "DESTDIR") + bundle + "/Contents/PkgInfo"); | 
|---|
| 269 | project->values( "QMAKE_BUNDLE_RESOURCE_FILE").append(project->first( "DESTDIR") + bundle + "/Contents/Resources/empty.lproj"); | 
|---|
| 270 | } else if(project->first( "TEMPLATE") == "lib"&& !project->isActiveConfig( "staticlib") && | 
|---|
| 271 | ((!project->isActiveConfig( "plugin") && project->isActiveConfig( "lib_bundle")) || | 
|---|
| 272 | (project->isActiveConfig( "plugin") && project->isActiveConfig( "plugin_bundle")))) { | 
|---|
| 273 | bundle = project->first( "TARGET"); | 
|---|
| 274 | if(project->isActiveConfig( "plugin")) { | 
|---|
| 275 | if(!project->isEmpty( "QMAKE_PLUGIN_BUNDLE_NAME")) | 
|---|
| 276 | bundle = project->first( "QMAKE_PLUGIN_BUNDLE_NAME"); | 
|---|
| 277 | if (project->isEmpty( "QMAKE_BUNDLE_EXTENSION")) | 
|---|
| 278 | project->values( "QMAKE_BUNDLE_EXTENSION").append( ".plugin"); | 
|---|
| 279 | if (!bundle.endsWith(project->first( "QMAKE_BUNDLE_EXTENSION"))) | 
|---|
| 280 | bundle += project->first( "QMAKE_BUNDLE_EXTENSION"); | 
|---|
| 281 | if(project->isEmpty( "QMAKE_BUNDLE_LOCATION")) | 
|---|
| 282 | project->values( "QMAKE_BUNDLE_LOCATION").append( "Contents/MacOS"); | 
|---|
| 283 | } else { | 
|---|
| 284 | if(!project->isEmpty( "QMAKE_FRAMEWORK_BUNDLE_NAME")) | 
|---|
| 285 | bundle = project->first( "QMAKE_FRAMEWORK_BUNDLE_NAME"); | 
|---|
| 286 | if (project->isEmpty( "QMAKE_BUNDLE_EXTENSION")) | 
|---|
| 287 | project->values( "QMAKE_BUNDLE_EXTENSION").append( ".framework"); | 
|---|
| 288 | if (!bundle.endsWith(project->first( "QMAKE_BUNDLE_EXTENSION"))) | 
|---|
| 289 | bundle += project->first( "QMAKE_BUNDLE_EXTENSION"); | 
|---|
| 290 | } | 
|---|
| 291 | } | 
|---|
| 292 | if(!bundle.isEmpty()) { | 
|---|
| 293 | project->values( "QMAKE_BUNDLE") = ProStringList(bundle); | 
|---|
| 294 | } else { | 
|---|
| 295 | project->values( "QMAKE_BUNDLE").clear(); | 
|---|
| 296 | project->values( "QMAKE_BUNDLE_LOCATION").clear(); | 
|---|
| 297 | } | 
|---|
| 298 | } else { //no bundling here | 
|---|
| 299 | project->values( "QMAKE_BUNDLE").clear(); | 
|---|
| 300 | project->values( "QMAKE_BUNDLE_LOCATION").clear(); | 
|---|
| 301 | } | 
|---|
| 302 |  | 
|---|
| 303 | init2(); | 
|---|
| 304 | ProString target = project->first( "TARGET"); | 
|---|
| 305 | int slsh = target.lastIndexOf(Option::dir_sep); | 
|---|
| 306 | if (slsh != -1) | 
|---|
| 307 | target.chopFront(slsh + 1); | 
|---|
| 308 | project->values( "LIB_TARGET").prepend(target); | 
|---|
| 309 | } | 
|---|
| 310 |  | 
|---|
| 311 | QStringList | 
|---|
| 312 | &UnixMakefileGenerator::findDependencies(const QString &f) | 
|---|
| 313 | { | 
|---|
| 314 | QStringList &ret = MakefileGenerator::findDependencies(f); | 
|---|
| 315 | if (doPrecompiledHeaders() && !project->isEmpty( "PRECOMPILED_HEADER")) { | 
|---|
| 316 | ProString file = f; | 
|---|
| 317 | QString ; | 
|---|
| 318 | if(!project->isEmpty( "PRECOMPILED_DIR")) | 
|---|
| 319 | header_prefix = project->first( "PRECOMPILED_DIR").toQString(); | 
|---|
| 320 | header_prefix += project->first( "QMAKE_ORIG_TARGET").toQString(); | 
|---|
| 321 | header_prefix += project->first( "QMAKE_PCH_OUTPUT_EXT").toQString(); | 
|---|
| 322 | if (project->isActiveConfig( "icc_pch_style")) { | 
|---|
| 323 | // icc style | 
|---|
| 324 | ProStringList pchArchs = project->values( "QMAKE_PCH_ARCHS"); | 
|---|
| 325 | if (pchArchs.isEmpty()) | 
|---|
| 326 | pchArchs << ProString(); // normal single-arch PCH | 
|---|
| 327 | for (const ProString &arch : qAsConst(pchArchs)) { | 
|---|
| 328 | auto pfx = header_prefix; | 
|---|
| 329 | if (!arch.isEmpty()) | 
|---|
| 330 | pfx.replace(QLatin1String( "${QMAKE_PCH_ARCH}"), arch.toQString()); | 
|---|
| 331 | for (QStringList::Iterator it = Option::cpp_ext.begin(); | 
|---|
| 332 | it != Option::cpp_ext.end(); ++it) { | 
|---|
| 333 | if (file.endsWith(*it)) { | 
|---|
| 334 | ret += pfx; | 
|---|
| 335 | break; | 
|---|
| 336 | } | 
|---|
| 337 | } | 
|---|
| 338 | } | 
|---|
| 339 | } else { | 
|---|
| 340 | // gcc style (including clang_pch_style) | 
|---|
| 341 | QString  = project->isActiveConfig( "clang_pch_style") | 
|---|
| 342 | ? project->first( "QMAKE_PCH_OUTPUT_EXT").toQString() : ""; | 
|---|
| 343 | header_prefix += Option::dir_sep + project->first( "QMAKE_PRECOMP_PREFIX"); | 
|---|
| 344 |  | 
|---|
| 345 | for (const ProString &compiler : project->values( "QMAKE_BUILTIN_COMPILERS")) { | 
|---|
| 346 | if (project->isEmpty(ProKey( "QMAKE_"+ compiler + "FLAGS_PRECOMPILE"))) | 
|---|
| 347 | continue; | 
|---|
| 348 |  | 
|---|
| 349 | ProString language = project->first(ProKey( "QMAKE_LANGUAGE_"+ compiler)); | 
|---|
| 350 | if (language.isEmpty()) | 
|---|
| 351 | continue; | 
|---|
| 352 |  | 
|---|
| 353 | // Unfortunately we were not consistent about the C++ naming | 
|---|
| 354 | ProString extensionSuffix = compiler; | 
|---|
| 355 | if (extensionSuffix == "CXX") | 
|---|
| 356 | extensionSuffix = ProString( "CPP"); | 
|---|
| 357 |  | 
|---|
| 358 | for (const ProString &extension : project->values(ProKey( "QMAKE_EXT_"+ extensionSuffix))) { | 
|---|
| 359 | if (!file.endsWith(extension.toQString())) | 
|---|
| 360 | continue; | 
|---|
| 361 |  | 
|---|
| 362 | ProStringList pchArchs = project->values( "QMAKE_PCH_ARCHS"); | 
|---|
| 363 | if (pchArchs.isEmpty()) | 
|---|
| 364 | pchArchs << ProString(); // normal single-arch PCH | 
|---|
| 365 | for (const ProString &arch : qAsConst(pchArchs)) { | 
|---|
| 366 | QString  = header_prefix + language + header_suffix; | 
|---|
| 367 | if (!arch.isEmpty()) { | 
|---|
| 368 | precompiledHeader.replace(QLatin1String( "${QMAKE_PCH_ARCH}"), | 
|---|
| 369 | arch.toQString()); | 
|---|
| 370 | } | 
|---|
| 371 | if (!ret.contains(precompiledHeader)) | 
|---|
| 372 | ret += precompiledHeader; | 
|---|
| 373 | } | 
|---|
| 374 |  | 
|---|
| 375 | goto foundPrecompiledDependency; | 
|---|
| 376 | } | 
|---|
| 377 | } | 
|---|
| 378 | foundPrecompiledDependency: | 
|---|
| 379 | ; // Hurray!! | 
|---|
| 380 | } | 
|---|
| 381 | } | 
|---|
| 382 | return ret; | 
|---|
| 383 | } | 
|---|
| 384 |  | 
|---|
| 385 | ProString | 
|---|
| 386 | UnixMakefileGenerator::fixLibFlag(const ProString &lib) | 
|---|
| 387 | { | 
|---|
| 388 | return escapeFilePath(lib); | 
|---|
| 389 | } | 
|---|
| 390 |  | 
|---|
| 391 | bool | 
|---|
| 392 | UnixMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) | 
|---|
| 393 | { | 
|---|
| 394 | QList<QMakeLocalFileName> libdirs, frameworkdirs; | 
|---|
| 395 | int libidx = 0, fwidx = 0; | 
|---|
| 396 | for (const ProString &dlib : project->values( "QMAKE_DEFAULT_LIBDIRS")) | 
|---|
| 397 | libdirs.append(QMakeLocalFileName(dlib.toQString())); | 
|---|
| 398 | frameworkdirs.append(QMakeLocalFileName( "/System/Library/Frameworks")); | 
|---|
| 399 | frameworkdirs.append(QMakeLocalFileName( "/Library/Frameworks")); | 
|---|
| 400 | ProStringList extens; | 
|---|
| 401 | extens << project->first( "QMAKE_EXTENSION_SHLIB") << "a"; | 
|---|
| 402 | static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE", | 
|---|
| 403 | "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr }; | 
|---|
| 404 | for (int i = 0; lflags[i]; i++) { | 
|---|
| 405 | ProStringList &l = project->values(lflags[i]); | 
|---|
| 406 | for (ProStringList::Iterator it = l.begin(); it != l.end(); ) { | 
|---|
| 407 | QString opt = (*it).toQString(); | 
|---|
| 408 | if(opt.startsWith( "-")) { | 
|---|
| 409 | if(opt.startsWith( "-L")) { | 
|---|
| 410 | QString lib = opt.mid(2); | 
|---|
| 411 | QMakeLocalFileName f(lib); | 
|---|
| 412 | int idx = libdirs.indexOf(f); | 
|---|
| 413 | if (idx >= 0 && idx < libidx) { | 
|---|
| 414 | it = l.erase(it); | 
|---|
| 415 | continue; | 
|---|
| 416 | } | 
|---|
| 417 | libdirs.insert(libidx++, f); | 
|---|
| 418 | } else if(opt.startsWith( "-l")) { | 
|---|
| 419 | QString lib = opt.mid(2); | 
|---|
| 420 | for (const QMakeLocalFileName &libdir : qAsConst(libdirs)) { | 
|---|
| 421 | QString libBase = libdir.local() + '/' | 
|---|
| 422 | + project->first( "QMAKE_PREFIX_SHLIB") + lib; | 
|---|
| 423 | if (linkPrl && processPrlFile(libBase, true)) | 
|---|
| 424 | goto found; | 
|---|
| 425 | for (ProStringList::Iterator extit = extens.begin(); extit != extens.end(); ++extit) { | 
|---|
| 426 | if (exists(libBase + '.' + (*extit))) | 
|---|
| 427 | goto found; | 
|---|
| 428 | } | 
|---|
| 429 | } | 
|---|
| 430 | found: ; | 
|---|
| 431 | } else if (target_mode == TARG_MAC_MODE && opt.startsWith( "-F")) { | 
|---|
| 432 | QMakeLocalFileName f(opt.mid(2)); | 
|---|
| 433 | if (!frameworkdirs.contains(f)) | 
|---|
| 434 | frameworkdirs.insert(fwidx++, f); | 
|---|
| 435 | } else if (target_mode == TARG_MAC_MODE && opt == "-framework") { | 
|---|
| 436 | if (linkPrl) { | 
|---|
| 437 | opt = (*++it).toQString(); | 
|---|
| 438 | static const QChar suffixMarker = ','; | 
|---|
| 439 | const int suffixPosition = opt.indexOf(suffixMarker); | 
|---|
| 440 | const bool hasSuffix = suffixPosition >= 0; | 
|---|
| 441 | QString frameworkName = opt; | 
|---|
| 442 | if (hasSuffix) { | 
|---|
| 443 | frameworkName.truncate(suffixPosition); | 
|---|
| 444 | opt.remove(suffixMarker); // Apply suffix by removing marker | 
|---|
| 445 | } | 
|---|
| 446 | for (const QMakeLocalFileName &dir : qAsConst(frameworkdirs)) { | 
|---|
| 447 | auto processPrlIfFound = [&](QString directory) { | 
|---|
| 448 | QString suffixedPrl = directory + opt; | 
|---|
| 449 | if (processPrlFile(suffixedPrl, true)) | 
|---|
| 450 | return true; | 
|---|
| 451 | if (hasSuffix) { | 
|---|
| 452 | QString unsuffixedPrl = directory + frameworkName; | 
|---|
| 453 | if (processPrlFile(unsuffixedPrl, true)) | 
|---|
| 454 | return true; | 
|---|
| 455 | } | 
|---|
| 456 | return false; | 
|---|
| 457 | }; | 
|---|
| 458 | QString frameworkDirectory = dir.local() + "/"+ frameworkName + + ".framework/"; | 
|---|
| 459 | if (processPrlIfFound(frameworkDirectory + "Resources/") | 
|---|
| 460 | || processPrlIfFound(frameworkDirectory)) | 
|---|
| 461 | break; | 
|---|
| 462 | } | 
|---|
| 463 | } else { | 
|---|
| 464 | if (opt.length() == 10) | 
|---|
| 465 | ++it; | 
|---|
| 466 | // Skip | 
|---|
| 467 | } | 
|---|
| 468 | } | 
|---|
| 469 | } else if (linkPrl) { | 
|---|
| 470 | processPrlFile(opt, false); | 
|---|
| 471 | } | 
|---|
| 472 |  | 
|---|
| 473 | ProStringList &prl_libs = project->values( "QMAKE_CURRENT_PRL_LIBS"); | 
|---|
| 474 | for (int prl = 0; prl < prl_libs.size(); ++prl) | 
|---|
| 475 | it = l.insert(++it, prl_libs.at(prl)); | 
|---|
| 476 | prl_libs.clear(); | 
|---|
| 477 | ++it; | 
|---|
| 478 | } | 
|---|
| 479 |  | 
|---|
| 480 | if (mergeLflags) { | 
|---|
| 481 | QHash<ProKey, ProStringList> lflags; | 
|---|
| 482 | for(int lit = 0; lit < l.size(); ++lit) { | 
|---|
| 483 | ProKey arch( "default"); | 
|---|
| 484 | ProString opt = l.at(lit); | 
|---|
| 485 | if (opt.startsWith('-')) { | 
|---|
| 486 | if (target_mode == TARG_MAC_MODE && opt.startsWith( "-Xarch")) { | 
|---|
| 487 | if (opt.length() > 7) { | 
|---|
| 488 | arch = opt.mid(7).toKey(); | 
|---|
| 489 | opt = l.at(++lit); | 
|---|
| 490 | } | 
|---|
| 491 | } | 
|---|
| 492 |  | 
|---|
| 493 | if (opt.startsWith( "-L") | 
|---|
| 494 | || (target_mode == TARG_MAC_MODE && opt.startsWith( "-F"))) { | 
|---|
| 495 | if (!lflags[arch].contains(opt)) | 
|---|
| 496 | lflags[arch].append(opt); | 
|---|
| 497 | } else if (opt.startsWith( "-l") || opt == "-pthread") { | 
|---|
| 498 | // Make sure we keep the dependency order of libraries | 
|---|
| 499 | lflags[arch].removeAll(opt); | 
|---|
| 500 | lflags[arch].append(opt); | 
|---|
| 501 | } else if (target_mode == TARG_MAC_MODE | 
|---|
| 502 | && (opt == "-framework"|| opt == "-force_load")) { | 
|---|
| 503 | // Handle space separated options | 
|---|
| 504 | ProString dashOpt = opt; | 
|---|
| 505 | opt = l.at(++lit); | 
|---|
| 506 | if (opt.startsWith( "-Xarch")) | 
|---|
| 507 | opt = l.at(++lit); // The user has done the right thing and prefixed each part | 
|---|
| 508 | for(int x = 0; x < lflags[arch].size(); ++x) { | 
|---|
| 509 | if (lflags[arch].at(x) == dashOpt && lflags[arch].at(++x) == opt) { | 
|---|
| 510 | lflags[arch].remove(x - 1, 2); | 
|---|
| 511 | break; | 
|---|
| 512 | } | 
|---|
| 513 | } | 
|---|
| 514 | lflags[arch].append(dashOpt); | 
|---|
| 515 | lflags[arch].append(opt); | 
|---|
| 516 | } else { | 
|---|
| 517 | lflags[arch].append(opt); | 
|---|
| 518 | } | 
|---|
| 519 | } else if(!opt.isNull()) { | 
|---|
| 520 | for (const ProString &ext : extens) { | 
|---|
| 521 | if (opt.size() > ext.size() && opt.endsWith(ext) | 
|---|
| 522 | && opt.at(opt.size() - ext.size() - 1) == '.') { | 
|---|
| 523 | // Make sure we keep the dependency order of libraries | 
|---|
| 524 | lflags[arch].removeAll(opt); | 
|---|
| 525 | lflags[arch].append(opt); | 
|---|
| 526 | goto found2; | 
|---|
| 527 | } | 
|---|
| 528 | } | 
|---|
| 529 | if(!lflags[arch].contains(opt)) | 
|---|
| 530 | lflags[arch].append(opt); | 
|---|
| 531 | found2: ; | 
|---|
| 532 | } | 
|---|
| 533 | } | 
|---|
| 534 |  | 
|---|
| 535 | l =  lflags.take( "default"); | 
|---|
| 536 |  | 
|---|
| 537 | // Process architecture specific options (Xarch) | 
|---|
| 538 | QHash<ProKey, ProStringList>::const_iterator archIterator = lflags.constBegin(); | 
|---|
| 539 | while (archIterator != lflags.constEnd()) { | 
|---|
| 540 | const ProStringList &archOptions = archIterator.value(); | 
|---|
| 541 | for (int i = 0; i < archOptions.size(); ++i) { | 
|---|
| 542 | l.append(QLatin1String( "-Xarch_") + archIterator.key()); | 
|---|
| 543 | l.append(archOptions.at(i)); | 
|---|
| 544 | } | 
|---|
| 545 | ++archIterator; | 
|---|
| 546 | } | 
|---|
| 547 | } | 
|---|
| 548 | } | 
|---|
| 549 | return false; | 
|---|
| 550 | } | 
|---|
| 551 |  | 
|---|
| 552 | #ifdef Q_OS_WIN // MinGW x-compiling for QNX | 
|---|
| 553 | QString UnixMakefileGenerator::installRoot() const | 
|---|
| 554 | { | 
|---|
| 555 | /* | 
|---|
| 556 | We include a magic prefix on the path to bypass mingw-make's "helpful" | 
|---|
| 557 | intervention in the environment, recognising variables that look like | 
|---|
| 558 | paths and adding the msys system root as prefix, which we don't want. | 
|---|
| 559 | Once this hack has smuggled INSTALL_ROOT into make's variable space, we | 
|---|
| 560 | can trivially strip the magic prefix back off to get the path we meant. | 
|---|
| 561 | */ | 
|---|
| 562 | return QStringLiteral( "$(INSTALL_ROOT:@msyshack@%=%)"); | 
|---|
| 563 | } | 
|---|
| 564 | #endif | 
|---|
| 565 |  | 
|---|
| 566 | QString | 
|---|
| 567 | UnixMakefileGenerator::defaultInstall(const QString &t) | 
|---|
| 568 | { | 
|---|
| 569 | if(t != "target"|| project->first( "TEMPLATE") == "subdirs") | 
|---|
| 570 | return QString(); | 
|---|
| 571 |  | 
|---|
| 572 | enum { NoBundle, SolidBundle, SlicedBundle } bundle = NoBundle; | 
|---|
| 573 | bool isAux = (project->first( "TEMPLATE") == "aux"); | 
|---|
| 574 | const QString root = installRoot(); | 
|---|
| 575 | ProStringList &uninst = project->values(ProKey(t + ".uninstall")); | 
|---|
| 576 | QString ret, destdir = project->first( "DESTDIR").toQString(); | 
|---|
| 577 | if(!destdir.isEmpty() && destdir.right(1) != Option::dir_sep) | 
|---|
| 578 | destdir += Option::dir_sep; | 
|---|
| 579 | QString targetdir = fileFixify(project->first( "target.path").toQString(), FileFixifyAbsolute); | 
|---|
| 580 | if(targetdir.right(1) != Option::dir_sep) | 
|---|
| 581 | targetdir += Option::dir_sep; | 
|---|
| 582 |  | 
|---|
| 583 | ProStringList links; | 
|---|
| 584 | QString target= "$(TARGET)"; | 
|---|
| 585 | const ProStringList &targets = project->values(ProKey(t + ".targets")); | 
|---|
| 586 | if(!project->isEmpty( "QMAKE_BUNDLE")) { | 
|---|
| 587 | target = project->first( "QMAKE_BUNDLE").toQString(); | 
|---|
| 588 | bundle = project->isActiveConfig( "sliced_bundle") ? SlicedBundle : SolidBundle; | 
|---|
| 589 | } else if(project->first( "TEMPLATE") == "app") { | 
|---|
| 590 | target = "$(QMAKE_TARGET)"; | 
|---|
| 591 | } else if(project->first( "TEMPLATE") == "lib") { | 
|---|
| 592 | if (!project->isActiveConfig( "staticlib") | 
|---|
| 593 | && !project->isActiveConfig( "plugin") | 
|---|
| 594 | && !project->isActiveConfig( "unversioned_libname")) { | 
|---|
| 595 | if(project->isEmpty( "QMAKE_HPUX_SHLIB")) { | 
|---|
| 596 | links << "$(TARGET0)"<< "$(TARGET1)"<< "$(TARGET2)"; | 
|---|
| 597 | } else { | 
|---|
| 598 | links << "$(TARGET0)"; | 
|---|
| 599 | } | 
|---|
| 600 | } | 
|---|
| 601 | } | 
|---|
| 602 | for(int i = 0; i < targets.size(); ++i) { | 
|---|
| 603 | QString src = targets.at(i).toQString(), | 
|---|
| 604 | dst = escapeFilePath(filePrefixRoot(root, targetdir + src.section('/', -1))); | 
|---|
| 605 | if(!ret.isEmpty()) | 
|---|
| 606 | ret += "\n\t"; | 
|---|
| 607 | ret += "$(QINSTALL) "+ escapeFilePath(Option::fixPathToTargetOS(src, false)) + ' ' + dst; | 
|---|
| 608 | if(!uninst.isEmpty()) | 
|---|
| 609 | uninst.append( "\n\t"); | 
|---|
| 610 | uninst.append( "-$(DEL_FILE) "+ dst); | 
|---|
| 611 | } | 
|---|
| 612 |  | 
|---|
| 613 | { | 
|---|
| 614 | QString src_targ = target; | 
|---|
| 615 | if(!destdir.isEmpty()) | 
|---|
| 616 | src_targ = Option::fixPathToTargetOS(destdir + target, false); | 
|---|
| 617 | QString plain_targ = filePrefixRoot(root, fileFixify(targetdir + target, FileFixifyAbsolute)); | 
|---|
| 618 | QString dst_targ = plain_targ; | 
|---|
| 619 | plain_targ = escapeFilePath(plain_targ); | 
|---|
| 620 | if (bundle != NoBundle) { | 
|---|
| 621 | QString suffix; | 
|---|
| 622 | if (project->first( "TEMPLATE") == "lib") { | 
|---|
| 623 | if (!project->isActiveConfig( "shallow_bundle")) | 
|---|
| 624 | suffix += "/Versions/"+ project->first( "QMAKE_FRAMEWORK_VERSION"); | 
|---|
| 625 | suffix += "/$(TARGET)"; | 
|---|
| 626 | } else { | 
|---|
| 627 | suffix = "/"+ project->first( "QMAKE_BUNDLE_LOCATION") + "/$(QMAKE_TARGET)"; | 
|---|
| 628 | } | 
|---|
| 629 | dst_targ += suffix; | 
|---|
| 630 | if (bundle == SolidBundle) { | 
|---|
| 631 | if (!ret.isEmpty()) | 
|---|
| 632 | ret += "\n\t"; | 
|---|
| 633 | ret += "$(DEL_FILE) -r "+ plain_targ + "\n\t"; | 
|---|
| 634 | } else { | 
|---|
| 635 | src_targ += suffix; | 
|---|
| 636 | } | 
|---|
| 637 | } | 
|---|
| 638 | src_targ = escapeFilePath(src_targ); | 
|---|
| 639 | dst_targ = escapeFilePath(dst_targ); | 
|---|
| 640 |  | 
|---|
| 641 | QString copy_cmd; | 
|---|
| 642 | if (bundle == SolidBundle) { | 
|---|
| 643 | copy_cmd += "$(QINSTALL) "+ src_targ + ' ' + plain_targ; | 
|---|
| 644 | } else if (project->first( "TEMPLATE") == "lib"&& project->isActiveConfig( "staticlib")) { | 
|---|
| 645 | copy_cmd += "$(QINSTALL) "+ src_targ + ' ' + dst_targ; | 
|---|
| 646 | } else if (!isAux) { | 
|---|
| 647 | if (bundle == SlicedBundle) { | 
|---|
| 648 | if (!ret.isEmpty()) | 
|---|
| 649 | ret += "\n\t"; | 
|---|
| 650 | ret += mkdir_p_asstring( "\"`dirname "+ dst_targ + "`\"", false); | 
|---|
| 651 | } | 
|---|
| 652 | copy_cmd += "$(QINSTALL_PROGRAM) "+ src_targ + ' ' + dst_targ; | 
|---|
| 653 | } | 
|---|
| 654 | if(project->first( "TEMPLATE") == "lib"&& !project->isActiveConfig( "staticlib") | 
|---|
| 655 | && project->values(ProKey(t + ".CONFIG")).indexOf( "fix_rpath") != -1) { | 
|---|
| 656 | if (!ret.isEmpty()) | 
|---|
| 657 | ret += "\n\t"; | 
|---|
| 658 | if(!project->isEmpty( "QMAKE_FIX_RPATH")) { | 
|---|
| 659 | ret += copy_cmd; | 
|---|
| 660 | ret += "\n\t-"+ var( "QMAKE_FIX_RPATH") + ' ' + dst_targ + ' ' + dst_targ; | 
|---|
| 661 | } else if(!project->isEmpty( "QMAKE_LFLAGS_RPATH")) { | 
|---|
| 662 | ret += "-$(LINK) $(LFLAGS) "+ var( "QMAKE_LFLAGS_RPATH") + targetdir + " -o "+ | 
|---|
| 663 | dst_targ + " $(OBJECTS) $(LIBS) $(OBJCOMP)"; | 
|---|
| 664 | } else { | 
|---|
| 665 | ret += copy_cmd; | 
|---|
| 666 | } | 
|---|
| 667 | } else if (!copy_cmd.isEmpty()) { | 
|---|
| 668 | if (!ret.isEmpty()) | 
|---|
| 669 | ret += "\n\t"; | 
|---|
| 670 | ret += copy_cmd; | 
|---|
| 671 | } | 
|---|
| 672 |  | 
|---|
| 673 | if (isAux) { | 
|---|
| 674 | } else if (project->first( "TEMPLATE") == "lib"&& project->isActiveConfig( "staticlib")) { | 
|---|
| 675 | if(!project->isEmpty( "QMAKE_RANLIB")) | 
|---|
| 676 | ret += QString( "\n\t$(RANLIB) ") + dst_targ; | 
|---|
| 677 | } else if (!project->isActiveConfig( "debug_info") && !project->isActiveConfig( "nostrip") | 
|---|
| 678 | && !project->isEmpty( "QMAKE_STRIP")) { | 
|---|
| 679 | ret += "\n\t-$(STRIP)"; | 
|---|
| 680 | if (project->first( "TEMPLATE") == "lib") { | 
|---|
| 681 | if (!project->isEmpty( "QMAKE_STRIPFLAGS_LIB")) | 
|---|
| 682 | ret += " "+ var( "QMAKE_STRIPFLAGS_LIB"); | 
|---|
| 683 | } else if (project->first( "TEMPLATE") == "app") { | 
|---|
| 684 | if (!project->isEmpty( "QMAKE_STRIPFLAGS_APP")) | 
|---|
| 685 | ret += " "+ var( "QMAKE_STRIPFLAGS_APP"); | 
|---|
| 686 | } | 
|---|
| 687 | ret += ' ' + dst_targ; | 
|---|
| 688 | } | 
|---|
| 689 | if(!uninst.isEmpty()) | 
|---|
| 690 | uninst.append( "\n\t"); | 
|---|
| 691 | if (bundle == SolidBundle) | 
|---|
| 692 | uninst.append( "-$(DEL_FILE) -r "+ plain_targ); | 
|---|
| 693 | else if (!isAux) | 
|---|
| 694 | uninst.append( "-$(DEL_FILE) "+ dst_targ); | 
|---|
| 695 | if (bundle == SlicedBundle) { | 
|---|
| 696 | int dstlen = project->first( "DESTDIR").length(); | 
|---|
| 697 | for (const ProString &src : project->values( "QMAKE_BUNDLED_FILES")) { | 
|---|
| 698 | ProString file = src.mid(dstlen); | 
|---|
| 699 | QString dst = escapeFilePath( | 
|---|
| 700 | filePrefixRoot(root, fileFixify(targetdir + file, FileFixifyAbsolute))); | 
|---|
| 701 | if (!ret.isEmpty()) | 
|---|
| 702 | ret += "\n\t"; | 
|---|
| 703 | ret += mkdir_p_asstring( "\"`dirname "+ dst + "`\"", false) + "\n\t"; | 
|---|
| 704 | ret += "-$(DEL_FILE) "+ dst + "\n\t"; // Can't overwrite symlinks to directories | 
|---|
| 705 | ret += "$(QINSTALL) "+ escapeFilePath(src) + " "+ dst; | 
|---|
| 706 | if (!uninst.isEmpty()) | 
|---|
| 707 | uninst.append( "\n\t"); | 
|---|
| 708 | uninst.append( "-$(DEL_FILE) "+ dst); | 
|---|
| 709 | } | 
|---|
| 710 | } | 
|---|
| 711 | if(!links.isEmpty()) { | 
|---|
| 712 | for(int i = 0; i < links.size(); ++i) { | 
|---|
| 713 | if (target_mode == TARG_UNIX_MODE || target_mode == TARG_MAC_MODE) { | 
|---|
| 714 | QString link = Option::fixPathToTargetOS(destdir + links[i], false); | 
|---|
| 715 | int lslash = link.lastIndexOf(Option::dir_sep); | 
|---|
| 716 | if(lslash != -1) | 
|---|
| 717 | link = link.right(link.length() - (lslash + 1)); | 
|---|
| 718 | QString dst_link = escapeFilePath( | 
|---|
| 719 | filePrefixRoot(root, fileFixify(targetdir + link, FileFixifyAbsolute))); | 
|---|
| 720 | ret += "\n\t-$(SYMLINK) $(TARGET) "+ dst_link; | 
|---|
| 721 | if(!uninst.isEmpty()) | 
|---|
| 722 | uninst.append( "\n\t"); | 
|---|
| 723 | uninst.append( "-$(DEL_FILE) "+ dst_link); | 
|---|
| 724 | } | 
|---|
| 725 | } | 
|---|
| 726 | } | 
|---|
| 727 | } | 
|---|
| 728 | if (isAux || project->first( "TEMPLATE") == "lib") { | 
|---|
| 729 | QStringList types; | 
|---|
| 730 | types << "prl"<< "libtool"<< "pkgconfig"; | 
|---|
| 731 | for(int i = 0; i < types.size(); ++i) { | 
|---|
| 732 | const QString type = types.at(i); | 
|---|
| 733 | QString meta; | 
|---|
| 734 | if(type == "prl"&& project->isActiveConfig( "create_prl") && !project->isActiveConfig( "no_install_prl") && | 
|---|
| 735 | !project->isEmpty( "QMAKE_INTERNAL_PRL_FILE")) | 
|---|
| 736 | meta = prlFileName(false); | 
|---|
| 737 | if (type == "libtool"&& project->isActiveConfig( "create_libtool")) | 
|---|
| 738 | meta = libtoolFileName(false); | 
|---|
| 739 | if(type == "pkgconfig"&& project->isActiveConfig( "create_pc")) | 
|---|
| 740 | meta = pkgConfigFileName(false); | 
|---|
| 741 | if(!meta.isEmpty()) { | 
|---|
| 742 | QString src_meta = meta; | 
|---|
| 743 | if(!destdir.isEmpty()) | 
|---|
| 744 | src_meta = Option::fixPathToTargetOS(destdir + meta, false); | 
|---|
| 745 | QString dst_meta = filePrefixRoot(root, fileFixify(targetdir + meta, FileFixifyAbsolute)); | 
|---|
| 746 | if(!uninst.isEmpty()) | 
|---|
| 747 | uninst.append( "\n\t"); | 
|---|
| 748 | uninst.append( "-$(DEL_FILE) "+ escapeFilePath(dst_meta)); | 
|---|
| 749 | const QString dst_meta_dir = fileInfo(dst_meta).path(); | 
|---|
| 750 | if(!dst_meta_dir.isEmpty()) { | 
|---|
| 751 | if(!ret.isEmpty()) | 
|---|
| 752 | ret += "\n\t"; | 
|---|
| 753 | ret += mkdir_p_asstring(dst_meta_dir, true); | 
|---|
| 754 | } | 
|---|
| 755 | if (!ret.isEmpty()) | 
|---|
| 756 | ret += "\n\t"; | 
|---|
| 757 | ret += installMetaFile(ProKey( "QMAKE_"+ type.toUpper() + "_INSTALL_REPLACE"), src_meta, dst_meta); | 
|---|
| 758 | } | 
|---|
| 759 | } | 
|---|
| 760 | } | 
|---|
| 761 | return ret; | 
|---|
| 762 | } | 
|---|
| 763 |  | 
|---|
| 764 | QString | 
|---|
| 765 | UnixMakefileGenerator::escapeFilePath(const QString &path) const | 
|---|
| 766 | { | 
|---|
| 767 | QString ret = path; | 
|---|
| 768 | if(!ret.isEmpty()) { | 
|---|
| 769 | ret.replace(QLatin1Char(' '), QLatin1String( "\\ ")) | 
|---|
| 770 | .replace(QLatin1Char('\t'), QLatin1String( "\\\t")); | 
|---|
| 771 | debug_msg(2, "EscapeFilePath: %s -> %s", path.toLatin1().constData(), ret.toLatin1().constData()); | 
|---|
| 772 | } | 
|---|
| 773 | return ret; | 
|---|
| 774 | } | 
|---|
| 775 |  | 
|---|
| 776 | QT_END_NAMESPACE | 
|---|
| 777 |  | 
|---|