private static Type GenerateDebugProject(IAssemblyInfo assemblyInfo, bool isSetupProject, string startArguments, IDictionary <string, Type> visited, string[] defines)
        {
            string displayName = assemblyInfo.DebugProjectName;

            if (string.IsNullOrEmpty(displayName))
            {
                displayName = isSetupProject ? "sharpmake_debug" : $"sharpmake_package_{assemblyInfo.Id.GetHashCode():X8}";
            }

            Type generatedProject;

            if (visited.TryGetValue(assemblyInfo.Id, out generatedProject))
            {
                if (generatedProject == null)
                {
                    throw new Error($"Circular sharpmake package dependency on {displayName}");
                }
                return(generatedProject);
            }

            visited[assemblyInfo.Id] = null;

            ProjectContent project = new ProjectContent
            {
                ProjectFolder  = RootPath,
                IsSetupProject = isSetupProject,
                DisplayName    = displayName,
                StartArguments = startArguments
            };

            generatedProject = CreateProject(displayName);
            DebugProjects.Add(generatedProject, project);

            // Add sources
            foreach (var source in assemblyInfo.SourceFiles)
            {
                project.ProjectFiles.Add(source);
            }

            // Add references
            var references = new HashSet <string>();

            if (assemblyInfo.UseDefaultReferences)
            {
                foreach (string defaultReference in Assembler.DefaultReferences)
                {
                    references.Add(Assembler.GetAssemblyDllPath(defaultReference));
                }
            }

            foreach (var assemblerRef in assemblyInfo.References)
            {
                if (!assemblyInfo.SourceReferences.ContainsKey(assemblerRef))
                {
                    references.Add(assemblerRef);
                }
            }

            project.References.AddRange(references);

            foreach (var refInfo in assemblyInfo.SourceReferences.Values)
            {
                project.ProjectReferences.Add(GenerateDebugProject(refInfo, false, string.Empty, visited, defines));
            }

            if (defines != null)
            {
                project.Defines.AddRange(defines);
            }

            visited[assemblyInfo.Id] = generatedProject;

            return(generatedProject);
        }
Example #2
0
        public static TDelegate BuildDelegate <TDelegate>(string sourceFilePath, string fullFunctionName, Assembly[] assemblies)
            where TDelegate : class
        {
            FileInfo fileInfo = new FileInfo(sourceFilePath);

            if (!fileInfo.Exists)
            {
                throw new Error("source file name not found: {0}", sourceFilePath);
            }

            Type delegateType = typeof(TDelegate);

            Error.Valid(IsDelegate(delegateType), "BuildDelegate<FUNC_TYPE>(), FUNC_TYPE is not a delegate");
            MethodInfo delegateMethodInfo = GetDelegateMethodInfo(delegateType);


            ParameterInfo[] delegateParameterInfos = delegateMethodInfo.GetParameters();
            ParameterInfo   delegateReturnInfos    = delegateMethodInfo.ReturnParameter;

            Assembler assembler = new Assembler();

            assembler.UseDefaultReferences = false;
            assembler.Assemblies.AddRange(assemblies);

            Assembly assembly = assembler.BuildAssembly(fileInfo.FullName);

            List <MethodInfo> matchMethods = new List <MethodInfo>();

            foreach (Type type in assembly.GetTypes())
            {
                MethodInfo[] methodInfos = type.GetMethods();

                foreach (MethodInfo methodInfo in methodInfos)
                {
                    string fullName = methodInfo.DeclaringType.FullName + "." + methodInfo.Name;
                    if (fullFunctionName == fullName &&
                        methodInfo.IsStatic && methodInfo.GetParameters().Length == delegateMethodInfo.GetParameters().Length)
                    {
                        ParameterInfo[] parameterInfos = methodInfo.GetParameters();
                        ParameterInfo   returnInfos    = methodInfo.ReturnParameter;

                        bool equal = (returnInfos.GetType() == delegateReturnInfos.GetType() &&
                                      parameterInfos.Length == delegateParameterInfos.Length);

                        if (equal)
                        {
                            for (int i = 0; i < parameterInfos.Length; ++i)
                            {
                                if (parameterInfos[i].GetType() != delegateParameterInfos[i].GetType())
                                {
                                    equal = false;
                                    break;
                                }
                            }
                        }
                        if (equal)
                        {
                            matchMethods.Add(methodInfo);
                        }
                    }
                }
            }

            if (matchMethods.Count != 1)
            {
                throw new Error("Cannot find method name {0} that match {1} in {2}", fullFunctionName, delegateMethodInfo.ToString(), sourceFilePath);
            }

            MethodInfo method = matchMethods[0];

            // bind the method
            Delegate returnDelegate;

            try
            {
                returnDelegate = method.CreateDelegate(delegateType);
                InternalError.Valid(returnDelegate != null);
            }
            catch (Exception e)
            {
                throw new InternalError(e);
            }

            TDelegate result = returnDelegate as TDelegate;

            InternalError.Valid(result != null, "Cannot cast built delegate into user delegate");

            return(result);
        }
