supports binary-format, only esp* supported for now
This commit is contained in:
@@ -42,6 +42,7 @@ import (
|
||||
"github.com/goplus/llgo/internal/clang"
|
||||
"github.com/goplus/llgo/internal/crosscompile"
|
||||
"github.com/goplus/llgo/internal/env"
|
||||
"github.com/goplus/llgo/internal/firmware"
|
||||
"github.com/goplus/llgo/internal/mockable"
|
||||
"github.com/goplus/llgo/internal/packages"
|
||||
"github.com/goplus/llgo/internal/typepatch"
|
||||
@@ -629,23 +630,76 @@ func compileExtraFiles(ctx *context, verbose bool) ([]string, error) {
|
||||
return objFiles, nil
|
||||
}
|
||||
|
||||
func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, global llssa.Package, conf *Config, mode Mode, verbose bool) {
|
||||
pkgPath := pkg.PkgPath
|
||||
name := path.Base(pkgPath)
|
||||
app := conf.OutFile
|
||||
if app == "" {
|
||||
if mode == ModeBuild && len(ctx.initial) > 1 {
|
||||
// generateOutputFilenames generates the final output filename (app) and intermediate filename (orgApp)
|
||||
// based on configuration and build context.
|
||||
func generateOutputFilenames(outFile, binPath, appExt, binExt, pkgName string, mode Mode, isMultiplePkgs bool) (app, orgApp string, err error) {
|
||||
if outFile == "" {
|
||||
if mode == ModeBuild && isMultiplePkgs {
|
||||
// For multiple packages in ModeBuild mode, use temporary file
|
||||
tmpFile, err := os.CreateTemp("", name+"*"+conf.AppExt)
|
||||
check(err)
|
||||
name := pkgName
|
||||
if binExt != "" {
|
||||
name += "*" + binExt
|
||||
} else {
|
||||
name += "*" + appExt
|
||||
}
|
||||
tmpFile, err := os.CreateTemp("", name)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
app = tmpFile.Name()
|
||||
tmpFile.Close()
|
||||
} else {
|
||||
app = filepath.Join(conf.BinPath, name+conf.AppExt)
|
||||
app = filepath.Join(binPath, pkgName+appExt)
|
||||
}
|
||||
orgApp = app
|
||||
} else {
|
||||
// outFile is not empty, use it as base part
|
||||
base := outFile
|
||||
if binExt != "" {
|
||||
// If binExt has value, use temporary file as orgApp for firmware conversion
|
||||
tmpFile, err := os.CreateTemp("", "llgo-*"+appExt)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
orgApp = tmpFile.Name()
|
||||
tmpFile.Close()
|
||||
// Check if base already ends with binExt, if so, don't add it again
|
||||
if strings.HasSuffix(base, binExt) {
|
||||
app = base
|
||||
} else {
|
||||
app = base + binExt
|
||||
}
|
||||
} else {
|
||||
// No binExt, use base + AppExt directly
|
||||
if filepath.Ext(base) == "" {
|
||||
app = base + appExt
|
||||
} else {
|
||||
app = base
|
||||
}
|
||||
orgApp = app
|
||||
}
|
||||
} else if filepath.Ext(app) == "" {
|
||||
app += conf.AppExt
|
||||
}
|
||||
return app, orgApp, nil
|
||||
}
|
||||
|
||||
func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, global llssa.Package, conf *Config, mode Mode, verbose bool) {
|
||||
pkgPath := pkg.PkgPath
|
||||
name := path.Base(pkgPath)
|
||||
binFmt := ctx.crossCompile.BinaryFormat
|
||||
binExt := firmware.BinaryExt(binFmt)
|
||||
|
||||
// app: converted firmware output file or executable file
|
||||
// orgApp: before converted output file
|
||||
app, orgApp, err := generateOutputFilenames(
|
||||
conf.OutFile,
|
||||
conf.BinPath,
|
||||
conf.AppExt,
|
||||
binExt,
|
||||
name,
|
||||
mode,
|
||||
len(ctx.initial) > 1,
|
||||
)
|
||||
check(err)
|
||||
|
||||
needRuntime := false
|
||||
needPyInit := false
|
||||
@@ -701,9 +755,15 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, global l
|
||||
linkArgs = append(linkArgs, exargs...)
|
||||
}
|
||||
|
||||
err = linkObjFiles(ctx, app, objFiles, linkArgs, verbose)
|
||||
err = linkObjFiles(ctx, orgApp, objFiles, linkArgs, verbose)
|
||||
check(err)
|
||||
|
||||
if orgApp != app {
|
||||
fmt.Printf("cross compile: %#v\n", ctx.crossCompile)
|
||||
err = firmware.MakeFirmwareImage(orgApp, app, ctx.crossCompile.BinaryFormat)
|
||||
check(err)
|
||||
}
|
||||
|
||||
switch mode {
|
||||
case ModeTest:
|
||||
cmd := exec.Command(app, conf.RunArgs...)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/goplus/llgo/internal/mockable"
|
||||
@@ -93,3 +94,173 @@ func TestExtest(t *testing.T) {
|
||||
func TestCmpTest(t *testing.T) {
|
||||
mockRun([]string{"../../cl/_testgo/runtest"}, &Config{Mode: ModeCmpTest})
|
||||
}
|
||||
|
||||
func TestGenerateOutputFilenames(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
outFile string
|
||||
binPath string
|
||||
appExt string
|
||||
binExt string
|
||||
pkgName string
|
||||
mode Mode
|
||||
isMultiplePkgs bool
|
||||
wantAppSuffix string
|
||||
wantOrgAppDiff bool // true if orgApp should be different from app
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "empty outFile, single package",
|
||||
outFile: "",
|
||||
binPath: "/usr/local/bin",
|
||||
appExt: "",
|
||||
binExt: "",
|
||||
pkgName: "hello",
|
||||
mode: ModeBuild,
|
||||
isMultiplePkgs: false,
|
||||
wantAppSuffix: "/usr/local/bin/hello",
|
||||
wantOrgAppDiff: false,
|
||||
},
|
||||
{
|
||||
name: "empty outFile with appExt",
|
||||
outFile: "",
|
||||
binPath: "/usr/local/bin",
|
||||
appExt: ".exe",
|
||||
binExt: "",
|
||||
pkgName: "hello",
|
||||
mode: ModeBuild,
|
||||
isMultiplePkgs: false,
|
||||
wantAppSuffix: "/usr/local/bin/hello.exe",
|
||||
wantOrgAppDiff: false,
|
||||
},
|
||||
{
|
||||
name: "outFile without binExt",
|
||||
outFile: "myapp",
|
||||
binPath: "/usr/local/bin",
|
||||
appExt: ".exe",
|
||||
binExt: "",
|
||||
pkgName: "hello",
|
||||
mode: ModeBuild,
|
||||
isMultiplePkgs: false,
|
||||
wantAppSuffix: "myapp.exe",
|
||||
wantOrgAppDiff: false,
|
||||
},
|
||||
{
|
||||
name: "outFile with existing extension, no binExt",
|
||||
outFile: "myapp.exe",
|
||||
binPath: "/usr/local/bin",
|
||||
appExt: ".exe",
|
||||
binExt: "",
|
||||
pkgName: "hello",
|
||||
mode: ModeBuild,
|
||||
isMultiplePkgs: false,
|
||||
wantAppSuffix: "myapp.exe",
|
||||
wantOrgAppDiff: false,
|
||||
},
|
||||
{
|
||||
name: "outFile with binExt, different from existing extension",
|
||||
outFile: "myapp",
|
||||
binPath: "/usr/local/bin",
|
||||
appExt: ".exe",
|
||||
binExt: ".bin",
|
||||
pkgName: "hello",
|
||||
mode: ModeBuild,
|
||||
isMultiplePkgs: false,
|
||||
wantAppSuffix: "myapp.bin",
|
||||
wantOrgAppDiff: true,
|
||||
},
|
||||
{
|
||||
name: "outFile already ends with binExt",
|
||||
outFile: "t.bin",
|
||||
binPath: "/usr/local/bin",
|
||||
appExt: ".exe",
|
||||
binExt: ".bin",
|
||||
pkgName: "hello",
|
||||
mode: ModeBuild,
|
||||
isMultiplePkgs: false,
|
||||
wantAppSuffix: "t.bin",
|
||||
wantOrgAppDiff: true,
|
||||
},
|
||||
{
|
||||
name: "outFile with full path already ends with binExt",
|
||||
outFile: "/path/to/t.bin",
|
||||
binPath: "/usr/local/bin",
|
||||
appExt: ".exe",
|
||||
binExt: ".bin",
|
||||
pkgName: "hello",
|
||||
mode: ModeBuild,
|
||||
isMultiplePkgs: false,
|
||||
wantAppSuffix: "/path/to/t.bin",
|
||||
wantOrgAppDiff: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
app, orgApp, err := generateOutputFilenames(
|
||||
tt.outFile,
|
||||
tt.binPath,
|
||||
tt.appExt,
|
||||
tt.binExt,
|
||||
tt.pkgName,
|
||||
tt.mode,
|
||||
tt.isMultiplePkgs,
|
||||
)
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("generateOutputFilenames() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
if tt.wantAppSuffix != "" {
|
||||
if app != tt.wantAppSuffix {
|
||||
t.Errorf("generateOutputFilenames() app = %v, want %v", app, tt.wantAppSuffix)
|
||||
}
|
||||
}
|
||||
|
||||
if tt.wantOrgAppDiff {
|
||||
if app == orgApp {
|
||||
t.Errorf("generateOutputFilenames() orgApp should be different from app, but both are %v", app)
|
||||
}
|
||||
// Clean up temp file
|
||||
if orgApp != "" && strings.Contains(orgApp, "llgo-") {
|
||||
os.Remove(orgApp)
|
||||
}
|
||||
} else {
|
||||
if app != orgApp {
|
||||
t.Errorf("generateOutputFilenames() orgApp = %v, want %v (same as app)", orgApp, app)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateOutputFilenames_EdgeCases(t *testing.T) {
|
||||
// Test case where outFile has same extension as binExt
|
||||
app, orgApp, err := generateOutputFilenames(
|
||||
"firmware.bin",
|
||||
"/usr/local/bin",
|
||||
".exe",
|
||||
".bin",
|
||||
"esp32app",
|
||||
ModeBuild,
|
||||
false,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if app != "firmware.bin" {
|
||||
t.Errorf("Expected app to be 'firmware.bin', got '%s'", app)
|
||||
}
|
||||
|
||||
if app == orgApp {
|
||||
t.Errorf("Expected orgApp to be different from app when binExt is present, but both are '%s'", app)
|
||||
}
|
||||
|
||||
// Clean up temp file
|
||||
if orgApp != "" && strings.Contains(orgApp, "llgo-") {
|
||||
os.Remove(orgApp)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user