// 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 } }