Example #3
0
        public static TDelegate BuildDelegate <TDelegate>(string functionBody, string functionNamespace, string[] usingNamespaces, Assembly[] assemblies)
            where TDelegate : class
        {
            Assembler assembler = new Assembler();

            assembler.UseDefaultReferences = false;
            assembler.Assemblies.AddRange(assemblies);

            const string className  = "AssemblerBuildFunction_Class";
            const string methodName = "AssemblerBuildFunction_Method";

            // Fix : Bug with -> Path.GetTempFileName
            // http://msdn.microsoft.com/en-ca/library/windows/desktop/aa364991(v=vs.85).aspx
            // Limit of 65535 limit on files when generating the temp file. New temp file will use
            // a new Guid as filename and Sharpmake will clean the temporary files when done by aggregating
            // the temp files and deleting them.
            // eg. "C:\\fastbuild-work\\85f7d472c25d494ca09f2ea7fe282d50"
            //string sourceTmpFile = Path.GetTempFileName();
            string sourceTmpFile = Path.Combine(Path.GetTempPath(), (Guid.NewGuid().ToString("N") + ".tmp"));

            Type delegateType = typeof(TDelegate);

            Error.Valid(IsDelegate(delegateType), "BuildDelegate<TDelegate>(), TDelegate is not a delegate");

            MethodInfo methodInfo = GetDelegateMethodInfo(delegateType);

            using (StreamWriter writer = new StreamWriter(sourceTmpFile))
            {
                // add using namespace...
                foreach (string usingNamespace in usingNamespaces)
                {
                    writer.WriteLine("using {0};", usingNamespace);
                }
                writer.WriteLine();

                // namespace name
                writer.WriteLine("namespace {0}", functionNamespace);
                writer.WriteLine("{");
                writer.WriteLine("    public static class {0}", className);
                writer.WriteLine("    {");

                // write method signature
                string returnTypeName = methodInfo.ReturnType == typeof(void) ? "void" : methodInfo.ReturnType.FullName;
                writer.Write("        public static {0} {1}(", returnTypeName, methodName);
                ParameterInfo[] parameters = methodInfo.GetParameters();
                for (int i = 0; i < parameters.Length; i++)
                {
                    string parametersName = parameters[i].Name;
                    string parametersType = (parameters[i].ParameterType == typeof(Object)) ? "Object" : parameters[i].ParameterType.FullName;

                    writer.Write("{0}{1} {2}", i == 0 ? "" : ", ", parametersType, parametersName);
                }
                writer.WriteLine(")");
                // write method body
                writer.WriteLine("        {");
                writer.WriteLine("            {0}" + Environment.NewLine, functionBody.Replace("\n", "\n            "));
                writer.WriteLine("        }");
                writer.WriteLine("    }");
                writer.WriteLine("}");
            }

            // build in memory
            Assembly assembly = assembler.Build(builderContext: null, libraryFile: null, sources: sourceTmpFile).Assembly;

            InternalError.Valid(assembly != null);

            // Try to delete tmp file to prevent pollution, but useful while debugging
            //if (!System.Diagnostics.Debugger.IsAttached)
            Util.TryDeleteFile(sourceTmpFile);

            // Scan assembly to find our tmp class
            string fullClassName = functionNamespace + "." + className;
            Type   buildedType   = assembly.GetType(fullClassName);

            // get out method to bind into the delegate
            MethodInfo builtMethod = buildedType.GetMethod(methodName);

            InternalError.Valid(builtMethod != null);

            // bind the method
            Delegate returnDelegate;

            try
            {
                returnDelegate = builtMethod.CreateDelegate(delegateType);
                InternalError.Valid(returnDelegate != null);
            }
            catch (Exception e)
            {
                throw new InternalError(e);
            }

            TDelegate result = returnDelegate as TDelegate;

            InternalError.Valid(result != null, "Cannot cast built delegate into user delegate");

            return(result);
        }
