Skip to content

Commit 60888b1

Browse files
committed
fix(generator): add dynamic system header discovery for NixOS support
- Implement getSystemIncludes() to dynamically discover system header paths using gcc -v - Add NixOS detection by checking NIX_CC environment variable - Pass discovered include paths to libclang via -isystem flags - Update math constants test to check FFmpeg-specific constants (M_LOG2_10, M_PHI) instead of standard ones (M_E, M_PI) that may come from system headers This fixes the "math.h not found" error on NixOS where system headers are stored in /nix/store paths instead of standard locations like /usr/include. The solution maintains cross-platform compatibility with standard Linux distributions and macOS while enabling proper header discovery in Nix environments.
1 parent 9f3206b commit 60888b1

2 files changed

Lines changed: 60 additions & 19 deletions

File tree

bindings_test.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,14 +221,16 @@ func TestGeneratorConstants(t *testing.T) {
221221
})
222222

223223
t.Run("MathConstants", func(t *testing.T) {
224-
// Test that math constants are generated (except NAN/INFINITY which conflict)
225-
if ME == 0 {
226-
t.Error("M_E should not be 0")
224+
// Test that FFmpeg-specific math constants are generated
225+
// Note: Standard constants like M_E and M_PI may come from system headers
226+
// on Linux/NixOS and won't be redefined by FFmpeg
227+
if MLog210 == 0 {
228+
t.Error("M_LOG2_10 should not be 0")
227229
}
228-
if MPi == 0 {
229-
t.Error("M_PI should not be 0")
230+
if MPhi == 0 {
231+
t.Error("M_PHI should not be 0")
230232
}
231-
t.Logf("M_E: %f, M_PI: %f", ME, MPi)
233+
t.Logf("M_LOG2_10: %f, M_PHI: %f", MLog210, MPhi)
232234
})
233235
}
234236

internal/generator/parser.go

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package main
33
import (
44
"fmt"
55
"log"
6+
"os"
7+
"os/exec"
68
"path"
79
"path/filepath"
810
"runtime"
@@ -166,6 +168,37 @@ type Parser struct {
166168
tu clang.TranslationUnit
167169
}
168170

171+
// getSystemIncludes gets system include paths from the compiler
172+
func getSystemIncludes() []string {
173+
// Try to get include paths from gcc -v output
174+
cmd := exec.Command("gcc", "-E", "-x", "c", "-v", "/dev/null")
175+
output, err := cmd.CombinedOutput()
176+
if err != nil {
177+
return nil
178+
}
179+
180+
lines := strings.Split(string(output), "\n")
181+
inIncludes := false
182+
var includes []string
183+
184+
for _, line := range lines {
185+
if strings.Contains(line, "#include <...> search starts here:") {
186+
inIncludes = true
187+
continue
188+
}
189+
if strings.Contains(line, "End of search list.") {
190+
break
191+
}
192+
if inIncludes && strings.TrimSpace(line) != "" {
193+
// The path is preceded by a space
194+
path := strings.TrimSpace(line)
195+
includes = append(includes, "-I"+path)
196+
}
197+
}
198+
199+
return includes
200+
}
201+
169202
func getPlatformArgs() []string {
170203
args := []string{
171204
"-fparse-all-comments",
@@ -175,20 +208,26 @@ func getPlatformArgs() []string {
175208
"-D__STDC_CONSTANT_MACROS",
176209
}
177210

178-
// Add platform-specific includes
179-
switch runtime.GOOS {
180-
case "darwin":
181-
args = append(args, "-I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Kernel.framework/Headers/")
182-
case "linux":
183-
// For standard Linux distributions, add common include paths
184-
// These will be ignored if they don't exist, so it's safe to add them
185-
// NixOS will use its own paths through environment variables
186-
if runtime.GOARCH == "amd64" {
187-
args = append(args, "-I/usr/include/x86_64-linux-gnu")
188-
} else if runtime.GOARCH == "arm64" {
189-
args = append(args, "-I/usr/include/aarch64-linux-gnu")
211+
// Check if we're on NixOS by looking for NIX_CC environment variable
212+
if os.Getenv("NIX_CC") != "" {
213+
// On NixOS, get system includes from gcc
214+
systemIncludes := getSystemIncludes()
215+
args = append(args, systemIncludes...)
216+
} else {
217+
// Add platform-specific includes
218+
switch runtime.GOOS {
219+
case "darwin":
220+
args = append(args, "-I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Kernel.framework/Headers/")
221+
case "linux":
222+
// For standard Linux distributions, add common include paths
223+
// These will be ignored if they don't exist, so it's safe to add them
224+
if runtime.GOARCH == "amd64" {
225+
args = append(args, "-I/usr/include/x86_64-linux-gnu")
226+
} else if runtime.GOARCH == "arm64" {
227+
args = append(args, "-I/usr/include/aarch64-linux-gnu")
228+
}
229+
args = append(args, "-I/usr/include")
190230
}
191-
args = append(args, "-I/usr/include")
192231
}
193232

194233
return args

0 commit comments

Comments
 (0)