diff --git a/_demo/embed/test-esp-serial-startup.sh b/_demo/embed/test-esp-serial-startup.sh index 39437e4fcb..1b75af950f 100755 --- a/_demo/embed/test-esp-serial-startup.sh +++ b/_demo/embed/test-esp-serial-startup.sh @@ -1,44 +1,22 @@ #!/bin/bash -# ESP serial targets smoke test (build + emulator run only). +# ESP serial targets smoke test (emulator run only). set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TEMP_DIR="$SCRIPT_DIR/.test_tmp_$$" -TEST_GO="$TEMP_DIR/main.go" -ESP32C3_PREFIX="esp32c3_smoke" -ESP32_PREFIX="esp32_smoke" +CASE_ROOT="$SCRIPT_DIR/testdata/esp32-serial" cleanup() { rm -rf "$TEMP_DIR" } trap cleanup EXIT -build_target() { - local target="$1" - local prefix="$2" - local label="$3" - - echo "==> Building for $label target ($target): ELF + BIN..." - llgo build -target="$target" -o "$prefix" -obin "$TEST_GO" - - if [ ! -f "${prefix}.elf" ]; then - echo "✗ FAIL: Build failed, ${prefix}.elf not found" - exit 1 - fi - - if [ ! -f "${prefix}.bin" ]; then - echo "✗ FAIL: Build failed, ${prefix}.bin not found" - exit 1 - fi - - echo "✓ PASS: $label build artifacts generated" -} - run_emulator_smoke() { local target="$1" local label="$2" - local expected="$3" + local case_dir="$3" + local expected_file="$4" echo "" echo "=== Smoke: $label emulator output ===" @@ -47,7 +25,7 @@ run_emulator_smoke() { run_out_file=$(mktemp "${TEMP_DIR}/run_${target}.XXXX.log") set +e - llgo run -a -target="$target" -emulator . 2>&1 | tee "$run_out_file" + llgo run -a -target="$target" -emulator "$case_dir" 2>&1 | tee "$run_out_file" local run_rc=${PIPESTATUS[0]} set -e @@ -59,14 +37,33 @@ run_emulator_smoke() { echo "[WARN] $label emulator exited with code $run_rc; validating output tail instead" fi - local last_line - last_line=$(printf "%s\n" "$run_out" | tr -d '\r' | awk 'NF{line=$0} END{print line}') + local normalized_out + normalized_out=$(printf "%s\n" "$run_out" | tr -d '\r') - if [ "$last_line" = "$expected" ]; then - echo "✓ PASS: $label output ends with $expected" + local expected_tail + expected_tail=$(cat "$expected_file") + + local normalized_expected + normalized_expected=$(printf "%s" "$expected_tail" | tr -d '\r') + + local n + n=$(printf "%s\n" "$normalized_expected" | awk 'END{print NR}') + if [ -z "$n" ] || [ "$n" -le 0 ]; then + echo "✗ FAIL: invalid expected tail for $label" + exit 1 + fi + + local actual_tail + actual_tail=$(printf "%s\n" "$normalized_out" | awk 'NF{print}' | tail -n "$n") + + if [ "$actual_tail" = "$normalized_expected" ]; then + echo "✓ PASS: $label output tail (last $n line(s)) matched" else echo "✗ FAIL: $label output mismatch" - echo "Last line: $last_line" + echo "Expected tail (last $n line(s)):" + printf "%s\n" "$normalized_expected" + echo "Actual tail:" + printf "%s\n" "$actual_tail" echo "" echo "Full output:" echo "$run_out" @@ -74,31 +71,52 @@ run_emulator_smoke() { fi } -mkdir -p "$TEMP_DIR" +run_case() { + local case_dir="$1" + local case_name + case_name="$(basename "$case_dir")" -echo "==> Creating minimal test program..." -cat > "$TEST_GO" << 'EOGO' -package main - -import "github.com/goplus/lib/c" + local expected_file="$case_dir/expect.txt" + if [ ! -f "$case_dir/main.go" ]; then + echo "✗ FAIL: missing testcase source: $case_dir/main.go" + exit 1 + fi -func main() { - c.Printf(c.Str("Hello World\n")) + run_emulator_smoke "esp32c3-basic" "ESP32-C3 [$case_name]" "$case_dir" "$expected_file" + run_emulator_smoke "esp32" "ESP32 [$case_name]" "$case_dir" "$expected_file" } -EOGO -cd "$TEMP_DIR" +run_all_cases() { + local found=0 + local case_dir + exec 3< <(find "$CASE_ROOT" -mindepth 1 -maxdepth 1 -type d | sort) + while IFS= read -r case_dir <&3; do + if [ -f "$case_dir/main.go" ] && [ -f "$case_dir/expect.txt" ]; then + found=1 + run_case "$case_dir" + fi + done + exec 3<&- + + if [ "$found" -eq 0 ]; then + echo "✗ FAIL: no testcase found under $CASE_ROOT (need main.go + expect.txt)" + exit 1 + fi +} -echo "" -echo "=== ESP Serial Smoke Tests: Build + Emulator Run ===" +mkdir -p "$TEMP_DIR" +if [ ! -d "$CASE_ROOT" ]; then + echo "✗ FAIL: testcase root not found: $CASE_ROOT" + exit 1 +fi -build_target "esp32c3" "$ESP32C3_PREFIX" "ESP32-C3" -run_emulator_smoke "esp32c3-basic" "ESP32-C3" "Hello World" +cd "$SCRIPT_DIR" -build_target "esp32" "$ESP32_PREFIX" "ESP32" -run_emulator_smoke "esp32" "ESP32" "Hello World" +echo "" +echo "=== ESP Serial Smoke Tests: Emulator Run ===" +run_all_cases echo "" echo "=== Smoke Tests Passed ===" -echo "✓ ESP32-C3 build + emulator run passed" -echo "✓ ESP32 build + emulator run passed" +echo "✓ ESP32-C3 and ESP32 emulator smoke passed for all serial testcases" +echo "✓ Cases are discovered only from testdata/esp32-serial (main.go + expect.txt)" diff --git a/_demo/embed/testdata/esp32-serial/chello/expect.txt b/_demo/embed/testdata/esp32-serial/chello/expect.txt new file mode 100644 index 0000000000..557db03de9 --- /dev/null +++ b/_demo/embed/testdata/esp32-serial/chello/expect.txt @@ -0,0 +1 @@ +Hello World diff --git a/_demo/embed/testdata/esp32-serial/chello/main.go b/_demo/embed/testdata/esp32-serial/chello/main.go new file mode 100644 index 0000000000..1617b61abe --- /dev/null +++ b/_demo/embed/testdata/esp32-serial/chello/main.go @@ -0,0 +1,7 @@ +package main + +import "github.com/goplus/lib/c" + +func main() { + c.Printf(c.Str("Hello World\n")) +} diff --git a/_demo/embed/testdata/esp32-serial/float-1685/expect.txt b/_demo/embed/testdata/esp32-serial/float-1685/expect.txt new file mode 100644 index 0000000000..e1f1e8ca08 --- /dev/null +++ b/_demo/embed/testdata/esp32-serial/float-1685/expect.txt @@ -0,0 +1,5 @@ ++5.000000e+00 +8.000000e+00 +1 +2.000000e+00 +0x0 +0.000000e+00 notOk: true +0x0 +0.000000e+00 true +3 +6.280000e+00 diff --git a/_demo/embed/testdata/esp32-serial/float-1685/main.go b/_demo/embed/testdata/esp32-serial/float-1685/main.go new file mode 100644 index 0000000000..03935c0dc6 --- /dev/null +++ b/_demo/embed/testdata/esp32-serial/float-1685/main.go @@ -0,0 +1,60 @@ +package main + +type point struct { + x float64 + y float64 +} + +type myPoint = point + +func (p *point) scale(factor float64) { + p.x *= factor + p.y *= factor +} + +func (p *myPoint) move(dx, dy float64) { + p.x += dx + p.y += dy +} + +func pair(f float64) (int, float64) { + return 1, f +} + +type bar struct { + pb *byte + f float32 +} + +type foo struct { + pb *byte + f float32 +} + +func xadd(a, b int) int { + return a + b +} + +func double(v float64) float64 { + return v * 2 +} + +func main() { + pt := &myPoint{1, 2} + pt.scale(2) + pt.move(3, 4) + println(pt.x, pt.y) + + i, f := pair(2.0) + println(i, f) + + // Keep this case on the float-format path without triggering + // esp32 type-assert timeout cases tracked separately. + ret, ok := bar{}, false + println(ret.pb, ret.f, "notOk:", !ok) + + ret2, ok2 := foo{}, true + println(ret2.pb, ret2.f, ok2) + + println(xadd(1, 2), double(3.14)) +} diff --git a/internal/crosscompile/compile/libc/libc_test.go b/internal/crosscompile/compile/libc/libc_test.go index 960bd93812..f91a39408b 100644 --- a/internal/crosscompile/compile/libc/libc_test.go +++ b/internal/crosscompile/compile/libc/libc_test.go @@ -558,8 +558,8 @@ func TestGetNewlibESP32ConfigXtensa(t *testing.T) { } // Test Groups configuration - if len(config.Groups) != 3 { - t.Errorf("Expected 2 groups, got %d", len(config.Groups)) + if len(config.Groups) != 6 { + t.Errorf("Expected 6 groups, got %d", len(config.Groups)) } else { // Group 0: libcrt0 group0 := config.Groups[0] @@ -631,6 +631,92 @@ func TestGetNewlibESP32ConfigXtensa(t *testing.T) { } } + // Group 3: libm sources with -fbuiltin -fno-math-errno. + group3 := config.Groups[3] + expectedOutput3 := "libm-fbuiltin_fno_math_errno-" + target + ".a" + if group3.OutputFileName != expectedOutput3 { + t.Errorf("Group3 OutputFileName expected '%s', got '%s'", expectedOutput3, group3.OutputFileName) + } + for _, sample := range []string{ + filepath.Join(baseDir, "newlib", "libm", "common", "s_fpclassify.c"), + filepath.Join(baseDir, "newlib", "libm", "common", "sf_fpclassify.c"), + } { + found := false + for _, file := range group3.Files { + if file == sample { + found = true + break + } + } + if !found { + t.Errorf("Expected file '%s' not found in group3 files", sample) + } + } + if !slices.Contains(group3.CFlags, "-fbuiltin") || !slices.Contains(group3.CFlags, "-fno-math-errno") { + t.Errorf("Expected group3 CFlags to contain -fbuiltin and -fno-math-errno") + } + + // Group 4: default libm sources. + group4 := config.Groups[4] + expectedOutput4 := "libm-default-" + target + ".a" + if group4.OutputFileName != expectedOutput4 { + t.Errorf("Group4 OutputFileName expected '%s', got '%s'", expectedOutput4, group4.OutputFileName) + } + for _, sample := range []string{ + filepath.Join(baseDir, "newlib", "libm", "complex", "cabs.c"), + filepath.Join(baseDir, "newlib", "libm", "math", "e_acos.c"), + } { + found := false + for _, file := range group4.Files { + if file == sample { + found = true + break + } + } + if !found { + t.Errorf("Expected file '%s' not found in group4 files", sample) + } + } + if slices.Contains(group4.CFlags, "-fbuiltin") || slices.Contains(group4.CFlags, "-fno-math-errno") || slices.Contains(group4.CFlags, "-D_LIBM") { + t.Errorf("Expected group4 CFlags to not contain -fbuiltin/-fno-math-errno/-D_LIBM") + } + + // Group 5: machine/xtensa libm sources built with -D_LIBM. + group5 := config.Groups[5] + expectedOutput5 := "libm-machine_xtensa_d_libm-" + target + ".a" + if group5.OutputFileName != expectedOutput5 { + t.Errorf("Group5 OutputFileName expected '%s', got '%s'", expectedOutput5, group5.OutputFileName) + } + for _, sample := range []string{ + filepath.Join(baseDir, "newlib", "libm", "machine", "xtensa", "ef_sqrt.c"), + filepath.Join(baseDir, "newlib", "libm", "machine", "xtensa", "fegetenv.c"), + } { + found := false + for _, file := range group5.Files { + if file == sample { + found = true + break + } + } + if !found { + t.Errorf("Expected file '%s' not found in group5 files", sample) + } + } + if !slices.Contains(group5.CFlags, "-D_LIBM") { + t.Errorf("Expected group5 CFlags to contain -D_LIBM") + } + if !slices.Contains(group5.CFlags, "-I"+filepath.Join(baseDir, "newlib", "libc", "machine", "xtensa", "include")) { + t.Errorf("Expected group5 CFlags to contain xtensa machine include path") + } + if !slices.Contains(group5.CFlags, "-I"+filepath.Join(baseDir, "newlib", "libc", "xtensa")) { + t.Errorf("Expected group5 CFlags to contain xtensa sys include path") + } + + totalLibmFiles := len(group3.Files) + len(group4.Files) + len(group5.Files) + if totalLibmFiles != 380 { + t.Errorf("Expected 380 xtensa libm files from command-log build list, got %d", totalLibmFiles) + } + // Test LDFlags and CCFlags if len(group0.LDFlags) == 0 { t.Error("Expected non-empty LDFlags in group0") @@ -698,8 +784,8 @@ func TestGroupConfiguration(t *testing.T) { t.Run("Xtensa_GroupCount", func(t *testing.T) { config := getNewlibESP32ConfigXtensa(baseDir, target) - if len(config.Groups) != 3 { - t.Errorf("Expected 2 groups for Xtensa, got %d", len(config.Groups)) + if len(config.Groups) != 6 { + t.Errorf("Expected 6 groups for Xtensa, got %d", len(config.Groups)) } }) @@ -726,12 +812,13 @@ func TestGroupConfiguration(t *testing.T) { expectedNames := []string{ "libcrt0-" + target + ".a", "libgloss-" + target + ".a", + "libc-" + target + ".a", + "libm-fbuiltin_fno_math_errno-" + target + ".a", + "libm-default-" + target + ".a", + "libm-machine_xtensa_d_libm-" + target + ".a", } for i, group := range config.Groups { - if i >= len(expectedNames) { - return - } if group.OutputFileName != expectedNames[i] { t.Errorf("Group %d expected name '%s', got '%s'", i, expectedNames[i], group.OutputFileName) } diff --git a/internal/crosscompile/compile/libc/newlibesp.go b/internal/crosscompile/compile/libc/newlibesp.go index 00f16e7ebf..5e912ba0a6 100644 --- a/internal/crosscompile/compile/libc/newlibesp.go +++ b/internal/crosscompile/compile/libc/newlibesp.go @@ -1523,6 +1523,413 @@ func getNewlibESP32ConfigXtensa(baseDir, target string) compile.CompileConfig { "-I" + libcDir, } + // Keep this in sync with esp32 target ldflags: + // `--undefined=_printf_float` pulls nano-vfprintf float path, which + // requires libm fp classify symbols such as __fpclassifyd. + libmCommonCFlags := []string{ + "-DHAVE_CONFIG_H", + "-D_LIBC", + "-D__ESP__", + "-isystem" + filepath.Join(libcDir, "include"), + "-I" + filepath.Join(baseDir, "newlib"), + "-idirafter" + filepath.Join(baseDir, "include"), + "-I" + filepath.Join(baseDir, "newlib", "libm", "common"), + } + + // Full xtensa libm file groups are derived from goplus/newlib build + // command logs (equivalent to compile_commands extraction): + // - default flags + // - -fbuiltin -fno-math-errno + // - -D_LIBM (machine/xtensa) + libmDefaultFiles := []string{ + filepath.Join(baseDir, "newlib", "libm/complex/cabs.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cabsf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cabsl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cacos.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cacosf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cacosh.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cacoshf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cacoshl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cacosl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/carg.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cargf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cargl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/casin.c"), + filepath.Join(baseDir, "newlib", "libm/complex/casinf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/casinh.c"), + filepath.Join(baseDir, "newlib", "libm/complex/casinhf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/casinhl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/casinl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/catan.c"), + filepath.Join(baseDir, "newlib", "libm/complex/catanf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/catanh.c"), + filepath.Join(baseDir, "newlib", "libm/complex/catanhf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/catanhl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/catanl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/ccos.c"), + filepath.Join(baseDir, "newlib", "libm/complex/ccosf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/ccosh.c"), + filepath.Join(baseDir, "newlib", "libm/complex/ccoshf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/ccoshl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/ccosl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cephes_subr.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cephes_subrf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cephes_subrl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cexp.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cexpf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cexpl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cimag.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cimagf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cimagl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/clog.c"), + filepath.Join(baseDir, "newlib", "libm/complex/clog10.c"), + filepath.Join(baseDir, "newlib", "libm/complex/clog10f.c"), + filepath.Join(baseDir, "newlib", "libm/complex/clogf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/clogl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/conj.c"), + filepath.Join(baseDir, "newlib", "libm/complex/conjf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/conjl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cpow.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cpowf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cpowl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cproj.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cprojf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/cprojl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/creal.c"), + filepath.Join(baseDir, "newlib", "libm/complex/crealf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/creall.c"), + filepath.Join(baseDir, "newlib", "libm/complex/csin.c"), + filepath.Join(baseDir, "newlib", "libm/complex/csinf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/csinh.c"), + filepath.Join(baseDir, "newlib", "libm/complex/csinhf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/csinhl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/csinl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/csqrt.c"), + filepath.Join(baseDir, "newlib", "libm/complex/csqrtf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/csqrtl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/ctan.c"), + filepath.Join(baseDir, "newlib", "libm/complex/ctanf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/ctanh.c"), + filepath.Join(baseDir, "newlib", "libm/complex/ctanhf.c"), + filepath.Join(baseDir, "newlib", "libm/complex/ctanhl.c"), + filepath.Join(baseDir, "newlib", "libm/complex/ctanl.c"), + filepath.Join(baseDir, "newlib", "libm/fenv/fe_dfl_env.c"), + filepath.Join(baseDir, "newlib", "libm/fenv/feclearexcept.c"), + filepath.Join(baseDir, "newlib", "libm/fenv/fegetenv.c"), + filepath.Join(baseDir, "newlib", "libm/fenv/fegetexceptflag.c"), + filepath.Join(baseDir, "newlib", "libm/fenv/fegetround.c"), + filepath.Join(baseDir, "newlib", "libm/fenv/feholdexcept.c"), + filepath.Join(baseDir, "newlib", "libm/fenv/feraiseexcept.c"), + filepath.Join(baseDir, "newlib", "libm/fenv/fesetenv.c"), + filepath.Join(baseDir, "newlib", "libm/fenv/fesetexceptflag.c"), + filepath.Join(baseDir, "newlib", "libm/fenv/fesetround.c"), + filepath.Join(baseDir, "newlib", "libm/fenv/fetestexcept.c"), + filepath.Join(baseDir, "newlib", "libm/fenv/feupdateenv.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_acos.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_acosh.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_asin.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_atan2.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_atanh.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_cosh.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_exp.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_fmod.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_hypot.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_j0.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_j1.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_jn.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_log.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_log10.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_pow.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_rem_pio2.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_remainder.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_scalb.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_sinh.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_sqrt.c"), + filepath.Join(baseDir, "newlib", "libm/math/e_tgamma.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_acos.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_acosh.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_asin.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_atan2.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_atanh.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_cosh.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_exp.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_fmod.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_hypot.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_j0.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_j1.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_jn.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_log.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_log10.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_pow.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_rem_pio2.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_remainder.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_scalb.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_sinh.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_sqrt.c"), + filepath.Join(baseDir, "newlib", "libm/math/ef_tgamma.c"), + filepath.Join(baseDir, "newlib", "libm/math/el_hypot.c"), + filepath.Join(baseDir, "newlib", "libm/math/er_lgamma.c"), + filepath.Join(baseDir, "newlib", "libm/math/erf_lgamma.c"), + filepath.Join(baseDir, "newlib", "libm/math/k_cos.c"), + filepath.Join(baseDir, "newlib", "libm/math/k_rem_pio2.c"), + filepath.Join(baseDir, "newlib", "libm/math/k_sin.c"), + filepath.Join(baseDir, "newlib", "libm/math/k_standard.c"), + filepath.Join(baseDir, "newlib", "libm/math/k_tan.c"), + filepath.Join(baseDir, "newlib", "libm/math/kf_cos.c"), + filepath.Join(baseDir, "newlib", "libm/math/kf_rem_pio2.c"), + filepath.Join(baseDir, "newlib", "libm/math/kf_sin.c"), + filepath.Join(baseDir, "newlib", "libm/math/kf_tan.c"), + filepath.Join(baseDir, "newlib", "libm/math/s_asinh.c"), + filepath.Join(baseDir, "newlib", "libm/math/s_atan.c"), + filepath.Join(baseDir, "newlib", "libm/math/s_ceil.c"), + filepath.Join(baseDir, "newlib", "libm/math/s_cos.c"), + filepath.Join(baseDir, "newlib", "libm/math/s_erf.c"), + filepath.Join(baseDir, "newlib", "libm/math/s_fabs.c"), + filepath.Join(baseDir, "newlib", "libm/math/s_floor.c"), + filepath.Join(baseDir, "newlib", "libm/math/s_frexp.c"), + filepath.Join(baseDir, "newlib", "libm/math/s_ldexp.c"), + filepath.Join(baseDir, "newlib", "libm/math/s_signif.c"), + filepath.Join(baseDir, "newlib", "libm/math/s_sin.c"), + filepath.Join(baseDir, "newlib", "libm/math/s_tan.c"), + filepath.Join(baseDir, "newlib", "libm/math/s_tanh.c"), + filepath.Join(baseDir, "newlib", "libm/math/sf_asinh.c"), + filepath.Join(baseDir, "newlib", "libm/math/sf_atan.c"), + filepath.Join(baseDir, "newlib", "libm/math/sf_ceil.c"), + filepath.Join(baseDir, "newlib", "libm/math/sf_cos.c"), + filepath.Join(baseDir, "newlib", "libm/math/sf_erf.c"), + filepath.Join(baseDir, "newlib", "libm/math/sf_fabs.c"), + filepath.Join(baseDir, "newlib", "libm/math/sf_floor.c"), + filepath.Join(baseDir, "newlib", "libm/math/sf_frexp.c"), + filepath.Join(baseDir, "newlib", "libm/math/sf_ldexp.c"), + filepath.Join(baseDir, "newlib", "libm/math/sf_signif.c"), + filepath.Join(baseDir, "newlib", "libm/math/sf_sin.c"), + filepath.Join(baseDir, "newlib", "libm/math/sf_tan.c"), + filepath.Join(baseDir, "newlib", "libm/math/sf_tanh.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_acos.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_acosh.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_asin.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_atan2.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_atanh.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_cosh.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_drem.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_exp.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_exp2.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_fmod.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_gamma.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_hypot.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_j0.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_j1.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_jn.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_lgamma.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_log.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_log10.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_pow.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_remainder.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_scalb.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_sincos.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_sinh.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_sqrt.c"), + filepath.Join(baseDir, "newlib", "libm/math/w_tgamma.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_acos.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_acosh.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_asin.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_atan2.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_atanh.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_cosh.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_drem.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_exp.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_exp2.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_fmod.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_gamma.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_hypot.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_j0.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_j1.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_jn.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_lgamma.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_log.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_log10.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_log2.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_pow.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_remainder.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_scalb.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_sincos.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_sinh.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_sqrt.c"), + filepath.Join(baseDir, "newlib", "libm/math/wf_tgamma.c"), + filepath.Join(baseDir, "newlib", "libm/math/wr_gamma.c"), + filepath.Join(baseDir, "newlib", "libm/math/wr_lgamma.c"), + filepath.Join(baseDir, "newlib", "libm/math/wrf_gamma.c"), + filepath.Join(baseDir, "newlib", "libm/math/wrf_lgamma.c"), + } + + libmFBuiltinFiles := []string{ + filepath.Join(baseDir, "newlib", "libm/common/acoshl.c"), + filepath.Join(baseDir, "newlib", "libm/common/acosl.c"), + filepath.Join(baseDir, "newlib", "libm/common/asinhl.c"), + filepath.Join(baseDir, "newlib", "libm/common/asinl.c"), + filepath.Join(baseDir, "newlib", "libm/common/atan2l.c"), + filepath.Join(baseDir, "newlib", "libm/common/atanhl.c"), + filepath.Join(baseDir, "newlib", "libm/common/atanl.c"), + filepath.Join(baseDir, "newlib", "libm/common/cbrtl.c"), + filepath.Join(baseDir, "newlib", "libm/common/ceill.c"), + filepath.Join(baseDir, "newlib", "libm/common/copysignl.c"), + filepath.Join(baseDir, "newlib", "libm/common/cosf.c"), + filepath.Join(baseDir, "newlib", "libm/common/coshl.c"), + filepath.Join(baseDir, "newlib", "libm/common/cosl.c"), + filepath.Join(baseDir, "newlib", "libm/common/erfcl.c"), + filepath.Join(baseDir, "newlib", "libm/common/erfl.c"), + filepath.Join(baseDir, "newlib", "libm/common/exp.c"), + filepath.Join(baseDir, "newlib", "libm/common/exp2.c"), + filepath.Join(baseDir, "newlib", "libm/common/exp2l.c"), + filepath.Join(baseDir, "newlib", "libm/common/exp_data.c"), + filepath.Join(baseDir, "newlib", "libm/common/expl.c"), + filepath.Join(baseDir, "newlib", "libm/common/expm1l.c"), + filepath.Join(baseDir, "newlib", "libm/common/fabsl.c"), + filepath.Join(baseDir, "newlib", "libm/common/fdiml.c"), + filepath.Join(baseDir, "newlib", "libm/common/floorl.c"), + filepath.Join(baseDir, "newlib", "libm/common/fmal.c"), + filepath.Join(baseDir, "newlib", "libm/common/fmaxl.c"), + filepath.Join(baseDir, "newlib", "libm/common/fminl.c"), + filepath.Join(baseDir, "newlib", "libm/common/fmodl.c"), + filepath.Join(baseDir, "newlib", "libm/common/frexpl.c"), + filepath.Join(baseDir, "newlib", "libm/common/hypotl.c"), + filepath.Join(baseDir, "newlib", "libm/common/ilogbl.c"), + filepath.Join(baseDir, "newlib", "libm/common/ldexpl.c"), + filepath.Join(baseDir, "newlib", "libm/common/lgammal.c"), + filepath.Join(baseDir, "newlib", "libm/common/llrintl.c"), + filepath.Join(baseDir, "newlib", "libm/common/llroundl.c"), + filepath.Join(baseDir, "newlib", "libm/common/log.c"), + filepath.Join(baseDir, "newlib", "libm/common/log10l.c"), + filepath.Join(baseDir, "newlib", "libm/common/log1pl.c"), + filepath.Join(baseDir, "newlib", "libm/common/log2.c"), + filepath.Join(baseDir, "newlib", "libm/common/log2_data.c"), + filepath.Join(baseDir, "newlib", "libm/common/log2l.c"), + filepath.Join(baseDir, "newlib", "libm/common/log_data.c"), + filepath.Join(baseDir, "newlib", "libm/common/logbl.c"), + filepath.Join(baseDir, "newlib", "libm/common/logl.c"), + filepath.Join(baseDir, "newlib", "libm/common/lrintl.c"), + filepath.Join(baseDir, "newlib", "libm/common/lroundl.c"), + filepath.Join(baseDir, "newlib", "libm/common/math_err.c"), + filepath.Join(baseDir, "newlib", "libm/common/math_errf.c"), + filepath.Join(baseDir, "newlib", "libm/common/modfl.c"), + filepath.Join(baseDir, "newlib", "libm/common/nanl.c"), + filepath.Join(baseDir, "newlib", "libm/common/nearbyintl.c"), + filepath.Join(baseDir, "newlib", "libm/common/nextafterl.c"), + filepath.Join(baseDir, "newlib", "libm/common/nexttoward.c"), + filepath.Join(baseDir, "newlib", "libm/common/nexttowardf.c"), + filepath.Join(baseDir, "newlib", "libm/common/nexttowardl.c"), + filepath.Join(baseDir, "newlib", "libm/common/pow.c"), + filepath.Join(baseDir, "newlib", "libm/common/pow_log_data.c"), + filepath.Join(baseDir, "newlib", "libm/common/powl.c"), + filepath.Join(baseDir, "newlib", "libm/common/remainderl.c"), + filepath.Join(baseDir, "newlib", "libm/common/remquol.c"), + filepath.Join(baseDir, "newlib", "libm/common/rintl.c"), + filepath.Join(baseDir, "newlib", "libm/common/roundl.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_cbrt.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_copysign.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_exp10.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_expm1.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_fdim.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_finite.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_fma.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_fmax.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_fmin.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_fpclassify.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_ilogb.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_infinity.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_isinf.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_isinfd.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_isnan.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_isnand.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_llrint.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_llround.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_log1p.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_log2.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_logb.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_lrint.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_lround.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_modf.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_nan.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_nearbyint.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_nextafter.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_pow10.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_remquo.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_rint.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_round.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_scalbln.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_scalbn.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_signbit.c"), + filepath.Join(baseDir, "newlib", "libm/common/s_trunc.c"), + filepath.Join(baseDir, "newlib", "libm/common/scalblnl.c"), + filepath.Join(baseDir, "newlib", "libm/common/scalbnl.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_cbrt.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_copysign.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_exp.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_exp10.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_exp2.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_exp2_data.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_expm1.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_fdim.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_finite.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_fma.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_fmax.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_fmin.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_fpclassify.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_ilogb.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_infinity.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_isinf.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_isinff.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_isnan.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_isnanf.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_llrint.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_llround.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_log.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_log1p.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_log2.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_log2_data.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_log_data.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_logb.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_lrint.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_lround.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_modf.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_nan.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_nearbyint.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_nextafter.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_pow.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_pow10.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_pow_log2_data.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_remquo.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_rint.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_round.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_scalbln.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_scalbn.c"), + filepath.Join(baseDir, "newlib", "libm/common/sf_trunc.c"), + filepath.Join(baseDir, "newlib", "libm/common/sincosf.c"), + filepath.Join(baseDir, "newlib", "libm/common/sincosf_data.c"), + filepath.Join(baseDir, "newlib", "libm/common/sinf.c"), + filepath.Join(baseDir, "newlib", "libm/common/sinhl.c"), + filepath.Join(baseDir, "newlib", "libm/common/sinl.c"), + filepath.Join(baseDir, "newlib", "libm/common/sl_finite.c"), + filepath.Join(baseDir, "newlib", "libm/common/sqrtl.c"), + filepath.Join(baseDir, "newlib", "libm/common/tanhl.c"), + filepath.Join(baseDir, "newlib", "libm/common/tanl.c"), + filepath.Join(baseDir, "newlib", "libm/common/tgammal.c"), + filepath.Join(baseDir, "newlib", "libm/common/truncl.c"), + } + + libmLibmDefineFiles := []string{ + filepath.Join(baseDir, "newlib", "libm/machine/xtensa/ef_sqrt.c"), + filepath.Join(baseDir, "newlib", "libm/machine/xtensa/feclearexcept.c"), + filepath.Join(baseDir, "newlib", "libm/machine/xtensa/fegetenv.c"), + filepath.Join(baseDir, "newlib", "libm/machine/xtensa/fegetexcept.c"), + filepath.Join(baseDir, "newlib", "libm/machine/xtensa/fegetexceptflag.c"), + filepath.Join(baseDir, "newlib", "libm/machine/xtensa/fegetround.c"), + filepath.Join(baseDir, "newlib", "libm/machine/xtensa/feholdexcept.c"), + filepath.Join(baseDir, "newlib", "libm/machine/xtensa/feraiseexcept.c"), + filepath.Join(baseDir, "newlib", "libm/machine/xtensa/fetestexcept.c"), + filepath.Join(baseDir, "newlib", "libm/machine/xtensa/feupdateenv.c"), + } + return compile.CompileConfig{ ExportCFlags: libcIncludeDir, Groups: []compile.CompileGroup{ @@ -2489,6 +2896,38 @@ func getNewlibESP32ConfigXtensa(baseDir, target string) compile.CompileConfig { "-Wno-unused-command-line-argument", }), }, + { + OutputFileName: fmt.Sprintf("libm-fbuiltin_fno_math_errno-%s.a", target), + Files: libmFBuiltinFiles, + CFlags: append( + append([]string{}, libmCommonCFlags...), + "-fbuiltin", + "-fno-math-errno", + ), + LDFlags: _libcLDFlags, + CCFlags: _libcCCFlags, + }, + { + OutputFileName: fmt.Sprintf("libm-default-%s.a", target), + Files: libmDefaultFiles, + CFlags: append([]string{}, libmCommonCFlags...), + LDFlags: _libcLDFlags, + CCFlags: _libcCCFlags, + }, + { + OutputFileName: fmt.Sprintf("libm-machine_xtensa_d_libm-%s.a", target), + Files: libmLibmDefineFiles, + CFlags: append( + append([]string{}, libmCommonCFlags...), + "-D_LIBM", + // machine/xtensa sources include . + "-I"+filepath.Join(libcDir, "machine", "xtensa", "include"), + // Prefer xtensa sys/fenv.h instead of generic libc/include/sys/fenv.h. + "-I"+filepath.Join(libcDir, "xtensa"), + ), + LDFlags: _libcLDFlags, + CCFlags: _libcCCFlags, + }, }, } } diff --git a/internal/crosscompile/libc_test.go b/internal/crosscompile/libc_test.go index f03a46467a..6ed76356fc 100644 --- a/internal/crosscompile/libc_test.go +++ b/internal/crosscompile/libc_test.go @@ -61,8 +61,8 @@ func TestGetLibcCompileConfigByName(t *testing.T) { t.Fatalf("Unexpected error: %v", err) } - if len(cfg.Groups) != 3 { - t.Fatalf("Expected 3 group, got %d", len(cfg.Groups)) + if len(cfg.Groups) != 6 { + t.Fatalf("Expected 6 groups, got %d", len(cfg.Groups)) } group := cfg.Groups[0] diff --git a/targets/esp32.json b/targets/esp32.json index c88e5c4791..d335ae3653 100644 --- a/targets/esp32.json +++ b/targets/esp32.json @@ -14,6 +14,9 @@ "default-stack-size": 2048, "rtlib": "compiler-rt", "libc": "newlib-esp32", + "ldflags": [ + "--undefined=_printf_float" + ], "linkerscript": "targets/esp32.memory.elf.ld", "binary-format": "esp32", "flash-command": "esptool.py --chip=esp32 --port {port} write_flash 0x1000 {bin} -ff 80m -fm dout",