summaryrefslogtreecommitdiffstats
path: root/qmake
diff options
context:
space:
mode:
Diffstat (limited to 'qmake')
-rw-r--r--qmake/Makefile.unix6
-rw-r--r--qmake/Makefile.win321
-rw-r--r--qmake/doc/snippets/code/doc_src_qmake-manual.pro20
-rw-r--r--qmake/doc/src/qmake-manual.qdoc47
-rw-r--r--qmake/generators/mac/pbuilder_pbx.cpp18
-rw-r--r--qmake/generators/makefile.cpp4
-rw-r--r--qmake/generators/unix/unixmake.cpp26
-rw-r--r--qmake/generators/unix/unixmake2.cpp35
-rw-r--r--qmake/generators/win32/mingw_make.cpp7
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.cpp7
-rw-r--r--qmake/generators/win32/msvc_nmake.cpp28
-rw-r--r--qmake/generators/win32/msvc_objectmodel.h3
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp21
-rw-r--r--qmake/generators/win32/winmakefile.cpp28
-rw-r--r--qmake/library/proitems.cpp31
-rw-r--r--qmake/library/proitems.h3
-rw-r--r--qmake/library/qmakebuiltins.cpp10
-rw-r--r--qmake/library/qmakeevaluator.cpp46
-rw-r--r--qmake/library/qmakeevaluator.h2
-rw-r--r--qmake/library/qmakeglobals.h1
-rw-r--r--qmake/main.cpp71
21 files changed, 272 insertions, 143 deletions
diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix
index 86f884fe20..520ae667e9 100644
--- a/qmake/Makefile.unix
+++ b/qmake/Makefile.unix
@@ -13,7 +13,7 @@ OBJS=project.o option.o property.o main.o ioutils.o proitems.o \
#qt code
QOBJS=qtextcodec.o qutfcodec.o qstring.o qstring_compat.o qstringbuilder.o qtextstream.o qiodevice.o \
- qdebug.o qmalloc.o qglobal.o \
+ qringbuffer.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 \
@@ -44,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/tools/qringbuffer.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 \
@@ -242,6 +243,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
+qringbuffer.o: $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp
+
qdebug.o: $(SOURCE_PATH)/src/corelib/io/qdebug.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdebug.cpp
diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32
index 9dda6ca1e7..272a0c09b1 100644
--- a/qmake/Makefile.win32
+++ b/qmake/Makefile.win32
@@ -88,6 +88,7 @@ QTOBJS= \
qglobal.obj \
qhash.obj \
qiodevice.obj \
+ qringbuffer.obj \
qdebug.obj \
qlist.obj \
qlinkedlist.obj \
diff --git a/qmake/doc/snippets/code/doc_src_qmake-manual.pro b/qmake/doc/snippets/code/doc_src_qmake-manual.pro
index 335fa6f97e..7609a98111 100644
--- a/qmake/doc/snippets/code/doc_src_qmake-manual.pro
+++ b/qmake/doc/snippets/code/doc_src_qmake-manual.pro
@@ -186,21 +186,6 @@ DEFINES += USE_MY_STUFF
#! [27]
-#! [28]
-myFiles.files = path\*.png
-DEPLOYMENT += myFiles
-#! [28]
-
-
-#! [29]
-myFiles.files = path\file1.ext1 path2\file2.ext1 path3\*
-myFiles.path = \some\path\on\device
-someother.files = C:\additional\files\*
-someother.path = \myFiles\path2
-DEPLOYMENT += myFiles someother
-#! [29]
-
-
#! [30]
DESTDIR = ../../lib
#! [30]
@@ -987,3 +972,8 @@ QMAKE_SONAME_PREFIX = /Library/Frameworks
#! [185]
VERSION_PE_HEADER = 1.2
#! [185]
+
+#! [186]
+RC_DEFINES += USE_MY_STUFF
+#! [186]
+
diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc
index 56d9dd35ae..6f855ba9ca 100644
--- a/qmake/doc/src/qmake-manual.qdoc
+++ b/qmake/doc/src/qmake-manual.qdoc
@@ -1120,38 +1120,6 @@
Specifies a list of all directories to look in to resolve dependencies. This
variable is used when crawling through \c included files.
- \target DEPLOYMENT
- \section1 DEPLOYMENT
-
- \note This variable is used only on the Windows CE platform.
-
- Specifies which additional files will be deployed. Deployment means the
- transfer of files from the development system to the target device or
- emulator.
-
- Files can be deployed by either creating a Visual Studio project or using
- the \l {Using Qt Test remotely on Windows CE}{cetest} executable.
-
- For example, the following definition uploads all PNG images in \c path to
- the directory where the build target is deployed:
-
- \snippet code/doc_src_qmake-manual.pro 28
-
- The default deployment target path for Windows CE is
- \c{%CSIDL_PROGRAM_FILES%\target}, which usually gets expanded to
- \c{\Program Files\target}.
-
- It is also possible to specify multiple \c sources to be deployed on
- target \c paths. In addition, different variables can be used for
- deployment to different directories.
-
- For example:
-
- \snippet code/doc_src_qmake-manual.pro 29
-
- \note In Windows CE all linked Qt libraries will be deployed to the path
- specified by \c{myFiles.path}.
-
\target DEPLOYMENT_PLUGIN
\section1 DEPLOYMENT_PLUGIN
@@ -1276,6 +1244,13 @@
For more information, see \l{Installing Files}.
+ This variable is also used to specify which additional files will be
+ deployed to embedded devices.
+
+ For Windows CE, the default deployment target path is
+ \c{%CSIDL_PROGRAM_FILES%\target}, which usually gets expanded to
+ \c{\Program Files\target}.
+
\target LEXIMPLS
\section1 LEXIMPLS
@@ -2314,6 +2289,14 @@
.rc file. This is only utilized if the \l{VERSION} or \l{RC_ICONS} variable
is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set.
+ \target RC_DEFINES
+ \section1 RC_DEFINES
+
+ Windows only. qmake adds the values of this variable as RC preprocessor macros
+ (/d option). If this variable is not set, the \l{DEFINES} variable is used instead.
+
+ \snippet code/doc_src_qmake-manual.pro 186
+
\target RC_ICONS
\section1 RC_ICONS
diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp
index fcd6bf8308..deacac2c83 100644
--- a/qmake/generators/mac/pbuilder_pbx.cpp
+++ b/qmake/generators/mac/pbuilder_pbx.cpp
@@ -810,7 +810,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
if(!project->isActiveConfig("staticlib")) { //DUMP LIBRARIES
ProStringList &libdirs = project->values("QMAKE_PBX_LIBPATHS"),
&frameworkdirs = project->values("QMAKE_FRAMEWORKPATH");
- static const char * const libs[] = { "QMAKE_LFLAGS", "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 };
+ static const char * const libs[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 };
for (int i = 0; libs[i]; i++) {
tmp = project->values(libs[i]);
for(int x = 0; x < tmp.count();) {
@@ -821,9 +821,6 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
QString r = opt.mid(2).toQString();
fixForOutput(r);
libdirs.append(r);
- } else if(opt == "-prebind") {
- project->values("QMAKE_DO_PREBINDING").append("TRUE");
- remove = true;
} else if(opt.startsWith("-l")) {
name = opt.mid(2).toQString();
QString lib("lib" + name);
@@ -921,7 +918,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
if(!path.isEmpty() && !libdirs.contains(path))
libdirs += path;
}
- library = fileFixify(library, FileFixifyFromOutdir);
+ library = fileFixify(library, FileFixifyFromOutdir | FileFixifyAbsolute);
QString key = keyFor(library);
if (!project->values("QMAKE_PBX_LIBRARIES").contains(key)) {
bool is_frmwrk = (library.endsWith(".framework"));
@@ -1812,11 +1809,14 @@ ProjectBuilderMakefileGenerator::openOutput(QFile &file, const QString &build) c
}
output += QString("project.pbxproj");
file.setFileName(output);
+ bool ret = UnixMakefileGenerator::openOutput(file, build);
+ ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir.section(Option::dir_sep, 0, -1);
+ Option::output_dir = pbx_dir.section(Option::dir_sep, 0, -2);
+ return ret;
}
- bool ret = UnixMakefileGenerator::openOutput(file, build);
- ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir.section(Option::dir_sep, 0, -1);
- Option::output_dir = pbx_dir.section(Option::dir_sep, 0, -2);
- return ret;
+
+ ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir;
+ return UnixMakefileGenerator::openOutput(file, build);
}
/* This function is such a hack it is almost pointless, but it
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index f5e8248af5..4a03fafd77 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -2019,7 +2019,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
for(int i = 0; i < pre_deps.size(); ++i)
deps << replaceExtraCompilerVariables(pre_deps.at(i), inpf, out, NoShell);
}
- QString cmd = replaceExtraCompilerVariables(tmp_cmd, inpf, out, LocalShell);
+ QString cmd = replaceExtraCompilerVariables(tmp_cmd, inpf, out, TargetShell);
// NOTE: The var -> QMAKE_COMP_var replace feature is unsupported, do not use!
for (ProStringList::ConstIterator it3 = vars.constBegin(); it3 != vars.constEnd(); ++it3)
cmd.replace("$(" + (*it3) + ")", "$(QMAKE_COMP_" + (*it3)+")");
@@ -2240,7 +2240,7 @@ QString MakefileGenerator::buildArgs()
QString ret;
foreach (const QString &arg, Option::globals->qmake_args)
- ret += " " + escapeFilePath(arg);
+ ret += " " + shellQuote(arg);
return ret;
}
diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp
index efea807209..c4750cb8a4 100644
--- a/qmake/generators/unix/unixmake.cpp
+++ b/qmake/generators/unix/unixmake.cpp
@@ -612,7 +612,7 @@ UnixMakefileGenerator::processPrlFiles()
ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS");
if(!prl_libs.isEmpty()) {
for(int prl = 0; prl < prl_libs.size(); ++prl)
- l.insert(lit+prl+1, prl_libs.at(prl).toQString());
+ l.insert(++lit, prl_libs.at(prl));
prl_libs.clear();
}
}
@@ -699,6 +699,7 @@ UnixMakefileGenerator::defaultInstall(const QString &t)
return QString();
enum { NoBundle, SolidBundle, SlicedBundle } bundle = NoBundle;
+ bool isAux = (project->first("TEMPLATE") == "aux");
const QString root = "$(INSTALL_ROOT)";
ProStringList &uninst = project->values(ProKey(t + ".uninstall"));
QString ret, destdir = project->first("DESTDIR").toQString();
@@ -773,21 +774,21 @@ UnixMakefileGenerator::defaultInstall(const QString &t)
}
src_targ = escapeFilePath(src_targ);
dst_targ = escapeFilePath(dst_targ);
- if(!ret.isEmpty())
- ret += "\n\t";
- QString copy_cmd("-");
+ QString copy_cmd;
if (bundle == SolidBundle) {
- copy_cmd += "$(INSTALL_DIR) " + src_targ + ' ' + plain_targ;
+ copy_cmd += "-$(INSTALL_DIR) " + src_targ + ' ' + plain_targ;
} else if (project->first("TEMPLATE") == "lib" && project->isActiveConfig("staticlib")) {
- copy_cmd += "$(INSTALL_FILE) " + src_targ + ' ' + dst_targ;
- } else {
+ copy_cmd += "-$(INSTALL_FILE) " + src_targ + ' ' + dst_targ;
+ } else if (!isAux) {
if (bundle == SlicedBundle)
ret += mkdir_p_asstring("\"`dirname " + dst_targ + "`\"", false) + "\n\t";
- copy_cmd += "$(INSTALL_PROGRAM) " + src_targ + ' ' + dst_targ;
+ copy_cmd += "-$(INSTALL_PROGRAM) " + src_targ + ' ' + dst_targ;
}
if(project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib")
&& project->values(ProKey(t + ".CONFIG")).indexOf("fix_rpath") != -1) {
+ if (!ret.isEmpty())
+ ret += "\n\t";
if(!project->isEmpty("QMAKE_FIX_RPATH")) {
ret += copy_cmd;
ret += "\n\t-" + var("QMAKE_FIX_RPATH") + ' ' + dst_targ + ' ' + dst_targ;
@@ -797,11 +798,14 @@ UnixMakefileGenerator::defaultInstall(const QString &t)
} else {
ret += copy_cmd;
}
- } else {
+ } else if (!copy_cmd.isEmpty()) {
+ if (!ret.isEmpty())
+ ret += "\n\t";
ret += copy_cmd;
}
- if(project->first("TEMPLATE") == "lib" && project->isActiveConfig("staticlib")) {
+ if (isAux) {
+ } else if (project->first("TEMPLATE") == "lib" && project->isActiveConfig("staticlib")) {
if(!project->isEmpty("QMAKE_RANLIB"))
ret += QString("\n\t$(RANLIB) ") + dst_targ;
} else if (!project->isActiveConfig("debug_info") && !project->isActiveConfig("nostrip")
@@ -820,7 +824,7 @@ UnixMakefileGenerator::defaultInstall(const QString &t)
uninst.append("\n\t");
if (bundle == SolidBundle)
uninst.append("-$(DEL_FILE) -r " + plain_targ);
- else
+ else if (!isAux)
uninst.append("-$(DEL_FILE) " + dst_targ);
if (bundle == SlicedBundle) {
int dstlen = project->first("DESTDIR").length();
diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp
index 9b9e54c461..5cde7c4ac2 100644
--- a/qmake/generators/unix/unixmake2.cpp
+++ b/qmake/generators/unix/unixmake2.cpp
@@ -807,11 +807,10 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
} else {
info_plist = escapeFilePath(fileFixify(info_plist));
}
- bool isApp = (project->first("TEMPLATE") == "app");
- QString info_plist_out =
- bundle_dir + (isApp ? "Contents/Info.plist"
- : "Versions/" + project->first("QMAKE_FRAMEWORK_VERSION")
- + "/Resources/Info.plist");
+ bool isFramework = project->first("TEMPLATE") == "lib" && project->isActiveConfig("lib_bundle");
+ QString info_plist_out = bundle_dir +
+ (isFramework ? ("Versions/" + project->first("QMAKE_FRAMEWORK_VERSION") + "/Resources/Info.plist")
+ : "Contents/Info.plist");
bundledFiles << info_plist_out;
alldeps << info_plist_out;
QString destdir = info_plist_out.section(Option::dir_sep, 0, -2);
@@ -842,7 +841,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
bundleIdentifier.chop(10);
commonSedArgs << "-e \"s,@BUNDLEIDENTIFIER@," << bundleIdentifier << ",g\" ";
- if (isApp) {
+ if (!isFramework) {
QString icon = fileFixify(var("ICON"));
t << "@$(DEL_FILE) " << info_plist_out << "\n\t"
<< "@sed ";
@@ -850,6 +849,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << arg;
t << "-e \"s,@ICON@," << icon.section(Option::dir_sep, -1) << ",g\" "
<< "-e \"s,@EXECUTABLE@," << var("QMAKE_ORIG_TARGET") << ",g\" "
+ << "-e \"s,@LIBRARY@," << var("QMAKE_ORIG_TARGET") << ",g\" "
<< "-e \"s,@TYPEINFO@,"<< (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ?
QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << ",g\" "
<< "" << info_plist << " >" << info_plist_out << endl;
@@ -922,17 +922,18 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
}
}
}
- QString bundle_dir_f = escapeFilePath(bundle_dir);
- QHash<QString, QString>::ConstIterator symIt = symlinks.constBegin(),
- symEnd = symlinks.constEnd();
- for (; symIt != symEnd; ++symIt) {
- bundledFiles << symIt.key();
- alldeps << symIt.key();
- t << escapeDependencyPath(symIt.key()) << ":\n\t"
- << mkdir_p_asstring(bundle_dir) << "\n\t"
- << "@$(SYMLINK) " << escapeFilePath(symIt.value()) << ' ' << bundle_dir_f << endl;
- }
- if (!project->first("QMAKE_FRAMEWORK_VERSION").isEmpty()) {
+ if (!symlinks.isEmpty()) {
+ QString bundle_dir_f = escapeFilePath(bundle_dir);
+ QHash<QString, QString>::ConstIterator symIt = symlinks.constBegin(),
+ symEnd = symlinks.constEnd();
+ for (; symIt != symEnd; ++symIt) {
+ bundledFiles << symIt.key();
+ alldeps << symIt.key();
+ t << escapeDependencyPath(symIt.key()) << ":\n\t"
+ << mkdir_p_asstring(bundle_dir) << "\n\t"
+ << "@$(SYMLINK) " << escapeFilePath(symIt.value()) << ' ' << bundle_dir_f << endl;
+ }
+
QString currentLink = bundle_dir + "Versions/Current";
QString currentLink_f = escapeDependencyPath(currentLink);
bundledFiles << currentLink;
diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp
index c19e17bc0e..57955dc456 100644
--- a/qmake/generators/win32/mingw_make.cpp
+++ b/qmake/generators/win32/mingw_make.cpp
@@ -405,9 +405,14 @@ void MingwMakefileGenerator::writeRcFilePart(QTextStream &t)
}
if (!rc_file.isEmpty()) {
+
+ ProString defines = varGlue("RC_DEFINES", " -D", " -D", "");
+ if (defines.isEmpty())
+ defines = ProString(" $(DEFINES)");
+
t << escapeDependencyPath(var("RES_FILE")) << ": " << escapeDependencyPath(rc_file) << "\n\t"
<< var("QMAKE_RC") << " -i " << escapeFilePath(rc_file) << " -o " << fileVar("RES_FILE")
- << incPathStr << " $(DEFINES)\n\n";
+ << incPathStr << defines << "\n\n";
}
}
diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp
index 6c2d2c6206..cbf7cf26dc 100644
--- a/qmake/generators/win32/msbuild_objectmodel.cpp
+++ b/qmake/generators/win32/msbuild_objectmodel.cpp
@@ -608,10 +608,13 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool)
xml.setIndentString(" ");
+ const QString toolsVersion = (tool.SdkVersion == QStringLiteral("10.0")) ? QStringLiteral("14.0")
+ : QStringLiteral("4.0");
+
xml << decl("1.0", "utf-8")
<< tag("Project")
<< attrTag("DefaultTargets","Build")
- << attrTag("ToolsVersion", "4.0")
+ << attrTag("ToolsVersion", toolsVersion)
<< attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003")
<< tag("ItemGroup")
<< attrTag("Label", "ProjectConfigurations");
@@ -640,7 +643,7 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool)
<< tagValue("DefaultLanguage", "en")
<< tagValue("AppContainerApplication", "true")
<< tagValue("ApplicationType", isWinPhone ? "Windows Phone" : "Windows Store")
- << tagValue("ApplicationTypeRevision", tool.SdkVersion);
+ << tagValue("ApplicationTypeRevision", tool.SdkVersion == "10.0" ? "8.2" : tool.SdkVersion);
}
xml << closetag();
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
index eb8ae23384..dfa8f8837b 100644
--- a/qmake/generators/win32/msvc_nmake.cpp
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -176,11 +176,34 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
const QString vcInstallDir = "/fake/vc_install_dir";
const QString kitDir = "/fake/sdk_install_dir";
#endif // Q_OS_WIN
-
QStringList incDirs;
QStringList libDirs;
QStringList binDirs;
- if (isPhone) {
+ if (msvcVer == QStringLiteral("14.0")) {
+ binDirs << vcInstallDir + QStringLiteral("bin/") + compiler;
+ binDirs << vcInstallDir + QStringLiteral("bin/"); // Maybe remove for x86 again?
+ binDirs << kitDir + QStringLiteral("bin/") + (arch == QStringLiteral("arm") ? QStringLiteral("x86") : arch);
+ binDirs << vcInstallDir + QStringLiteral("../Common7/Tools/bin");
+ binDirs << vcInstallDir + QStringLiteral("../Common7/Tools");
+ binDirs << vcInstallDir + QStringLiteral("../Common7/ide");
+ binDirs << kitDir + QStringLiteral("Windows Performance Toolkit/");
+
+ incDirs << vcInstallDir + QStringLiteral("include");
+ incDirs << vcInstallDir + QStringLiteral("atlmfc/include");
+ // ### Investigate why VS uses 10056 first
+ incDirs << kitDir + QStringLiteral("Include/10.0.10056.0/ucrt");
+ incDirs << kitDir + QStringLiteral("Include/10.0.10069.0/ucrt");
+ incDirs << kitDir + QStringLiteral("Include/10.0.10069.0/um");
+ incDirs << kitDir + QStringLiteral("Include/10.0.10069.0/shared");
+ incDirs << kitDir + QStringLiteral("Include/10.0.10069.0/winrt");
+
+ libDirs << vcInstallDir + QStringLiteral("lib/store/") + compilerArch;
+ libDirs << vcInstallDir + QStringLiteral("atlmfc/lib") + compilerArch;
+ // ### Investigate why VS uses 10056 first
+ libDirs << kitDir + QStringLiteral("lib/10.0.10056.0/ucrt/") + arch;
+ libDirs << kitDir + QStringLiteral("lib/10.0.10069.0/ucrt/") + arch;
+ libDirs << kitDir + QStringLiteral("lib/10.0.10069.0/um/") + arch;
+ } else if (isPhone) {
QString sdkDir = vcInstallDir;
if (!QDir(sdkDir).exists()) {
fprintf(stderr, "Failed to find the Windows Phone SDK in %s.\n"
@@ -208,7 +231,6 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
<< kitDir + QStringLiteral("/include/shared")
<< kitDir + QStringLiteral("/include/winrt");
}
-
// Inherit PATH
binDirs << QString::fromLocal8Bit(qgetenv("PATH")).split(QLatin1Char(';'));
diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h
index 59136b16c8..7092da3e59 100644
--- a/qmake/generators/win32/msvc_objectmodel.h
+++ b/qmake/generators/win32/msvc_objectmodel.h
@@ -56,7 +56,8 @@ enum DotNET {
NET2008 = 0x90,
NET2010 = 0xa0,
NET2012 = 0xb0,
- NET2013 = 0xc0
+ NET2013 = 0xc0,
+ NET2015 = 0xd0
};
/*
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index 1fa117afda..b8f9c8135d 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -71,6 +71,7 @@ struct DotNetCombo {
const char *regKey;
} dotNetCombo[] = {
#ifdef Q_OS_WIN64
+ {NET2015, "MSVC.NET 2015 (14.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"},
{NET2013, "MSVC.NET 2013 (12.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"},
{NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"},
{NET2012, "MSVC.NET 2012 (11.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\11.0\\Setup\\VC\\ProductDir"},
@@ -84,6 +85,7 @@ struct DotNetCombo {
{NET2003, "MSVC.NET 2003 (7.1)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"},
{NET2002, "MSVC.NET 2002 (7.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"},
#else
+ {NET2015, "MSVC.NET 2015 (14.0)", "Software\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"},
{NET2013, "MSVC.NET 2013 (12.0)", "Software\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"},
{NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"},
{NET2012, "MSVC.NET 2012 (11.0)", "Software\\Microsoft\\VisualStudio\\11.0\\Setup\\VC\\ProductDir"},
@@ -175,6 +177,8 @@ const char _slnHeader110[] = "Microsoft Visual Studio Solution File, Format
"\n# Visual Studio 2012";
const char _slnHeader120[] = "Microsoft Visual Studio Solution File, Format Version 12.00"
"\n# Visual Studio 2013";
+const char _slnHeader140[] = "Microsoft Visual Studio Solution File, Format Version 12.00"
+ "\n# Visual Studio 2015";
// The following UUID _may_ change for later servicepacks...
// If so we need to search through the registry at
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.0\Projects
@@ -401,6 +405,8 @@ QString VcprojGenerator::retrievePlatformToolSet() const
return QStringLiteral("v110") + suffix;
case NET2013:
return QStringLiteral("v120") + suffix;
+ case NET2015:
+ return QStringLiteral("v140") + suffix;
default:
return QString();
}
@@ -647,6 +653,8 @@ void VcprojGenerator::writeSubDirs(QTextStream &t)
}
switch (which_dotnet_version(project->first("MSVC_VER").toLatin1())) {
+ case NET2015:
+ t << _slnHeader140;
case NET2013:
t << _slnHeader120;
break;
@@ -972,6 +980,9 @@ void VcprojGenerator::initProject()
// Own elements -----------------------------
vcProject.Name = project->first("QMAKE_ORIG_TARGET").toQString();
switch (which_dotnet_version(project->first("MSVC_VER").toLatin1())) {
+ case NET2015:
+ vcProject.Version = "14.00";
+ break;
case NET2013:
vcProject.Version = "12.00";
break;
@@ -1213,7 +1224,12 @@ void VcprojGenerator::initLinkerTool()
void VcprojGenerator::initResourceTool()
{
VCConfiguration &conf = vcProject.Configuration;
- conf.resource.PreprocessorDefinitions = conf.compiler.PreprocessorDefinitions;
+
+ ProStringList rcDefines = project->values("RC_DEFINES");
+ if (rcDefines.size() > 0)
+ conf.resource.PreprocessorDefinitions = rcDefines.toQStringList();
+ else
+ conf.resource.PreprocessorDefinitions = conf.compiler.PreprocessorDefinitions;
foreach (const ProString &path, project->values("RC_INCLUDEPATH")) {
QString fixedPath = fileFixify(path.toQString());
@@ -1369,8 +1385,7 @@ void VcprojGenerator::initDeploymentTool()
}
}
- // foreach item in DEPLOYMENT
- foreach (const ProString &item, project->values("DEPLOYMENT")) {
+ foreach (const ProString &item, project->values("INSTALLS")) {
// get item.path
QString devicePath = project->first(ProKey(item + ".path")).toQString();
if (!conf.WinRT) {
diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp
index 6ea129f82c..0d761b08a2 100644
--- a/qmake/generators/win32/winmakefile.cpp
+++ b/qmake/generators/win32/winmakefile.cpp
@@ -100,10 +100,13 @@ ProString Win32MakefileGenerator::fixLibFlag(const ProString &lib)
{
if (lib.startsWith('/')) {
if (lib.startsWith("/LIBPATH:"))
- return QStringLiteral("/LIBPATH:") + escapeFilePath(lib.mid(9));
+ return QLatin1String("/LIBPATH:")
+ + escapeFilePath(Option::fixPathToTargetOS(lib.mid(9).toQString(), false));
+ // This appears to be a user-supplied flag. Assume sufficient quoting.
return lib;
}
- return escapeFilePath(lib);
+ // This must be a fully resolved library path.
+ return escapeFilePath(Option::fixPathToTargetOS(lib.toQString(), false));
}
bool
@@ -231,7 +234,7 @@ Win32MakefileGenerator::processPrlFiles()
}
ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS");
for (int prl = 0; prl < prl_libs.size(); ++prl)
- l.insert(lit + prl + 1, prl_libs.at(prl));
+ l.insert(++lit, prl_libs.at(prl));
prl_libs.clear();
}
@@ -752,10 +755,6 @@ void Win32MakefileGenerator::writeRcFilePart(QTextStream &t)
if(!project->values("RC_FILE").isEmpty()) {
const ProString res_file = project->first("RES_FILE");
const QString rc_file = fileFixify(project->first("RC_FILE").toQString());
- // The resource tool needs to have the same defines passed in as the compiler, since you may
- // use these defines in the .rc file itself. Also, we need to add the _DEBUG define manually
- // since the compiler defines this symbol by itself, and we use it in the automatically
- // created rc file when VERSION is define the .pro file.
const ProStringList rcIncPaths = project->values("RC_INCLUDEPATH");
QString incPathStr;
@@ -767,9 +766,20 @@ void Win32MakefileGenerator::writeRcFilePart(QTextStream &t)
incPathStr += escapeFilePath(path);
}
+ // The resource tool may use defines. This might be the same defines passed in as the
+ // compiler, since you may use these defines in the .rc file itself.
+ // As the escape syntax for the command line defines for RC is different from that for CL,
+ // we might have to set specific defines for RC.
+ ProString defines = varGlue("RC_DEFINES", " -D", " -D", "");
+ if (defines.isEmpty())
+ defines = ProString(" $(DEFINES)");
+
+ // Also, we need to add the _DEBUG define manually since the compiler defines this symbol
+ // by itself, and we use it in the automatically created rc file when VERSION is defined
+ // in the .pro file.
t << escapeDependencyPath(res_file) << ": " << escapeDependencyPath(rc_file) << "\n\t"
<< var("QMAKE_RC") << (project->isActiveConfig("debug") ? " -D_DEBUG" : "")
- << " $(DEFINES)" << incPathStr << " -fo " << escapeFilePath(res_file)
+ << defines << incPathStr << " -fo " << escapeFilePath(res_file)
<< ' ' << escapeFilePath(rc_file);
t << endl << endl;
}
@@ -784,7 +794,7 @@ QString Win32MakefileGenerator::defaultInstall(const QString &t)
{
if((t != "target" && t != "dlltarget") ||
(t == "dlltarget" && (project->first("TEMPLATE") != "lib" || !project->isActiveConfig("shared"))) ||
- project->first("TEMPLATE") == "subdirs")
+ project->first("TEMPLATE") == "subdirs" || project->first("TEMPLATE") == "aux")
return QString();
const QString root = "$(INSTALL_ROOT)";
diff --git a/qmake/library/proitems.cpp b/qmake/library/proitems.cpp
index e780259417..a610da6b69 100644
--- a/qmake/library/proitems.cpp
+++ b/qmake/library/proitems.cpp
@@ -159,6 +159,18 @@ QString &ProString::toQString(QString &tmp) const
return tmp.setRawData(m_string.constData() + m_offset, m_length);
}
+/*!
+ * \brief ProString::prepareExtend
+ * \param extraLen number of new characters to be added
+ * \param thisTarget offset to which current contents should be moved
+ * \param extraTarget offset at which new characters will be added
+ * \return pointer to storage location for new characters
+ *
+ * Prepares the string for adding new characters.
+ * If the string is detached and has enough space, it will be changed in place.
+ * Otherwise, it will be replaced with a new string object, thus detaching.
+ * In either case, the hash will be reset.
+ */
QChar *ProString::prepareExtend(int extraLen, int thisTarget, int extraTarget)
{
if (m_string.isDetached() && m_length + extraLen <= m_string.capacity()) {
@@ -473,4 +485,23 @@ ProFile::~ProFile()
{
}
+ProString ProFile::getStr(const ushort *&tPtr)
+{
+ uint len = *tPtr++;
+ ProString ret(items(), tPtr - tokPtr(), len);
+ ret.setSource(this);
+ tPtr += len;
+ return ret;
+}
+
+ProKey ProFile::getHashStr(const ushort *&tPtr)
+{
+ uint hash = *tPtr++;
+ hash |= (uint)*tPtr++ << 16;
+ uint len = *tPtr++;
+ ProKey ret(items(), tPtr - tokPtr(), len, hash);
+ tPtr += len;
+ return ret;
+}
+
QT_END_NAMESPACE
diff --git a/qmake/library/proitems.h b/qmake/library/proitems.h
index d31367361d..9430d28521 100644
--- a/qmake/library/proitems.h
+++ b/qmake/library/proitems.h
@@ -352,6 +352,9 @@ public:
bool isHostBuild() const { return m_hostBuild; }
void setHostBuild(bool host_build) { m_hostBuild = host_build; }
+ ProString getStr(const ushort *&tPtr);
+ ProKey getHashStr(const ushort *&tPtr);
+
private:
ProItemRefCount m_refCount;
QString m_proitems;
diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp
index e384d26f4c..02d5d5dd31 100644
--- a/qmake/library/qmakebuiltins.cpp
+++ b/qmake/library/qmakebuiltins.cpp
@@ -214,7 +214,7 @@ static QString windowsErrorCode()
NULL);
QString ret = QString::fromWCharArray(string);
LocalFree((HLOCAL)string);
- return ret;
+ return ret.trimmed();
}
#endif
@@ -362,7 +362,7 @@ QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::Open
{
QString errStr;
if (!m_vfs->writeFile(fn, mode, contents, &errStr)) {
- evalError(fL1S("Cannot write %1file %2: %3.")
+ evalError(fL1S("Cannot write %1file %2: %3")
.arg(ctx, QDir::toNativeSeparators(fn), errStr));
return ReturnFalse;
}
@@ -1121,7 +1121,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
switch (func_t) {
case T_DEFINED: {
if (args.count() < 1 || args.count() > 2) {
- evalError(fL1S("defined(function, [\"test\"|\"replace\"])"
+ evalError(fL1S("defined(function, [\"test\"|\"replace\"|\"var\"])"
" requires one or two arguments."));
return ReturnFalse;
}
@@ -1582,7 +1582,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (rHand == INVALID_HANDLE_VALUE) {
- evalError(fL1S("Cannot open() reference file %1: %2.").arg(rfn, windowsErrorCode()));
+ evalError(fL1S("Cannot open reference file %1: %2").arg(rfn, windowsErrorCode()));
return ReturnFalse;
}
FILETIME ft;
@@ -1592,7 +1592,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
GENERIC_WRITE, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (wHand == INVALID_HANDLE_VALUE) {
- evalError(fL1S("Cannot open() %1: %2.").arg(tfn, windowsErrorCode()));
+ evalError(fL1S("Cannot open %1: %2").arg(tfn, windowsErrorCode()));
return ReturnFalse;
}
SetFileTime(wHand, 0, 0, &ft);
diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp
index 5c9dc45f3a..8e247d9afa 100644
--- a/qmake/library/qmakeevaluator.cpp
+++ b/qmake/library/qmakeevaluator.cpp
@@ -188,7 +188,8 @@ void QMakeEvaluator::initStatics()
{ "QMAKE_RPATH", "QMAKE_LFLAGS_RPATH" },
{ "QMAKE_FRAMEWORKDIR", "QMAKE_FRAMEWORKPATH" },
{ "QMAKE_FRAMEWORKDIR_FLAGS", "QMAKE_FRAMEWORKPATH_FLAGS" },
- { "IN_PWD", "PWD" }
+ { "IN_PWD", "PWD" },
+ { "DEPLOYMENT", "INSTALLS" }
};
for (unsigned i = 0; i < sizeof(mapInits)/sizeof(mapInits[0]); ++i)
statics.varMap.insert(ProKey(mapInits[i].oldname), ProKey(mapInits[i].newname));
@@ -258,24 +259,6 @@ uint QMakeEvaluator::getBlockLen(const ushort *&tokPtr)
return len;
}
-ProString QMakeEvaluator::getStr(const ushort *&tokPtr)
-{
- uint len = *tokPtr++;
- ProString ret(m_current.pro->items(), tokPtr - m_current.pro->tokPtr(), len);
- ret.setSource(m_current.pro);
- tokPtr += len;
- return ret;
-}
-
-ProKey QMakeEvaluator::getHashStr(const ushort *&tokPtr)
-{
- uint hash = getBlockLen(tokPtr);
- uint len = *tokPtr++;
- ProKey ret(m_current.pro->items(), tokPtr - m_current.pro->tokPtr(), len, hash);
- tokPtr += len;
- return ret;
-}
-
void QMakeEvaluator::skipStr(const ushort *&tokPtr)
{
uint len = *tokPtr++;
@@ -314,7 +297,8 @@ ProStringList QMakeEvaluator::split_value_list(const QString &vals, const ProFil
switch (unicode) {
case '"':
case '\'':
- quote = unicode;
+ if (!quote)
+ quote = unicode;
hadWord = true;
break;
case ' ':
@@ -429,6 +413,7 @@ void QMakeEvaluator::evaluateExpression(
const ushort *&tokPtr, ProStringList *ret, bool joined)
{
debugMsg(2, joined ? "evaluating joined expression" : "evaluating expression");
+ ProFile *pro = m_current.pro;
if (joined)
*ret << ProString();
bool pending = false;
@@ -444,35 +429,35 @@ void QMakeEvaluator::evaluateExpression(
m_current.line = *tokPtr++;
break;
case TokLiteral: {
- const ProString &val = getStr(tokPtr);
+ const ProString &val = pro->getStr(tokPtr);
debugMsg(2, "literal %s", dbgStr(val));
addStr(val, ret, pending, joined);
break; }
case TokHashLiteral: {
- const ProKey &val = getHashStr(tokPtr);
+ const ProKey &val = pro->getHashStr(tokPtr);
debugMsg(2, "hashed literal %s", dbgStr(val.toString()));
addStr(val, ret, pending, joined);
break; }
case TokVariable: {
- const ProKey &var = getHashStr(tokPtr);
+ const ProKey &var = pro->getHashStr(tokPtr);
const ProStringList &val = values(map(var));
debugMsg(2, "variable %s => %s", dbgKey(var), dbgStrList(val));
addStrList(val, tok, ret, pending, joined);
break; }
case TokProperty: {
- const ProKey &var = getHashStr(tokPtr);
+ const ProKey &var = pro->getHashStr(tokPtr);
const ProString &val = propertyValue(var);
debugMsg(2, "property %s => %s", dbgKey(var), dbgStr(val));
addStr(val, ret, pending, joined);
break; }
case TokEnvVar: {
- const ProString &var = getStr(tokPtr);
+ const ProString &var = pro->getStr(tokPtr);
const ProString &val = ProString(m_option->getEnv(var.toQString(m_tmp1)));
debugMsg(2, "env var %s => %s", dbgStr(var), dbgStr(val));
addStr(val, ret, pending, joined);
break; }
case TokFuncName: {
- const ProKey &func = getHashStr(tokPtr);
+ const ProKey &func = pro->getHashStr(tokPtr);
debugMsg(2, "function %s", dbgKey(func));
addStrList(evaluateExpandFunction(func, tokPtr), tok, ret, pending, joined);
break; }
@@ -537,6 +522,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(
{
traceMsg("entering block");
ProStringList curr;
+ ProFile *pro = m_current.pro;
bool okey = true, or_op = false, invert = false;
uint blockLen;
while (ushort tok = *tokPtr++) {
@@ -596,7 +582,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(
blockLen = getBlockLen(tokPtr);
ret = visitProBlock(tokPtr);
} else if (okey != or_op) {
- const ProKey &variable = getHashStr(tokPtr);
+ const ProKey &variable = pro->getHashStr(tokPtr);
uint exprLen = getBlockLen(tokPtr);
const ushort *exprPtr = tokPtr;
tokPtr += exprLen;
@@ -616,7 +602,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(
case TokTestDef:
case TokReplaceDef:
if (m_cumulative || okey != or_op) {
- const ProKey &name = getHashStr(tokPtr);
+ const ProKey &name = pro->getHashStr(tokPtr);
blockLen = getBlockLen(tokPtr);
visitProFunctionDef(tok, name, tokPtr);
traceMsg("defined %s function %s",
@@ -796,8 +782,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProLoop(
forever {
if (infinite) {
if (!variable.isEmpty())
- m_valuemapStack.top()[variable] = ProStringList(ProString(QString::number(index++)));
- if (index > 1000) {
+ m_valuemapStack.top()[variable] = ProStringList(ProString(QString::number(index)));
+ if (++index > 1000) {
evalError(fL1S("Ran into infinite loop (> 1000 iterations)."));
break;
}
diff --git a/qmake/library/qmakeevaluator.h b/qmake/library/qmakeevaluator.h
index 4f2acf25ee..a60adde84e 100644
--- a/qmake/library/qmakeevaluator.h
+++ b/qmake/library/qmakeevaluator.h
@@ -150,8 +150,6 @@ public:
{ return b ? ReturnTrue : ReturnFalse; }
static ALWAYS_INLINE uint getBlockLen(const ushort *&tokPtr);
- ProString getStr(const ushort *&tokPtr);
- ProKey getHashStr(const ushort *&tokPtr);
void evaluateExpression(const ushort *&tokPtr, ProStringList *ret, bool joined);
static ALWAYS_INLINE void skipStr(const ushort *&tokPtr);
static ALWAYS_INLINE void skipHashStr(const ushort *&tokPtr);
diff --git a/qmake/library/qmakeglobals.h b/qmake/library/qmakeglobals.h
index 7c77450523..de46ebbe74 100644
--- a/qmake/library/qmakeglobals.h
+++ b/qmake/library/qmakeglobals.h
@@ -135,6 +135,7 @@ public:
bool initProperties();
# else
void setProperties(const QHash<QString, QString> &props);
+ void setProperties(const QHash<ProKey, ProString> &props) { properties = props; }
# endif
ProString propertyValue(const ProKey &name) const { return properties.value(name); }
#endif
diff --git a/qmake/main.cpp b/qmake/main.cpp
index 27969932bc..bde537dcca 100644
--- a/qmake/main.cpp
+++ b/qmake/main.cpp
@@ -163,6 +163,75 @@ static int doSed(int argc, char **argv)
return 0;
}
+static int doLink(int argc, char **argv)
+{
+ bool isSymlink = false;
+ bool force = false;
+ QList<const char *> inFiles;
+ for (int i = 0; i < argc; i++) {
+ if (!strcmp(argv[i], "-s")) {
+ isSymlink = true;
+ } else if (!strcmp(argv[i], "-f")) {
+ force = true;
+ } else if (argv[i][0] == '-') {
+ fprintf(stderr, "Error: unrecognized ln option '%s'\n", argv[i]);
+ return 3;
+ } else {
+ inFiles << argv[i];
+ }
+ }
+ if (inFiles.size() != 2) {
+ fprintf(stderr, "Error: this ln requires exactly two file arguments\n");
+ return 3;
+ }
+ if (!isSymlink) {
+ fprintf(stderr, "Error: this ln supports faking symlinks only\n");
+ return 3;
+ }
+ QString target = QString::fromLocal8Bit(inFiles[0]);
+ QString linkname = QString::fromLocal8Bit(inFiles[1]);
+
+ QDir destdir;
+ QFileInfo tfi(target);
+ QFileInfo lfi(linkname);
+ if (lfi.isDir()) {
+ destdir.setPath(linkname);
+ lfi.setFile(destdir, tfi.fileName());
+ } else {
+ destdir.setPath(lfi.path());
+ }
+ if (!destdir.exists()) {
+ fprintf(stderr, "Error: destination directory %s does not exist\n", qPrintable(destdir.path()));
+ return 1;
+ }
+ tfi.setFile(destdir.absoluteFilePath(tfi.filePath()));
+ if (!tfi.exists()) {
+ fprintf(stderr, "Error: this ln does not support symlinking non-existing targets\n");
+ return 3;
+ }
+ if (tfi.isDir()) {
+ fprintf(stderr, "Error: this ln does not support symlinking directories\n");
+ return 3;
+ }
+ if (lfi.exists()) {
+ if (!force) {
+ fprintf(stderr, "Error: %s exists\n", qPrintable(lfi.filePath()));
+ return 1;
+ }
+ if (!QFile::remove(lfi.filePath())) {
+ fprintf(stderr, "Error: cannot overwrite %s\n", qPrintable(lfi.filePath()));
+ return 1;
+ }
+ }
+ if (!QFile::copy(tfi.filePath(), lfi.filePath())) {
+ fprintf(stderr, "Error: cannot copy %s to %s\n",
+ qPrintable(tfi.filePath()), qPrintable(lfi.filePath()));
+ return 1;
+ }
+
+ return 0;
+}
+
static int doInstall(int argc, char **argv)
{
if (!argc) {
@@ -171,6 +240,8 @@ static int doInstall(int argc, char **argv)
}
if (!strcmp(argv[0], "sed"))
return doSed(argc - 1, argv + 1);
+ if (!strcmp(argv[0], "ln"))
+ return doLink(argc - 1, argv + 1);
fprintf(stderr, "Error: unrecognized -install subcommand '%s'\n", argv[0]);
return 3;
}