Example #4
0
        private static void Execute(Type type, object instance, string commandLine, string[] namespaces)
        {
            bool isStatic = instance == null;

            Parameter[] parameters = GetParameters(commandLine);
            if (parameters.Length == 0)
            {
                return;
            }

            HashSet <string> namespacesSet = new HashSet <string>();

            namespacesSet.UnionWith(namespaces);
            namespacesSet.Add(type.Namespace);

            StringBuilder errors = new StringBuilder();

            Dictionary <string, List <MethodInfo> > optionsNameMethodMapping = GetMethodsMapping(type, isStatic);

            // use to not call more than one for method with parameter overloading...
            HashSet <string> executedMethods = new HashSet <string>();

            // tell to use all loaded assembly
            List <Assembly> assemblies = new List <Assembly>(AppDomain.CurrentDomain.GetAssemblies());

            // in case of scripted c#, associated assembly may not be loaded in the current application domain.
            if (!assemblies.Contains(type.Assembly))
            {
                assemblies.Add(type.Assembly);
            }

            foreach (Parameter parameter in parameters)
            {
                executedMethods.Clear();

                List <MethodInfo> methodInfos;
                if (optionsNameMethodMapping.TryGetValue(parameter.Name, out methodInfos))
                {
                    foreach (MethodInfo methodInfo in methodInfos)
                    {
                        try
                        {
                            string uniqueExecutedMethodName = methodInfo.Name + parameter;
                            if (executedMethods.Contains(uniqueExecutedMethodName))
                            {
                                continue;
                            }

                            if (isStatic)
                            {
                                string executeCode = String.Format("{0}.{1}({2});", type.FullName.Replace("+", "."), methodInfo.Name, parameter.Args);
                                Action execute     = Assembler.BuildDelegate <Action>(executeCode, type.Namespace, DefaultNamespaces.ToArray(), assemblies.ToArray());

                                execute();
                            }
                            else
                            {
                                string          executeCode = String.Format("((global::{0})obj).{1}({2});", type.FullName.Replace("+", "."), methodInfo.Name, parameter.Args);
                                Action <object> execute     = Assembler.BuildDelegate <Action <object> >(executeCode, type.Namespace, DefaultNamespaces.ToArray(), assemblies.ToArray());

                                execute(instance);
                            }
                            executedMethods.Add(uniqueExecutedMethodName);
                        }
                        catch (Error e)
                        {
                            string[] parametersName = methodInfo.GetParameters().Select((ParameterInfo p) => p.ToString()).ToArray();
                            errors.Append(String.Format("Command line option '/{0}' have invalid parameters '({1})', maybe not compatible with '({2})'" + Environment.NewLine + "\t",
                                                        parameter.Name,
                                                        parameter.Args,
                                                        String.Join(", ", parametersName)));

                            errors.Append(e.Message + Environment.NewLine);
                        }
                    }
                }
            }
            if (errors.Length != 0)
            {
                throw new Error(errors.ToString());
            }
        }