AutotoolsTarget.cs 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070
  1. #region BSD License
  2. /*
  3. Copyright (c) 2004 - 2008
  4. Matthew Holmes ([email protected]),
  5. Dan Moorehead ([email protected]),
  6. Dave Hudson ([email protected]),
  7. C.J. Adams-Collier ([email protected]),
  8. Redistribution and use in source and binary forms, with or without
  9. modification, are permitted provided that the following conditions are
  10. met:
  11. * Redistributions of source code must retain the above copyright
  12. notice, this list of conditions and the following disclaimer.
  13. * Redistributions in binary form must reproduce the above copyright
  14. notice, this list of conditions and the following disclaimer in the
  15. documentation and/or other materials provided with the distribution.
  16. * The name of the author may not be used to endorse or promote
  17. products derived from this software without specific prior written
  18. permission.
  19. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  20. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  23. INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  25. SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  27. STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  28. IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29. POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #endregion
  32. #region MIT X11 license
  33. /*
  34. Portions of this file authored by Lluis Sanchez Gual
  35. Copyright (C) 2006 Novell, Inc (http://www.novell.com)
  36. Permission is hereby granted, free of charge, to any person obtaining
  37. a copy of this software and associated documentation files (the
  38. "Software"), to deal in the Software without restriction, including
  39. without limitation the rights to use, copy, modify, merge, publish,
  40. distribute, sublicense, and/or sell copies of the Software, and to
  41. permit persons to whom the Software is furnished to do so, subject to
  42. the following conditions:
  43. The above copyright notice and this permission notice shall be
  44. included in all copies or substantial portions of the Software.
  45. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  46. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  47. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  48. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  49. LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  50. OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  51. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  52. */
  53. #endregion
  54. using System;
  55. using System.Collections.Generic;
  56. using System.IO;
  57. using System.Reflection;
  58. using System.Text;
  59. using System.Text.RegularExpressions;
  60. using System.Xml;
  61. using System.Xml.Xsl;
  62. using System.Net;
  63. using System.Diagnostics;
  64. using Prebuild.Core.Attributes;
  65. using Prebuild.Core.Interfaces;
  66. using Prebuild.Core.Nodes;
  67. using Prebuild.Core.Utilities;
  68. namespace Prebuild.Core.Targets
  69. {
  70. public enum ClrVersion
  71. {
  72. Default,
  73. Net_1_1,
  74. Net_2_0
  75. }
  76. public class SystemPackage
  77. {
  78. string name;
  79. string version;
  80. string description;
  81. string[] assemblies;
  82. bool isInternal;
  83. ClrVersion targetVersion;
  84. public void Initialize(string name,
  85. string version,
  86. string description,
  87. string[] assemblies,
  88. ClrVersion targetVersion,
  89. bool isInternal)
  90. {
  91. this.isInternal = isInternal;
  92. this.name = name;
  93. this.version = version;
  94. this.assemblies = assemblies;
  95. this.description = description;
  96. this.targetVersion = targetVersion;
  97. }
  98. public string Name
  99. {
  100. get { return name; }
  101. }
  102. public string Version
  103. {
  104. get { return version; }
  105. }
  106. public string Description
  107. {
  108. get { return description; }
  109. }
  110. public ClrVersion TargetVersion
  111. {
  112. get { return targetVersion; }
  113. }
  114. // The package is part of the mono SDK
  115. public bool IsCorePackage
  116. {
  117. get { return name == "mono"; }
  118. }
  119. // The package has been registered by an add-in, and is not installed
  120. // in the system.
  121. public bool IsInternalPackage
  122. {
  123. get { return isInternal; }
  124. }
  125. public string[] Assemblies
  126. {
  127. get { return assemblies; }
  128. }
  129. }
  130. /// <summary>
  131. ///
  132. /// </summary>
  133. [Target("autotools")]
  134. public class AutotoolsTarget : ITarget
  135. {
  136. #region Fields
  137. Kernel m_Kernel;
  138. XmlDocument autotoolsDoc;
  139. XmlUrlResolver xr;
  140. System.Security.Policy.Evidence e;
  141. readonly Dictionary<string, SystemPackage> assemblyPathToPackage = new Dictionary<string, SystemPackage>();
  142. readonly Dictionary<string, string> assemblyFullNameToPath = new Dictionary<string, string>();
  143. readonly Dictionary<string, SystemPackage> packagesHash = new Dictionary<string, SystemPackage>();
  144. readonly List<SystemPackage> packages = new List<SystemPackage>();
  145. #endregion
  146. #region Private Methods
  147. private static void mkdirDashP(string dirName)
  148. {
  149. DirectoryInfo di = new DirectoryInfo(dirName);
  150. if (di.Exists)
  151. return;
  152. string parentDirName = System.IO.Path.GetDirectoryName(dirName);
  153. DirectoryInfo parentDi = new DirectoryInfo(parentDirName);
  154. if (!parentDi.Exists)
  155. mkdirDashP(parentDirName);
  156. di.Create();
  157. }
  158. private static void chkMkDir(string dirName)
  159. {
  160. System.IO.DirectoryInfo di =
  161. new System.IO.DirectoryInfo(dirName);
  162. if (!di.Exists)
  163. di.Create();
  164. }
  165. private void transformToFile(string filename, XsltArgumentList argList, string nodeName)
  166. {
  167. // Create an XslTransform for this file
  168. XslTransform templateTransformer =
  169. new XslTransform();
  170. // Load up the template
  171. XmlNode templateNode =
  172. autotoolsDoc.SelectSingleNode(nodeName + "/*");
  173. templateTransformer.Load(templateNode.CreateNavigator(), xr, e);
  174. // Create a writer for the transformed template
  175. XmlTextWriter templateWriter =
  176. new XmlTextWriter(filename, null);
  177. // Perform transformation, writing the file
  178. templateTransformer.Transform
  179. (m_Kernel.CurrentDoc, argList, templateWriter, xr);
  180. }
  181. static string NormalizeAsmName(string name)
  182. {
  183. int i = name.IndexOf(", PublicKeyToken=null");
  184. if (i != -1)
  185. return name.Substring(0, i).Trim();
  186. return name;
  187. }
  188. private void AddAssembly(string assemblyfile, SystemPackage package)
  189. {
  190. if (!File.Exists(assemblyfile))
  191. return;
  192. try
  193. {
  194. System.Reflection.AssemblyName an = System.Reflection.AssemblyName.GetAssemblyName(assemblyfile);
  195. assemblyFullNameToPath[NormalizeAsmName(an.FullName)] = assemblyfile;
  196. assemblyPathToPackage[assemblyfile] = package;
  197. }
  198. catch
  199. {
  200. }
  201. }
  202. private static List<string> GetAssembliesWithLibInfo(string line, string file)
  203. {
  204. List<string> references = new List<string>();
  205. List<string> libdirs = new List<string>();
  206. List<string> retval = new List<string>();
  207. foreach (string piece in line.Split(' '))
  208. {
  209. if (piece.ToLower().Trim().StartsWith("/r:") || piece.ToLower().Trim().StartsWith("-r:"))
  210. {
  211. references.Add(ProcessPiece(piece.Substring(3).Trim(), file));
  212. }
  213. else if (piece.ToLower().Trim().StartsWith("/lib:") || piece.ToLower().Trim().StartsWith("-lib:"))
  214. {
  215. libdirs.Add(ProcessPiece(piece.Substring(5).Trim(), file));
  216. }
  217. }
  218. foreach (string refrnc in references)
  219. {
  220. foreach (string libdir in libdirs)
  221. {
  222. if (File.Exists(libdir + Path.DirectorySeparatorChar + refrnc))
  223. {
  224. retval.Add(libdir + Path.DirectorySeparatorChar + refrnc);
  225. }
  226. }
  227. }
  228. return retval;
  229. }
  230. private static List<string> GetAssembliesWithoutLibInfo(string line, string file)
  231. {
  232. List<string> references = new List<string>();
  233. foreach (string reference in line.Split(' '))
  234. {
  235. if (reference.ToLower().Trim().StartsWith("/r:") || reference.ToLower().Trim().StartsWith("-r:"))
  236. {
  237. string final_ref = reference.Substring(3).Trim();
  238. references.Add(ProcessPiece(final_ref, file));
  239. }
  240. }
  241. return references;
  242. }
  243. private static string ProcessPiece(string piece, string pcfile)
  244. {
  245. int start = piece.IndexOf("${");
  246. if (start == -1)
  247. return piece;
  248. int end = piece.IndexOf("}");
  249. if (end == -1)
  250. return piece;
  251. string variable = piece.Substring(start + 2, end - start - 2);
  252. string interp = GetVariableFromPkgConfig(variable, Path.GetFileNameWithoutExtension(pcfile));
  253. return ProcessPiece(piece.Replace("${" + variable + "}", interp), pcfile);
  254. }
  255. private static string GetVariableFromPkgConfig(string var, string pcfile)
  256. {
  257. ProcessStartInfo psi = new ProcessStartInfo("pkg-config");
  258. psi.RedirectStandardOutput = true;
  259. psi.UseShellExecute = false;
  260. psi.Arguments = String.Format("--variable={0} {1}", var, pcfile);
  261. Process p = new Process();
  262. p.StartInfo = psi;
  263. p.Start();
  264. string ret = p.StandardOutput.ReadToEnd().Trim();
  265. p.WaitForExit();
  266. if (String.IsNullOrEmpty(ret))
  267. return String.Empty;
  268. return ret;
  269. }
  270. private void ParsePCFile(string pcfile)
  271. {
  272. // Don't register the package twice
  273. string pname = Path.GetFileNameWithoutExtension(pcfile);
  274. if (packagesHash.ContainsKey(pname))
  275. return;
  276. List<string> fullassemblies = null;
  277. string version = "";
  278. string desc = "";
  279. SystemPackage package = new SystemPackage();
  280. using (StreamReader reader = new StreamReader(pcfile))
  281. {
  282. string line;
  283. while ((line = reader.ReadLine()) != null)
  284. {
  285. string lowerLine = line.ToLower();
  286. if (lowerLine.StartsWith("libs:") && lowerLine.IndexOf(".dll") != -1)
  287. {
  288. string choppedLine = line.Substring(5).Trim();
  289. if (choppedLine.IndexOf("-lib:") != -1 || choppedLine.IndexOf("/lib:") != -1)
  290. {
  291. fullassemblies = GetAssembliesWithLibInfo(choppedLine, pcfile);
  292. }
  293. else
  294. {
  295. fullassemblies = GetAssembliesWithoutLibInfo(choppedLine, pcfile);
  296. }
  297. }
  298. else if (lowerLine.StartsWith("version:"))
  299. {
  300. // "version:".Length == 8
  301. version = line.Substring(8).Trim();
  302. }
  303. else if (lowerLine.StartsWith("description:"))
  304. {
  305. // "description:".Length == 12
  306. desc = line.Substring(12).Trim();
  307. }
  308. }
  309. }
  310. if (fullassemblies == null)
  311. return;
  312. foreach (string assembly in fullassemblies)
  313. {
  314. AddAssembly(assembly, package);
  315. }
  316. package.Initialize(pname,
  317. version,
  318. desc,
  319. fullassemblies.ToArray(),
  320. ClrVersion.Default,
  321. false);
  322. packages.Add(package);
  323. packagesHash[pname] = package;
  324. }
  325. void RegisterSystemAssemblies(string prefix, string version, ClrVersion ver)
  326. {
  327. SystemPackage package = new SystemPackage();
  328. List<string> list = new List<string>();
  329. string dir = Path.Combine(prefix, version);
  330. if (!Directory.Exists(dir))
  331. {
  332. return;
  333. }
  334. foreach (string assembly in Directory.GetFiles(dir, "*.dll"))
  335. {
  336. AddAssembly(assembly, package);
  337. list.Add(assembly);
  338. }
  339. package.Initialize("mono",
  340. version,
  341. "The Mono runtime",
  342. list.ToArray(),
  343. ver,
  344. false);
  345. packages.Add(package);
  346. }
  347. void RunInitialization()
  348. {
  349. string versionDir;
  350. if (Environment.Version.Major == 1)
  351. {
  352. versionDir = "1.0";
  353. }
  354. else
  355. {
  356. versionDir = "2.0";
  357. }
  358. //Pull up assemblies from the installed mono system.
  359. string prefix = Path.GetDirectoryName(typeof(int).Assembly.Location);
  360. if (prefix.IndexOf(Path.Combine("mono", versionDir)) == -1)
  361. prefix = Path.Combine(prefix, "mono");
  362. else
  363. prefix = Path.GetDirectoryName(prefix);
  364. RegisterSystemAssemblies(prefix, "1.0", ClrVersion.Net_1_1);
  365. RegisterSystemAssemblies(prefix, "2.0", ClrVersion.Net_2_0);
  366. string search_dirs = Environment.GetEnvironmentVariable("PKG_CONFIG_PATH");
  367. string libpath = Environment.GetEnvironmentVariable("PKG_CONFIG_LIBPATH");
  368. if (String.IsNullOrEmpty(libpath))
  369. {
  370. string path_dirs = Environment.GetEnvironmentVariable("PATH");
  371. foreach (string pathdir in path_dirs.Split(Path.PathSeparator))
  372. {
  373. if (pathdir == null)
  374. continue;
  375. if (File.Exists(pathdir + Path.DirectorySeparatorChar + "pkg-config"))
  376. {
  377. libpath = Path.Combine(pathdir, "..");
  378. libpath = Path.Combine(libpath, "lib");
  379. libpath = Path.Combine(libpath, "pkgconfig");
  380. break;
  381. }
  382. }
  383. }
  384. search_dirs += Path.PathSeparator + libpath;
  385. if (!string.IsNullOrEmpty(search_dirs))
  386. {
  387. List<string> scanDirs = new List<string>();
  388. foreach (string potentialDir in search_dirs.Split(Path.PathSeparator))
  389. {
  390. if (!scanDirs.Contains(potentialDir))
  391. scanDirs.Add(potentialDir);
  392. }
  393. foreach (string pcdir in scanDirs)
  394. {
  395. if (pcdir == null)
  396. continue;
  397. if (Directory.Exists(pcdir))
  398. {
  399. foreach (string pcfile in Directory.GetFiles(pcdir, "*.pc"))
  400. {
  401. ParsePCFile(pcfile);
  402. }
  403. }
  404. }
  405. }
  406. }
  407. private void WriteCombine(SolutionNode solution)
  408. {
  409. #region "Create Solution directory if it doesn't exist"
  410. string solutionDir = Path.Combine(solution.FullPath,
  411. Path.Combine("autotools",
  412. solution.Name));
  413. chkMkDir(solutionDir);
  414. #endregion
  415. #region "Write Solution-level files"
  416. XsltArgumentList argList = new XsltArgumentList();
  417. argList.AddParam("solutionName", "", solution.Name);
  418. // $solutionDir is $rootDir/$solutionName/
  419. transformToFile(Path.Combine(solutionDir, "configure.ac"),
  420. argList, "/Autotools/SolutionConfigureAc");
  421. transformToFile(Path.Combine(solutionDir, "Makefile.am"),
  422. argList, "/Autotools/SolutionMakefileAm");
  423. transformToFile(Path.Combine(solutionDir, "autogen.sh"),
  424. argList, "/Autotools/SolutionAutogenSh");
  425. #endregion
  426. foreach (ProjectNode project in solution.ProjectsTableOrder)
  427. {
  428. m_Kernel.Log.Write(String.Format("Writing project: {0}",
  429. project.Name));
  430. WriteProject(solution, project);
  431. }
  432. }
  433. private static string FindFileReference(string refName,
  434. ProjectNode project)
  435. {
  436. foreach (ReferencePathNode refPath in project.ReferencePaths)
  437. {
  438. string fullPath =
  439. Helper.MakeFilePath(refPath.Path, refName, "dll");
  440. if (File.Exists(fullPath)) {
  441. return fullPath;
  442. }
  443. }
  444. return null;
  445. }
  446. /// <summary>
  447. /// Gets the XML doc file.
  448. /// </summary>
  449. /// <param name="project">The project.</param>
  450. /// <param name="conf">The conf.</param>
  451. /// <returns></returns>
  452. public static string GetXmlDocFile(ProjectNode project, ConfigurationNode conf)
  453. {
  454. if (conf == null)
  455. {
  456. throw new ArgumentNullException("conf");
  457. }
  458. if (project == null)
  459. {
  460. throw new ArgumentNullException("project");
  461. }
  462. string docFile = (string)conf.Options["XmlDocFile"];
  463. // if(docFile != null && docFile.Length == 0)//default to assembly name if not specified
  464. // {
  465. // return Path.GetFileNameWithoutExtension(project.AssemblyName) + ".xml";
  466. // }
  467. return docFile;
  468. }
  469. /// <summary>
  470. /// Normalizes the path.
  471. /// </summary>
  472. /// <param name="path">The path.</param>
  473. /// <returns></returns>
  474. public static string NormalizePath(string path)
  475. {
  476. if (path == null)
  477. {
  478. return "";
  479. }
  480. StringBuilder tmpPath;
  481. if (Core.Parse.Preprocessor.GetOS() == "Win32")
  482. {
  483. tmpPath = new StringBuilder(path.Replace('\\', '/'));
  484. tmpPath.Replace("/", @"\\");
  485. }
  486. else
  487. {
  488. tmpPath = new StringBuilder(path.Replace('\\', '/'));
  489. tmpPath = tmpPath.Replace('/', Path.DirectorySeparatorChar);
  490. }
  491. return tmpPath.ToString();
  492. }
  493. private void WriteProject(SolutionNode solution, ProjectNode project)
  494. {
  495. string solutionDir = Path.Combine(solution.FullPath, Path.Combine("autotools", solution.Name));
  496. string projectDir = Path.Combine(solutionDir, project.Name);
  497. string projectVersion = project.Version;
  498. bool hasAssemblyConfig = false;
  499. chkMkDir(projectDir);
  500. List<string>
  501. compiledFiles = new List<string>(),
  502. contentFiles = new List<string>(),
  503. embeddedFiles = new List<string>(),
  504. binaryLibs = new List<string>(),
  505. pkgLibs = new List<string>(),
  506. systemLibs = new List<string>(),
  507. runtimeLibs = new List<string>(),
  508. extraDistFiles = new List<string>(),
  509. localCopyTargets = new List<string>();
  510. // If there exists a .config file for this assembly, copy
  511. // it to the project folder
  512. // TODO: Support copying .config.osx files
  513. // TODO: support processing the .config file for native library deps
  514. string projectAssemblyName = project.Name;
  515. if (project.AssemblyName != null)
  516. projectAssemblyName = project.AssemblyName;
  517. if (File.Exists(Path.Combine(project.FullPath, projectAssemblyName) + ".dll.config"))
  518. {
  519. hasAssemblyConfig = true;
  520. System.IO.File.Copy(Path.Combine(project.FullPath, projectAssemblyName + ".dll.config"), Path.Combine(projectDir, projectAssemblyName + ".dll.config"), true);
  521. extraDistFiles.Add(project.AssemblyName + ".dll.config");
  522. }
  523. foreach (ConfigurationNode conf in project.Configurations)
  524. {
  525. if (conf.Options.KeyFile != string.Empty)
  526. {
  527. // Copy snk file into the project's directory
  528. // Use the snk from the project directory directly
  529. string source = Path.Combine(project.FullPath, conf.Options.KeyFile);
  530. string keyFile = conf.Options.KeyFile;
  531. Regex re = new Regex(".*/");
  532. keyFile = re.Replace(keyFile, "");
  533. string dest = Path.Combine(projectDir, keyFile);
  534. // Tell the user if there's a problem copying the file
  535. try
  536. {
  537. mkdirDashP(System.IO.Path.GetDirectoryName(dest));
  538. System.IO.File.Copy(source, dest, true);
  539. }
  540. catch (System.IO.IOException e)
  541. {
  542. Console.WriteLine(e.Message);
  543. }
  544. }
  545. }
  546. // Copy compiled, embedded and content files into the project's directory
  547. foreach (string filename in project.Files)
  548. {
  549. string source = Path.Combine(project.FullPath, filename);
  550. string dest = Path.Combine(projectDir, filename);
  551. if (filename.Contains("AssemblyInfo.cs"))
  552. {
  553. // If we've got an AssemblyInfo.cs, pull the version number from it
  554. string[] sources = { source };
  555. string[] args = { "" };
  556. Microsoft.CSharp.CSharpCodeProvider cscp =
  557. new Microsoft.CSharp.CSharpCodeProvider();
  558. string tempAssemblyFile = Path.Combine(Path.GetTempPath(), project.Name + "-temp.dll");
  559. System.CodeDom.Compiler.CompilerParameters cparam =
  560. new System.CodeDom.Compiler.CompilerParameters(args, tempAssemblyFile);
  561. System.CodeDom.Compiler.CompilerResults cr =
  562. cscp.CompileAssemblyFromFile(cparam, sources);
  563. foreach (System.CodeDom.Compiler.CompilerError error in cr.Errors)
  564. Console.WriteLine("Error! '{0}'", error.ErrorText);
  565. try {
  566. string projectFullName = cr.CompiledAssembly.FullName;
  567. Regex verRegex = new Regex("Version=([\\d\\.]+)");
  568. Match verMatch = verRegex.Match(projectFullName);
  569. if (verMatch.Success)
  570. projectVersion = verMatch.Groups[1].Value;
  571. }catch{
  572. Console.WriteLine("Couldn't compile AssemblyInfo.cs");
  573. }
  574. // Clean up the temp file
  575. try
  576. {
  577. if (File.Exists(tempAssemblyFile))
  578. File.Delete(tempAssemblyFile);
  579. }
  580. catch
  581. {
  582. Console.WriteLine("Error! '{0}'", e);
  583. }
  584. }
  585. // Tell the user if there's a problem copying the file
  586. try
  587. {
  588. mkdirDashP(System.IO.Path.GetDirectoryName(dest));
  589. System.IO.File.Copy(source, dest, true);
  590. }
  591. catch (System.IO.IOException e)
  592. {
  593. Console.WriteLine(e.Message);
  594. }
  595. switch (project.Files.GetBuildAction(filename))
  596. {
  597. case BuildAction.Compile:
  598. compiledFiles.Add(filename);
  599. break;
  600. case BuildAction.Content:
  601. contentFiles.Add(filename);
  602. extraDistFiles.Add(filename);
  603. break;
  604. case BuildAction.EmbeddedResource:
  605. embeddedFiles.Add(filename);
  606. break;
  607. }
  608. }
  609. // Set up references
  610. for (int refNum = 0; refNum < project.References.Count; refNum++)
  611. {
  612. ReferenceNode refr = project.References[refNum];
  613. Assembly refAssembly = Assembly.LoadWithPartialName(refr.Name);
  614. /* Determine which pkg-config (.pc) file refers to
  615. this assembly */
  616. SystemPackage package = null;
  617. if (packagesHash.ContainsKey(refr.Name))
  618. {
  619. package = packagesHash[refr.Name];
  620. }
  621. else
  622. {
  623. string assemblyFullName = string.Empty;
  624. if (refAssembly != null)
  625. assemblyFullName = refAssembly.FullName;
  626. string assemblyFileName = string.Empty;
  627. if (assemblyFullName != string.Empty &&
  628. assemblyFullNameToPath.ContainsKey(assemblyFullName)
  629. )
  630. assemblyFileName =
  631. assemblyFullNameToPath[assemblyFullName];
  632. if (assemblyFileName != string.Empty &&
  633. assemblyPathToPackage.ContainsKey(assemblyFileName)
  634. )
  635. package = assemblyPathToPackage[assemblyFileName];
  636. }
  637. /* If we know the .pc file and it is not "mono"
  638. (already in the path), add a -pkg: argument */
  639. if (package != null &&
  640. package.Name != "mono" &&
  641. !pkgLibs.Contains(package.Name)
  642. )
  643. pkgLibs.Add(package.Name);
  644. string fileRef =
  645. FindFileReference(refr.Name, (ProjectNode)refr.Parent);
  646. if (refr.LocalCopy ||
  647. solution.ProjectsTable.ContainsKey(refr.Name) ||
  648. fileRef != null ||
  649. refr.Path != null
  650. )
  651. {
  652. /* Attempt to copy the referenced lib to the
  653. project's directory */
  654. string filename = refr.Name + ".dll";
  655. string source = filename;
  656. if (refr.Path != null)
  657. source = Path.Combine(refr.Path, source);
  658. source = Path.Combine(project.FullPath, source);
  659. string dest = Path.Combine(projectDir, filename);
  660. /* Since we depend on this binary dll to build, we
  661. * will add a compile- time dependency on the
  662. * copied dll, and add the dll to the list of
  663. * files distributed with this package
  664. */
  665. binaryLibs.Add(refr.Name + ".dll");
  666. extraDistFiles.Add(refr.Name + ".dll");
  667. // TODO: Support copying .config.osx files
  668. // TODO: Support for determining native dependencies
  669. if (File.Exists(source + ".config"))
  670. {
  671. System.IO.File.Copy(source + ".config", Path.GetDirectoryName(dest), true);
  672. extraDistFiles.Add(refr.Name + ".dll.config");
  673. }
  674. try
  675. {
  676. System.IO.File.Copy(source, dest, true);
  677. }
  678. catch (System.IO.IOException)
  679. {
  680. if (solution.ProjectsTable.ContainsKey(refr.Name)){
  681. /* If an assembly is referenced, marked for
  682. * local copy, in the list of projects for
  683. * this solution, but does not exist, put a
  684. * target into the Makefile.am to build the
  685. * assembly and copy it to this project's
  686. * directory
  687. */
  688. ProjectNode sourcePrj =
  689. ((solution.ProjectsTable[refr.Name]));
  690. string target =
  691. String.Format("{0}:\n" +
  692. "\t$(MAKE) -C ../{1}\n" +
  693. "\tln ../{2}/$@ $@\n",
  694. filename,
  695. sourcePrj.Name,
  696. sourcePrj.Name );
  697. localCopyTargets.Add(target);
  698. }
  699. }
  700. }
  701. else if( !pkgLibs.Contains(refr.Name) )
  702. {
  703. // Else, let's assume it's in the GAC or the lib path
  704. string assemName = string.Empty;
  705. int index = refr.Name.IndexOf(",");
  706. if (index > 0)
  707. assemName = refr.Name.Substring(0, index);
  708. else
  709. assemName = refr.Name;
  710. m_Kernel.Log.Write(String.Format(
  711. "Warning: Couldn't find an appropriate assembly " +
  712. "for reference:\n'{0}'", refr.Name
  713. ));
  714. systemLibs.Add(assemName);
  715. }
  716. }
  717. const string lineSep = " \\\n\t";
  718. string compiledFilesString = string.Empty;
  719. if (compiledFiles.Count > 0)
  720. compiledFilesString =
  721. lineSep + string.Join(lineSep, compiledFiles.ToArray());
  722. string embeddedFilesString = "";
  723. if (embeddedFiles.Count > 0)
  724. embeddedFilesString =
  725. lineSep + string.Join(lineSep, embeddedFiles.ToArray());
  726. string contentFilesString = "";
  727. if (contentFiles.Count > 0)
  728. contentFilesString =
  729. lineSep + string.Join(lineSep, contentFiles.ToArray());
  730. string extraDistFilesString = "";
  731. if (extraDistFiles.Count > 0)
  732. extraDistFilesString =
  733. lineSep + string.Join(lineSep, extraDistFiles.ToArray());
  734. string pkgLibsString = "";
  735. if (pkgLibs.Count > 0)
  736. pkgLibsString =
  737. lineSep + string.Join(lineSep, pkgLibs.ToArray());
  738. string binaryLibsString = "";
  739. if (binaryLibs.Count > 0)
  740. binaryLibsString =
  741. lineSep + string.Join(lineSep, binaryLibs.ToArray());
  742. string systemLibsString = "";
  743. if (systemLibs.Count > 0)
  744. systemLibsString =
  745. lineSep + string.Join(lineSep, systemLibs.ToArray());
  746. string localCopyTargetsString = "";
  747. if (localCopyTargets.Count > 0)
  748. localCopyTargetsString =
  749. string.Join("\n", localCopyTargets.ToArray());
  750. string monoPath = "";
  751. foreach (string runtimeLib in runtimeLibs)
  752. {
  753. monoPath += ":`pkg-config --variable=libdir " + runtimeLib + "`";
  754. }
  755. // Add the project name to the list of transformation
  756. // parameters
  757. XsltArgumentList argList = new XsltArgumentList();
  758. argList.AddParam("projectName", "", project.Name);
  759. argList.AddParam("solutionName", "", solution.Name);
  760. argList.AddParam("assemblyName", "", projectAssemblyName);
  761. argList.AddParam("compiledFiles", "", compiledFilesString);
  762. argList.AddParam("embeddedFiles", "", embeddedFilesString);
  763. argList.AddParam("contentFiles", "", contentFilesString);
  764. argList.AddParam("extraDistFiles", "", extraDistFilesString);
  765. argList.AddParam("pkgLibs", "", pkgLibsString);
  766. argList.AddParam("binaryLibs", "", binaryLibsString);
  767. argList.AddParam("systemLibs", "", systemLibsString);
  768. argList.AddParam("monoPath", "", monoPath);
  769. argList.AddParam("localCopyTargets", "", localCopyTargetsString);
  770. argList.AddParam("projectVersion", "", projectVersion);
  771. argList.AddParam("hasAssemblyConfig", "", hasAssemblyConfig ? "true" : "");
  772. // Transform the templates
  773. transformToFile(Path.Combine(projectDir, "configure.ac"), argList, "/Autotools/ProjectConfigureAc");
  774. transformToFile(Path.Combine(projectDir, "Makefile.am"), argList, "/Autotools/ProjectMakefileAm");
  775. transformToFile(Path.Combine(projectDir, "autogen.sh"), argList, "/Autotools/ProjectAutogenSh");
  776. if (project.Type == Core.Nodes.ProjectType.Library)
  777. transformToFile(Path.Combine(projectDir, project.Name + ".pc.in"), argList, "/Autotools/ProjectPcIn");
  778. if (project.Type == Core.Nodes.ProjectType.Exe || project.Type == Core.Nodes.ProjectType.WinExe)
  779. transformToFile(Path.Combine(projectDir, project.Name.ToLower() + ".in"), argList, "/Autotools/ProjectWrapperScriptIn");
  780. }
  781. private void CleanProject(ProjectNode project)
  782. {
  783. m_Kernel.Log.Write("...Cleaning project: {0}", project.Name);
  784. string projectFile = Helper.MakeFilePath(project.FullPath, "Include", "am");
  785. Helper.DeleteIfExists(projectFile);
  786. }
  787. private void CleanSolution(SolutionNode solution)
  788. {
  789. m_Kernel.Log.Write("Cleaning Autotools make files for", solution.Name);
  790. string slnFile = Helper.MakeFilePath(solution.FullPath, "Makefile", "am");
  791. Helper.DeleteIfExists(slnFile);
  792. slnFile = Helper.MakeFilePath(solution.FullPath, "Makefile", "in");
  793. Helper.DeleteIfExists(slnFile);
  794. slnFile = Helper.MakeFilePath(solution.FullPath, "configure", "ac");
  795. Helper.DeleteIfExists(slnFile);
  796. slnFile = Helper.MakeFilePath(solution.FullPath, "configure");
  797. Helper.DeleteIfExists(slnFile);
  798. slnFile = Helper.MakeFilePath(solution.FullPath, "Makefile");
  799. Helper.DeleteIfExists(slnFile);
  800. foreach (ProjectNode project in solution.Projects)
  801. {
  802. CleanProject(project);
  803. }
  804. m_Kernel.Log.Write("");
  805. }
  806. #endregion
  807. #region ITarget Members
  808. /// <summary>
  809. /// Writes the specified kern.
  810. /// </summary>
  811. /// <param name="kern">The kern.</param>
  812. public void Write(Kernel kern)
  813. {
  814. if (kern == null)
  815. {
  816. throw new ArgumentNullException("kern");
  817. }
  818. m_Kernel = kern;
  819. m_Kernel.Log.Write("Parsing system pkg-config files");
  820. RunInitialization();
  821. const string streamName = "autotools.xml";
  822. string fqStreamName = String.Format("Prebuild.data.{0}",
  823. streamName
  824. );
  825. // Retrieve stream for the autotools template XML
  826. Stream autotoolsStream = Assembly.GetExecutingAssembly()
  827. .GetManifestResourceStream(fqStreamName);
  828. if(autotoolsStream == null) {
  829. /*
  830. * try without the default namespace prepended, in
  831. * case prebuild.exe assembly was compiled with
  832. * something other than Visual Studio .NET
  833. */
  834. autotoolsStream = Assembly.GetExecutingAssembly()
  835. .GetManifestResourceStream(streamName);
  836. if(autotoolsStream == null){
  837. string errStr =
  838. String.Format("Could not find embedded resource file:\n" +
  839. "'{0}' or '{1}'",
  840. streamName, fqStreamName
  841. );
  842. m_Kernel.Log.Write(errStr);
  843. throw new System.Reflection.TargetException(errStr);
  844. }
  845. }
  846. // Create an XML URL Resolver with default credentials
  847. xr = new System.Xml.XmlUrlResolver();
  848. xr.Credentials = CredentialCache.DefaultCredentials;
  849. // Create a default evidence - no need to limit access
  850. e = new System.Security.Policy.Evidence();
  851. // Load the autotools XML
  852. autotoolsDoc = new XmlDocument();
  853. autotoolsDoc.Load(autotoolsStream);
  854. /* rootDir is the filesystem location where the Autotools
  855. * build tree will be created - for now we'll make it
  856. * $PWD/autotools
  857. */
  858. string pwd = Directory.GetCurrentDirectory();
  859. //string pwd = System.Environment.GetEnvironmentVariable("PWD");
  860. //if (pwd.Length != 0)
  861. //{
  862. string rootDir = Path.Combine(pwd, "autotools");
  863. //}
  864. //else
  865. //{
  866. // pwd = Assembly.GetExecutingAssembly()
  867. //}
  868. chkMkDir(rootDir);
  869. foreach (SolutionNode solution in kern.Solutions)
  870. {
  871. m_Kernel.Log.Write(String.Format("Writing solution: {0}",
  872. solution.Name));
  873. WriteCombine(solution);
  874. }
  875. m_Kernel = null;
  876. }
  877. /// <summary>
  878. /// Cleans the specified kern.
  879. /// </summary>
  880. /// <param name="kern">The kern.</param>
  881. public virtual void Clean(Kernel kern)
  882. {
  883. if (kern == null)
  884. {
  885. throw new ArgumentNullException("kern");
  886. }
  887. m_Kernel = kern;
  888. foreach (SolutionNode sol in kern.Solutions)
  889. {
  890. CleanSolution(sol);
  891. }
  892. m_Kernel = null;
  893. }
  894. /// <summary>
  895. /// Gets the name.
  896. /// </summary>
  897. /// <value>The name.</value>
  898. public string Name
  899. {
  900. get
  901. {
  902. return "autotools";
  903. }
  904. }
  905. #endregion
  906. }
  907. }