= 10000) {
Log.LogError("Qt::BuildLock[{0}]: Timeout; wait aborted", Name);
return false;
}
} while (!buildLock.WaitOne(1000));
}
} else {
// Unlock
buildLock.Set();
}
]]>
{
"AccessedTime", "CreatedTime", "DefiningProjectDirectory",
"DefiningProjectExtension", "DefiningProjectFullPath", "DefiningProjectName",
"Directory", "Extension", "Filename", "FullPath", "Identity", "ModifiedTime",
"RecursiveDir", "RelativeDir", "RootDir",
};
if (Metadata == null)
Metadata = "";
var requestedNames = new HashSet(Metadata.Split(new[] { ';' },
StringSplitOptions.RemoveEmptyEntries));
var itemXml = new StringBuilder();
if (Items.Any()) {
foreach (var item in Items) {
if (itemXml.Length > 0)
itemXml.Append("\r\n");
itemXml.AppendFormat("<{0} Include=\"{1}\"", ItemType, item.ItemSpec);
var names = item.MetadataNames.Cast()
.Where(x => (DumpReserved || !reserved.Contains(x))
&& (!requestedNames.Any() || requestedNames.Contains(x)))
.OrderBy(x => x);
if (names.Any()) {
itemXml.Append(">\r\n");
foreach (string name in names) {
if (!DumpReserved && reserved.Contains(name))
continue;
if (!item.MetadataNames.Cast().Contains(name))
continue;
var value = item.GetMetadata(name);
if (!string.IsNullOrEmpty(value))
itemXml.AppendFormat(" <{0}>{1}{0}>\r\n", name, value);
else
itemXml.AppendFormat(" <{0}/>\r\n", name);
}
itemXml.AppendFormat("{0}>", ItemType);
} else {
itemXml.Append("/>");
}
}
} else {
itemXml.AppendFormat("<{0}/>", ItemType);
}
Log.LogMessage(MessageImportance.High, itemXml.ToString());
]]>
(StringComparer.InvariantCultureIgnoreCase)
{
"AccessedTime", "CreatedTime", "DefiningProjectDirectory",
"DefiningProjectExtension", "DefiningProjectFullPath", "DefiningProjectName",
"Directory", "Extension", "Filename", "FullPath", "Identity", "ModifiedTime",
"RecursiveDir", "RelativeDir", "RootDir",
};
var newItems = new List();
foreach (var item in Items) {
var newItem = new TaskItem(item);
if (BaseItem != null)
BaseItem.CopyMetadataTo(newItem);
var itemExt = newItem.GetMetadata("Extension");
if (!string.IsNullOrEmpty(itemExt))
newItem.SetMetadata("Suffix", itemExt.Substring(1));
if (Template != null) {
var metadataNames = Template.MetadataNames
.Cast().Where(x => !reserved.Contains(x));
foreach (var metadataName in metadataNames) {
var metadataValue = Template.GetMetadata(metadataName);
newItem.SetMetadata(metadataName,
Regex.Replace(metadataValue, @"(%<)(\w+)(>)",
match => newItem.GetMetadata(match.Groups[2].Value)));
}
}
newItems.Add(newItem);
}
Result = newItems.ToArray();
]]>
{
"AccessedTime", "CreatedTime", "DefiningProjectDirectory",
"DefiningProjectExtension", "DefiningProjectFullPath", "DefiningProjectName",
"Directory", "Extension", "Filename", "FullPath", "Identity", "ModifiedTime",
"RecursiveDir", "RelativeDir", "RootDir",
};
if (Metadata == null)
Metadata = new string[0];
var requestedNames = new HashSet(Metadata.Where(x => !string.IsNullOrEmpty(x)));
var newItems = new List();
foreach (var item in Items) {
var itemName = item.ItemSpec;
var names = item.MetadataNames.Cast().Where(x => !reserved.Contains(x)
&& (!requestedNames.Any() || requestedNames.Contains(x)));
foreach (string name in names) {
var values = item.GetMetadata(name).Split(';');
foreach (string value in values.Where(v => !string.IsNullOrEmpty(v))) {
newItems.Add(new TaskItem(string.Format("{0}={1}", name, value),
new Dictionary
{
{ "Item", itemName },
{ "Name", name },
{ "Value", value },
}));
}
}
}
Result = newItems.ToArray();
]]>
x)
.Select(x => string.Format("[{0}={1}]", x, Item.GetMetadata(x))))
.ToUpper());
using (var dataZipped = new MemoryStream()) {
using (var zip = new DeflateStream(dataZipped, CompressionLevel.Fastest))
zip.Write(data, 0, data.Length);
Hash = Convert.ToBase64String(dataZipped.ToArray());
}
]]>
()
.Where(x => x.Groups.Count > 2 && x.Groups[1].Success && x.Groups[2].Success
&& !string.IsNullOrEmpty(x.Groups[1].Value))
.GroupBy(x => x.Groups[1].Value)
.ToDictionary(g => g.Key, g => g.Last().Groups[2].Value);
OutVars = VarDefs
.Where(x => makefileVars.ContainsKey(x.GetMetadata("Name")))
.Select(x => new TaskItem(x.ItemSpec, new Dictionary
{ {
"Value",
string.Join(";", Regex
.Matches(makefileVars[x.GetMetadata("Name")], x.GetMetadata("Pattern"))
.Cast()
.Select(y => Regex
.Replace(y.Value, x.GetMetadata("Pattern"), x.GetMetadata("Value")))
.Where(y => !string.IsNullOrEmpty(y)
&& !ExcludeValues.Contains(y,
StringComparer.InvariantCultureIgnoreCase))
.ToHashSet())
} }))
.Where(x => !string.IsNullOrEmpty(x.GetMetadata("Value")))
.ToArray();
]]>
{
string.Format("{0}/{1}", RemoteProjectDir, WorkingDirectory)
};
var localFilesToCopyRemotelyMapping = new string[0];
if (Inputs != null) {
localFilesToCopyRemotelyMapping = Inputs
.Select(x => string.Format(@"{0}:={1}/{2}",
x.GetMetadata("Item"),
RemoteProjectDir,
x.GetMetadata("Value")))
.ToArray();
createDirs.AddRange(Inputs
.Select(x => string.Format("\x24(dirname {0})", x.GetMetadata("Value"))));
}
var remoteFilesToCopyLocallyMapping = new string[0];
if (Outputs != null) {
remoteFilesToCopyLocallyMapping = Outputs
.Select(x => string.Format(@"{0}/{1}:={2}",
RemoteProjectDir,
x.GetMetadata("Value"),
x.GetMetadata("Item")))
.ToArray();
createDirs.AddRange(Outputs
.Select(x => string.Format("\x24(dirname {0})", x.GetMetadata("Value"))));
}
Command = "(" + Command + ")";
if (RedirectStdOut == "NUL" || RedirectStdOut == "/dev/null")
Command += " 1> /dev/null";
else if (!string.IsNullOrEmpty(RedirectStdOut))
Command += " 1> " + RedirectStdOut;
if (RedirectStdErr == "NUL" || RedirectStdErr == "/dev/null")
Command += " 2> /dev/null";
else if (RedirectStdErr == "STDOUT")
Command += " 2>&1";
else if (!string.IsNullOrEmpty(RedirectStdErr))
Command += " 2> " + RedirectStdErr;
Command = string.Format("cd {0}/{1}; {2}", RemoteProjectDir, WorkingDirectory, Command);
var taskCopyFiles = new Microsoft.Build.Linux.Tasks.Execute()
{
BuildEngine = BuildEngine,
HostObject = HostObject,
ProjectDir = @"$(ProjectDir)",
IntermediateDir = @"$(IntDir)",
RemoteTarget = RemoteTarget,
RemoteProjectDir = RemoteProjectDir,
Command = string.Join("; ", createDirs.Select(x => string.Format("mkdir -p {0}", x))),
LocalFilesToCopyRemotelyMapping = localFilesToCopyRemotelyMapping,
};
var taskExec = new Microsoft.Build.Linux.Tasks.Execute()
{
BuildEngine = BuildEngine,
HostObject = HostObject,
ProjectDir = @"$(ProjectDir)",
IntermediateDir = @"$(IntDir)",
RemoteTarget = RemoteTarget,
RemoteProjectDir = RemoteProjectDir,
Command = Command,
RemoteFilesToCopyLocallyMapping = remoteFilesToCopyLocallyMapping,
};
Log.LogMessage("\r\n==== HostExec: Microsoft.Build.Linux.Tasks.Execute");
Log.LogMessage("ProjectDir: {0}", taskExec.ProjectDir);
Log.LogMessage("IntermediateDir: {0}", taskExec.IntermediateDir);
Log.LogMessage("RemoteTarget: {0}", taskExec.RemoteTarget);
Log.LogMessage("RemoteProjectDir: {0}", taskExec.RemoteProjectDir);
if (taskExec.LocalFilesToCopyRemotelyMapping.Any())
Log.LogMessage("LocalFilesToCopyRemotelyMapping: {0}",
taskExec.LocalFilesToCopyRemotelyMapping);
if (taskExec.RemoteFilesToCopyLocallyMapping.Any())
Log.LogMessage("RemoteFilesToCopyLocallyMapping: {0}",
taskExec.RemoteFilesToCopyLocallyMapping);
Log.LogMessage("CreateDirs: {0}", taskCopyFiles.Command);
Log.LogMessage("Command: {0}", taskExec.Command);
if (!taskCopyFiles.ExecuteTool()) {
ExitCode = taskCopyFiles.ExitCode;
return false;
}
bool ok = taskExec.ExecuteTool();
Log.LogMessage("== {0} ExitCode: {1}\r\n", ok ? "OK" : "FAIL", taskExec.ExitCode);
ExitCode = taskExec.ExitCode;
if (!ok && !IgnoreExitCode) {
Log.LogError("Host command failed.");
return false;
}
]]>
/dev/null";
else if (!string.IsNullOrEmpty(RedirectStdOut))
Command += " 1> " + RedirectStdOut;
if (RedirectStdErr == "NUL" || RedirectStdErr == "/dev/null")
Command += " 2> /dev/null";
else if (RedirectStdErr == "STDOUT")
Command += " 2>&1";
else if (!string.IsNullOrEmpty(RedirectStdErr))
Command += " 2> " + RedirectStdErr;
var createDirs = new List();
if (Inputs != null) {
createDirs.AddRange(Inputs
.Select(x => string.Format("\x24(dirname {0})", x.GetMetadata("Value"))));
}
if (Outputs != null) {
createDirs.AddRange(Outputs
.Select(x => string.Format("\x24(dirname {0})", x.GetMetadata("Value"))));
}
if (!string.IsNullOrEmpty(WorkingDirectory)) {
createDirs.Add(WorkingDirectory);
Command = string.Format("cd {0}; {1}", WorkingDirectory, Command);
}
if (createDirs.Any()) {
Command = string.Format("{0}; {1}",
string.Join("; ", createDirs.Select(x => string.Format("mkdir -p {0}", x))),
Command);
}
var taskExec = new Microsoft.Build.Linux.WSL.Tasks.ExecuteCommand()
{
BuildEngine = BuildEngine,
HostObject = HostObject,
ProjectDir = @"$(ProjectDir)",
IntermediateDir = @"$(IntDir)",
WSLPath = @"$(WSLPath)",
Command = Command,
};
Log.LogMessage("\r\n==== HostExec: Microsoft.Build.Linux.WSL.Tasks.ExecuteCommand");
Log.LogMessage("ProjectDir: {0}", taskExec.ProjectDir);
Log.LogMessage("IntermediateDir: {0}", taskExec.IntermediateDir);
Log.LogMessage("WSLPath: {0}", taskExec.WSLPath);
Log.LogMessage("Command: {0}", taskExec.Command);
bool ok = taskExec.Execute();
Log.LogMessage("== {0} ExitCode: {1}\r\n", ok ? "OK" : "FAIL", taskExec.ExitCode);
ExitCode = taskExec.ExitCode;
if (!ok && !IgnoreExitCode) {
Log.LogError("Host command failed.");
return false;
}
]]>
NUL";
else if (!string.IsNullOrEmpty(RedirectStdOut))
Command += " 1> " + RedirectStdOut;
if (RedirectStdErr == "NUL" || RedirectStdErr == "/dev/null")
Command += " 2> NUL";
else if (RedirectStdErr == "STDOUT")
Command += " 2>&1";
else if (!string.IsNullOrEmpty(RedirectStdErr))
Command += " 2> " + RedirectStdErr;
var taskExec = new Microsoft.Build.Tasks.Exec()
{
BuildEngine = BuildEngine,
HostObject = HostObject,
WorkingDirectory = WorkingDirectory,
Command = Command,
IgnoreExitCode = IgnoreExitCode,
};
Log.LogMessage("\r\n==== HostExec: Microsoft.Build.Tasks.Exec");
Log.LogMessage("WorkingDirectory: {0}", taskExec.WorkingDirectory);
Log.LogMessage("Command: {0}", taskExec.Command);
bool ok = taskExec.Execute();
Log.LogMessage("== {0} ExitCode: {1}\r\n", ok ? "OK" : "FAIL", taskExec.ExitCode);
ExitCode = taskExec.ExitCode;
if (!ok)
return false;
]]>
();
foreach (var item in Items) {
string itemName = item.GetMetadata("Name");
string itemValue = item.GetMetadata("Value");
if (Names.Contains(itemName)) {
if (Path.IsPathRooted(itemValue) && !itemValue.StartsWith("/")) {
var projectdir = new Uri(@"$(ProjectDir)");
var itemFileName = Path.GetFileName(itemValue);
var itemDirName = Path.GetFullPath(Path.GetDirectoryName(itemValue));
if (!itemDirName.EndsWith(@"\"))
itemDirName += @"\";
var itemDir = new Uri(itemDirName);
if (projectdir.IsBaseOf(itemDir)) {
itemValue = projectdir.MakeRelativeUri(itemDir).OriginalString
+ itemFileName;
} else {
Log.LogWarning("Unable to translate path: {0}", itemValue);
}
} else {
itemValue = itemValue.Replace(@"\", "/");
}
}
newItems.Add(new TaskItem(item.ItemSpec,
new Dictionary
{
{ "Item", item.GetMetadata("Item") },
{ "Name", itemName },
{ "Value", itemValue },
}));
}
Result = newItems.ToArray();
]]>
();
foreach (var item in Items) {
string itemName = item.GetMetadata("Name");
string itemValue = item.GetMetadata("Value");
if (Names.Contains(itemName)) {
if (Path.IsPathRooted(itemValue) && !itemValue.StartsWith("/"))
itemValue = PathUtils.TranslateWindowsPathToWSLPath(itemValue);
else
itemValue = itemValue.Replace(@"\", "/");
}
newItems.Add(new TaskItem(item.ItemSpec,
new Dictionary
{
{ "Item", item.GetMetadata("Item") },
{ "Name", itemName },
{ "Value", itemValue },
}));
}
Result = newItems.ToArray();
]]>
files = qrc
.Element("RCC")
.Elements("qresource")
.Elements("file");
Uri QrcPath = new Uri(QrcFilePath);
Result = files
.Select(x => new Uri(QrcPath, x.Value).LocalPath)
.ToArray();
]]>
()
.Where((Match x) => x.Groups.Count > 4 && !string.IsNullOrEmpty(x.Groups[1].Value))
.Select((Match x) => x.Groups
.Cast()
.Select((Group y) => !string.IsNullOrEmpty(y.Value) ? y.Value : null)
.ToArray())
.Select((string[] x) => new TaskItem(x[1],
new Dictionary
{
{ "Name" , x[2] ?? x[1] },
{ "Pattern" , x[3] ?? ".*" },
{ "Value" , x[4] ?? "$0" },
}))
.ToArray();
]]>
KeyString = (x, y) => string.Format("{0}{{{1}}}", x, y);
Func Key = (item) =>
KeyString(item.GetMetadata("WorkType"), item.ItemSpec);
var workItemKeys = new HashSet(QtWork.Select(x => Key(x)), Comparer);
// Work items, indexed by %(Identity)
var workItemsByIdentity = QtWork
.GroupBy(x => x.ItemSpec, x => Key(x), Comparer)
.ToDictionary(x => x.Key, x => new List(x), Comparer);
// Work items, indexed by work item key
var workItems = QtWork.Select(x => new
{
Self = x,
Key = Key(x),
ToolPath = x.GetMetadata("ToolPath"),
Message = x.GetMetadata("Message"),
DependsOn = new HashSet(comparer: Comparer,
collection: x.GetMetadata("DependsOn")
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
.Where(y => workItemsByIdentity.ContainsKey(y))
.SelectMany(y => workItemsByIdentity[y])
.Union(x.GetMetadata("DependsOnWork")
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
.Select(y => KeyString(y, x.ItemSpec))
.Where(y => workItemKeys.Contains(y)))
.GroupBy(y => y, Comparer).Select(y => y.Key)
.Where(y => !y.Equals(Key(x), Comparison))),
ProcessStartInfo = new ProcessStartInfo
{
FileName = x.GetMetadata("ToolPath"),
Arguments = x.GetMetadata("Options"),
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
},
})
// In case of items with duplicate keys, use only the first one
.GroupBy(x => x.Key, Comparer)
.ToDictionary(x => x.Key, x => x.First(), Comparer);
// Result
var result = workItems.Values
.ToDictionary(x => x.Key, x => new TaskItem(x.Self));
// Dependency relation [item -> dependent items]
var dependentsOf = workItems.Values
.Where(x => x.DependsOn.Any())
.SelectMany(x => x.DependsOn.Select(y => new { Dependent = x.Key, Dependency = y }))
.GroupBy(x => x.Dependency, x => x.Dependent, Comparer)
.ToDictionary(x => x.Key, x => new List(x), Comparer);
// Work items that are ready to start; initially queue all independent items
var workQueue = new Queue(workItems.Values
.Where(x => !x.DependsOn.Any())
.Select(x => x.Key));
if (QtDebug) {
Log.LogMessage(MessageImportance.High,
string.Format("## QtRunWork queueing\r\n## {0}",
string.Join("\r\n## ", workQueue)));
}
// Postponed items; save dependent items to queue later when ready
var postponedItems = new HashSet(workItems.Values
.Where(x => x.DependsOn.Any())
.Select(x => x.Key));
if (QtDebug && postponedItems.Any()) {
Log.LogMessage(MessageImportance.High,
string.Format("## QtRunWork postponed dependents\r\n## {0}",
string.Join("\r\n## ", postponedItems
.Select(x => string.Format("{0} <- {1}", x,
string.Join(", ", workItems[x].DependsOn))))));
}
// Work items that are running; must synchronize with the exit of all processes
var running = new Queue>();
// Work items that have terminated
var terminated = new HashSet(Comparer);
// While there are work items queued, start a process for each item
while (ok && workQueue.Any()) {
var workItem = workItems[workQueue.Dequeue()];
Log.LogMessage(MessageImportance.High, workItem.Message);
try {
var proc = Process.Start(workItem.ProcessStartInfo);
proc.OutputDataReceived += (object sender, DataReceivedEventArgs e) =>
{
if (!string.IsNullOrEmpty(e.Data))
Log.LogMessage(MessageImportance.High, string.Join(" ", new[]
{
(QtDebug ? "[" + (((Process)sender).Id.ToString()) + "]" : ""),
e.Data
}));
};
proc.ErrorDataReceived += (object sender, DataReceivedEventArgs e) =>
{
if (!string.IsNullOrEmpty(e.Data))
Log.LogMessage(MessageImportance.High, string.Join(" ", new[]
{
(QtDebug ? "[" + (((Process)sender).Id.ToString()) + "]" : ""),
e.Data
}));
};
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
running.Enqueue(new KeyValuePair(workItem.Key, proc));
} catch (Exception e) {
Log.LogError(
string.Format("[QtRunWork] Error starting process {0}: {1}",
workItem.ToolPath, e.Message));
ok = false;
}
string qtDebugRunning = "";
if (QtDebug) {
qtDebugRunning = string.Format("## QtRunWork waiting {0}",
string.Join(", ", running
.Select(x => string.Format("{0} [{1}]", x.Key, x.Value.Id))));
}
// Wait for process to terminate when there are processes running, and...
while (ok && running.Any()
// ...work is queued but already reached the maximum number of processes, or...
&& ((workQueue.Any() && running.Count >= QtMaxProcs)
// ...work queue is empty but there are dependents that haven't yet been queued
|| (!workQueue.Any() && postponedItems.Any()))) {
var itemProc = running.Dequeue();
workItem = workItems[itemProc.Key];
var proc = itemProc.Value;
if (QtDebug && !string.IsNullOrEmpty(qtDebugRunning)) {
Log.LogMessage(MessageImportance.High, qtDebugRunning);
qtDebugRunning = "";
}
if (proc.WaitForExit(100)) {
if (QtDebug) {
Log.LogMessage(MessageImportance.High,
string.Format("## QtRunWork exit {0} [{1}] = {2} ({3:0.00} msecs)",
workItem.Key, proc.Id, proc.ExitCode,
(proc.ExitTime - proc.StartTime).TotalMilliseconds));
}
// Process terminated; check exit code and close
terminated.Add(workItem.Key);
result[workItem.Key].SetMetadata("ExitCode", proc.ExitCode.ToString());
ok &= (proc.ExitCode == 0);
proc.Close();
// Add postponed dependent items to work queue
if (ok && dependentsOf.ContainsKey(workItem.Key)) {
// Dependents of workItem...
var readyDependents = dependentsOf[workItem.Key]
// ...that have not yet been queued...
.Where(x => postponedItems.Contains(x)
// ...and whose dependending items have all terminated.
&& workItems[x].DependsOn.All(y => terminated.Contains(y)));
if (QtDebug && readyDependents.Any()) {
Log.LogMessage(MessageImportance.High,
string.Format("## QtRunWork queueing\r\n## {0}",
string.Join("\r\n## ", readyDependents)));
}
foreach (var dependent in readyDependents) {
postponedItems.Remove(dependent);
workQueue.Enqueue(dependent);
}
}
} else {
// Process is still running; feed it back into the running queue
running.Enqueue(itemProc);
}
}
}
// If there are items still haven't been queued, that means a circular dependency exists
if (ok && postponedItems.Any()) {
ok = false;
Log.LogError("[QtRunWork] Error: circular dependency");
if (QtDebug) {
Log.LogMessage(MessageImportance.High,
string.Format("## QtRunWork circularity\r\n## {0}",
string.Join("\r\n## ", postponedItems
.Select(x => string.Format("{0} <- {1}", x,
string.Join(", ", workItems[x].DependsOn))))));
}
}
if (ok && QtDebug) {
Log.LogMessage(MessageImportance.High,
"## QtRunWork all work queued");
if (running.Any()) {
Log.LogMessage(MessageImportance.High,
string.Format("## QtRunWork waiting {0}",
string.Join(", ", running
.Select(x => string.Format("{0} [{1}]", x.Key, x.Value.Id)))));
}
}
// Wait for all running processes to terminate
while (running.Any()) {
var itemProc = running.Dequeue();
var workItem = workItems[itemProc.Key];
var proc = itemProc.Value;
if (proc.WaitForExit(100)) {
if (QtDebug) {
Log.LogMessage(MessageImportance.High,
string.Format("## QtRunWork exit {0} [{1}] = {2} ({3:0.00} msecs)",
workItem.Key, proc.Id, proc.ExitCode,
(proc.ExitTime - proc.StartTime).TotalMilliseconds));
}
// Process terminated; check exit code and close
result[workItem.Key].SetMetadata("ExitCode", proc.ExitCode.ToString());
ok &= (proc.ExitCode == 0);
proc.Close();
} else {
// Process is still running; feed it back into the running queue
running.Enqueue(itemProc);
}
}
if (QtDebug) {
Log.LogMessage(MessageImportance.High,
string.Format("## QtRunWork result {0}", (ok ? "ok" : "FAILED!")));
}
Result = result.Values.ToArray();
if (!ok)
return false;
]]>