public void ProcessAssemblies() { // // * Linking // Copy assemblies to LinkDirectory // Link and save to PreBuildDirectory // If marshalling native exceptions: // * Generate/calculate P/Invoke wrappers and save to PreBuildDirectory // [AOT assemblies in BuildDirectory] // Strip managed code save to TargetDirectory (or just copy the file if stripping is disabled). // // * No linking // If marshalling native exceptions: // Generate/calculate P/Invoke wrappers and save to PreBuildDirectory. // If not marshalling native exceptions: // Copy assemblies to PreBuildDirectory // Copy unmodified assemblies to BuildDirectory // [AOT assemblies in BuildDirectory] // Strip managed code save to TargetDirectory (or just copy the file if stripping is disabled). // // Note that we end up copying assemblies around quite much, // this is because we we're comparing contents instead of // filestamps, so we need the previous file around to be // able to do the actual comparison. For instance: in the // 'No linking' case above, we copy the assembly to PreBuild // before removing the resources and saving that result to Build. // The copy in PreBuild is required for the next build iteration, // to see if the original assembly has been modified or not (the // file in the Build directory might be different due to resource // removal even if the original assembly didn't change). // // This can probably be improved by storing digests/hashes instead // of the entire files, but this turned out a bit messy when // trying to make it work with the linker, so I decided to go for // simple file copying for now. // // // Other notes: // // * We need all assemblies in the same directory when doing AOT-compilation. // * We cannot overwrite in-place, because it will mess up dependency tracking // and besides if we overwrite in place we might not be able to ignore // insignificant changes (such as only a GUID change - the code is identical, // but we still need the original assembly since the AOT-ed image also stores // the GUID, and we fail at runtime if the GUIDs in the assembly and the AOT-ed // image don't match - if we overwrite in-place we lose the original assembly and // its GUID). // LinkDirectory = Path.Combine(ArchDirectory, "Link"); if (!Directory.Exists(LinkDirectory)) { Directory.CreateDirectory(LinkDirectory); } PreBuildDirectory = Path.Combine(ArchDirectory, "PreBuild"); if (!Directory.Exists(PreBuildDirectory)) { Directory.CreateDirectory(PreBuildDirectory); } BuildDirectory = Path.Combine(ArchDirectory, "Build"); if (!Directory.Exists(BuildDirectory)) { Directory.CreateDirectory(BuildDirectory); } if (!Directory.Exists(TargetDirectory)) { Directory.CreateDirectory(TargetDirectory); } ManagedLink(); if (App.RequiresPInvokeWrappers) { // Write P/Invokes var state = MarshalNativeExceptionsState; if (state.Started) { // The generator is 'started' by the linker, which means it may not // be started if the linker was not executed due to re-using cached results. state.End(); } PinvokesTask.Create(compile_tasks, Abis, this, state.SourcePath); if (App.FastDev) { // In this case assemblies must link with the resulting dylib, // so we can't compile the pinvoke dylib in parallel with later // stuff. compile_tasks.ExecuteInParallel(); } } // Now the assemblies are in PreBuildDirectory. foreach (var a in Assemblies) { var target = Path.Combine(BuildDirectory, a.FileName); if (!a.CopyAssembly(a.FullPath, target)) { Driver.Log(3, "Target '{0}' is up-to-date.", target); } a.FullPath = target; } Driver.GatherFrameworks(this, Frameworks, WeakFrameworks); // Make sure there are no duplicates between frameworks and weak frameworks. // Keep the weak ones. Frameworks.ExceptWith(WeakFrameworks); }
public void ProcessAssemblies() { // // * Linking // Copy assemblies to LinkDirectory // Link and save to PreBuildDirectory // * Has resourced to be removed: // Remove resource and save to NoResDirectory // Copy to BuildDirectory. [Why not save directly to BuildDirectory? Because otherwise if we're rebuilding // and the only thing that changed is the resources we're removing in this step, // we won't be able to detect that the remaining parts of the assembly // haven't changed.] // * No resources to be removed: // Copy to BuildDirectory. // [AOT assemblies in BuildDirectory] // Strip managed code save to TargetDirectory (or just copy the file if stripping is disabled). // // * No linking // Copy assembly to PreBuildDirectory. // * Has resourced to be removed: // Remove resource and save to NoResDirectory // Copy to BuildDirectory. // * No resources to be removed: // Copy to BuildDirectory. // [AOT assemblies in BuildDirectory] // Strip managed code save to TargetDirectory (or just copy the file if stripping is disabled). // // Note that we end up copying assemblies around quite much, // this is because we we're comparing contents instead of // filestamps, so we need the previous file around to be // able to do the actual comparison. For instance: in the // 'No linking' case above, we copy the assembly to PreBuild // before removing the resources and saving that result to Build. // The copy in PreBuild is required for the next build iteration, // to see if the original assembly has been modified or not (the // file in the Build directory might be different due to resource // removal even if the original assembly didn't change). // // This can probably be improved by storing digests/hashes instead // of the entire files, but this turned out a bit messy when // trying to make it work with the linker, so I decided to go for // simple file copying for now. // // // Other notes: // // * We need all assemblies in the same directory when doing AOT-compilation. // * We cannot overwrite in-place, because it will mess up dependency tracking // and besides if we overwrite in place we might not be able to ignore // insignificant changes (such as only a GUID change - the code is identical, // but we still need the original assembly since the AOT-ed image also stores // the GUID, and we fail at runtime if the GUIDs in the assembly and the AOT-ed // image don't match - if we overwrite in-place we lose the original assembly and // its GUID). // LinkDirectory = Path.Combine(ArchDirectory, "Link"); if (!Directory.Exists(LinkDirectory)) { Directory.CreateDirectory(LinkDirectory); } PreBuildDirectory = Path.Combine(ArchDirectory, "PreBuild"); if (!Directory.Exists(PreBuildDirectory)) { Directory.CreateDirectory(PreBuildDirectory); } BuildDirectory = Path.Combine(ArchDirectory, "Build"); if (!Directory.Exists(BuildDirectory)) { Directory.CreateDirectory(BuildDirectory); } NoResDirectory = Path.Combine(ArchDirectory, "NoRes"); if (!Directory.Exists(NoResDirectory)) { Directory.CreateDirectory(NoResDirectory); } if (!Directory.Exists(TargetDirectory)) { Directory.CreateDirectory(TargetDirectory); } ManagedLink(); // Now the assemblies are in PreBuildDirectory. // // PreBuildDirectory -> BuildDirectory [resource removal] // // Resource removal // * Remove any __monotouch_content_* or __monotouch_page_* resources // - This is already done in the linker, so there is no need to do it here if the linker is enabled (for user assemblies). // - It is only done for device-builds. Xamarin Studio requires the resources to be present (to extract // them) - which is not a problem for device-builds since we operate on a copied assembly, not the // original like Xamarin Studio does). // * Remove any LinkWith-related resources // var remove_res = App.IsDeviceBuild && App.LinkMode != LinkMode.All; foreach (var a in Assemblies) { var target = Path.Combine(BuildDirectory, a.FileName); if (!Application.IsUptodate(a.FullPath, target)) { a.RemoveResources(remove_res, BuildDirectory, NoResDirectory); } else { a.FullPath = target; Driver.Log(3, "Target '{0}' is up-to-date.", target); } } Driver.Watch("Removing Resources", 1); Driver.GatherFrameworks(this, Frameworks, WeakFrameworks); // Make sure there are no duplicates between frameworks and weak frameworks. // Keep the weak ones. Frameworks.ExceptWith(WeakFrameworks); }