github.com/atrn/dcc@v0.0.0-20220806184050-4470d2553272/find.go (about) 1 // dcc - dependency-driven C/C++ compiler front end 2 // 3 // Copyright © A.Newman 2015. 4 // 5 // This source code is released under version 2 of the GNU Public License. 6 // See the file LICENSE for details. 7 // 8 9 package main 10 11 import ( 12 "log" 13 "os" 14 "path/filepath" 15 ) 16 17 // FindFile returns a path for a filename and a flag indicating if the 18 // file was actually found. 19 // 20 func FindFile(filename string) (string, bool) { 21 ofilename := filename 22 if DebugFind { 23 log.Printf("DEBUG FIND: FindFile %q", ofilename) 24 } 25 path, _, exists, err := FindFileFromCwd(filename) 26 if err == nil && exists { 27 if DebugFind { 28 log.Printf("DEBUG FIND: FindFile %q -> %q", filename, path) 29 } 30 return path, true 31 } 32 if err != nil { 33 log.Print(err) 34 } 35 if DebugFind { 36 log.Printf("DEBUG FIND: FindFile %q -> %q", filename, filename) 37 } 38 return filename, false 39 } 40 41 // FindFileFromCwd finds a file starting from the current directory and searching towards the root. 42 // 43 func FindFileFromCwd(filename string) (string, os.FileInfo, bool, error) { 44 if DebugFind { 45 log.Printf("DEBUG FIND: FindFileFromCwd %q", filename) 46 } 47 return FindFileFromDirectory(filename, MustGetwd()) 48 } 49 50 // FindFileFromDirectory finds a file starting from the specified directory, search towards the root. 51 // 52 func FindFileFromDirectory(filename, dir string) (string, os.FileInfo, bool, error) { 53 if DebugFind { 54 log.Printf("DEBUG FIND: FindFileFromDirectory %q %q", filename, dir) 55 } 56 if !filepath.IsAbs(dir) { 57 path, err := filepath.Abs(dir) 58 if err != nil { 59 return "", nil, false, err 60 } 61 dir = path 62 } 63 paths := []string{dir} 64 for !platform.IsRoot(dir) { 65 dir = filepath.Dir(dir) 66 paths = append(paths, dir) 67 } 68 paths = append(paths, dir) 69 return FindFileOnPath(paths, filename) 70 } 71 72 // FindFileOnPath finds a file along a search path. 73 // 74 func FindFileOnPath(paths []string, filename string) (string, os.FileInfo, bool, error) { 75 if DebugFind { 76 log.Printf("DEBUG FIND: FindFileOnPath %q %q", paths, filename) 77 } 78 for _, dir := range paths { 79 if path, info, found, err := FindFileInDirectory(filename, dir); err != nil { 80 return "", nil, false, err 81 } else if found { 82 return path, info, true, nil 83 } 84 } 85 if DebugFind { 86 log.Printf("DEBUG FIND: %q not found", filename) 87 } 88 return "", nil, false, nil 89 } 90 91 func FindFileInDirectory(filename string, dirname string) (string, os.FileInfo, bool, error) { 92 try := func(dirname, filename string) (string, os.FileInfo, bool, error) { 93 path := filepath.Join(dirname, filename) 94 if DebugFind { 95 log.Printf("DEBUG FIND: FindFileInDirectory trying %q", path) 96 } 97 if info, err := Stat(path); err == nil { 98 if DebugFind { 99 log.Printf("DEBUG FIND: FindFileInDirectory returning %q", path) 100 } 101 return path, info, true, nil 102 } else if !os.IsNotExist(err) { 103 if DebugFind { 104 log.Printf("DEBUG FIND: FindFileInDirectory %q: %s", path, err.Error()) 105 } 106 return path, nil, true, err 107 } 108 return "", nil, false, nil 109 } 110 111 tryAll := func() (string, os.FileInfo, bool, error) { 112 if path, info, found, err := try(dirname, OsAndArchSpecificFilename(filename)); err != nil || found { 113 return path, info, found, err 114 } 115 if path, info, found, err := try(dirname, OsSpecificFilename(filename)); err != nil || found { 116 return path, info, found, err 117 } 118 if path, info, found, err := try(dirname, ArchSpecificFilename(filename)); err != nil || found { 119 return path, info, found, err 120 } 121 return try(dirname, filename) 122 } 123 124 if path, info, found, err := tryAll(); err != nil || found { 125 return path, info, found, err 126 } 127 128 dirname = filepath.Join(dirname, DccDir) 129 130 if path, info, found, err := tryAll(); err != nil || found { 131 return path, info, found, err 132 } 133 134 return "", nil, false, nil 135 } 136 137 // FindLibrary finds a library file on a search path, either static or dynamic. 138 // 139 func FindLibrary(paths []string, name string) (string, os.FileInfo, bool, error) { 140 if path, info, found, err := FindFileOnPath(paths, platform.DynamicLibrary(name)); found || err != nil { 141 return path, info, found, err 142 } 143 if path, info, found, err := FindFileOnPath(paths, platform.StaticLibrary(name)); found || err != nil { 144 return path, info, found, err 145 } 146 return "", nil, false, nil 147 }