aboutsummaryrefslogtreecommitdiffstats
path: root/src/qtvstools.core/QMakeConf.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/qtvstools.core/QMakeConf.cs')
-rw-r--r--src/qtvstools.core/QMakeConf.cs166
1 files changed, 166 insertions, 0 deletions
diff --git a/src/qtvstools.core/QMakeConf.cs b/src/qtvstools.core/QMakeConf.cs
new file mode 100644
index 00000000..2701772c
--- /dev/null
+++ b/src/qtvstools.core/QMakeConf.cs
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt VS Tools.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+using System;
+using System.Collections;
+using System.IO;
+
+namespace QtVsTools.Core
+{
+ public class QMakeConf
+ {
+ public Hashtable Entries { get; private set; }
+ public string QMakeSpecDirectory { get; private set; }
+
+ public QMakeConf(VersionInformation versionInfo, QMakeQuery qmakeQuery = null)
+ {
+ Entries = new Hashtable();
+ QMakeSpecDirectory = Path.Combine(versionInfo.qtDir, "mkspecs", "default");
+ var qmakeConf = Path.Combine(QMakeSpecDirectory, "qmake.conf");
+
+ // Starting from Qt5 beta2 there is no more "\\mkspecs\\default" folder available
+ // To find location of "qmake.conf" there is a need to run "qmake -query" command
+ // This is what happens below.
+ if (!File.Exists(qmakeConf)) {
+ if (qmakeQuery == null)
+ qmakeQuery = new QMakeQuery(versionInfo);
+
+ string qtPrefix = qmakeQuery["QT_INSTALL_PREFIX"];
+ if (string.IsNullOrEmpty(qtPrefix))
+ throw new QtVSException("qmake error: no value for QT_INSTALL_PREFIX");
+
+ string qtArchData = qmakeQuery["QT_INSTALL_ARCHDATA"];
+ if (string.IsNullOrEmpty(qtArchData))
+ throw new QtVSException("qmake error: no value for QT_INSTALL_ARCHDATA");
+
+ string qmakeXSpec = qmakeQuery["QMAKE_XSPEC"];
+ if (string.IsNullOrEmpty(qtArchData))
+ throw new QtVSException("qmake error: no value for QMAKE_XSPEC");
+
+ qmakeConf = Path.Combine(qtPrefix, qtArchData, "mkspecs", qmakeXSpec, "qmake.conf");
+
+ if (!File.Exists(qmakeConf))
+ throw new QtVSException("qmake.conf expected at " + qmakeConf + " not found");
+ }
+
+ ParseFile(qmakeConf);
+ }
+
+ private void ParseFile(string filename)
+ {
+ var fileInfo = new FileInfo(filename);
+ if (fileInfo.Exists) {
+ var streamReader = new StreamReader(filename);
+ var line = streamReader.ReadLine();
+ while (line != null) {
+ line = line.Trim();
+ var commentStartIndex = line.IndexOf('#');
+ if (commentStartIndex >= 0)
+ line = line.Remove(commentStartIndex);
+ var pos = line.IndexOf('=');
+ if (pos > 0) {
+ var op = "=";
+ if (line[pos - 1] == '+' || line[pos - 1] == '-')
+ op = line[pos - 1] + "=";
+
+ var lineKey = line.Substring(0, pos - op.Length + 1).Trim();
+ var lineValue = ExpandVariables(line.Substring(pos + 1).Trim());
+
+ if (op == "+=") {
+ Entries[lineKey] += " " + lineValue;
+ } else if (op == "-=") {
+ foreach (var remval in lineValue.Split(' ', '\t'))
+ RemoveValue(lineKey, remval);
+ } else {
+ Entries[lineKey] = lineValue;
+ }
+ } else if (line.StartsWith("include", StringComparison.Ordinal)) {
+ pos = line.IndexOf('(');
+ var posEnd = line.LastIndexOf(')');
+ if (pos > 0 && pos < posEnd) {
+ var filenameToInclude = line.Substring(pos + 1, posEnd - pos - 1);
+ var saveCurrentDir = Environment.CurrentDirectory;
+ Environment.CurrentDirectory = fileInfo.Directory.FullName;
+ var fileInfoToInclude = new FileInfo(filenameToInclude);
+ if (fileInfoToInclude.Exists)
+ ParseFile(fileInfoToInclude.FullName);
+ Environment.CurrentDirectory = saveCurrentDir;
+ }
+ }
+ line = streamReader.ReadLine();
+ }
+ streamReader.Close();
+
+ RemoveValue("QMAKE_LFLAGS_CONSOLE", "@QMAKE_SUBSYSTEM_SUFFIX@");
+ RemoveValue("QMAKE_LFLAGS_WINDOWS", "@QMAKE_SUBSYSTEM_SUFFIX@");
+ }
+ }
+
+ private string ExpandVariables(string value)
+ {
+ var pos = value.IndexOf("$$", StringComparison.Ordinal);
+ while (pos != -1) {
+ var startPos = pos + 2;
+ var endPos = startPos;
+
+ if (value[startPos] != '[') { // at the moment no handling of qmake internal variables
+ for (; endPos < value.Length; ++endPos) {
+ if ((Char.IsPunctuation(value[endPos]) && value[endPos] != '_')
+ || Char.IsWhiteSpace(value[endPos])) {
+ break;
+ }
+ }
+ if (endPos > startPos) {
+ var varName = value.Substring(startPos, endPos - startPos);
+ var varValue = (Entries[varName] ?? string.Empty).ToString();
+ value = value.Substring(0, pos) + varValue + value.Substring(endPos);
+ endPos = pos + varValue.Length;
+ }
+ }
+
+ pos = value.IndexOf("$$", endPos, StringComparison.Ordinal);
+ }
+ return value;
+ }
+
+ private void RemoveValue(string key, string valueToRemove)
+ {
+ var pos = -1;
+ if (!Entries.Contains(key))
+ return;
+
+ var value = Entries[key].ToString();
+ do {
+ pos = value.IndexOf(valueToRemove, StringComparison.Ordinal);
+ if (pos >= 0)
+ value = value.Remove(pos, valueToRemove.Length);
+ } while (pos >= 0);
+ Entries[key] = value;
+ }
+ }
+}