// NAnt - A .NET build tool
// Copyright (C) 2001-2003 Gerry Shaw
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Ian Maclean (imaclean@gmail.com)
// Jaroslaw Kowalski (jkowalski@users.sourceforge.net)
// Gert Driesen (gert.driesen@ardatis.com)
using System;
using System.ComponentModel;
using System.IO;
using System.Collections;
using System.Reflection;
using System.Globalization;
using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Tasks;
using NAnt.Core.Types;
using NAnt.Core.Util;
namespace NAnt.Core.Functions {
[FunctionSet("pkg-config", "Unix/Cygwin")]
public class PkgConfigFunctions : FunctionSetBase {
#region Public Instance Constructors
public PkgConfigFunctions(Project project, PropertyDictionary properties) : base(project, properties) {
}
#endregion Public Instance Constructors
#region Public Instance Methods
///
/// Gets the value of a variable for the specified package.
///
/// The package for which the variable should be retrieved.
/// The name of the variable.
///
/// The value of variable for the specified
/// package.
///
/// pkg-config could not be started.
/// does not exist.
[Function("get-variable")]
public string GetVariable(string package, string name) {
if (!Exists(package)) {
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA1100"), package));
}
return RunPkgConfigString(new Argument[] { new Argument("--variable=\"" + name + "\""),
new Argument(package) });
}
///
/// Gets the link flags required to compile the package, including all
/// its dependencies.
///
/// The package for which the link flags should be retrieved.
///
/// The link flags required to compile the package.
///
/// pkg-config could not be started.
/// does not exist.
[Function("get-link-flags")]
public string GetLinkFlags(string package) {
if (!Exists(package)) {
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA1100"), package));
}
return RunPkgConfigString(new Argument[] { new Argument("--libs"),
new Argument(package) });
}
///
/// Gets the compile flags required to compile the package, including all
/// its dependencies.
///
/// The package for which the compile flags should be retrieved.
///
/// The pre-processor and compile flags required to compile the package.
///
/// pkg-config could not be started.
/// does not exist.
[Function("get-compile-flags")]
public string GetCompileFlags(string package) {
if (!Exists(package)) {
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA1100"), package));
}
return RunPkgConfigString(new Argument[] { new Argument("--cflags"),
new Argument(package) });
}
///
/// Determines the version of the given package.
///
/// The package to get the version of.
///
/// The version of the given package.
///
/// pkg-config could not be started.
/// does not exist.
[Function("get-mod-version")]
public string GetModVersion(string package) {
if (!Exists(package)) {
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA1100"), package));
}
return RunPkgConfigString( new Argument[]{ new Argument("--modversion"),
new Argument(package) });
}
///
/// Determines whether the given package is at least version
/// .
///
/// The package to check.
/// The version the package should at least have.
///
/// if the given package is at least version
/// ; otherwise, .
///
/// pkg-config could not be started.
[Function("is-atleast-version")]
public bool IsAtLeastVersion(string package, string version) {
return RunPkgConfigBool( new Argument[]{ new Argument("--atleast-version=\"" + version + "\""),
new Argument(package) });
}
///
/// Determines whether the given package is exactly version
/// .
///
/// The package to check.
/// The version the package should have.
///
/// if the given package is exactly version
/// ; otherwise, .
///
/// pkg-config could not be started.
[Function("is-exact-version")]
public bool IsExactVersion(string package, string version) {
return RunPkgConfigBool( new Argument[]{ new Argument("--exact-version=\"" + version + "\""),
new Argument(package)});
}
///
/// Determines whether the given package is at no newer than version
/// .
///
/// The package to check.
/// The version the package should maximum have.
///
/// if the given package is at no newer than
/// version ; otherwise, .
///
/// pkg-config could not be started.
[Function("is-max-version")]
public bool IsMaxVersion(string package, string version) {
return RunPkgConfigBool( new Argument[]{ new Argument("--max-version=\"" + version + "\""),
new Argument(package) });
}
///
/// Determines whether the given package is between two versions.
///
/// The package to check.
/// The version the package should at least have.
/// The version the package should maximum have.
///
/// if the given package is between
/// and ; otherwise, .
///
/// pkg-config could not be started.
[Function("is-between-version")]
public bool IsBetweenVersion(string package, string minVersion, string maxVersion) {
return RunPkgConfigBool( new Argument[]{ new Argument("--atleast-version=\"" + minVersion + "\""),
new Argument("--max-version=\"" + maxVersion + "\""),
new Argument(package)
} );
}
///
/// Determines whether the given package exists.
///
/// The package to check.
///
/// if the package exists; otherwise,
/// .
///
/// pkg-config could not be started.
[Function("exists")]
public bool Exists(string package) {
return RunPkgConfigBool( new Argument[]{ new Argument("--exists"), new Argument(package)} );
}
#endregion Public Instance Methods
#region Private Instance Methods
///
/// Runs pkg-config with the specified arguments and returns a
/// based on the exit code.
///
/// The arguments to pass to pkg-config.
///
/// if pkg-config exited with exit code 0;
/// otherwise,
///
private bool RunPkgConfigBool(Argument[] args) {
MemoryStream ms = new MemoryStream();
ExecTask execTask = GetTask(ms);
execTask.Arguments.AddRange(args);
try {
execTask.Execute();
return true;
} catch (Exception) {
if (execTask.ExitCode == ExternalProgramBase.UnknownExitCode) {
// process could not be started or did not exit in time
throw;
}
return false;
}
}
///
/// Runs pkg-config with the specified arguments and returns the result
/// as a .
///
/// The arguments to pass to pkg-config.
///
/// The result of running pkg-config with the specified arguments.
///
private string RunPkgConfigString(Argument[] args) {
MemoryStream ms = new MemoryStream();
ExecTask execTask = GetTask(ms);
execTask.Arguments.AddRange(args);
try {
execTask.Execute();
ms.Position = 0;
StreamReader sr = new StreamReader(ms);
string output = sr.ReadLine();
sr.Close();
return output;
} catch (Exception ex) {
ms.Position = 0;
StreamReader sr = new StreamReader(ms);
string output = sr.ReadToEnd();
sr.Close();
if (output.Length != 0) {
throw new BuildException(output, ex);
} else {
throw;
}
}
}
///
/// Factory method to return a new instance of ExecTask
///
///
///
private ExecTask GetTask(Stream stream) {
ExecTask execTask = new ExecTask();
execTask.Parent = Project;
execTask.Project = Project;
execTask.FileName = "pkg-config";
execTask.Threshold = Level.None;
execTask.ErrorWriter = execTask.OutputWriter = new StreamWriter(stream);
return execTask;
}
#endregion Private Instance Methods
}
}