Beispiel #1
0
        /// <summary>
        /// Initialize the config system with the given types
        /// </summary>
        public static bool ReadConfigFiles()
        {
            // Find all the configurable types
            List <Type> ConfigTypes = FindConfigurableTypes();

            // Find all the input files
            FileReference[] InputFiles = FindInputFiles().Select(x => x.Location).ToArray();

            // Get the path to the cache file
            FileReference CacheFile  = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "Build", "XmlConfigCache.bin");
            FileReference SchemaFile = GetSchemaLocation();

            // Try to read the existing cache from disk
            XmlConfigData CachedValues;

            if (IsCacheUpToDate(CacheFile, InputFiles) && FileReference.Exists(SchemaFile))
            {
                if (XmlConfigData.TryRead(CacheFile, ConfigTypes, out CachedValues) && Enumerable.SequenceEqual(InputFiles, CachedValues.InputFiles))
                {
                    Values = CachedValues;
                }
            }

            // If that failed, regenerate it
            if (Values == null)
            {
                // Find all the configurable fields from the given types
                Dictionary <string, Dictionary <string, FieldInfo> > CategoryToFields = new Dictionary <string, Dictionary <string, FieldInfo> >();
                FindConfigurableFields(ConfigTypes, CategoryToFields);

                // Create a schema for the config files
                XmlSchema Schema = CreateSchema(CategoryToFields);
                WriteSchema(Schema, SchemaFile);

                // Read all the XML files and validate them against the schema
                Dictionary <Type, Dictionary <FieldInfo, object> > TypeToValues = new Dictionary <Type, Dictionary <FieldInfo, object> >();
                foreach (FileReference InputFile in InputFiles)
                {
                    if (!TryReadFile(InputFile, CategoryToFields, TypeToValues, Schema))
                    {
                        Log.TraceError("Failed to properly read XML file : {0}", InputFile.FullName);

                        return(false);
                    }
                }

                // Create the new cache
                Values = new XmlConfigData(InputFiles, TypeToValues.ToDictionary(x => x.Key, x => x.Value.ToArray()));
                Values.Write(CacheFile);
            }

            // Apply all the static field values
            foreach (KeyValuePair <Type, KeyValuePair <FieldInfo, object>[]> TypeValuesPair in Values.TypeToValues)
            {
                foreach (KeyValuePair <FieldInfo, object> FieldValuePair in TypeValuesPair.Value)
                {
                    if (FieldValuePair.Key.IsStatic)
                    {
                        object Value = InstanceValue(FieldValuePair.Value, FieldValuePair.Key.FieldType);
                        FieldValuePair.Key.SetValue(null, Value);
                    }
                }
            }
            return(true);
        }
