BuildContext.bf 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073
  1. using System.Collections.Generic;
  2. using System;
  3. using IDE.Compiler;
  4. using System.IO;
  5. using System.Diagnostics;
  6. using Beefy;
  7. using IDE.util;
  8. namespace IDE
  9. {
  10. class BuildContext
  11. {
  12. public Project mHotProject;
  13. public Workspace.Options mWorkspaceOptions;
  14. public Dictionary<Project, String> mImpLibMap = new .() ~
  15. {
  16. for (let val in _.Values)
  17. delete val;
  18. delete _;
  19. };
  20. public ScriptManager mScriptManager ~ delete _;
  21. public bool Failed
  22. {
  23. get
  24. {
  25. if (mScriptManager != null)
  26. return mScriptManager.mFailed;
  27. return false;
  28. }
  29. }
  30. public enum CustomBuildCommandResult
  31. {
  32. NoCommands,
  33. HadCommands,
  34. Failed
  35. }
  36. public CustomBuildCommandResult QueueProjectCustomBuildCommands(Project project, String targetPath, Project.BuildCommandTrigger trigger, List<String> cmdList)
  37. {
  38. if (cmdList.IsEmpty)
  39. return .NoCommands;
  40. if (trigger == .Never)
  41. return .NoCommands;
  42. if ((trigger == .IfFilesChanged) && (!project.mForceCustomCommands))
  43. {
  44. int64 highestDateTime = 0;
  45. int64 targetDateTime = File.GetLastWriteTime(targetPath).Get().ToFileTime();
  46. bool forceRebuild = false;
  47. for (var depName in project.mDependencies)
  48. {
  49. var depProject = gApp.mWorkspace.FindProject(depName.mProjectName);
  50. if (depProject != null)
  51. {
  52. if (depProject.mLastDidBuild)
  53. forceRebuild = true;
  54. }
  55. }
  56. project.WithProjectItems(scope [&] (projectItem) =>
  57. {
  58. var projectSource = projectItem as ProjectSource;
  59. var importPath = scope String();
  60. projectSource.GetFullImportPath(importPath);
  61. Result<DateTime> fileDateTime = File.GetLastWriteTime(importPath);
  62. if (fileDateTime case .Ok)
  63. {
  64. let date = fileDateTime.Get().ToFileTime();
  65. /*if (date > targetDateTime)
  66. Console.WriteLine("Custom build higher time: {0}", importPath);*/
  67. highestDateTime = Math.Max(highestDateTime, date);
  68. }
  69. });
  70. if ((highestDateTime <= targetDateTime) && (!forceRebuild))
  71. return .NoCommands;
  72. project.mLastDidBuild = true;
  73. }
  74. Workspace.Options workspaceOptions = gApp.GetCurWorkspaceOptions();
  75. Project.Options options = gApp.GetCurProjectOptions(project);
  76. bool didCommands = false;
  77. let targetName = scope String("Project ", project.mProjectName);
  78. //Console.WriteLine("Executing custom command {0} {1} {2}", highestDateTime, targetDateTime, forceRebuild);
  79. for (let origCustomCmd in cmdList)
  80. {
  81. bool isCommand = false;
  82. for (let c in origCustomCmd.RawChars)
  83. {
  84. if ((c == '\"') || (c == '$'))
  85. break;
  86. if (c == '(')
  87. isCommand = true;
  88. }
  89. String customCmd = scope String();
  90. if (isCommand)
  91. {
  92. customCmd.Append(origCustomCmd);
  93. }
  94. else
  95. {
  96. customCmd.Append("%exec ");
  97. gApp.ResolveConfigString(workspaceOptions, project, options, origCustomCmd, "custom command", customCmd);
  98. }
  99. if (customCmd.IsWhiteSpace)
  100. continue;
  101. if (mScriptManager == null)
  102. {
  103. mScriptManager = new .();
  104. mScriptManager.mProjectName = new String(project.mProjectName);
  105. mScriptManager.mAllowCompiling = true;
  106. mScriptManager.mSoftFail = true;
  107. mScriptManager.mVerbosity = gApp.mVerbosity;
  108. didCommands = true;
  109. }
  110. mScriptManager.QueueCommands(customCmd, project.mProjectName, .NoLines);
  111. continue;
  112. }
  113. let targetCompleteCmd = new IDEApp.TargetCompletedCmd(project);
  114. if (didCommands)
  115. {
  116. mScriptManager.QueueCommands(scope String()..AppendF("%targetComplete {}", project.mProjectName), targetName, .NoLines);
  117. targetCompleteCmd.mIsReady = false;
  118. project.mNeedsTargetRebuild = true;
  119. }
  120. gApp.mExecutionQueue.Add(targetCompleteCmd);
  121. return didCommands ? .HadCommands : .NoCommands;
  122. }
  123. bool QueueProjectGNULink(Project project, String targetPath, Workspace.Options workspaceOptions, Project.Options options, String objectsArg)
  124. {
  125. bool isDebug = gApp.mConfigName.IndexOf("Debug", true) != -1;
  126. #if BF_PLATFORM_WINDOWS
  127. String llvmDir = scope String(IDEApp.sApp.mInstallDir);
  128. IDEUtils.FixFilePath(llvmDir);
  129. llvmDir.Append("llvm/");
  130. #else
  131. String llvmDir = "";
  132. #endif
  133. //String error = scope String();
  134. bool isExe = project.mGeneralOptions.mTargetType != Project.TargetType.BeefLib;
  135. if (isExe)
  136. {
  137. String linkLine = scope String(isDebug ? "-g " : "-g -O2 "); //-O2 -Rpass=inline
  138. //(doClangCPP ? "-lc++abi " : "") +
  139. linkLine.Append("-o ");
  140. IDEUtils.AppendWithOptionalQuotes(linkLine, targetPath);
  141. linkLine.Append(" ");
  142. /*if (options.mBuildOptions.mLinkerType == Project.LinkerType.GCC)
  143. {
  144. // ...
  145. }
  146. else
  147. {
  148. linkLine.Append("--target=");
  149. GetTargetName(workspaceOptions, linkLine);
  150. linkLine.Append(" ");
  151. }*/
  152. if ((project.mGeneralOptions.mTargetType == Project.TargetType.BeefWindowsApplication) ||
  153. (project.mGeneralOptions.mTargetType == Project.TargetType.C_WindowsApplication))
  154. {
  155. linkLine.Append("-mwindows ");
  156. }
  157. linkLine.Append("-no-pie ");
  158. linkLine.Append(objectsArg);
  159. //var destDir = scope String();
  160. //Path.GetDirectoryName();
  161. //TODO: Make an option
  162. if (options.mBuildOptions.mCLibType == Project.CLibType.Static)
  163. {
  164. linkLine.Append("-static-libgcc -static-libstdc++ ");
  165. }
  166. else
  167. {
  168. #if BF_PLATFORM_WINDOWS
  169. String[] mingwFiles;
  170. String fromDir;
  171. if (workspaceOptions.mMachineType == Workspace.MachineType.x86)
  172. {
  173. fromDir = scope:: String(llvmDir, "i686-w64-mingw32/bin/");
  174. mingwFiles = scope:: String[] { "libgcc_s_dw2-1.dll", "libstdc++-6.dll" };
  175. }
  176. else
  177. {
  178. fromDir = scope:: String(llvmDir, "x86_64-w64-mingw32/bin/");
  179. mingwFiles = scope:: String[] { "libgcc_s_seh-1.dll", "libstdc++-6.dll", "libwinpthread-1.dll" };
  180. }
  181. for (var mingwFile in mingwFiles)
  182. {
  183. String fromPath = scope String(fromDir, mingwFile);
  184. //string toPath = projectBuildDir + "/" + mingwFile;
  185. String toPath = scope String();
  186. Path.GetDirectoryPath(targetPath, toPath);
  187. toPath.Append("/", mingwFile);
  188. if (!File.Exists(toPath))
  189. {
  190. if (File.Copy(fromPath, toPath) case .Err)
  191. {
  192. gApp.OutputLineSmart("ERROR: Failed to copy mingw file {0}", fromPath);
  193. return false;
  194. }
  195. }
  196. }
  197. #endif
  198. }
  199. List<Project> depProjectList = scope List<Project>();
  200. gApp.GetDependentProjectList(project, depProjectList);
  201. if (depProjectList.Count > 0)
  202. {
  203. for (var dep in project.mDependencies)
  204. {
  205. var depProject = gApp.mWorkspace.FindProject(dep.mProjectName);
  206. if (depProject == null)
  207. {
  208. gApp.OutputLine("Failed to locate dependent library: {0}", dep.mProjectName);
  209. return false;
  210. }
  211. else
  212. {
  213. /*if (depProject.mNeedsTargetRebuild)
  214. project.mNeedsTargetRebuild = true;*/
  215. var depOptions = gApp.GetCurProjectOptions(depProject);
  216. if (depOptions.mClangObjectFiles != null)
  217. {
  218. var argBuilder = scope IDEApp.ArgBuilder(linkLine, true);
  219. for (var fileName in depOptions.mClangObjectFiles)
  220. {
  221. //AppendWithOptionalQuotes(linkLine, fileName);
  222. argBuilder.AddFileName(fileName);
  223. argBuilder.AddSep();
  224. }
  225. }
  226. /*String depLibTargetPath = scope String();
  227. ResolveConfigString(depProject, depOptions, "$(TargetPath)", error, depLibTargetPath);
  228. IDEUtils.FixFilePath(depLibTargetPath);
  229. String depDir = scope String();
  230. Path.GetDirectoryName(depLibTargetPath, depDir);
  231. String depFileName = scope String();
  232. Path.GetFileNameWithoutExtension(depLibTargetPath, depFileName);
  233. AppendWithOptionalQuotes(linkLine, depLibTargetPath);
  234. linkLine.Append(" ");*/
  235. }
  236. }
  237. }
  238. #if BF_PLATFORM_WINDOWS
  239. String gccExePath = "c:/mingw/bin/g++.exe";
  240. String clangExePath = scope String(llvmDir, "bin/clang++.exe");
  241. #else
  242. String gccExePath = "/usr/bin/c++";
  243. String clangExePath = scope String("/usr/bin/c++");
  244. #endif
  245. if (project.mNeedsTargetRebuild)
  246. {
  247. if (File.Delete(targetPath) case .Err)
  248. {
  249. gApp.OutputLine("Failed to delete {0}", targetPath);
  250. return false;
  251. }
  252. if (workspaceOptions.mToolsetType == .GNU)
  253. {
  254. if (workspaceOptions.mMachineType == Workspace.MachineType.x86)
  255. {
  256. }
  257. else
  258. {
  259. IDEUtils.AppendWithOptionalQuotes(linkLine, scope String("-L", llvmDir, "/x86_64-w64-mingw32/lib"));
  260. linkLine.Append(" ");
  261. IDEUtils.AppendWithOptionalQuotes(linkLine, scope String("-L", llvmDir, "/lib/gcc/x86_64-w64-mingw32/5.2.0"));
  262. linkLine.Append(" ");
  263. }
  264. }
  265. else // Microsoft
  266. {
  267. if (workspaceOptions.mMachineType == Workspace.MachineType.x86)
  268. {
  269. //linkLine.Append("-L\"C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.10586.0\\ucrt\\x86\" ");
  270. for (var libPath in gApp.mSettings.mVSSettings.mLib32Paths)
  271. {
  272. linkLine.AppendF("-L\"{0}\" ", libPath);
  273. }
  274. }
  275. else
  276. {
  277. /*linkLine.Append("-L\"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\lib\\amd64\" ");
  278. linkLine.Append("-L\"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\atlmfc\\lib\\amd64\" ");
  279. linkLine.Append("-L\"C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.14393.0\\ucrt\\x64\" ");
  280. linkLine.Append("-L\"C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.14393.0\\um\\x64\" ");*/
  281. for (var libPath in gApp.mSettings.mVSSettings.mLib64Paths)
  282. {
  283. linkLine.AppendF("-L\"{0}\" ", libPath);
  284. }
  285. }
  286. }
  287. if (options.mBuildOptions.mOtherLinkFlags.Length != 0)
  288. {
  289. var linkFlags = scope String();
  290. gApp.ResolveConfigString(workspaceOptions, project, options, options.mBuildOptions.mOtherLinkFlags, "link flags", linkFlags);
  291. linkLine.Append(linkFlags, " ");
  292. }
  293. String compilerExePath = (workspaceOptions.mToolsetType == .GNU) ? gccExePath : clangExePath;
  294. String workingDir = scope String();
  295. if (!llvmDir.IsEmpty)
  296. {
  297. workingDir.Append(llvmDir, "bin");
  298. }
  299. else
  300. {
  301. workingDir.Append(gApp.mInstallDir);
  302. }
  303. var runCmd = gApp.QueueRun(compilerExePath, linkLine, workingDir, .UTF8);
  304. runCmd.mOnlyIfNotFailed = true;
  305. var tagetCompletedCmd = new IDEApp.TargetCompletedCmd(project);
  306. tagetCompletedCmd.mOnlyIfNotFailed = true;
  307. gApp.mExecutionQueue.Add(tagetCompletedCmd);
  308. String logStr = scope String();
  309. logStr.AppendF("IDE Process {0}\r\n", Platform.BfpProcess_GetCurrentId());
  310. logStr.Append(linkLine);
  311. String targetLogPath = scope String(targetPath, ".build.txt");
  312. Utils.WriteTextFile(targetLogPath, logStr);
  313. project.mLastDidBuild = true;
  314. }
  315. }
  316. return true;
  317. }
  318. public static void GetPdbPath(String targetPath, Workspace.Options workspaceOptions, Project.Options options, String outPdbPath)
  319. {
  320. int lastDotPos = targetPath.LastIndexOf('.');
  321. outPdbPath.Append(targetPath, 0, lastDotPos);
  322. if (workspaceOptions.mToolsetType == .LLVM)
  323. outPdbPath.Append("_lld");
  324. outPdbPath.Append(".pdb");
  325. }
  326. public static void GetRtLibNames(Workspace.Options workspaceOptions, Project.Options options, bool dynName, String outRt, String outDbg)
  327. {
  328. if ((!dynName) || (options.mBuildOptions.mBeefLibType != .Static))
  329. {
  330. outRt.Append("Beef", IDEApp.sRTVersionStr, "RT");
  331. outRt.Append((workspaceOptions.mMachineType == .x86) ? "32" : "64");
  332. switch (options.mBuildOptions.mBeefLibType)
  333. {
  334. case .Dynamic:
  335. case .DynamicDebug: outRt.Append("_d");
  336. case .Static:
  337. switch (options.mBuildOptions.mCLibType)
  338. {
  339. case .None:
  340. case .Dynamic, .SystemMSVCRT: outRt.Append("_s");
  341. case .DynamicDebug: outRt.Append("_sd");
  342. case .Static: outRt.Append("_ss");
  343. case .StaticDebug: outRt.Append("_ssd");
  344. }
  345. }
  346. outRt.Append(dynName ? ".dll" : ".lib");
  347. }
  348. if ((workspaceOptions.mEnableObjectDebugFlags) || (workspaceOptions.mAllocType == .Debug))
  349. {
  350. outDbg.Append("Beef", IDEApp.sRTVersionStr, "Dbg");
  351. outDbg.Append((workspaceOptions.mMachineType == .x86) ? "32" : "64");
  352. if (options.mBuildOptions.mBeefLibType == .DynamicDebug)
  353. outDbg.Append("_d");
  354. outDbg.Append(dynName ? ".dll" : ".lib");
  355. }
  356. /*if ((workspaceOptions.mEnableObjectDebugFlags) &&
  357. ((!dynName) || (options.mBuildOptions.mBeefLibType != .Static)))
  358. {
  359. outDbg.Append("Beef", IDEApp.sRTVersionStr, "Dbg");
  360. outDbg.Append((workspaceOptions.mMachineType == .x86) ? "32" : "64");
  361. switch (options.mBuildOptions.mBeefLibType)
  362. {
  363. case .Dynamic:
  364. case .DynamicDebug: outDbg.Append("_d");
  365. case .Static:
  366. switch (options.mBuildOptions.mCLibType)
  367. {
  368. case .None:
  369. case .Dynamic, .SystemMSVCRT: outDbg.Append("_s");
  370. case .DynamicDebug: outDbg.Append("_sd");
  371. case .Static: outDbg.Append("_ss");
  372. case .StaticDebug: outDbg.Append("_ssd");
  373. }
  374. }
  375. outDbg.Append(dynName ? ".dll" : ".lib");
  376. }*/
  377. }
  378. bool QueueProjectMSLink(Project project, String targetPath, String configName, Workspace.Options workspaceOptions, Project.Options options, String objectsArg)
  379. {
  380. String llvmDir = scope String(IDEApp.sApp.mInstallDir);
  381. IDEUtils.FixFilePath(llvmDir);
  382. llvmDir.Append("llvm/");
  383. TestManager.ProjectInfo testProjectInfo = null;
  384. if (gApp.mTestManager != null)
  385. testProjectInfo = gApp.mTestManager.GetProjectInfo(project);
  386. bool isExe = (project.mGeneralOptions.mTargetType != Project.TargetType.BeefLib) || (testProjectInfo != null);
  387. if (isExe)
  388. {
  389. String linkLine = scope String();
  390. linkLine.Append("-out:");
  391. IDEUtils.AppendWithOptionalQuotes(linkLine, targetPath);
  392. linkLine.Append(" ");
  393. if (testProjectInfo != null)
  394. linkLine.Append("-subsystem:console ");
  395. else if (project.mGeneralOptions.mTargetType == .BeefWindowsApplication)
  396. linkLine.Append("-subsystem:windows ");
  397. else if (project.mGeneralOptions.mTargetType == .C_WindowsApplication)
  398. linkLine.Append("-subsystem:console ");
  399. else if (project.mGeneralOptions.mTargetType == .BeefDynLib)
  400. {
  401. linkLine.Append("-dll ");
  402. if (targetPath.EndsWith(".dll", .InvariantCultureIgnoreCase))
  403. {
  404. linkLine.Append("-implib:\"");
  405. linkLine.Append(targetPath, 0, targetPath.Length - 4);
  406. linkLine.Append(".lib\" ");
  407. }
  408. }
  409. linkLine.Append(objectsArg);
  410. //var destDir = scope String();
  411. //Path.GetDirectoryName();
  412. //TODO: Allow selecting lib file. Check date when copying instead of just ALWAYS copying...
  413. LibBlock:
  414. {
  415. List<String> stdLibFileNames = scope .(2);
  416. String fromDir;
  417. fromDir = scope String(gApp.mInstallDir);
  418. bool AddLib(String dllName)
  419. {
  420. stdLibFileNames.Add(dllName);
  421. String fromPath = scope String(fromDir, dllName);
  422. String toPath = scope String();
  423. Path.GetDirectoryPath(targetPath, toPath);
  424. toPath.Append("/", dllName);
  425. if (File.CopyIfNewer(fromPath, toPath) case .Err)
  426. {
  427. gApp.OutputLine("Failed to copy lib file {0}", fromPath);
  428. return false;
  429. }
  430. return true;
  431. }
  432. String rtName = scope String();
  433. String dbgName = scope String();
  434. GetRtLibNames(workspaceOptions, options, true, rtName, dbgName);
  435. if (!rtName.IsEmpty)
  436. if (!AddLib(rtName))
  437. return false;
  438. if (!dbgName.IsEmpty)
  439. if (!AddLib(dbgName))
  440. return false;
  441. switch (workspaceOptions.mAllocType)
  442. {
  443. case .JEMalloc:
  444. if (!AddLib("jemalloc.dll"))
  445. return false;
  446. default:
  447. }
  448. }
  449. List<Project> depProjectList = scope List<Project>();
  450. gApp.GetDependentProjectList(project, depProjectList);
  451. if (depProjectList.Count > 0)
  452. {
  453. for (var dep in project.mDependencies)
  454. {
  455. var depProject = gApp.mWorkspace.FindProject(dep.mProjectName);
  456. if (depProject == null)
  457. {
  458. gApp.OutputLine("Failed to locate dependent library: {0}", dep.mProjectName);
  459. return false;
  460. }
  461. else
  462. {
  463. /*if (depProject.mNeedsTargetRebuild)
  464. project.mNeedsTargetRebuild = true;*/
  465. var depOptions = gApp.GetCurProjectOptions(depProject);
  466. if (depOptions != null)
  467. {
  468. if (depOptions.mClangObjectFiles != null)
  469. {
  470. var argBuilder = scope IDEApp.ArgBuilder(linkLine, true);
  471. for (var fileName in depOptions.mClangObjectFiles)
  472. {
  473. //AppendWithOptionalQuotes(linkLine, fileName);
  474. argBuilder.AddFileName(fileName);
  475. argBuilder.AddSep();
  476. }
  477. }
  478. }
  479. if (depProject.mGeneralOptions.mTargetType == .BeefDynLib)
  480. {
  481. if (mImpLibMap.TryGetValue(depProject, var libPath))
  482. {
  483. IDEUtils.AppendWithOptionalQuotes(linkLine, libPath);
  484. linkLine.Append(" ");
  485. }
  486. }
  487. if (depProject.mGeneralOptions.mTargetType == .BeefLib)
  488. {
  489. let depProjectOptions = gApp.GetCurProjectOptions(depProject);
  490. var linkFlags = scope String();
  491. gApp.ResolveConfigString(workspaceOptions, depProject, depProjectOptions, depProjectOptions.mBuildOptions.mOtherLinkFlags, "link flags", linkFlags);
  492. if (!linkFlags.IsWhiteSpace)
  493. linkLine.Append(linkFlags, " ");
  494. }
  495. /*String depLibTargetPath = scope String();
  496. ResolveConfigString(depProject, depOptions, "$(TargetPath)", error, depLibTargetPath);
  497. IDEUtils.FixFilePath(depLibTargetPath);
  498. String depDir = scope String();
  499. Path.GetDirectoryName(depLibTargetPath, depDir);
  500. String depFileName = scope String();
  501. Path.GetFileNameWithoutExtension(depLibTargetPath, depFileName);
  502. AppendWithOptionalQuotes(linkLine, depLibTargetPath);
  503. linkLine.Append(" ");*/
  504. }
  505. }
  506. }
  507. if (project.mNeedsTargetRebuild)
  508. {
  509. /*if (File.Delete(targetPath).Failed(true))
  510. {
  511. OutputLine("Failed to delete {0}", targetPath);
  512. return false;
  513. }*/
  514. switch (options.mBuildOptions.mCLibType)
  515. {
  516. case .None:
  517. linkLine.Append("-nodefaultlib ");
  518. case .Dynamic:
  519. //linkLine.Append((workspaceOptions.mMachineType == .x86) ? "-defaultlib:msvcprt " : "-defaultlib:msvcrt ");
  520. linkLine.Append("-defaultlib:msvcrt ");
  521. case .Static:
  522. //linkLine.Append((workspaceOptions.mMachineType == .x86) ? "-defaultlib:libcpmt " : "-defaultlib:libcmt ");
  523. linkLine.Append("-defaultlib:libcmt ");
  524. case .DynamicDebug:
  525. //linkLine.Append((workspaceOptions.mMachineType == .x86) ? "-defaultlib:msvcprtd " : "-defaultlib:msvcrtd ");
  526. linkLine.Append("-defaultlib:msvcrtd ");
  527. case .StaticDebug:
  528. //linkLine.Append((workspaceOptions.mMachineType == .x86) ? "-defaultlib:libcpmtd " : "-defaultlib:libcmtd ");
  529. linkLine.Append("-defaultlib:libcmtd ");
  530. case .SystemMSVCRT:
  531. linkLine.Append("-nodefaultlib ");
  532. String minRTModName = scope String();
  533. if ((project.mGeneralOptions.mTargetType == .BeefWindowsApplication) ||
  534. (project.mGeneralOptions.mTargetType == .C_WindowsApplication))
  535. minRTModName.Append("g");
  536. if (options.mBuildOptions.mBeefLibType == .DynamicDebug)
  537. minRTModName.Append("d");
  538. if (!minRTModName.IsEmpty)
  539. minRTModName.Insert(0, "_");
  540. if (workspaceOptions.mMachineType == .x86)
  541. linkLine.Append(gApp.mInstallDir, @"lib\x86\msvcrt.lib Beef", IDEApp.sRTVersionStr,"MinRT32", minRTModName, ".lib ");
  542. else
  543. linkLine.Append(gApp.mInstallDir, @"lib\x64\msvcrt.lib Beef", IDEApp.sRTVersionStr,"MinRT64", minRTModName, ".lib ");
  544. linkLine.Append("ntdll.lib user32.lib kernel32.lib gdi32.lib winmm.lib shell32.lib ole32.lib rpcrt4.lib chkstk.obj -ignore:4049 -ignore:4217 ");
  545. }
  546. linkLine.Append("-nologo ");
  547. //linkLine.Append("-fixed ");
  548. // Incremental just seems to be slower for Beef. Test on larger projects to verify
  549. linkLine.Append("-incremental:no ");
  550. if (options.mBuildOptions.mStackSize > 0)
  551. linkLine.AppendF("-stack:{} ", options.mBuildOptions.mStackSize);
  552. linkLine.Append("-pdb:");
  553. let pdbName = scope String();
  554. GetPdbPath(targetPath, workspaceOptions, options, pdbName);
  555. IDEUtils.AppendWithOptionalQuotes(linkLine, pdbName);
  556. linkLine.Append(" ");
  557. //TODO: Only add -debug if we have some debug info?
  558. //if (isDebug)
  559. if (workspaceOptions.mEmitDebugInfo != .No)
  560. linkLine.Append("-debug ");
  561. if (workspaceOptions.mBfOptimizationLevel.IsOptimized())
  562. //linkLine.Append("-opt:ref -verbose ");
  563. linkLine.Append("-opt:ref ");
  564. else
  565. linkLine.Append("-opt:noref ");
  566. if (workspaceOptions.mMachineType == .x86)
  567. {
  568. //linkLine.Append("-libpath:\"C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.10586.0\\ucrt\\x86\" ");
  569. for (var libPath in gApp.mSettings.mVSSettings.mLib32Paths)
  570. {
  571. linkLine.AppendF("-libpath:\"{0}\" ", libPath);
  572. }
  573. linkLine.Append("-libpath:\"", gApp.mInstallDir, "lib\\x86\" ");
  574. }
  575. else
  576. {
  577. /*linkLine.Append("-libpath:\"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\lib\\amd64\" ");
  578. linkLine.Append("-libpath:\"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\atlmfc\\lib\\amd64\" ");
  579. linkLine.Append("-libpath:\"C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.14393.0\\ucrt\\x64\" ");
  580. linkLine.Append("-libpath:\"C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.14393.0\\um\\x64\" ");*/
  581. for (var libPath in gApp.mSettings.mVSSettings.mLib64Paths)
  582. {
  583. linkLine.AppendF("-libpath:\"{0}\" ", libPath);
  584. }
  585. linkLine.Append("-libpath:\"", gApp.mInstallDir, "lib\\x64\" ");
  586. }
  587. String targetDir = scope String();
  588. Path.GetDirectoryPath(targetPath, targetDir);
  589. linkLine.Append("-libpath:");
  590. IDEUtils.AppendWithOptionalQuotes(linkLine, targetDir);
  591. linkLine.Append(" ");
  592. if (options.mBuildOptions.mOtherLinkFlags.Length != 0)
  593. {
  594. var linkFlags = scope String();
  595. gApp.ResolveConfigString(workspaceOptions, project, options, options.mBuildOptions.mOtherLinkFlags, "link flags", linkFlags);
  596. linkLine.Append(linkFlags, " ");
  597. }
  598. let winOptions = project.mWindowsOptions;
  599. /*if (!String.IsNullOrWhiteSpace(project.mWindowsOptions.mManifestFile))
  600. {
  601. String manifestPath = scope String();
  602. String error = scope String();
  603. ResolveConfigString(project, options, winOptions.mManifestFile, error, manifestPath);
  604. if (!manifestPath.IsWhiteSpace)
  605. {
  606. linkLine.Append("/MANIFEST:EMBED /MANIFESTINPUT:");
  607. IDEUtils.AppendWithOptionalQuotes(linkLine, manifestPath);
  608. linkLine.Append(" ");
  609. }
  610. }*/
  611. // Put back
  612. if ((!String.IsNullOrWhiteSpace(project.mWindowsOptions.mIconFile)) ||
  613. (!String.IsNullOrWhiteSpace(project.mWindowsOptions.mManifestFile)) ||
  614. (winOptions.HasVersionInfo()))
  615. {
  616. String projectBuildDir = scope String();
  617. gApp.GetProjectBuildDir(project, projectBuildDir);
  618. String resOutPath = scope String();
  619. resOutPath.Append(projectBuildDir, "\\Resource.res");
  620. String iconPath = scope String();
  621. gApp.ResolveConfigString(workspaceOptions, project, options, winOptions.mIconFile, "icon file", iconPath);
  622. // Generate resource
  623. Result<void> CreateResourceFile()
  624. {
  625. ResourceGen resGen = scope ResourceGen();
  626. if (resGen.Start(resOutPath) case .Err)
  627. {
  628. gApp.OutputErrorLine("Failed to create resource file '{0}'", resOutPath);
  629. return .Err;
  630. }
  631. if (!iconPath.IsWhiteSpace)
  632. {
  633. Path.GetAbsolutePath(scope String(iconPath), project.mProjectDir, iconPath..Clear());
  634. if (resGen.AddIcon(iconPath) case .Err)
  635. {
  636. gApp.OutputErrorLine("Failed to add icon");
  637. return .Err;
  638. }
  639. }
  640. let targetFileName = scope String();
  641. Path.GetFileName(targetPath, targetFileName);
  642. if (resGen.AddVersion(winOptions.mDescription, winOptions.mComments, winOptions.mCompany, winOptions.mProduct,
  643. winOptions.mCopyright, winOptions.mFileVersion, winOptions.mProductVersion, targetFileName) case .Err)
  644. {
  645. gApp.OutputErrorLine("Failed to add version");
  646. return .Err;
  647. }
  648. String manifestPath = scope String();
  649. gApp.ResolveConfigString(workspaceOptions, project, options, winOptions.mManifestFile, "manifest file", manifestPath);
  650. if (!manifestPath.IsWhiteSpace)
  651. {
  652. Path.GetAbsolutePath(scope String(manifestPath), project.mProjectDir, manifestPath..Clear());
  653. if (resGen.AddManifest(manifestPath) case .Err)
  654. {
  655. gApp.OutputErrorLine("Failed to add manifest file");
  656. return .Err;
  657. }
  658. }
  659. Try!(resGen.Finish());
  660. return .Ok;
  661. }
  662. if (CreateResourceFile() case .Err)
  663. {
  664. gApp.OutputErrorLine("Failed to generate resource file: {0}", resOutPath);
  665. return false;
  666. }
  667. IDEUtils.AppendWithOptionalQuotes(linkLine, resOutPath);
  668. }
  669. //String linkerPath = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe";
  670. let binPath = (workspaceOptions.mMachineType == .x86) ? gApp.mSettings.mVSSettings.mBin32Path : gApp.mSettings.mVSSettings.mBin64Path;
  671. if (binPath.IsWhiteSpace)
  672. {
  673. gApp.OutputErrorLine("Visual Studio tool path not configured. Check Visual Studio configuration in File\\Preferences\\Settings.");
  674. return false;
  675. }
  676. String linkerPath = scope String();
  677. linkerPath.Append(binPath);
  678. linkerPath.Append("/link.exe");
  679. if (workspaceOptions.mToolsetType == .LLVM)
  680. {
  681. linkerPath.Clear();
  682. linkerPath.Append(gApp.mInstallDir);
  683. linkerPath.Append(@"llvm\bin\lld-link.exe");
  684. //linkerPath = @"C:\Program Files\LLVM\bin\lld-link.exe";
  685. var ltoType = workspaceOptions.mLTOType;
  686. if (options.mBeefOptions.mLTOType != null)
  687. ltoType = options.mBeefOptions.mLTOType.Value;
  688. if (ltoType == .Thin)
  689. {
  690. linkLine.Append(" /lldltocache:");
  691. String ltoPath = scope String();
  692. Path.GetDirectoryPath(targetPath, ltoPath);
  693. ltoPath.Append("/ltocache");
  694. IDEUtils.AppendWithOptionalQuotes(linkLine, ltoPath);
  695. }
  696. }
  697. //String linkerPath = "C:\\Beef\\IDE\\dist\\BeefLink.exe";
  698. //QueueRun(compilerExePath, linkLine, @"c:\mingw\bin", (options.mGeneralOptions.mLinkerType == Project.LinkerType.Clang) && (linkLine.Length > 1024));
  699. //QueueRun(compilerExePath, linkLine, @"c:\mingw\bin", (linkLine.Length > 1024));
  700. var runCmd = gApp.QueueRun(linkerPath, linkLine, gApp.mInstallDir, .UTF16WithBom);
  701. runCmd.mOnlyIfNotFailed = true;
  702. var tagetCompletedCmd = new IDEApp.TargetCompletedCmd(project);
  703. tagetCompletedCmd.mOnlyIfNotFailed = true;
  704. gApp.mExecutionQueue.Add(tagetCompletedCmd);
  705. String logStr = scope String();
  706. logStr.AppendF("IDE Process {0}\r\n", Platform.BfpProcess_GetCurrentId());
  707. logStr.Append(linkLine);
  708. String targetLogPath = scope String(targetPath, ".build.txt");
  709. Utils.WriteTextFile(targetLogPath, logStr);
  710. project.mLastDidBuild = true;
  711. }
  712. }
  713. return true;
  714. }
  715. public bool QueueProjectCompile(Project project, Project hotProject, IDEApp.BuildCompletedCmd completedCompileCmd, List<String> hotFileNames, bool runAfter)
  716. {
  717. project.mLastDidBuild = false;
  718. TestManager.ProjectInfo testProjectInfo = null;
  719. if (gApp.mTestManager != null)
  720. testProjectInfo = gApp.mTestManager.GetProjectInfo(project);
  721. var configSelection = gApp.GetCurConfigSelection(project);
  722. Project.Options options = gApp.GetCurProjectOptions(project);
  723. if (options == null)
  724. return true;
  725. Workspace.Options workspaceOptions = gApp.GetCurWorkspaceOptions();
  726. BfCompiler bfCompiler = gApp.mBfBuildCompiler;
  727. var bfProject = gApp.mBfBuildSystem.mProjectMap[project];
  728. bool bfHadOutputChanges;
  729. List<String> bfFileNames = scope List<String>();
  730. bfCompiler.GetOutputFileNames(bfProject, true, out bfHadOutputChanges, bfFileNames);
  731. defer ClearAndDeleteItems(bfFileNames);//DeleteAndClearItems!(bfFileNames);
  732. if (bfHadOutputChanges)
  733. project.mNeedsTargetRebuild = true;
  734. List<ProjectSource> allFileNames = scope List<ProjectSource>();
  735. List<String> clangAllObjNames = scope List<String>();
  736. //List<String> clangObjNames = scope List<String>();
  737. gApp.GetClangFiles(project.mRootFolder, allFileNames);
  738. String workspaceBuildDir = scope String();
  739. gApp.GetWorkspaceBuildDir(workspaceBuildDir);
  740. String projectBuildDir = scope String();
  741. gApp.GetProjectBuildDir(project, projectBuildDir);
  742. if (!projectBuildDir.IsEmpty)
  743. Directory.CreateDirectory(projectBuildDir).IgnoreError();
  744. //List<String> buildFileNames = new List<String>();
  745. String targetPath = scope String();
  746. String outputDir = scope String();
  747. String absOutputDir = scope String();
  748. if (testProjectInfo != null)
  749. {
  750. absOutputDir.Append(projectBuildDir);
  751. outputDir = absOutputDir;
  752. targetPath.Append(outputDir, "/", project.mProjectName);
  753. #if BF_PLATFORM_WINDOWS
  754. targetPath.Append(".exe");
  755. #endif
  756. Debug.Assert(testProjectInfo.mTestExePath == null);
  757. testProjectInfo.mTestExePath = new String(targetPath);
  758. }
  759. else
  760. {
  761. gApp.ResolveConfigString(workspaceOptions, project, options, options.mBuildOptions.mTargetDirectory, "target directory", outputDir);
  762. Path.GetAbsolutePath(project.mProjectDir, outputDir, absOutputDir);
  763. outputDir = absOutputDir;
  764. gApp.ResolveConfigString(workspaceOptions, project, options, "$(TargetPath)", "target path", targetPath);
  765. }
  766. IDEUtils.FixFilePath(targetPath);
  767. if (!File.Exists(targetPath))
  768. {
  769. project.mNeedsTargetRebuild = true;
  770. String targetDir = scope String();
  771. Path.GetDirectoryPath(targetPath, targetDir);
  772. if (!targetDir.IsEmpty)
  773. Directory.CreateDirectory(targetDir).IgnoreError();
  774. }
  775. if (project.mGeneralOptions.mTargetType == .BeefDynLib)
  776. {
  777. if (targetPath.EndsWith(".dll", .InvariantCultureIgnoreCase))
  778. {
  779. String libPath = new .();
  780. libPath.Append(targetPath, 0, targetPath.Length - 4);
  781. libPath.Append(".lib");
  782. mImpLibMap.Add(project, libPath);
  783. }
  784. }
  785. if (hotProject == null)
  786. {
  787. switch (QueueProjectCustomBuildCommands(project, targetPath, runAfter ? options.mBuildOptions.mBuildCommandsOnRun : options.mBuildOptions.mBuildCommandsOnCompile, options.mBuildOptions.mPostBuildCmds))
  788. {
  789. case .NoCommands:
  790. case .HadCommands:
  791. case .Failed:
  792. completedCompileCmd.mFailed = true;
  793. }
  794. }
  795. if (project.mGeneralOptions.mTargetType == .CustomBuild)
  796. {
  797. return true;
  798. }
  799. #if IDE_C_SUPPORT
  800. bool buildAll = false;
  801. String buildStringFilePath = scope String();
  802. mDepClang.GetBuildStringFileName(projectBuildDir, project, buildStringFilePath);
  803. String newBuildString = scope String();
  804. GetClangBuildString(project, options, workspaceOptions, true, newBuildString);
  805. String clangBuildString = scope String();
  806. GetClangBuildString(project, options, workspaceOptions, false, clangBuildString);
  807. newBuildString.Append("|", clangBuildString);
  808. if (mDepClang.mDoDependencyCheck)
  809. {
  810. String prependStr = scope String();
  811. options.mCOptions.mCompilerType.ToString(prependStr);
  812. prependStr.Append("|");
  813. newBuildString.Insert(0, prependStr);
  814. String oldBuildString;
  815. mDepClang.mProjectBuildString.TryGetValue(project, out oldBuildString);
  816. if (oldBuildString == null)
  817. {
  818. oldBuildString = new String();
  819. File.ReadAllText(buildStringFilePath, oldBuildString).IgnoreError();
  820. mDepClang.mProjectBuildString[project] = oldBuildString;
  821. }
  822. if (newBuildString != oldBuildString)
  823. {
  824. buildAll = true;
  825. if (case .Err = File.WriteAllText(buildStringFilePath, newBuildString))
  826. OutputLine("Failed to write {0}", buildStringFilePath);
  827. delete oldBuildString;
  828. mDepClang.mProjectBuildString[project] = new String(newBuildString);
  829. }
  830. }
  831. using (mDepClang.mMonitor.Enter())
  832. {
  833. if (options.mClangObjectFiles == null)
  834. options.mClangObjectFiles = new List<String>();
  835. else
  836. ClearAndDeleteItems(options.mClangObjectFiles);
  837. for (var projectSource in allFileNames)
  838. {
  839. var fileEntry = mDepClang.GetProjectEntry(projectSource);
  840. Debug.Assert((fileEntry != null) || (!mDepClang.mCompileWaitsForQueueEmpty));
  841. String filePath = scope String();
  842. projectSource.GetFullImportPath(filePath);
  843. String baseName = scope String();
  844. Path.GetFileNameWithoutExtension(filePath, baseName);
  845. String objName = stack String();
  846. objName.Append(projectBuildDir, "/", baseName, (options.mCOptions.mGenerateLLVMAsm ? ".ll" : ".obj"));
  847. if (filePath.Contains("test2.cpp"))
  848. {
  849. NOP!();
  850. }
  851. bool needsRebuild = true;
  852. if ((!buildAll) && (fileEntry != null))
  853. {
  854. mDepClang.SetEntryObjFileName(fileEntry, objName);
  855. mDepClang.SetEntryBuildStringFileName(fileEntry, buildStringFilePath);
  856. needsRebuild = mDepClang.DoesEntryNeedRebuild(fileEntry);
  857. }
  858. if (needsRebuild)
  859. {
  860. if (hotProject != null)
  861. {
  862. OutputLine("Hot swap detected disallowed C/C++ change: {0}", filePath);
  863. return false;
  864. }
  865. project.mNeedsTargetRebuild = true;
  866. var runCmd = CompileSource(project, workspaceOptions, options, filePath);
  867. runCmd.mParallelGroup = 1;
  868. }
  869. options.mClangObjectFiles.Add(new String(objName));
  870. if (hotProject != null)
  871. continue;
  872. clangAllObjNames.Add(objName);
  873. IdSpan sourceCharIdData;
  874. String sourceCode = scope String();
  875. FindProjectSourceContent(projectSource, out sourceCharIdData, true, sourceCode);
  876. mWorkspace.ProjectSourceCompiled(projectSource, sourceCode, sourceCharIdData);
  877. sourceCharIdData.Dispose();
  878. String* fileEntryPtr;
  879. if (completedCompileCmd.mClangCompiledFiles.Add(filePath, out fileEntryPtr))
  880. *fileEntryPtr = new String(filePath);
  881. }
  882. }
  883. #endif
  884. String llvmDir = scope String(IDEApp.sApp.mInstallDir);
  885. IDEUtils.FixFilePath(llvmDir);
  886. llvmDir.Append("llvm/");
  887. if (hotProject != null)
  888. {
  889. if ((hotProject == project) || (hotProject.HasDependency(project.mProjectName)))
  890. {
  891. for (var fileName in bfFileNames)
  892. hotFileNames.Add(new String(fileName));
  893. }
  894. return true;
  895. }
  896. String objectsArg = scope String();
  897. var argBuilder = scope IDEApp.ArgBuilder(objectsArg, workspaceOptions.mToolsetType != .GNU);
  898. for (var bfFileName in bfFileNames)
  899. {
  900. argBuilder.AddFileName(bfFileName);
  901. argBuilder.AddSep();
  902. }
  903. for (var objName in clangAllObjNames)
  904. {
  905. IDEUtils.AppendWithOptionalQuotes(objectsArg, objName);
  906. objectsArg.Append(" ");
  907. }
  908. if (workspaceOptions.mToolsetType == .GNU)
  909. {
  910. if (!QueueProjectGNULink(project, targetPath, workspaceOptions, options, objectsArg))
  911. return false;
  912. }
  913. else // MS
  914. {
  915. if (!QueueProjectMSLink(project, targetPath, configSelection.mConfig, workspaceOptions, options, objectsArg))
  916. return false;
  917. }
  918. return true;
  919. }
  920. }
  921. }