GIR: Rework lookup logic to instead rely on name resolution in `findSo` etc.
Signed-off-by: Felicitas Pojtinger <felicitas@pojtinger.com>
- commit
- e282e1ceb2e136ac61e2370c2c5b6175505ecd43
- author
- Felicitas Pojtinger · · 2025-10-18 03:48 UTC
- committer
- Jeroen Wijenbergh · · 2025-10-22 07:42 UTC
- parent
- e97e9fe
- signature
- unsigned
1 file · +21 -85
M internal/core/core.go +21 -85
| @@ -65,25 +65,26 @@ func SetSharedLibraries(libName string, sharedLibs []string) { | |||
| 65 | 65 | } | |
| 66 | 66 | } | |
| 67 | 67 | ||
| 68 | - | // findSo tries to find a shared object from a path and a library name | |
| 69 | - | // It does this by mapping the library name to a suitable shared object filename and then trying some suffixes | |
| 70 | - | func findSo(path string, name string) string { | |
| 68 | + | // findSos tries to find all shared objects from a path and a library name | |
| 69 | + | // It does this by mapping the library name to all suitable shared object filenames and then trying some suffixes | |
| 70 | + | func findSos(path string, name string) []string { | |
| 71 | + | sos := []string{} | |
| 71 | 72 | for _, n := range names[name] { | |
| 72 | 73 | suffixes := []string{"", ".0", ".1", ".2"} | |
| 73 | 74 | fn := filepath.Join(path, n) | |
| 74 | 75 | for _, s := range suffixes { | |
| 75 | 76 | if _, err := os.Stat(fn + s); err == nil { | |
| 76 | - | return fn + s | |
| 77 | + | sos = append(sos, fn+s) | |
| 77 | 78 | } | |
| 78 | 79 | } | |
| 79 | 80 | } | |
| 80 | - | return "" | |
| 81 | + | return sos | |
| 81 | 82 | } | |
| 82 | 83 | ||
| 83 | - | // findPkgConf finds a shared object file with pkg-config | |
| 84 | + | // findPkgConf finds all shared object files with pkg-config | |
| 84 | 85 | // it does this by running pkg-config --libs-only-L libname | |
| 85 | - | // and then it loops over the directories returned and finds a suitable one | |
| 86 | - | func findPkgConf(name string) string { | |
| 86 | + | // and then it loops over the directories returned and finds all suitable ones | |
| 87 | + | func findPkgConf(name string) []string { | |
| 87 | 88 | cmd := exec.Command("pkg-config", "--libs-only-L", pkgConfNames[name]) | |
| 88 | 89 | var out, outerr bytes.Buffer | |
| 89 | 90 | cmd.Stdout = &out | |
| @@ -91,7 +92,7 @@ func findPkgConf(name string) string { | |||
| 91 | 92 | err := cmd.Run() | |
| 92 | 93 | if err != nil { | |
| 93 | 94 | fmt.Fprintf(os.Stderr, "pkg-config, failed with: %v and stderr: %s\n", err, outerr.String()) | |
| 94 | - | return "" | |
| 95 | + | return []string{} | |
| 95 | 96 | } | |
| 96 | 97 | outs := strings.Split(out.String(), "-L") | |
| 97 | 98 | for _, v := range outs { | |
| @@ -99,15 +100,15 @@ func findPkgConf(name string) string { | |||
| 99 | 100 | if c == "" { | |
| 100 | 101 | continue | |
| 101 | 102 | } | |
| 102 | - | g := findSo(c, name) | |
| 103 | - | if g != "" { | |
| 103 | + | g := findSos(c, name) | |
| 104 | + | if len(g) > 0 { | |
| 104 | 105 | return g | |
| 105 | 106 | } | |
| 106 | 107 | } | |
| 107 | - | return "" | |
| 108 | + | return []string{} | |
| 108 | 109 | } | |
| 109 | 110 | ||
| 110 | - | // getPath gets a shared object file from a library name | |
| 111 | + | // GetPaths gets all shared object files from a library name | |
| 111 | 112 | // it does it in the following order | |
| 112 | 113 | // see if PUREGOTK_LIBNAME_PATH is set (full path to the lib) | |
| 113 | 114 | // - e.g. PUREGOTK_GTK_PATH | |
| @@ -117,18 +118,18 @@ func findPkgConf(name string) string { | |||
| 117 | 118 | // panic if failed | |
| 118 | 119 | // TODO: Hardcore a library shared object with linker -X flag | |
| 119 | 120 | // This is useful for packaging | |
| 120 | - | func getPath(name string) string { | |
| 121 | + | func GetPaths(name string) []string { | |
| 121 | 122 | // try to get from env var | |
| 122 | 123 | ev := fmt.Sprintf("PUREGOTK_%s_PATH", name) | |
| 123 | 124 | if v := os.Getenv(ev); v != "" { | |
| 124 | - | return v | |
| 125 | + | return []string{v} | |
| 125 | 126 | } | |
| 126 | 127 | ||
| 127 | 128 | // Or if a general folder is set where everywhere is located, return that | |
| 128 | 129 | ep := os.Getenv("PUREGOTK_LIB_FOLDER") | |
| 129 | 130 | if ep != "" { | |
| 130 | - | g := findSo(ep, name) | |
| 131 | - | if g == "" { | |
| 131 | + | g := findSos(ep, name) | |
| 132 | + | if len(g) == 0 { | |
| 132 | 133 | panic(fmt.Sprintf("Could not find lib: %s, at path: %s with env: %s", name, ep, "PUREGOTK_FOLDER")) | |
| 133 | 134 | } | |
| 134 | 135 | return g | |
| @@ -139,8 +140,8 @@ func getPath(name string) string { | |||
| 139 | 140 | if ok { | |
| 140 | 141 | // try to loop over paths | |
| 141 | 142 | for _, p := range gp { | |
| 142 | - | g := findSo(p, name) | |
| 143 | - | if g != "" { | |
| 143 | + | g := findSos(p, name) | |
| 144 | + | if len(g) > 0 { | |
| 144 | 145 | return g | |
| 145 | 146 | } | |
| 146 | 147 | ||
| @@ -148,7 +149,7 @@ func getPath(name string) string { | |||
| 148 | 149 | } | |
| 149 | 150 | // last effort: pkg-config | |
| 150 | 151 | g := findPkgConf(name) | |
| 151 | - | if g != "" { | |
| 152 | + | if len(g) > 0 { | |
| 152 | 153 | return g | |
| 153 | 154 | } | |
| 154 | 155 | ||
| @@ -172,68 +173,3 @@ func GoString(c uintptr) string { | |||
| 172 | 173 | } | |
| 173 | 174 | return string(unsafe.Slice((*byte)(ptr), length)) | |
| 174 | 175 | } | |
| 175 | - | ||
| 176 | - | // GetPaths gets all shared object file paths for a library name that may have multiple libraries. | |
| 177 | - | // This is used when a package needs to load multiple shared libraries (e.g., GLIB needs both libgobject and libglib). | |
| 178 | - | // Returns a slice of full paths to all libraries for this package. | |
| 179 | - | func GetPaths(name string) []string { | |
| 180 | - | libNames, ok := names[name] | |
| 181 | - | if !ok || len(libNames) == 0 { | |
| 182 | - | // Fallback to single GetPath for backward compatibility | |
| 183 | - | return []string{getPath(name)} | |
| 184 | - | } | |
| 185 | - | ||
| 186 | - | // If only one library, use the original GetPath logic | |
| 187 | - | if len(libNames) == 1 { | |
| 188 | - | return []string{getPath(name)} | |
| 189 | - | } | |
| 190 | - | ||
| 191 | - | var result []string | |
| 192 | - | for _, libName := range libNames { | |
| 193 | - | // Try PUREGOTK_LIB_FOLDER first | |
| 194 | - | ep := os.Getenv("PUREGOTK_LIB_FOLDER") | |
| 195 | - | if ep != "" { | |
| 196 | - | suffixes := []string{"", ".0", ".1", ".2"} | |
| 197 | - | found := false | |
| 198 | - | for _, s := range suffixes { | |
| 199 | - | fullPath := filepath.Join(ep, libName+s) | |
| 200 | - | if _, err := os.Stat(fullPath); err == nil { | |
| 201 | - | result = append(result, fullPath) | |
| 202 | - | found = true | |
| 203 | - | break | |
| 204 | - | } | |
| 205 | - | } | |
| 206 | - | if found { | |
| 207 | - | continue | |
| 208 | - | } | |
| 209 | - | } | |
| 210 | - | ||
| 211 | - | // Try hardcoded paths | |
| 212 | - | gp, pathsOk := paths[runtime.GOARCH] | |
| 213 | - | if pathsOk { | |
| 214 | - | found := false | |
| 215 | - | for _, p := range gp { | |
| 216 | - | suffixes := []string{"", ".0", ".1", ".2"} | |
| 217 | - | fn := filepath.Join(p, libName) | |
| 218 | - | for _, s := range suffixes { | |
| 219 | - | if _, err := os.Stat(fn + s); err == nil { | |
| 220 | - | result = append(result, fn+s) | |
| 221 | - | found = true | |
| 222 | - | break | |
| 223 | - | } | |
| 224 | - | } | |
| 225 | - | if found { | |
| 226 | - | break | |
| 227 | - | } | |
| 228 | - | } | |
| 229 | - | if found { | |
| 230 | - | continue | |
| 231 | - | } | |
| 232 | - | } | |
| 233 | - | ||
| 234 | - | // If we get here, we couldn't find this library | |
| 235 | - | panic(fmt.Sprintf("Path for library %s (package %s) not found. Please set PUREGOTK_LIB_FOLDER or ensure the library is in standard paths", libName, name)) | |
| 236 | - | } | |
| 237 | - | ||
| 238 | - | return result | |
| 239 | - | } | |
| @@ -65,25 +65,26 @@ func SetSharedLibraries(libName string, sharedLibs []string) { | |||||
| 65 | } | 65 | } | ||
| 66 | } | 66 | } | ||
| 67 | 67 | ||||
| 68 | - | // findSo tries to find a shared object from a path and a library name | 68 | + | // findSos tries to find all shared objects from a path and a library name |
| 69 | - | // It does this by mapping the library name to a suitable shared object filename and then trying some suffixes | 69 | + | // It does this by mapping the library name to all suitable shared object filenames and then trying some suffixes |
| 70 | - | func findSo(path string, name string) string { | 70 | + | func findSos(path string, name string) []string { |
| 71 | + | sos := []string{} | |||
| 71 | for _, n := range names[name] { | 72 | for _, n := range names[name] { | ||
| 72 | suffixes := []string{"", ".0", ".1", ".2"} | 73 | suffixes := []string{"", ".0", ".1", ".2"} | ||
| 73 | fn := filepath.Join(path, n) | 74 | fn := filepath.Join(path, n) | ||
| 74 | for _, s := range suffixes { | 75 | for _, s := range suffixes { | ||
| 75 | if _, err := os.Stat(fn + s); err == nil { | 76 | if _, err := os.Stat(fn + s); err == nil { | ||
| 76 | - | return fn + s | 77 | + | sos = append(sos, fn+s) |
| 77 | } | 78 | } | ||
| 78 | } | 79 | } | ||
| 79 | } | 80 | } | ||
| 80 | - | return "" | 81 | + | return sos |
| 81 | } | 82 | } | ||
| 82 | 83 | ||||
| 83 | - | // findPkgConf finds a shared object file with pkg-config | 84 | + | // findPkgConf finds all shared object files with pkg-config |
| 84 | // it does this by running pkg-config --libs-only-L libname | 85 | // it does this by running pkg-config --libs-only-L libname | ||
| 85 | - | // and then it loops over the directories returned and finds a suitable one | 86 | + | // and then it loops over the directories returned and finds all suitable ones |
| 86 | - | func findPkgConf(name string) string { | 87 | + | func findPkgConf(name string) []string { |
| 87 | cmd := exec.Command("pkg-config", "--libs-only-L", pkgConfNames[name]) | 88 | cmd := exec.Command("pkg-config", "--libs-only-L", pkgConfNames[name]) | ||
| 88 | var out, outerr bytes.Buffer | 89 | var out, outerr bytes.Buffer | ||
| 89 | cmd.Stdout = &out | 90 | cmd.Stdout = &out | ||
| @@ -91,7 +92,7 @@ func findPkgConf(name string) string { | |||||
| 91 | err := cmd.Run() | 92 | err := cmd.Run() | ||
| 92 | if err != nil { | 93 | if err != nil { | ||
| 93 | fmt.Fprintf(os.Stderr, "pkg-config, failed with: %v and stderr: %s\n", err, outerr.String()) | 94 | fmt.Fprintf(os.Stderr, "pkg-config, failed with: %v and stderr: %s\n", err, outerr.String()) | ||
| 94 | - | return "" | 95 | + | return []string{} |
| 95 | } | 96 | } | ||
| 96 | outs := strings.Split(out.String(), "-L") | 97 | outs := strings.Split(out.String(), "-L") | ||
| 97 | for _, v := range outs { | 98 | for _, v := range outs { | ||
| @@ -99,15 +100,15 @@ func findPkgConf(name string) string { | |||||
| 99 | if c == "" { | 100 | if c == "" { | ||
| 100 | continue | 101 | continue | ||
| 101 | } | 102 | } | ||
| 102 | - | g := findSo(c, name) | 103 | + | g := findSos(c, name) |
| 103 | - | if g != "" { | 104 | + | if len(g) > 0 { |
| 104 | return g | 105 | return g | ||
| 105 | } | 106 | } | ||
| 106 | } | 107 | } | ||
| 107 | - | return "" | 108 | + | return []string{} |
| 108 | } | 109 | } | ||
| 109 | 110 | ||||
| 110 | - | // getPath gets a shared object file from a library name | 111 | + | // GetPaths gets all shared object files from a library name |
| 111 | // it does it in the following order | 112 | // it does it in the following order | ||
| 112 | // see if PUREGOTK_LIBNAME_PATH is set (full path to the lib) | 113 | // see if PUREGOTK_LIBNAME_PATH is set (full path to the lib) | ||
| 113 | // - e.g. PUREGOTK_GTK_PATH | 114 | // - e.g. PUREGOTK_GTK_PATH | ||
| @@ -117,18 +118,18 @@ func findPkgConf(name string) string { | |||||
| 117 | // panic if failed | 118 | // panic if failed | ||
| 118 | // TODO: Hardcore a library shared object with linker -X flag | 119 | // TODO: Hardcore a library shared object with linker -X flag | ||
| 119 | // This is useful for packaging | 120 | // This is useful for packaging | ||
| 120 | - | func getPath(name string) string { | 121 | + | func GetPaths(name string) []string { |
| 121 | // try to get from env var | 122 | // try to get from env var | ||
| 122 | ev := fmt.Sprintf("PUREGOTK_%s_PATH", name) | 123 | ev := fmt.Sprintf("PUREGOTK_%s_PATH", name) | ||
| 123 | if v := os.Getenv(ev); v != "" { | 124 | if v := os.Getenv(ev); v != "" { | ||
| 124 | - | return v | 125 | + | return []string{v} |
| 125 | } | 126 | } | ||
| 126 | 127 | ||||
| 127 | // Or if a general folder is set where everywhere is located, return that | 128 | // Or if a general folder is set where everywhere is located, return that | ||
| 128 | ep := os.Getenv("PUREGOTK_LIB_FOLDER") | 129 | ep := os.Getenv("PUREGOTK_LIB_FOLDER") | ||
| 129 | if ep != "" { | 130 | if ep != "" { | ||
| 130 | - | g := findSo(ep, name) | 131 | + | g := findSos(ep, name) |
| 131 | - | if g == "" { | 132 | + | if len(g) == 0 { |
| 132 | panic(fmt.Sprintf("Could not find lib: %s, at path: %s with env: %s", name, ep, "PUREGOTK_FOLDER")) | 133 | panic(fmt.Sprintf("Could not find lib: %s, at path: %s with env: %s", name, ep, "PUREGOTK_FOLDER")) | ||
| 133 | } | 134 | } | ||
| 134 | return g | 135 | return g | ||
| @@ -139,8 +140,8 @@ func getPath(name string) string { | |||||
| 139 | if ok { | 140 | if ok { | ||
| 140 | // try to loop over paths | 141 | // try to loop over paths | ||
| 141 | for _, p := range gp { | 142 | for _, p := range gp { | ||
| 142 | - | g := findSo(p, name) | 143 | + | g := findSos(p, name) |
| 143 | - | if g != "" { | 144 | + | if len(g) > 0 { |
| 144 | return g | 145 | return g | ||
| 145 | } | 146 | } | ||
| 146 | 147 | ||||
| @@ -148,7 +149,7 @@ func getPath(name string) string { | |||||
| 148 | } | 149 | } | ||
| 149 | // last effort: pkg-config | 150 | // last effort: pkg-config | ||
| 150 | g := findPkgConf(name) | 151 | g := findPkgConf(name) | ||
| 151 | - | if g != "" { | 152 | + | if len(g) > 0 { |
| 152 | return g | 153 | return g | ||
| 153 | } | 154 | } | ||
| 154 | 155 | ||||
| @@ -172,68 +173,3 @@ func GoString(c uintptr) string { | |||||
| 172 | } | 173 | } | ||
| 173 | return string(unsafe.Slice((*byte)(ptr), length)) | 174 | return string(unsafe.Slice((*byte)(ptr), length)) | ||
| 174 | } | 175 | } | ||
| 175 | - | ||||
| 176 | - | // GetPaths gets all shared object file paths for a library name that may have multiple libraries. | |||
| 177 | - | // This is used when a package needs to load multiple shared libraries (e.g., GLIB needs both libgobject and libglib). | |||
| 178 | - | // Returns a slice of full paths to all libraries for this package. | |||
| 179 | - | func GetPaths(name string) []string { | |||
| 180 | - | libNames, ok := names[name] | |||
| 181 | - | if !ok || len(libNames) == 0 { | |||
| 182 | - | // Fallback to single GetPath for backward compatibility | |||
| 183 | - | return []string{getPath(name)} | |||
| 184 | - | } | |||
| 185 | - | ||||
| 186 | - | // If only one library, use the original GetPath logic | |||
| 187 | - | if len(libNames) == 1 { | |||
| 188 | - | return []string{getPath(name)} | |||
| 189 | - | } | |||
| 190 | - | ||||
| 191 | - | var result []string | |||
| 192 | - | for _, libName := range libNames { | |||
| 193 | - | // Try PUREGOTK_LIB_FOLDER first | |||
| 194 | - | ep := os.Getenv("PUREGOTK_LIB_FOLDER") | |||
| 195 | - | if ep != "" { | |||
| 196 | - | suffixes := []string{"", ".0", ".1", ".2"} | |||
| 197 | - | found := false | |||
| 198 | - | for _, s := range suffixes { | |||
| 199 | - | fullPath := filepath.Join(ep, libName+s) | |||
| 200 | - | if _, err := os.Stat(fullPath); err == nil { | |||
| 201 | - | result = append(result, fullPath) | |||
| 202 | - | found = true | |||
| 203 | - | break | |||
| 204 | - | } | |||
| 205 | - | } | |||
| 206 | - | if found { | |||
| 207 | - | continue | |||
| 208 | - | } | |||
| 209 | - | } | |||
| 210 | - | ||||
| 211 | - | // Try hardcoded paths | |||
| 212 | - | gp, pathsOk := paths[runtime.GOARCH] | |||
| 213 | - | if pathsOk { | |||
| 214 | - | found := false | |||
| 215 | - | for _, p := range gp { | |||
| 216 | - | suffixes := []string{"", ".0", ".1", ".2"} | |||
| 217 | - | fn := filepath.Join(p, libName) | |||
| 218 | - | for _, s := range suffixes { | |||
| 219 | - | if _, err := os.Stat(fn + s); err == nil { | |||
| 220 | - | result = append(result, fn+s) | |||
| 221 | - | found = true | |||
| 222 | - | break | |||
| 223 | - | } | |||
| 224 | - | } | |||
| 225 | - | if found { | |||
| 226 | - | break | |||
| 227 | - | } | |||
| 228 | - | } | |||
| 229 | - | if found { | |||
| 230 | - | continue | |||
| 231 | - | } | |||
| 232 | - | } | |||
| 233 | - | ||||
| 234 | - | // If we get here, we couldn't find this library | |||
| 235 | - | panic(fmt.Sprintf("Path for library %s (package %s) not found. Please set PUREGOTK_LIB_FOLDER or ensure the library is in standard paths", libName, name)) | |||
| 236 | - | } | |||
| 237 | - | ||||
| 238 | - | return result | |||
| 239 | - | } | |||