/// <summary> /// Performs the link. /// </summary> /// <param name="TheLibrary">The root library to link.</param> /// <returns>CompileResult.OK if the link succeeded. Otherwise, CompileResult.Fail.</returns> public static CompileResult Link(IL.ILLibrary TheLibrary, bool dependency = false, string Name = null) { bool OK = true; // If: Link to ELF and Libraries // - Link sub-libs to .a files // - Link main lib to .elf file (if present) // If: Link to ISO // - Generate basic link-script // - Generate full link-script by inserting necessary file location instructions for all object files // - Execute ld to build bin file // - Execute ISO9660Generator to build .ISO file if (Options.LinkMode == Options.LinkModes.ELF) { // Check for main method. If found, that library gets linked to Executable not Shared Lib List<string> depLibNames = new List<string>(); foreach (IL.ILLibrary depLib in TheLibrary.Dependencies) { string depLibName = Utilities.CleanFileName(depLib.TheAssembly.GetName().Name); if (Options.ShortenDependencyNames) { if (!DependencyNameMapping.ContainsKey(depLibName)) { DependencyNameMapping.Add(depLibName, (NameGenerator++).ToString()); } depLibName = DependencyNameMapping[depLibName]; } depLibNames.Add(depLibName); OK = OK && (Link(depLib, true, depLibName) == CompileResult.OK); if (!OK) { break; } } if (!OK) { return CompileResult.Fail; } List<ASM.ASMBlock> SequencedASMBlocks = new List<ASM.ASMBlock>(); SequencedASMBlocks.AddRange(TheLibrary.TheASMLibrary.ASMBlocks); SequencedASMBlocks.Sort(GetOrder); SequencedASMBlocks.ForEach(delegate(ASM.ASMBlock block) { if (block != null && block.OriginMethodInfo != null) { DebugDataWriter.AddMethodMapping(block.OriginMethodInfo.ID, block.ASMOutputFilePath); } }); // Find start method if any, use as ENTRY point bool ExecutableOutput = false; string EntryPoint = null; if (IL.ILLibrary.SpecialMethods.ContainsKey(typeof(Attributes.MainMethodAttribute))) { Types.MethodInfo mainMethodInfo = IL.ILLibrary.SpecialMethods[typeof(Attributes.MainMethodAttribute)].First(); IL.ILBlock mainMethodBlock = TheLibrary.GetILBlock(mainMethodInfo, false); if (mainMethodBlock != null) { ExecutableOutput = true; EntryPoint = mainMethodInfo.ID; } } if (Options.ShortenDependencyNames && string.IsNullOrWhiteSpace(Name)) { Name = "Driver"; } string AssemblyName = string.IsNullOrWhiteSpace(Name) ? Utilities.CleanFileName(TheLibrary.TheAssembly.GetName().Name) : Name; DebugDataWriter.SaveDataFiles(Options.OutputPath, AssemblyName); DebugDataWriter.SaveLibraryInfo(Options.OutputPath, TheLibrary); LinkInformation LinkInfo = new LinkInformation() { ToolsPath = Options.ToolsPath, LinkScriptCmdPath = Path.Combine(Options.OutputPath, @"DriversCompiler\" + AssemblyName + "_linker_command.txt"), LinkScriptPath = Path.Combine(Options.OutputPath, @"DriversCompiler\" + AssemblyName + "_linker.ld"), BinPath = Path.Combine(Options.OutputPath, "Output\\" + (ExecutableOutput ? AssemblyName + ".elf" : "Lib" + AssemblyName + ".a")), MapPath = Path.Combine(Options.OutputPath, AssemblyName + ".map"), ASMPath = Path.Combine(Options.OutputPath, AssemblyName + ".new.asm"), LdWorkingDir = Path.Combine(Options.OutputPath, "") + "\\", ExecutableOutput = ExecutableOutput, EntryPoint = EntryPoint, SequencedASMBlocks = SequencedASMBlocks, depLibNames = depLibNames }; if (!Directory.Exists(Path.GetDirectoryName(LinkInfo.BinPath))) { Directory.CreateDirectory(Path.GetDirectoryName(LinkInfo.BinPath)); } OK = TargetArchitecture.TargetFunctions.LinkELF(TheLibrary, LinkInfo); if (OK) { DebugDataWriter.ProcessMapFile(LinkInfo.MapPath); } } else if (Options.LinkMode == Options.LinkModes.ISO) { List<ASM.ASMBlock> SequencedASMBlocks = new List<ASM.ASMBlock>(); List<IL.ILLibrary> FlattenedLibs = TheLibrary.Flatten(); foreach (IL.ILLibrary depLib in FlattenedLibs) { SequencedASMBlocks.AddRange(depLib.TheASMLibrary.ASMBlocks); DebugDataWriter.SaveLibraryInfo(Options.OutputPath, depLib); } SequencedASMBlocks.Sort(GetOrder); SequencedASMBlocks.ForEach(delegate(ASM.ASMBlock block) { if (block != null && block.OriginMethodInfo != null) { DebugDataWriter.AddMethodMapping(block.OriginMethodInfo.ID, block.ASMOutputFilePath); } }); string AssemblyName = Utilities.CleanFileName(TheLibrary.TheAssembly.GetName().Name); DebugDataWriter.SaveDataFiles(Options.OutputPath, AssemblyName); DebugDataWriter.SaveLibraryInfo(Options.OutputPath, TheLibrary); LinkInformation LinkInfo = new LinkInformation() { ToolsPath = Options.ToolsPath, ISOGenPath = Path.Combine(Options.ToolsPath, @"ISO9660Generator.exe"), ISOToolsDirPath = Path.Combine(Options.ToolsPath, @"ISO"), ISODirPath = Path.Combine(Options.OutputPath, @"DriversCompiler\ISO"), LinkScriptPath = Path.Combine(Options.OutputPath, @"DriversCompiler\linker.ld"), BinPath = Path.Combine(Options.OutputPath, @"DriversCompiler\ISO\Kernel.bin"), ISOLinuxPath = Path.Combine(Options.OutputPath, @"DriversCompiler\ISO\" + (Options.BuildMode == Options.BuildModes.Debug ? "isolinux-debug.bin" : "isolinux.bin")), ISOPath = Path.Combine(Options.OutputPath, AssemblyName + ".iso"), MapPath = Path.Combine(Options.OutputPath, AssemblyName + ".map"), ASMPath = Path.Combine(Options.OutputPath, AssemblyName + ".new.asm"), LdWorkingDir = Path.Combine(Options.OutputPath, "DriversCompiler") + "\\", SequencedASMBlocks = SequencedASMBlocks }; if (Directory.Exists(LinkInfo.ISODirPath)) { Directory.Delete(LinkInfo.ISODirPath, true); } CopyDirectory(LinkInfo.ISOToolsDirPath, LinkInfo.ISODirPath, true); OK = TargetArchitecture.TargetFunctions.LinkISO(TheLibrary, LinkInfo); if (OK) { DebugDataWriter.ProcessMapFile(LinkInfo.MapPath); } } return OK ? CompileResult.OK : CompileResult.Fail; }