Beispiel #2
0
        /// <summary>
        /// Initialize the config system with the given types
        /// </summary>
        /// <param name="OverrideCacheFile">Force use of the cached XML config without checking if it's valid (useful for remote builds)</param>
        public static void ReadConfigFiles(FileReference OverrideCacheFile)
        {
            // Find all the configurable types
            List <Type> ConfigTypes = FindConfigurableTypes();

            // Update the cache if necessary
            if (OverrideCacheFile != null)
            {
                // Set the cache file to the overriden value
                CacheFile = OverrideCacheFile;

                // Never rebuild the cache; just try to load it.
                if (!XmlConfigData.TryRead(CacheFile, ConfigTypes, out Values))
                {
                    throw new BuildException("Unable to load XML config cache ({0})", CacheFile);
                }
            }
            else
            {
                // Get the default cache file
                CacheFile = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "Build", "XmlConfigCache.bin");
                if (UnrealBuildTool.IsEngineInstalled())
                {
                    DirectoryReference UserSettingsDir = Utils.GetUserSettingDirectory();
                    if (UserSettingsDir != null)
                    {
                        CacheFile = FileReference.Combine(UserSettingsDir, "UnrealEngine", String.Format("XmlConfigCache-{0}.bin", UnrealBuildTool.RootDirectory.FullName.Replace(":", "").Replace(Path.DirectorySeparatorChar, '+')));
                    }
                }

                // Find all the input files
                FileReference[] InputFiles = FindInputFiles().Select(x => x.Location).ToArray();

                // Get the path to the schema
                FileReference SchemaFile = GetSchemaLocation();

                // Try to read the existing cache from disk
                XmlConfigData CachedValues;
                if (IsCacheUpToDate(CacheFile, InputFiles) && FileReference.Exists(SchemaFile))
                {
                    if (XmlConfigData.TryRead(CacheFile, ConfigTypes, out CachedValues) && Enumerable.SequenceEqual(InputFiles, CachedValues.InputFiles))
                    {
                        Values = CachedValues;
                    }
                }

                // If that failed, regenerate it
                if (Values == null)
                {
                    // Find all the configurable fields from the given types
                    Dictionary <string, Dictionary <string, FieldInfo> > CategoryToFields = new Dictionary <string, Dictionary <string, FieldInfo> >();
                    FindConfigurableFields(ConfigTypes, CategoryToFields);

                    // Create a schema for the config files
                    XmlSchema Schema = CreateSchema(CategoryToFields);
                    if (!UnrealBuildTool.IsEngineInstalled())
                    {
                        WriteSchema(Schema, SchemaFile);
                    }

                    // Read all the XML files and validate them against the schema
                    Dictionary <Type, Dictionary <FieldInfo, object> > TypeToValues = new Dictionary <Type, Dictionary <FieldInfo, object> >();
                    foreach (FileReference InputFile in InputFiles)
                    {
                        if (!TryReadFile(InputFile, CategoryToFields, TypeToValues, Schema))
                        {
                            throw new BuildException("Failed to properly read XML file : {0}", InputFile.FullName);
                        }
                    }

                    // Make sure the cache directory exists
                    DirectoryReference.CreateDirectory(CacheFile.Directory);

                    // Create the new cache
                    Values = new XmlConfigData(InputFiles, TypeToValues.ToDictionary(x => x.Key, x => x.Value.ToArray()));
                    Values.Write(CacheFile);
                }
            }

            // Apply all the static field values
            foreach (KeyValuePair <Type, KeyValuePair <FieldInfo, object>[]> TypeValuesPair in Values.TypeToValues)
            {
                foreach (KeyValuePair <FieldInfo, object> FieldValuePair in TypeValuesPair.Value)
                {
                    if (FieldValuePair.Key.IsStatic)
                    {
                        object Value = InstanceValue(FieldValuePair.Value, FieldValuePair.Key.FieldType);
                        FieldValuePair.Key.SetValue(null, Value);
                    }
                }
            }
        }
        /// <summary>
        /// Attempts to read a previous block of config values from disk
        /// </summary>
        /// <param name="Location">The file to read from</param>
        /// <param name="Types">Array of valid types. Used to resolve serialized type names to concrete types.</param>
        /// <param name="Data">On success, receives the parsed data</param>
        /// <returns>True if the data was read and is valid</returns>
        public static bool TryRead(FileReference Location, IEnumerable <Type> Types, out XmlConfigData Data)
        {
            // Check the file exists first
            if (!FileReference.Exists(Location))
            {
                Data = null;
                return(false);
            }

            // Read the cache from disk
            using (BinaryReader Reader = new BinaryReader(File.Open(Location.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)))
            {
                // Check the serialization version matches
                if (Reader.ReadInt32() != SerializationVersion)
                {
                    Data = null;
                    return(false);
                }

                // Read the input files
                FileReference[] InputFiles = Reader.ReadArray(() => Reader.ReadFileReference());

                // Read the types
                int NumTypes = Reader.ReadInt32();
                Dictionary <Type, KeyValuePair <FieldInfo, object>[]> TypeToValues = new Dictionary <Type, KeyValuePair <FieldInfo, object>[]>(NumTypes);
                for (int TypeIdx = 0; TypeIdx < NumTypes; TypeIdx++)
                {
                    // Read the type name
                    string TypeName = Reader.ReadString();

                    // Try to find it in the list of configurable types
                    Type Type = Types.FirstOrDefault(x => x.Name == TypeName);
                    if (Type == null)
                    {
                        Data = null;
                        return(false);
                    }

                    // Read all the values
                    KeyValuePair <FieldInfo, object>[] Values = new KeyValuePair <FieldInfo, object> [Reader.ReadInt32()];
                    for (int ValueIdx = 0; ValueIdx < Values.Length; ValueIdx++)
                    {
                        string FieldName = Reader.ReadString();

                        // Find the matching field on the output type
                        FieldInfo Field = Type.GetField(FieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
                        if (Field == null || Field.GetCustomAttribute <XmlConfigFileAttribute>() == null)
                        {
                            Data = null;
                            return(false);
                        }

                        // Try to parse the value and add it to the output array
                        object Value = Reader.ReadObject(Field.FieldType);
                        Values[ValueIdx] = new KeyValuePair <FieldInfo, object>(Field, Value);
                    }

                    // Add it to the type map
                    TypeToValues.Add(Type, Values);
                }

                // Return the parsed data
                Data = new XmlConfigData(InputFiles.ToArray(), TypeToValues);
                return(true);
            }
        }