/// <summary> /// Adds a rule which matches a filename relative to a given base directory. /// </summary> /// <param name="FileName">The filename to add a rule for</param> /// <param name="BaseDirectoryName">Base directory for the rule</param> /// <param name="Type">Whether to add an include or exclude rule</param> public void AddRuleForFile(FileReference File, DirectoryReference BaseDirectory, FileFilterType Type) { AddRuleForFiles(new FileReference[] { File }, BaseDirectory, Type); }
/// <summary> /// Applies the filter to each element in a sequence, and returns the list of files that match /// </summary> /// <param name="FileNames">List of filenames</param> /// <returns>List of filenames which match the filter</returns> public IEnumerable <FileReference> ApplyTo(DirectoryReference BaseDirectory, IEnumerable <FileReference> FileNames) { return(FileNames.Where(x => Matches(x.MakeRelativeTo(BaseDirectory)))); }
/// <summary> /// Combine several fragments with a base directory, to form a new filename /// </summary> /// <param name="BaseDirectory">The base directory</param> /// <param name="Fragments">Fragments to combine with the base directory</param> /// <returns>The new file name</returns> public static FileReference Combine(DirectoryReference BaseDirectory, params string[] Fragments) { string FullName = FileSystemReference.CombineStrings(BaseDirectory, Fragments); return(new FileReference(FullName, FullName.ToLowerInvariant())); }
/// <summary> /// Create a full path by concatenating multiple strings /// </summary> /// <returns></returns> static protected string CombineStrings(DirectoryReference BaseDirectory, params string[] Fragments) { // Get the initial string to append to, and strip any root directory suffix from it StringBuilder NewFullName = new StringBuilder(BaseDirectory.FullName); if (NewFullName.Length > 0 && NewFullName[NewFullName.Length - 1] == Path.DirectorySeparatorChar) { NewFullName.Remove(NewFullName.Length - 1, 1); } // Scan through the fragments to append, appending them to a string and updating the base length as we go foreach (string Fragment in Fragments) { // Check if this fragment is an absolute path if ((Fragment.Length >= 2 && Fragment[1] == ':') || (Fragment.Length >= 1 && (Fragment[0] == '\\' || Fragment[0] == '/'))) { // It is. Reset the new name to the full version of this path. NewFullName.Clear(); NewFullName.Append(Path.GetFullPath(Fragment).TrimEnd(Path.DirectorySeparatorChar)); } else { // Append all the parts of this fragment to the end of the existing path. int StartIdx = 0; while (StartIdx < Fragment.Length) { // Find the end of this fragment. We may have been passed multiple paths in the same string. int EndIdx = StartIdx; while (EndIdx < Fragment.Length && Fragment[EndIdx] != '\\' && Fragment[EndIdx] != '/') { EndIdx++; } // Ignore any empty sections, like leading or trailing slashes, and '.' directory references. int Length = EndIdx - StartIdx; if (Length == 0) { // Multiple directory separators in a row; illegal. throw new ArgumentException(String.Format("Path fragment '{0}' contains invalid directory separators.", Fragment)); } else if (Length == 2 && Fragment[StartIdx] == '.' && Fragment[StartIdx + 1] == '.') { // Remove the last directory name for (int SeparatorIdx = NewFullName.Length - 1; SeparatorIdx >= 0; SeparatorIdx--) { if (NewFullName[SeparatorIdx] == Path.DirectorySeparatorChar) { NewFullName.Remove(SeparatorIdx, NewFullName.Length - SeparatorIdx); break; } } } else if (Length != 1 || Fragment[StartIdx] != '.') { // Append this fragment NewFullName.Append(Path.DirectorySeparatorChar); NewFullName.Append(Fragment, StartIdx, Length); } // Move to the next part StartIdx = EndIdx + 1; } } } // Append the directory separator if (NewFullName.Length == 0 || (NewFullName.Length == 2 && NewFullName[1] == ':')) { NewFullName.Append(Path.DirectorySeparatorChar); } // Set the new path variables return(NewFullName.ToString()); }
/// <summary> /// Creates a relative path from the given base directory /// </summary> /// <param name="Directory">The directory to create a relative path from</param> /// <returns>A relative path from the given directory</returns> public string MakeRelativeTo(DirectoryReference Directory) { // Find how much of the path is common between the two paths. This length does not include a trailing directory separator character. int CommonDirectoryLength = -1; for (int Idx = 0; ; Idx++) { if (Idx == CanonicalName.Length) { // The two paths are identical. Just return the "." character. if (Idx == Directory.CanonicalName.Length) { return("."); } // Check if we're finishing on a complete directory name if (Directory.CanonicalName[Idx] == Path.DirectorySeparatorChar) { CommonDirectoryLength = Idx; } break; } else if (Idx == Directory.CanonicalName.Length) { // Check whether the end of the directory name coincides with a boundary for the current name. if (CanonicalName[Idx] == Path.DirectorySeparatorChar) { CommonDirectoryLength = Idx; } break; } else { // Check the two paths match, and bail if they don't. Increase the common directory length if we've reached a separator. if (CanonicalName[Idx] != Directory.CanonicalName[Idx]) { break; } if (CanonicalName[Idx] == Path.DirectorySeparatorChar) { CommonDirectoryLength = Idx; } } } // If there's no relative path, just return the absolute path if (CommonDirectoryLength == -1) { return(FullName); } // Append all the '..' separators to get back to the common directory, then the rest of the string to reach the target item StringBuilder Result = new StringBuilder(); for (int Idx = CommonDirectoryLength + 1; Idx < Directory.CanonicalName.Length; Idx++) { // Move up a directory Result.Append(".."); Result.Append(Path.DirectorySeparatorChar); // Scan to the next directory separator while (Idx < Directory.CanonicalName.Length && Directory.CanonicalName[Idx] != Path.DirectorySeparatorChar) { Idx++; } } if (CommonDirectoryLength + 1 < FullName.Length) { Result.Append(FullName, CommonDirectoryLength + 1, FullName.Length - CommonDirectoryLength - 1); } return(Result.ToString()); }
/// <summary> /// Determines if the given object is at or under the given directory /// </summary> /// <param name="Directory"></param> /// <returns></returns> public bool IsUnderDirectory(DirectoryReference Other) { return(CanonicalName.StartsWith(Other.CanonicalName) && (CanonicalName.Length == Other.CanonicalName.Length || CanonicalName[Other.CanonicalName.Length] == Path.DirectorySeparatorChar)); }
/// <summary> /// Gets include directories that the compiler knows about. /// </summary> public static void GetSystemIncludeDirectories(CompileEnvironment CompileEnv, DirectoryReference InputDir, List <DirectoryReference> ExtraSystemIncludePaths) { // FIXME: assumes clang now, and assumes certain hard-coded dirs. Can be improved by querying the compiler instead. DirectoryReference SysRootDir = CompileEnv.Options.Where(x => x.Name.StartsWith("--sysroot=")).Select(x => new DirectoryReference(x.Name.Substring(10))).First(); string CompilerFullPath = CompileEnv.Compiler.FullName; ExtraSystemIncludePaths.Add(DirectoryReference.Combine(SysRootDir, "usr", "include")); string CompilerVersionString = DetermineClangVersionDir(CompilerFullPath); if (!String.IsNullOrEmpty(CompilerVersionString)) { ExtraSystemIncludePaths.Add(DirectoryReference.Combine(SysRootDir, "lib", "clang", CompilerVersionString, "include")); } ExtraSystemIncludePaths.Add(DirectoryReference.Combine(InputDir, "Engine", "Source", "ThirdParty", "Linux", "LibCxx", "include", "c++", "v1")); }