diff options
Diffstat (limited to 'src/qtvstools.core/QMakeConf.cs')
-rw-r--r-- | src/qtvstools.core/QMakeConf.cs | 166 |
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; + } + } +} |