diff options
Diffstat (limited to 'qmake')
23 files changed, 375 insertions, 283 deletions
diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index ef1c542f57..10c72bf28f 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -12,7 +12,8 @@ OBJS=project.o option.o property.o main.o ioutils.o proitems.o \ gbuild.o cesdkhandler.o #qt code -QOBJS=qtextcodec.o qutfcodec.o qstring.o qstring_compat.o qstringbuilder.o qtextstream.o qiodevice.o qmalloc.o qglobal.o \ +QOBJS=qtextcodec.o qutfcodec.o qstring.o qstring_compat.o qstringbuilder.o qtextstream.o qiodevice.o \ + qdebug.o qmalloc.o qglobal.o \ qarraydata.o qbytearray.o qbytearraymatcher.o qdatastream.o qbuffer.o qlist.o qfiledevice.o qfile.o \ qfilesystementry.o qfilesystemengine.o qfsfileengine.o qfsfileengine_iterator.o qregexp.o qvector.o \ qbitarray.o qdir.o qdiriterator.o quuid.o qhash.o qfileinfo.o qdatetime.o qstringlist.o \ @@ -43,6 +44,7 @@ DEPEND_SRC = \ $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp \ $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp \ $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \ + $(SOURCE_PATH)/src/corelib/io/qdebug.cpp \ $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp \ $(SOURCE_PATH)/src/corelib/global/qglobal.cpp $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \ $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp\ @@ -101,7 +103,7 @@ CPPFLAGS = -g $(EXTRA_CPPFLAGS) \ -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL \ -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_NO_COMPONENT -DQT_NO_COMPRESS \ -DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM \ - -DQT_CRYPTOGRAPHICHASH_ONLY_SHA1 -DQT_JSON_READONLY + -DQT_CRYPTOGRAPHICHASH_ONLY_SHA1 -DQT_JSON_READONLY -DQT_NO_STANDARDPATHS CXXFLAGS = $(EXTRA_CXXFLAGS) $(CPPFLAGS) @@ -240,6 +242,9 @@ qsettings_win.o: $(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp qiodevice.o: $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp +qdebug.o: $(SOURCE_PATH)/src/corelib/io/qdebug.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdebug.cpp + qmalloc.o: $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index b1936f3cec..bac6e950be 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -27,7 +27,7 @@ LINKER = link !if "$(QMAKESPEC)" == "win32-msvc2005" CFLAGS_EXTRA = /Zc:wchar_t- !elseif "$(QMAKESPEC)" == "win32-msvc2008" || "$(QMAKESPEC)" == "win32-msvc2010" || "$(QMAKESPEC)" == "win32-msvc2012" || "$(QMAKESPEC)" == "win32-msvc2013" -CFLAGS_EXTRA = /MP +CFLAGS_EXTRA = /MP /D_CRT_SECURE_NO_WARNINGS !endif CFLAGS_BARE = -c -Fo./ -Fdqmake.pdb \ @@ -41,7 +41,7 @@ CFLAGS_BARE = -c -Fo./ -Fdqmake.pdb \ -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL \ -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_NO_COMPONENT -DQT_NO_COMPRESS \ -DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM \ - -DUNICODE -DQT_CRYPTOGRAPHICHASH_ONLY_SHA1 -DQT_JSON_READONLY + -DUNICODE -DQT_CRYPTOGRAPHICHASH_ONLY_SHA1 -DQT_JSON_READONLY -DQT_NO_STANDARDPATHS CFLAGS = -Yuqmake_pch.h -FIqmake_pch.h -Fpqmake_pch.pch $(CFLAGS_BARE) $(CFLAGS) $(EXTRA_CPPFLAGS) CXXFLAGS_BARE = $(CFLAGS_BARE) @@ -61,7 +61,7 @@ OBJS = project.obj main.obj ioutils.obj proitems.obj qmakevfs.obj \ qmakeglobals.obj qmakeparser.obj qmakeevaluator.obj qmakebuiltins.obj \ makefile.obj unixmake.obj unixmake2.obj mingw_make.obj \ option.obj winmakefile.obj projectgenerator.obj property.obj meta.obj \ - makefiledeps.obj metamakefile.obj xmloutput.obj pbuilder_pbx.obj \ + makefiledeps.obj metamakefile.obj xmloutput.obj \ msvc_nmake.obj msvc_vcproj.obj msvc_vcxproj.obj \ msvc_objectmodel.obj msbuild_objectmodel.obj registry.obj \ gbuild.obj cesdkhandler.obj @@ -94,6 +94,7 @@ QTOBJS= \ qglobal.obj \ qhash.obj \ qiodevice.obj \ + qdebug.obj \ qlist.obj \ qlinkedlist.obj \ qlocale.obj \ @@ -140,7 +141,6 @@ clean:: -del $(OBJS) -del qmake_pch.obj -del qmake_pch.pch - -del qsystemlibrary.obj -del qmake.pdb -del qmake.ilk -del qmake.tds diff --git a/qmake/doc/qmake.qdocconf b/qmake/doc/qmake.qdocconf index d8f970048c..bfdf1d1798 100644 --- a/qmake/doc/qmake.qdocconf +++ b/qmake/doc/qmake.qdocconf @@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) project = QMake description = QMake Manual -url = http://qt-project.org/doc/qt-$QT_VER qhp.projects = qmake diff --git a/qmake/doc/snippets/code/doc_src_qmake-manual.pro b/qmake/doc/snippets/code/doc_src_qmake-manual.pro index ff1edb878d..1bd89d2f04 100644 --- a/qmake/doc/snippets/code/doc_src_qmake-manual.pro +++ b/qmake/doc/snippets/code/doc_src_qmake-manual.pro @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -218,13 +218,6 @@ FORMS = mydialog.ui \ #! [32] -#! [33] -FORMS3 = my_uic3_dialog.ui \ - my_uic3_widget.ui \ - my_uic3_config.ui -#! [33] - - #! [34] HEADERS = myclass.h \ login.h \ @@ -977,3 +970,15 @@ int main() { return featureFunction(); } # <project root>/project.pro qtCompileTest(test) #! [182] + +#! [183] +# <project root>/project.pro +QMAKE_SONAME_PREFIX = @rpath +#! [183] + +#! [184] +# <project root>/project.pro +QMAKE_SONAME_PREFIX = @executable_path/../Frameworks +QMAKE_SONAME_PREFIX = @loader_path/Frameworks +QMAKE_SONAME_PREFIX = /Library/Frameworks +#! [184] diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index 58441064ad..dedb491959 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -657,9 +657,9 @@ qmake knows about many of these features, which can be accessed via specific variables that only take effect on the platforms where they are relevant. - \section1 Mac OS X + \section1 OS X and iOS - Features specific to this platform include support for creating universal + Features specific to these platforms include support for creating universal binaries, frameworks and bundles. \section2 Source and Binary Packages @@ -681,7 +681,7 @@ qmake is able to automatically generate build rules for linking against frameworks in the standard framework directory on - Mac OS X, located at \c{/Library/Frameworks/}. + OS X, located at \c{/Library/Frameworks/}. Directories other than the standard framework directory need to be specified to the build system, and this is achieved by appending linker options to the @@ -722,14 +722,14 @@ and \l{QMAKE_FRAMEWORK_VERSION} variables. By default, the values used for these variables are obtained from the \l{TARGET} and \l{VERSION} variables. - See \l{Qt for Mac OS X - Deployment} for more information about + See \l{Qt for OS X - Deployment} for more information about deploying applications and libraries. \section2 Creating and Moving Xcode Projects - Developers on Mac OS X can take advantage of the qmake support for Xcode + Developers on OS X can take advantage of the qmake support for Xcode project files, as described in - \l{Qt is Mac OS X Native#Development Tools}{Qt is Mac OS X Native}, + \l{Qt is OS X Native#Development Tools}{Qt is OS X Native}, by running qmake to generate an Xcode project from an existing qmake project file. For example: @@ -1026,7 +1026,7 @@ See \l{Platform Notes#Visual Studio Manifest Files}{Platform Notes} for more information about the options for embedding manifest files. - The following options take an effect only on Mac OS X: + The following options take an effect only on OS X: \table \header \li Option \li Description @@ -1360,7 +1360,7 @@ Indicates the header file for creating a precompiled header file, to increase the compilation speed of a project. Precompiled headers are currently only supported on some platforms - (Windows - all MSVC project types, Mac OS X - Xcode, Makefile, + (Windows - all MSVC project types, Apple - Xcode, Makefile, Unix - gcc 3.3 and up). \target PWD @@ -1409,7 +1409,7 @@ \target QMAKE_BUNDLE_DATA \section1 QMAKE_BUNDLE_DATA - \note This variable is used on Mac OS X only. + \note This variable is used on OS X and iOS only. Specifies the data that will be installed with a library bundle, and is often used to specify a collection of header files. @@ -1431,7 +1431,7 @@ \section1 QMAKE_BUNDLE_EXTENSION - \note This variable is used on Mac OS X only. + \note This variable is used on OS X and iOS only. Specifies the extension to be used for library bundles. This allows frameworks to be created with custom extensions instead of the @@ -1649,7 +1649,7 @@ \section1 QMAKE_FRAMEWORK_BUNDLE_NAME - \note This variable is used on Mac OS X only. + \note This variable is used on OS X and iOS only. In a framework project, this variable contains the name to be used for the framework that is built. @@ -1663,9 +1663,9 @@ \target QMAKE_FRAMEWORK_VERSION \section1 QMAKE_FRAMEWORK_VERSION - \note This variable is used on Mac OS X only. + \note This variable is used on OS X and iOS only. - For projects where the build target is a Mac OS X framework, this variable + For projects where the build target is an OS X or iOS framework, this variable is used to specify the version number that will be applied to the framework that is built. @@ -1739,10 +1739,10 @@ \target QMAKE_INFO_PLIST \section1 QMAKE_INFO_PLIST - \note This variable is used on Mac OS X platforms only. + \note This variable is used on OS X and iOS platforms only. Specifies the name of the property list file, \c{.plist}, you - would like to include in your Mac OS X application bundle. + would like to include in your OS X and iOS application bundle. In the \c{.plist} file, you can define some variables, e.g., @EXECUTABLE@, which qmake will replace with the actual executable name. Other variables @@ -1996,16 +1996,16 @@ \section1 QMAKE_MAC_SDK - This variable is used on Mac OS X when building universal binaries. + This variable is used on OS X when building universal binaries. \section1 QMAKE_MACOSX_DEPLOYMENT_TARGET - This variable only takes effect when building on Mac OS X. On that + This variable only takes effect when building on OS X. On that platform, the variable will be forwarded to the MACOSX_DEPLOYMENT_TARGET environment variable, which is interpreted by the compiler or linker. For more information, see the - \l{Qt for Mac OS X - Deployment#Mac OS X Version Dependencies}{Deploying - an Application on Mac OS X} document. + \l{Qt for OS X - Deployment#OS X Version Dependencies}{Deploying + an Application on OS X} document. \section1 QMAKE_MAKEFILE @@ -2071,6 +2071,39 @@ qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. + \section1 QMAKE_SONAME_PREFIX + + If defined, the value of this variable is used as a path to be prepended to + the built shared library's \c SONAME identifier. The \c SONAME is the + identifier that the dynamic linker will later use to reference the library. + In general this reference may be a library name or full library path. On OS + X and iOS, the path may be specified relatively using the following + placeholders: + + \table + \header \li Placeholder \li Effect + \row \li @rpath + \li Expands to paths defined by LC_RPATH mach-o commands in + the current process executable or the referring libraries. + \row \li @executable_path + \li Expands to the current process executable location. + \row \li @loader_path + \li Expands to the referring executable or library location. + \endtable + + In most cases, using \c @rpath is sufficient and recommended: + + \snippet code/doc_src_qmake-manual.pro 183 + + However, the prefix may be also specified using different placeholders, or + an absolute path, such as one of the following: + + \snippet code/doc_src_qmake-manual.pro 184 + + For more information, see + \l{https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/dyld.1.html}{dyld} + documentation on dynamic library install names. + \section1 QMAKE_TARGET Specifies the name of the project target. The value of this @@ -2417,13 +2450,6 @@ \li architecture \li The target architecture. Defaults to \c VCPROJ_ARCH. \row - \li arguments - \li Allows arguments to be passed to the executable. - \row - \li author - \li Package author. Defaults to \c{Default package author}. - This option is only available for Windows Phone. - \row \li background \li Tile background color. Defaults to \c{green}. \row @@ -2432,7 +2458,7 @@ \row \li capabilities_device \li Specifies device capabilities to add to the capability list - (location, webcam, and so on). This option is not available on Windows Phone. + (location, webcam, and so on). \row \li default_language \li The default language code of the application. Defaults to "en". @@ -2447,10 +2473,6 @@ \li Tile foreground (text) color. Defaults to \c{light}. This option is only available for Windows Store apps on Windows 8 and Windows RT. \row - \li genre - \li Package genre. Defaults to \c{apps.normal}. - This option is only available for Windows Phone. - \row \li iconic_tile_icon \li Image file for the \c{iconic} tile template icon. Default provided by the mkspec. @@ -2463,10 +2485,6 @@ \li The unique ID of the app. Defaults to reusing the existing generated manifest's UUID, or generates a new UUID if none is present. \row - \li languages - \li A list of additional language codes supported by the application. This list - is empty by default. - \row \li logo_large \li Large logo image file. Default provided by the mkspec. \row @@ -2482,12 +2500,17 @@ \li name \li The name of the package as displayed to the user. Defaults to TARGET. \row + \li phone_product_id + \li The GUID of the product. Defaults to the value of WINRT_MANIFEST.identity. (Windows Phone only) + \row + \li phone_publisher_id + \li The GUID of the publisher. Defaults to an invalid GUID. (Windows Phone only) + \row \li publisher \li Display name of the publisher. Defaults to \c{Default publisher display name}. \row \li publisher_id - \li On Windows 8 or Windows RT, the publisher's distinguished name (default: \c{CN=MyCN}). - On Windows Phone, the publisher's UUID (default: invalid UUID string). + \li The publisher's distinguished name (default: \c{CN=MyCN}). \row \li splash_screen \li Splash screen image file. Default provided by the mkspec. @@ -2506,12 +2529,8 @@ \code WINRT_MANIFEST.publisher = MyCompany WINRT_MANIFEST.logo_store = someImage.png - winphone { - WINRT_MANIFEST.capabilities += ID_CAP_LOCATION ID_CAP_NETWORKING - } else { - WINRT_MANIFEST.capabilities += internetClient - WINRT_MANIFEST.device_capabilities += location - } + WINRT_MANIFEST.capabilities += internetClient + WINRT_MANIFEST.device_capabilities += location \endcode Additionally, an input manifest file can be specified by using WINRT_MANIFEST. @@ -4110,7 +4129,7 @@ \li nmake \li Visual Studio projects (VS 2008 and later) \endlist - \li Mac OS X + \li OS X and iOS \list \li Makefile \li Xcode @@ -4481,7 +4500,7 @@ them uses project-specific variables to customize output files. Platform-specific variables are not described here. For more information, - see \l{Qt for Windows - Deployment} and \l{Qt for Mac OS X}. + see \l{Qt for Windows - Deployment} and \l{Qt for OS X}. \target Application \section1 Building an Application @@ -4630,7 +4649,7 @@ \endlist The target file name for the library is platform-dependent. For example, on - X11 and Mac OS X, the library name will be prefixed by \c lib. On Windows, + X11, OS X, and iOS, the library name will be prefixed by \c lib. On Windows, no prefix is added to the file name. \target Plugin diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index e1e373787c..418019405c 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -418,7 +418,7 @@ class ProjectBuilderSources bool buildable, object_output; QString key, group, compiler; public: - ProjectBuilderSources(const QString &key, bool buildable=false, const QString &group=QString(), const QString &compiler=QString(), bool producesObject=false); + ProjectBuilderSources(const QString &key, bool buildable = false, const QString &compiler = QString(), bool producesObject = false); QStringList files(QMakeProject *project) const; inline bool isBuildable() const { return buildable; } inline QString keyName() const { return key; } @@ -442,8 +442,8 @@ public: } }; -ProjectBuilderSources::ProjectBuilderSources(const QString &k, bool b, - const QString &g, const QString &c, bool o) : buildable(b), object_output(o), key(k), group(g), compiler(c) +ProjectBuilderSources::ProjectBuilderSources(const QString &k, bool b, const QString &c, bool o) : + buildable(b), object_output(o), key(k), compiler(c) { // Override group name for a few common keys if (k == "SOURCES" || k == "OBJECTIVE_SOURCES" || k == "HEADERS") @@ -463,10 +463,16 @@ ProjectBuilderSources::files(QMakeProject *project) const { QStringList ret = project->values(ProKey(key)).toQStringList(); if(key == "QMAKE_INTERNAL_INCLUDED_FILES") { + QString qtPrefix(QLibraryInfo::rawLocation(QLibraryInfo::PrefixPath, QLibraryInfo::EffectivePaths) + '/'); + QString qtSrcPrefix(QLibraryInfo::rawLocation(QLibraryInfo::PrefixPath, QLibraryInfo::EffectiveSourcePaths) + '/'); + QStringList newret; for(int i = 0; i < ret.size(); ++i) { - if(!ret.at(i).endsWith(Option::prf_ext)) - newret.append(ret.at(i)); + // Don't show files "internal" to Qt in Xcode + if (ret.at(i).startsWith(qtPrefix) || ret.at(i).startsWith(qtSrcPrefix)) + continue; + + newret.append(ret.at(i)); } ret = newret; } @@ -567,6 +573,9 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) // doesn't have access to any of the information it needs to resolve relative paths. project->values("QMAKE_INTERNAL_INCLUDED_FILES").prepend(fileFixify(project->projectFile(), qmake_getpwd(), input_dir)); + // Since we can't fileFixify inside ProjectBuilderSources::files(), we resolve the absolute paths here + project->values("QMAKE_INTERNAL_INCLUDED_FILES") = ProStringList(fileFixify(project->values("QMAKE_INTERNAL_INCLUDED_FILES").toQStringList(), FileFixifyAbsolute)); + //DUMP SOURCES QMap<QString, ProStringList> groups; QList<ProjectBuilderSources> sources; @@ -606,7 +615,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) } } sources.append(ProjectBuilderSources(inputs.at(input).toQString(), true, - QString(), (*it).toQString(), isObj)); + (*it).toQString(), isObj)); if (isObj) { inputs.removeAt(input); @@ -634,18 +643,22 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) continue; bool in_root = true; - QString src_key = keyFor(file), name = file; - if(project->isActiveConfig("flat")) { - QString flat_file = fileFixify(file, qmake_getpwd(), Option::output_dir, FileFixifyRelative); - if(flat_file.indexOf(Option::dir_sep) != -1) { - QStringList dirs = flat_file.split(Option::dir_sep); - name = dirs.back(); - } - } else { - QString flat_file = fileFixify(file, qmake_getpwd(), Option::output_dir, FileFixifyRelative); - if(QDir::isRelativePath(flat_file) && flat_file.indexOf(Option::dir_sep) != -1) { + QString src_key = keyFor(file); + + file = fileFixify(file, qmake_getpwd(), Option::output_dir, FileFixifyAbsolute); + QString name = file.split(Option::dir_sep).back(); + + if (!project->isActiveConfig("flat")) { + // Build group hierarchy for file references that match the source our build dir + QString relativePath = fileFixify(file, input_dir, qmake_getpwd(), FileFixifyRelative); + if (QDir::isRelativePath(relativePath) && relativePath.startsWith(QLatin1String("../"))) + relativePath = fileFixify(file, FileFixifyRelative); // Try build dir + + if (QDir::isRelativePath(relativePath) + && !relativePath.startsWith(QLatin1String("../")) + && relativePath.indexOf(Option::dir_sep) != -1) { QString last_grp("QMAKE_PBX_" + sources.at(source).groupName() + "_HEIR_GROUP"); - QStringList dirs = flat_file.split(Option::dir_sep); + QStringList dirs = relativePath.split(Option::dir_sep); name = dirs.back(); dirs.pop_back(); //remove the file portion as it will be added via src_key for(QStringList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { @@ -676,12 +689,12 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("path", escapeFilePath(file)) << ";\n"; if (name != file) t << "\t\t\t" << writeSettings("name", escapeFilePath(name)) << ";\n"; - t << "\t\t\t" << writeSettings("sourceTree", sourceTreeForFile(file)) << ";\n"; + t << "\t\t\t" << writeSettings("sourceTree", "<absolute>") << ";\n"; QString filetype = xcodeFiletypeForFilename(file); if (!filetype.isNull()) t << "\t\t\t" << writeSettings("lastKnownFileType", filetype) << ";\n"; t << "\t\t};\n"; - if (sources.at(source).isBuildable() && sources.at(source).isObjectOutput(file)) { //build reference + if (sources.at(source).isBuildable()) { //build reference QString build_key = keyFor(file + ".BUILDABLE"); t << "\t\t" << build_key << " = {\n" << "\t\t\t" << writeSettings("fileRef", src_key) << ";\n" @@ -690,7 +703,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t\t" << writeSettings("ATTRIBUTES", ProStringList(), SettingsAsList, 5) << ";\n" << "\t\t\t};\n" << "\t\t};\n"; - project->values("QMAKE_PBX_OBJ").append(build_key); + if (sources.at(source).isObjectOutput(file)) + project->values("QMAKE_PBX_OBJ").append(build_key); } } if(!src_list.isEmpty()) { @@ -960,7 +974,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("name", escapeFilePath(name)) << ";\n" << "\t\t\t" << writeSettings("path", escapeFilePath(library)) << ";\n" << "\t\t\t" << writeSettings("refType", QString::number(reftypeForFile(library)), SettingsNoQuote) << ";\n" - << "\t\t\t" << writeSettings("sourceTree", sourceTreeForFile(library)) << ";\n"; + << "\t\t\t" << writeSettings("sourceTree", "<absolute>") << ";\n"; if (is_frmwrk) t << "\t\t\t" << writeSettings("lastKnownFileType", "wrapper.framework") << ";\n"; t << "\t\t};\n"; @@ -1028,9 +1042,9 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("files", ProStringList(), SettingsAsList, 4) << ";\n" // The build phases are not executed in the order they are defined, but by their // resolved dependenices, so we have to ensure that this phase is run after the - // compilation phase, and before the link phase. Making the phase depend on all the - // object files, and "write" to the list of files to link achieves that. - << "\t\t\t" << writeSettings("inputPaths", ProStringList("$(OBJECT_FILE_DIR_$(CURRENT_VARIANT))/$(CURRENT_ARCH)/*" + Option::obj_ext), SettingsAsList, 4) << ";\n" + // compilation phase, and before the link phase. Making the phase depend on the + // object file directory, and "write" to the list of files to link achieves that. + << "\t\t\t" << writeSettings("inputPaths", ProStringList("$(OBJECT_FILE_DIR_$(CURRENT_VARIANT))/$(CURRENT_ARCH)/"), SettingsAsList, 4) << ";\n" << "\t\t\t" << writeSettings("outputPaths", ProStringList("$(LINK_FILE_LIST_$(CURRENT_VARIANT)_$(CURRENT_ARCH))"), SettingsAsList, 4) << ";\n" << "\t\t\t" << writeSettings("isa", "PBXShellScriptBuildPhase", SettingsNoQuote) << ";\n" << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" @@ -1101,12 +1115,9 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("shellScript", fixForOutput("cp -r $BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME " + escapeFilePath(destDir))) << ";\n" << "\t\t};\n"; } - // Copy Bundle Resources + // Copy Bundle Data if (!project->isEmpty("QMAKE_BUNDLE_DATA")) { ProStringList bundle_file_refs; - ProStringList bundle_resources_files; - - bool useCopyResourcesPhase = project->isActiveConfig("app_bundle") && project->first("TEMPLATE") == "app"; //all bundle data const ProStringList &bundle_data = project->values("QMAKE_BUNDLE_DATA"); @@ -1116,13 +1127,15 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) //all files const ProStringList &files = project->values(ProKey(bundle_data[i] + ".files")); for(int file = 0; file < files.count(); file++) { - QString fn = fileFixify(files[file].toQString(), Option::output_dir, input_dir); + QString fn = fileFixify(files[file].toQString(), Option::output_dir, input_dir, FileFixifyAbsolute); + QString name = fn.split(Option::dir_sep).back(); QString file_ref_key = keyFor("QMAKE_PBX_BUNDLE_DATA_FILE_REF." + bundle_data[i] + "-" + fn); bundle_file_refs += file_ref_key; t << "\t\t" << file_ref_key << " = {\n" << "\t\t\t" << writeSettings("isa", "PBXFileReference", SettingsNoQuote) << ";\n" << "\t\t\t" << writeSettings("path", escapeFilePath(fn)) << ";\n" - << "\t\t\t" << writeSettings("sourceTree", sourceTreeForFile(fn)) << ";\n" + << "\t\t\t" << writeSettings("name", name) << ";\n" + << "\t\t\t" << writeSettings("sourceTree", "<absolute>") << ";\n" << "\t\t};\n"; QString file_key = keyFor("QMAKE_PBX_BUNDLE_DATA_FILE." + bundle_data[i] + "-" + fn); bundle_files += file_key; @@ -1132,46 +1145,20 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t};\n"; } - if (!useCopyResourcesPhase || !path.isEmpty()) { - // The resource copy phase doesn't support paths, so we have to use - // a regular file copy phase (which doesn't optimize the resources). - QString phase_key = keyFor("QMAKE_PBX_BUNDLE_COPY." + bundle_data[i]); - if (!project->isEmpty(ProKey(bundle_data[i] + ".version"))) { - //### - } - - project->values("QMAKE_PBX_BUILDPHASES").append(phase_key); - t << "\t\t" << phase_key << " = {\n" - << "\t\t\t" << writeSettings("name", "Copy '" + bundle_data[i] + "' Files to Bundle") << ";\n" - << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n" - << "\t\t\t" << writeSettings("dstPath", escapeFilePath(path)) << ";\n" - << "\t\t\t" << writeSettings("dstSubfolderSpec", "1", SettingsNoQuote) << ";\n" - << "\t\t\t" << writeSettings("files", bundle_files, SettingsAsList, 4) << ";\n" - << "\t\t\t" << writeSettings("isa", "PBXCopyFilesBuildPhase", SettingsNoQuote) << ";\n" - << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" - << "\t\t};\n"; - } else { - // Otherwise we leave it to the resource copy phase below - bundle_resources_files += bundle_files; + QString phase_key = keyFor("QMAKE_PBX_BUNDLE_COPY." + bundle_data[i]); + if (!project->isEmpty(ProKey(bundle_data[i] + ".version"))) { + //### } - } - if (useCopyResourcesPhase) { - if (!project->isEmpty("ICON")) { - ProString icon = project->first("ICON"); - if (icon.length() >= 2 && (icon.at(0) == '"' || icon.at(0) == '\'') && icon.endsWith(icon.at(0))) - icon = icon.mid(1, icon.length() - 2); - bundle_resources_files += keyFor(icon + ".BUILDABLE"); - } - - QString grp("Copy Bundle Resources"), key = keyFor(grp); - project->values("QMAKE_PBX_BUILDPHASES").append(key); - t << "\t\t" << key << " = {\n" + project->values("QMAKE_PBX_BUILDPHASES").append(phase_key); + t << "\t\t" << phase_key << " = {\n" + << "\t\t\t" << writeSettings("name", "Copy '" + bundle_data[i] + "' Files to Bundle") << ";\n" << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n" - << "\t\t\t" << writeSettings("files", bundle_resources_files, SettingsAsList, 4) << ";\n" - << "\t\t\t" << writeSettings("isa", "PBXResourcesBuildPhase", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("dstPath", escapeFilePath(path)) << ";\n" + << "\t\t\t" << writeSettings("dstSubfolderSpec", "1", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("files", bundle_files, SettingsAsList, 4) << ";\n" + << "\t\t\t" << writeSettings("isa", "PBXCopyFilesBuildPhase", SettingsNoQuote) << ";\n" << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" - << "\t\t\t" << writeSettings("name", escapeFilePath(grp)) << ";\n" << "\t\t};\n"; } @@ -1180,11 +1167,35 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) t << "\t\t" << bundle_data_key << " = {\n" << "\t\t\t" << writeSettings("children", bundle_file_refs, SettingsAsList, 4) << ";\n" << "\t\t\t" << writeSettings("isa", "PBXGroup", SettingsNoQuote) << ";\n" - << "\t\t\t" << writeSettings("name", "Bundle Resources") << ";\n" + << "\t\t\t" << writeSettings("name", "Bundle Data") << ";\n" << "\t\t\t" << writeSettings("sourceTree", "<Group>") << ";\n" << "\t\t};\n"; } + // Copy bundle resources. Optimizes resources, and puts them into the Resources + // subdirectory on OSX, but doesn't support paths. + if (project->isActiveConfig("app_bundle") && project->first("TEMPLATE") == "app") { + ProStringList bundle_resources_files; + if (!project->isEmpty("ICON")) { + ProString icon = project->first("ICON"); + if (icon.length() >= 2 && (icon.at(0) == '"' || icon.at(0) == '\'') && icon.endsWith(icon.at(0))) + icon = icon.mid(1, icon.length() - 2); + bundle_resources_files += keyFor(icon + ".BUILDABLE"); + } + + // Always add "Copy Bundle Resources" phase, even when we have no bundle + // resources, since Xcode depends on it being there for e.g asset catalogs. + QString grp("Copy Bundle Resources"), key = keyFor(grp); + project->values("QMAKE_PBX_BUILDPHASES").append(key); + t << "\t\t" << key << " = {\n" + << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("files", bundle_resources_files, SettingsAsList, 4) << ";\n" + << "\t\t\t" << writeSettings("isa", "PBXResourcesBuildPhase", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("name", escapeFilePath(grp)) << ";\n" + << "\t\t};\n"; + } + //REFERENCE project->values("QMAKE_PBX_PRODUCTS").append(keyFor(pbx_dir + "QMAKE_PBX_REFERENCE")); t << "\t\t" << keyFor(pbx_dir + "QMAKE_PBX_REFERENCE") << " = {\n" @@ -1797,14 +1808,6 @@ ProjectBuilderMakefileGenerator::reftypeForFile(const QString &where) return ret; } -QString ProjectBuilderMakefileGenerator::sourceTreeForFile(const QString &where) -{ - Q_UNUSED(where) - // We always use absolute paths, instead of maintaining the SRCROOT - // build variable and making files relative to that. - return QLatin1String("<absolute>"); -} - QString ProjectBuilderMakefileGenerator::projectSuffix() const { diff --git a/qmake/generators/mac/pbuilder_pbx.h b/qmake/generators/mac/pbuilder_pbx.h index 8813a190a9..feb3f42c8f 100644 --- a/qmake/generators/mac/pbuilder_pbx.h +++ b/qmake/generators/mac/pbuilder_pbx.h @@ -63,7 +63,6 @@ class ProjectBuilderMakefileGenerator : public UnixMakefileGenerator ProStringList fixListForOutput(const char *where); ProStringList fixListForOutput(const ProStringList &list); int reftypeForFile(const QString &where); - QString sourceTreeForFile(const QString &where); QString projectSuffix() const; enum { SettingsAsList=0x01, SettingsNoQuote=0x02 }; inline QString writeSettings(const QString &var, const char *val, int flags=0, int indent_level=0) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 0e3e058c7b..7bc673bf7b 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -70,11 +70,6 @@ QT_BEGIN_NAMESPACE -// Well, Windows doesn't have this, so here's the macro -#ifndef S_ISDIR -# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -#endif - bool MakefileGenerator::canExecute(const QStringList &cmdline, int *a) const { int argv0 = -1; @@ -1749,23 +1744,7 @@ MakefileGenerator::verifyExtraCompiler(const ProString &comp, const QString &fil QString tmp_out = project->values(ProKey(comp + ".output")).first().toQString(); if(tmp_out.isEmpty()) return false; - QString tmp_cmd; - const ProKey ckey(comp + ".commands"); - if (!project->isEmpty(ckey)) { - int argv0 = -1; - ProStringList cmdline = project->values(ckey); - for(int i = 0; i < cmdline.count(); ++i) { - if(!cmdline.at(i).contains('=')) { - argv0 = i; - break; - } - } - if(argv0 != -1) { - cmdline[argv0] = Option::fixPathToTargetOS(cmdline.at(argv0).toQString(), false); - tmp_cmd = cmdline.join(' '); - } - } - + const QString tmp_cmd = project->values(ProKey(comp + ".commands")).join(' '); if (config.indexOf("combine") != -1) { QString cmd = replaceExtraCompilerVariables(tmp_cmd, QString(), tmp_out); if(system(cmd.toLatin1().constData())) @@ -1829,42 +1808,10 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) { QString tmp_out = fileFixify(project->first(ProKey(*it + ".output")).toQString(), Option::output_dir, Option::output_dir); - QString tmp_cmd; - const ProKey ckey(*it + ".commands"); - if (!project->isEmpty(ckey)) { - QStringList cmdline = project->values(ckey).toQStringList(); - int argv0 = findExecutable(cmdline); - if(argv0 != -1) { - cmdline[argv0] = escapeFilePath(Option::fixPathToTargetOS(cmdline.at(argv0), false)); - tmp_cmd = cmdline.join(' '); - } - } - QString tmp_dep_cmd; + const QString tmp_cmd = project->values(ProKey(*it + ".commands")).join(' '); + const QString tmp_dep_cmd = project->values(ProKey(*it + ".depend_command")).join(' '); QString dep_cd_cmd; - const ProKey dckey(*it + ".depend_command"); - if (!project->isEmpty(dckey)) { - int argv0 = -1; - ProStringList cmdline = project->values(dckey); - for(int i = 0; i < cmdline.count(); ++i) { - if(!cmdline.at(i).contains('=')) { - argv0 = i; - break; - } - } - if(argv0 != -1) { - QString arg = cmdline.at(argv0).toQString(); - const QString c = Option::fixPathToLocalOS(arg, true); - if(exists(c)) { - arg = escapeFilePath(Option::fixPathToLocalOS(arg, false)); - } else { - arg = escapeFilePath(arg); - } - QFileInfo cmdFileInfo(arg); - if (!cmdFileInfo.isAbsolute() || cmdFileInfo.exists()) { - cmdline[argv0] = arg; - tmp_dep_cmd = cmdline.join(' '); - } - } + if (!tmp_dep_cmd.isEmpty()) { dep_cd_cmd = QLatin1String("cd ") + escapeFilePath(Option::fixPathToLocalOS(Option::output_dir, false)) + QLatin1String(" && "); @@ -2254,6 +2201,25 @@ MakefileGenerator::writeMakefile(QTextStream &t) return true; } +void +MakefileGenerator::writeDefaultVariables(QTextStream &t) +{ + t << "QMAKE = " << var("QMAKE_QMAKE") << endl; + t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; + t << "CHK_DIR_EXISTS= " << var("QMAKE_CHK_DIR_EXISTS") << endl; + t << "MKDIR = " << var("QMAKE_MKDIR") << endl; + t << "COPY = " << var("QMAKE_COPY") << endl; + t << "COPY_FILE = " << var("QMAKE_COPY_FILE") << endl; + t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << endl; + t << "INSTALL_FILE = " << var("QMAKE_INSTALL_FILE") << endl; + t << "INSTALL_PROGRAM = " << var("QMAKE_INSTALL_PROGRAM") << endl; + t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << endl; + t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; + t << "SYMLINK = " << var("QMAKE_SYMBOLIC_LINK") << endl; + t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; + t << "MOVE = " << var("QMAKE_MOVE") << endl; +} + QString MakefileGenerator::fixifySpecdir(const QString &spec, const QString &outdir) { if (QFileInfo(spec).isAbsolute()) @@ -2464,20 +2430,7 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT t << "include " << (*qeui_it) << endl; if (!(flags & SubTargetSkipDefaultVariables)) { - t << "QMAKE = " << var("QMAKE_QMAKE") << endl; - t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; - t << "CHK_DIR_EXISTS= " << var("QMAKE_CHK_DIR_EXISTS") << endl; - t << "MKDIR = " << var("QMAKE_MKDIR") << endl; - t << "COPY = " << var("QMAKE_COPY") << endl; - t << "COPY_FILE = " << var("QMAKE_COPY_FILE") << endl; - t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << endl; - t << "INSTALL_FILE = " << var("QMAKE_INSTALL_FILE") << endl; - t << "INSTALL_PROGRAM = " << var("QMAKE_INSTALL_PROGRAM") << endl; - t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << endl; - t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; - t << "SYMLINK = " << var("QMAKE_SYMBOLIC_LINK") << endl; - t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; - t << "MOVE = " << var("QMAKE_MOVE") << endl; + writeDefaultVariables(t); t << "SUBTARGETS = "; // subtargets are sub-directory for(int target = 0; target < targets.size(); ++target) t << " \\\n\t\t" << targets.at(target)->target; diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h index a382ca6bf6..12186ebae3 100644 --- a/qmake/generators/makefile.h +++ b/qmake/generators/makefile.h @@ -107,6 +107,7 @@ protected: bool writeDummyMakefile(QTextStream &t); virtual bool writeStubMakefile(QTextStream &t); virtual bool writeMakefile(QTextStream &t); + virtual void writeDefaultVariables(QTextStream &t); QString pkgConfigPrefix() const; QString pkgConfigFileName(bool fixify=true); @@ -135,7 +136,7 @@ protected: const QString &out_directory_cdin, const QString &makefilein); virtual void writeSubMakeCall(QTextStream &t, const QString &outDirectory_cdin, const QString &makeFileIn); - void writeSubTargets(QTextStream &t, QList<SubTarget*> subtargets, int flags); + virtual void writeSubTargets(QTextStream &t, QList<SubTarget*> subtargets, int flags); //extra compiler interface bool verifyExtraCompiler(const ProString &c, const QString &f); diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp index a037a966f6..ababbb2076 100644 --- a/qmake/generators/metamakefile.cpp +++ b/qmake/generators/metamakefile.cpp @@ -444,7 +444,11 @@ MetaMakefileGenerator::createMakefileGenerator(QMakeProject *proj, bool noIO) } else if(gen == "MINGW") { mkfile = new MingwMakefileGenerator; } else if(gen == "PROJECTBUILDER" || gen == "XCODE") { +#ifdef Q_CC_MSVC + fprintf(stderr, "Generating Xcode projects is not supported with an MSVC build of Qt.\n"); +#else mkfile = new ProjectBuilderMakefileGenerator; +#endif } else if(gen == "MSVC.NET") { if (proj->first("TEMPLATE").startsWith("vc")) mkfile = new VcprojGenerator; diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 5ea47cc867..484ce19225 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -111,6 +111,8 @@ UnixMakefileGenerator::init() QString sroot = project->sourceRoot(); foreach (const ProString &iif, project->values("QMAKE_INTERNAL_INCLUDED_FILES")) { + if (iif == project->cacheFile()) + continue; if (iif.startsWith(sroot) && iif.at(sroot.length()) == QLatin1Char('/')) project->values("DISTFILES") += fileFixify(iif.toQString(), FileFixifyRelative); } @@ -169,11 +171,13 @@ UnixMakefileGenerator::init() } ProStringList &qmklibs = project->values("QMAKE_LIBS"); qmklibs = ldadd + qmklibs; - if(!project->isEmpty("QMAKE_RPATHDIR")) { + if (!project->isEmpty("QMAKE_RPATHDIR") && !project->isEmpty("QMAKE_LFLAGS_RPATH")) { const ProStringList &rpathdirs = project->values("QMAKE_RPATHDIR"); - for(int i = 0; i < rpathdirs.size(); ++i) { - if(!project->isEmpty("QMAKE_LFLAGS_RPATH")) - project->values("QMAKE_LFLAGS") += var("QMAKE_LFLAGS_RPATH") + escapeFilePath(QFileInfo(rpathdirs[i].toQString()).absoluteFilePath()); + for (int i = 0; i < rpathdirs.size(); ++i) { + QString rpathdir = rpathdirs[i].toQString(); + if (!rpathdir.startsWith('@') && !rpathdir.startsWith('$')) + rpathdir = QFileInfo(rpathdir).absoluteFilePath(); + project->values("QMAKE_LFLAGS") += var("QMAKE_LFLAGS_RPATH") + escapeFilePath(rpathdir); } } if (!project->isEmpty("QMAKE_RPATHLINKDIR")) { diff --git a/qmake/generators/unix/unixmake.h b/qmake/generators/unix/unixmake.h index 5820060adb..bada526967 100644 --- a/qmake/generators/unix/unixmake.h +++ b/qmake/generators/unix/unixmake.h @@ -69,6 +69,8 @@ protected: virtual QStringList &findDependencies(const QString &); virtual void init(); + virtual void writeDefaultVariables(QTextStream &t); + virtual void writeSubTargets(QTextStream &t, QList<SubTarget*> subtargets, int flags); void writeMakeParts(QTextStream &); bool writeMakefile(QTextStream &); diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index cc375f5c46..c68cebfd8c 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -98,6 +98,81 @@ UnixMakefileGenerator::writeMakefile(QTextStream &t) } void +UnixMakefileGenerator::writeDefaultVariables(QTextStream &t) +{ + MakefileGenerator::writeDefaultVariables(t); + t << "TAR = " << var("QMAKE_TAR") << endl; + t << "COMPRESS = " << var("QMAKE_GZIP") << endl; + + if (project->isEmpty("QMAKE_DISTNAME")) { + ProString distname = project->first("QMAKE_ORIG_TARGET"); + if (!project->isActiveConfig("no_dist_version")) + distname += project->first("VERSION"); + project->values("QMAKE_DISTNAME") = distname; + } + t << "DISTNAME = " << var("QMAKE_DISTNAME") << endl; + + if (project->isEmpty("QMAKE_DISTDIR")) + project->values("QMAKE_DISTDIR") = project->first("QMAKE_DISTNAME"); + t << "DISTDIR = " << escapeFilePath(fileFixify( + (project->isEmpty("OBJECTS_DIR") ? ProString(".tmp/") : project->first("OBJECTS_DIR")) + project->first("QMAKE_DISTDIR"), + Option::output_dir, Option::output_dir, FileFixifyAbsolute)) << endl; +} + +void +UnixMakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubTarget*> targets, int flags) +{ + MakefileGenerator::writeSubTargets(t, targets, flags); + + t << "dist: distdir FORCE" << endl; + t << "\t(cd `dirname $(DISTDIR)` && $(TAR) $(DISTNAME).tar $(DISTNAME) && $(COMPRESS) $(DISTNAME).tar)" + " && $(MOVE) `dirname $(DISTDIR)`/$(DISTNAME).tar.gz . && $(DEL_FILE) -r $(DISTDIR)"; + t << endl << endl; + + t << "distdir:"; + for (int target = 0; target < targets.size(); ++target) { + SubTarget *subtarget = targets.at(target); + t << " " << subtarget->target << "-distdir"; + } + t << " FORCE\n\t" + << mkdir_p_asstring("$(DISTDIR)", false) << "\n\t" + << "$(COPY_FILE) --parents " << var("DISTFILES") << " $(DISTDIR)" << Option::dir_sep << endl << endl; + + const QString abs_source_path = project->first("QMAKE_ABSOLUTE_SOURCE_PATH").toQString(); + for (int target = 0; target < targets.size(); ++target) { + SubTarget *subtarget = targets.at(target); + QString in_directory = subtarget->in_directory; + if (!in_directory.isEmpty() && !in_directory.endsWith(Option::dir_sep)) + in_directory += Option::dir_sep; + QString out_directory = subtarget->out_directory; + if (!out_directory.isEmpty() && !out_directory.endsWith(Option::dir_sep)) + out_directory += Option::dir_sep; + if (!abs_source_path.isEmpty() && out_directory.startsWith(abs_source_path)) + out_directory = Option::output_dir + out_directory.mid(abs_source_path.length()); + + QString dist_directory = out_directory; + if (dist_directory.endsWith(Option::dir_sep)) + dist_directory.chop(Option::dir_sep.length()); + if (!dist_directory.startsWith(Option::dir_sep)) + dist_directory.prepend(Option::dir_sep); + + QString out_directory_cdin = out_directory.isEmpty() ? "\n\t" + : "\n\tcd " + out_directory + " && "; + QString makefilein = " -e -f " + subtarget->makefile + " distdir DISTDIR=$(DISTDIR)" + dist_directory; + + QString out = subtarget->makefile; + QString in = escapeFilePath(fileFixify(in_directory + subtarget->profile, FileFixifyAbsolute)); + if (out.startsWith(in_directory)) + out.remove(0, in_directory.length()); + + t << subtarget->target << "-distdir: FORCE"; + writeSubTargetCall(t, in_directory, in, out_directory, out, + out_directory_cdin, makefilein); + t << endl; + } +} + +void UnixMakefileGenerator::writeMakeParts(QTextStream &t) { QString deps = fileFixify(Option::output.fileName()), target_deps, prl; @@ -142,6 +217,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << " " << var("QMAKE_FRAMEWORKPATH_FLAGS"); t << endl; + writeDefaultVariables(t); + if(!project->isActiveConfig("staticlib")) { t << "LINK = " << var("QMAKE_LINK") << endl; t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl; @@ -150,26 +227,10 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << "AR = " << var("QMAKE_AR") << endl; t << "RANLIB = " << var("QMAKE_RANLIB") << endl; - t << "QMAKE = " << var("QMAKE_QMAKE") << endl; - t << "TAR = " << var("QMAKE_TAR") << endl; - t << "COMPRESS = " << var("QMAKE_GZIP") << endl; if(project->isActiveConfig("compile_libtool")) t << "LIBTOOL = " << var("QMAKE_LIBTOOL") << endl; - t << "COPY = " << var("QMAKE_COPY") << endl; t << "SED = " << var("QMAKE_STREAM_EDITOR") << endl; - t << "COPY_FILE = " << var("QMAKE_COPY_FILE") << endl; - t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << endl; t << "STRIP = " << var("QMAKE_STRIP") << endl; - t << "INSTALL_FILE = " << var("QMAKE_INSTALL_FILE") << endl; - t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << endl; - t << "INSTALL_PROGRAM = " << var("QMAKE_INSTALL_PROGRAM") << endl; - - t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; - t << "SYMLINK = " << var("QMAKE_SYMBOLIC_LINK") << endl; - t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; - t << "MOVE = " << var("QMAKE_MOVE") << endl; - t << "CHK_DIR_EXISTS= " << var("QMAKE_CHK_DIR_EXISTS") << endl; - t << "MKDIR = " << var("QMAKE_MKDIR") << endl; t << endl; @@ -217,6 +278,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if(do_incremental && !src_incremental) do_incremental = false; t << "DIST = " << valList(fileFixify(project->values("DISTFILES").toQStringList())) << " " + << valList(escapeFilePaths(project->values("HEADERS"))) << " " << valList(escapeFilePaths(project->values("SOURCES"))) << endl; t << "QMAKE_TARGET = " << var("QMAKE_ORIG_TARGET") << endl; // The comment is important for mingw32-make.exe on Windows as otherwise trailing slashes @@ -828,21 +890,15 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) } } - ProString ddir; - ProString packageName(project->first("QMAKE_ORIG_TARGET")); - if(!project->isActiveConfig("no_dist_version")) - packageName += var("VERSION"); - if (project->isEmpty("QMAKE_DISTDIR")) - ddir = packageName; - else - ddir = project->first("QMAKE_DISTDIR"); - - QString ddir_c = escapeFilePath(fileFixify((project->isEmpty("OBJECTS_DIR") ? ProString(".tmp/") : - project->first("OBJECTS_DIR")) + ddir, - Option::output_dir, Option::output_dir)); - t << "dist: \n\t" - << mkdir_p_asstring(ddir_c, false) << "\n\t" - << "$(COPY_FILE) --parents $(DIST) " << ddir_c << Option::dir_sep << " && "; + t << "dist: distdir FORCE\n\t"; + t << "(cd `dirname $(DISTDIR)` && $(TAR) $(DISTNAME).tar $(DISTNAME) && $(COMPRESS) $(DISTNAME).tar)" + " && $(MOVE) `dirname $(DISTDIR)`" << Option::dir_sep << "$(DISTNAME).tar.gz ." + " && $(DEL_FILE) -r $(DISTDIR)"; + t << endl << endl; + + t << "distdir: FORCE\n\t" + << mkdir_p_asstring("$(DISTDIR)", false) << "\n\t" + << "$(COPY_FILE) --parents $(DIST) $(DISTDIR)" << Option::dir_sep << endl; if(!project->isEmpty("QMAKE_EXTRA_COMPILERS")) { const ProStringList &quc = project->values("QMAKE_EXTRA_COMPILERS"); for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) { @@ -851,20 +907,13 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) const ProStringList &val = project->values((*var_it).toKey()); if(val.isEmpty()) continue; - t << "$(COPY_FILE) --parents " << val.join(' ') << " " << ddir_c << Option::dir_sep << " && "; + t << "\t$(COPY_FILE) --parents " << val.join(' ') << " $(DISTDIR)" << Option::dir_sep << endl; } } } if(!project->isEmpty("TRANSLATIONS")) - t << "$(COPY_FILE) --parents " << var("TRANSLATIONS") << " " << ddir_c << Option::dir_sep << " && "; - t << "(cd `dirname " << ddir_c << "` && " - << "$(TAR) " << packageName << ".tar " << ddir << " && " - << "$(COMPRESS) " << packageName << ".tar) && " - << "$(MOVE) `dirname " << ddir_c << "`" << Option::dir_sep << packageName << ".tar.gz . && " - << "$(DEL_FILE) -r " << ddir_c - << endl << endl; - - t << endl; + t << "\t$(COPY_FILE) --parents " << var("TRANSLATIONS") << " $(DISTDIR)" << Option::dir_sep << endl; + t << endl << endl; QString clean_targets = "compiler_clean " + var("CLEAN_DEPS"); if(do_incremental) { @@ -1216,6 +1265,13 @@ void UnixMakefileGenerator::init2() if(!instpath.endsWith(Option::dir_sep)) instpath += Option::dir_sep; soname.prepend(instpath); + } else if (!project->isEmpty("QMAKE_SONAME_PREFIX")) { + QString sonameprefix = project->first("QMAKE_SONAME_PREFIX").toQString(); + if (!sonameprefix.startsWith('@') && !sonameprefix.startsWith('$')) + sonameprefix = Option::fixPathToTargetOS(sonameprefix, false); + if (!sonameprefix.endsWith(Option::dir_sep)) + sonameprefix += Option::dir_sep; + soname.prepend(sonameprefix); } project->values("QMAKE_LFLAGS_SONAME").first() += escapeFilePath(soname); } diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index 5fdfc52dba..87ff5ec895 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -636,7 +636,8 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool) << tagValue("Keyword", tool.Keyword); if (isWinRT) { - xml << tagValue("MinimumVisualStudioVersion", tool.Version); + xml << tagValue("MinimumVisualStudioVersion", tool.Version) + << tagValue("DefaultLanguage", "en"); if (isWinPhone80) { xml << tagValue("WinMDAssembly", "true"); if (tool.SingleProjects.at(0).Configuration.ConfigurationType == typeApplication) { diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 8e609fdcae..6189a01ef3 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -521,18 +521,23 @@ void NmakeMakefileGenerator::writeBuildRulesPart(QTextStream &t) const QString target = var("DEST_TARGET"); QString manifest = project->first("QMAKE_MANIFEST").toQString(); QString extraLFlags; + const bool linkerSupportsEmbedding = (msvcVersion() >= 1200); if (manifest.isEmpty()) { generateManifest = true; - manifest = escapeFilePath(target + ".embed.manifest"); - extraLFlags = "/MANIFEST /MANIFESTFILE:" + manifest; - project->values("QMAKE_CLEAN") << manifest; + if (linkerSupportsEmbedding) { + extraLFlags = "/MANIFEST:embed"; + } else { + manifest = escapeFilePath(target + ".embed.manifest"); + extraLFlags += "/MANIFEST /MANIFESTFILE:" + manifest; + project->values("QMAKE_CLEAN") << manifest; + } } else { manifest = escapeFilePath(fileFixify(manifest)); } const QString resourceId = (templateName == "app") ? "1" : "2"; const bool incrementalLinking = project->values("QMAKE_LFLAGS").toQStringList().filter(QRegExp("(/|-)INCREMENTAL:NO")).isEmpty(); - if (incrementalLinking) { + if (incrementalLinking && !linkerSupportsEmbedding) { // Link a resource that contains the manifest without modifying the exe/dll after linking. QString manifest_rc = escapeFilePath(target + "_manifest.rc"); @@ -565,8 +570,10 @@ void NmakeMakefileGenerator::writeBuildRulesPart(QTextStream &t) // directly embed the manifest in the executable after linking t << "\n\t"; writeLinkCommand(t, extraLFlags); - t << "\n\tmt.exe /nologo /manifest " << manifest - << " /outputresource:$(DESTDIR_TARGET);" << resourceId; + if (!linkerSupportsEmbedding) { + t << "\n\tmt.exe /nologo /manifest " << manifest + << " /outputresource:$(DESTDIR_TARGET);" << resourceId; + } } } else { t << "\n\t"; @@ -597,4 +604,13 @@ void NmakeMakefileGenerator::writeLinkCommand(QTextStream &t, const QString &ext t << "\n<<"; } +int NmakeMakefileGenerator::msvcVersion() const +{ + const int fallbackVersion = 800; // Visual Studio 2005 + const QString ver = project->first(ProKey("MSVC_VER")).toQString(); + bool ok; + float f = ver.toFloat(&ok); + return ok ? int(f * 100) : fallbackVersion; +} + QT_END_NAMESPACE diff --git a/qmake/generators/win32/msvc_nmake.h b/qmake/generators/win32/msvc_nmake.h index 4d3c69bdd6..8d8f5360e0 100644 --- a/qmake/generators/win32/msvc_nmake.h +++ b/qmake/generators/win32/msvc_nmake.h @@ -54,6 +54,7 @@ class NmakeMakefileGenerator : public Win32MakefileGenerator void writeImplicitRulesPart(QTextStream &t); void writeBuildRulesPart(QTextStream &t); void writeLinkCommand(QTextStream &t, const QString &extraFlags = QString(), const QString &extraInlineFileContent = QString()); + int msvcVersion() const; void init(); protected: diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index b2663e51c9..be7b547115 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -312,6 +312,18 @@ static QString vcCommandSeparator() return cmdSep; } +static void unknownOptionWarning(const char *tool, const char *option) +{ + static bool firstCall = true; + warn_msg(WarnLogic, "Could not parse %s option '%s'; added to AdditionalOptions.", tool, option); + if (firstCall) { + firstCall = false; + warn_msg(WarnLogic, + "You can suppress these warnings with CONFIG+=suppress_vcproj_warnings."); + } +} + + // VCCLCompilerTool ------------------------------------------------- VCCLCompilerTool::VCCLCompilerTool() : AssemblerOutput(asmListingNone), @@ -916,6 +928,8 @@ bool VCCLCompilerTool::parseOption(const char* option) ForceConformanceInForLoopScope = ((*c) == '-' ? _False : _True); else if(fourth == 'w') TreatWChar_tAsBuiltInType = ((*c) == '-' ? _False : _True); + else if (config->CompilerVersion >= NET2013 && strncmp(option + 4, "strictStrings", 13) == 0) + AdditionalOptions += option; else found = false; } else { @@ -1146,7 +1160,8 @@ bool VCCLCompilerTool::parseOption(const char* option) break; } if(!found) { - warn_msg(WarnLogic, "Could not parse Compiler option: %s, added as AdditionalOption", option); + if (!config->suppressUnknownOptionWarnings) + unknownOptionWarning("Compiler", option); AdditionalOptions += option; } return true; @@ -1741,7 +1756,8 @@ bool VCLinkerTool::parseOption(const char* option) break; } if(!found) { - warn_msg(WarnLogic, "Could not parse Linker options: %s, added as AdditionalOption", option); + if (!config->suppressUnknownOptionWarnings) + unknownOptionWarning("Linker", option); AdditionalOptions += option; } return found; diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h index 9a57a2c7a2..2c426afb1a 100644 --- a/qmake/generators/win32/msvc_objectmodel.h +++ b/qmake/generators/win32/msvc_objectmodel.h @@ -885,6 +885,7 @@ public: VCConfiguration(); ~VCConfiguration(){} + bool suppressUnknownOptionWarnings; DotNET CompilerVersion; bool WinRT, WinPhone, WinPhone80; diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index a28ddd63c4..c10ed3aacd 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -960,6 +960,7 @@ void VcprojGenerator::initConfiguration() // - Do this first since main configuration elements may need // - to know of certain compiler/linker options VCConfiguration &conf = vcProject.Configuration; + conf.suppressUnknownOptionWarnings = project->isActiveConfig("suppress_vcproj_warnings"); conf.CompilerVersion = which_dotnet_version(project->first("MSVC_VER").toLatin1()); initCompilerTool(); @@ -1480,10 +1481,7 @@ void VcprojGenerator::initFormFiles() vcProject.FormFiles.ParseFiles = _False; vcProject.FormFiles.Filter = "ui"; vcProject.FormFiles.Guid = _GUIDFormFiles; - vcProject.FormFiles.addFiles(project->values("FORMS")); - vcProject.FormFiles.addFiles(project->values("FORMS3")); - vcProject.FormFiles.Project = this; vcProject.FormFiles.Config = &(vcProject.Configuration); vcProject.FormFiles.CustomBuild = none; @@ -1543,7 +1541,6 @@ void VcprojGenerator::initExtraCompilerOutputs() { ProStringList otherFilters; otherFilters << "FORMS" - << "FORMS3" << "GENERATED_FILES" << "GENERATED_SOURCES" << "HEADERS" diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index da81b85e2a..1fee98fcbd 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -678,7 +678,9 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t) writeExtraCompilerVariables(t); writeExtraVariables(t); - t << "DIST = " << varList("DISTFILES") << endl; + t << "DIST = " << varList("DISTFILES") << " " + << varList("HEADERS") << " " + << varList("SOURCES") << endl; t << "QMAKE_TARGET = " << var("QMAKE_ORIG_TARGET") << endl; // The comment is important to maintain variable compatibility with Unix // Makefiles, while not interpreting a trailing-slash as a linebreak diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index 46934c83e9..9824b306b9 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -437,8 +437,9 @@ QByteArray QMakeEvaluator::getCommandOutput(const QString &args) const void QMakeEvaluator::populateDeps( const ProStringList &deps, const ProString &prefix, const ProStringList &suffixes, + const ProString &priosfx, QHash<ProKey, QSet<ProKey> > &dependencies, ProValueMap &dependees, - ProStringList &rootSet) const + QMultiMap<int, ProString> &rootSet) const { foreach (const ProString &item, deps) if (!dependencies.contains(item.toKey())) { @@ -447,13 +448,13 @@ void QMakeEvaluator::populateDeps( foreach (const ProString &suffix, suffixes) depends += values(ProKey(prefix + item + suffix)); if (depends.isEmpty()) { - rootSet << item; + rootSet.insert(first(ProKey(prefix + item + priosfx)).toInt(), item); } else { foreach (const ProString &dep, depends) { dset.insert(dep.toKey()); dependees[dep.toKey()] << item; } - populateDeps(depends, prefix, suffixes, dependencies, dependees, rootSet); + populateDeps(depends, prefix, suffixes, priosfx, dependencies, dependees, rootSet); } } } @@ -974,27 +975,31 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( break; case E_SORT_DEPENDS: case E_RESOLVE_DEPENDS: - if (args.count() < 1 || args.count() > 3) { - evalError(fL1S("%1(var, [prefix, [suffixes]]) requires one to three arguments.") + if (args.count() < 1 || args.count() > 4) { + evalError(fL1S("%1(var, [prefix, [suffixes, [prio-suffix]]]) requires one to four arguments.") .arg(func.toQString(m_tmp1))); } else { QHash<ProKey, QSet<ProKey> > dependencies; ProValueMap dependees; - ProStringList rootSet; + QMultiMap<int, ProString> rootSet; ProStringList orgList = values(args.at(0).toKey()); - populateDeps(orgList, (args.count() < 2 ? ProString() : args.at(1)), + ProString prefix = args.count() < 2 ? ProString() : args.at(1); + ProString priosfx = args.count() < 4 ? ProString(".priority") : args.at(3); + populateDeps(orgList, prefix, args.count() < 3 ? ProStringList(ProString(".depends")) : split_value_list(args.at(2).toQString(m_tmp2)), - dependencies, dependees, rootSet); - for (int i = 0; i < rootSet.size(); ++i) { - const ProString &item = rootSet.at(i); + priosfx, dependencies, dependees, rootSet); + while (!rootSet.isEmpty()) { + QMultiMap<int, ProString>::iterator it = rootSet.begin(); + const ProString item = *it; + rootSet.erase(it); if ((func_t == E_RESOLVE_DEPENDS) || orgList.contains(item)) ret.prepend(item); foreach (const ProString &dep, dependees[item.toKey()]) { QSet<ProKey> &dset = dependencies[dep.toKey()]; - dset.remove(rootSet.at(i).toKey()); // *Don't* use 'item' - rootSet may have changed! + dset.remove(item.toKey()); if (dset.isEmpty()) - rootSet << dep; + rootSet.insert(first(ProKey(prefix + dep + priosfx)).toInt(), dep); } } } diff --git a/qmake/library/qmakeevaluator.h b/qmake/library/qmakeevaluator.h index f322a48011..2cff82c164 100644 --- a/qmake/library/qmakeevaluator.h +++ b/qmake/library/qmakeevaluator.h @@ -49,8 +49,10 @@ #include "qmakeparser.h" #include "ioutils.h" +#include <qiodevice.h> #include <qlist.h> #include <qlinkedlist.h> +#include <qmap.h> #include <qset.h> #include <qstack.h> #include <qstring.h> @@ -238,8 +240,9 @@ public: void populateDeps( const ProStringList &deps, const ProString &prefix, const ProStringList &suffixes, - QHash<ProKey, QSet<ProKey> > &dependencies, - ProValueMap &dependees, ProStringList &rootSet) const; + const ProString &priosfx, + QHash<ProKey, QSet<ProKey> > &dependencies, ProValueMap &dependees, + QMultiMap<int, ProString> &rootSet) const; VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, const QString &contents); diff --git a/qmake/qmake.pri b/qmake/qmake.pri index 4457b2643b..4de41d63e6 100644 --- a/qmake/qmake.pri +++ b/qmake/qmake.pri @@ -159,7 +159,7 @@ bootstrap { #Qt code QT_BOOTSTRAPPED \ QT_NO_TEXTCODEC QT_NO_UNICODETABLES QT_NO_COMPONENT QT_NO_COMPRESS \ QT_NO_THREAD QT_NO_QOBJECT QT_NO_GEOM_VARIANT QT_NO_DATASTREAM \ - QT_CRYPTOGRAPHICHASH_ONLY_SHA1 QT_JSON_READONLY + QT_CRYPTOGRAPHICHASH_ONLY_SHA1 QT_JSON_READONLY QT_NO_STANDARDPATHS INCLUDEPATH += \ $$QT.core.includes $$QT.core_private.includes \ |