Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }