clone and build rosettax87

This commit is contained in:
2025-07-25 14:17:25 -07:00
parent d03c5ee7cc
commit 3d55a8da05
8 changed files with 272 additions and 81 deletions

View File

@@ -10,8 +10,8 @@ import (
)
var (
logger zerolog.Logger
wineLogger zerolog.Logger
logger zerolog.Logger
Writer io.Writer
)
func SetupLogging() {
@@ -22,30 +22,14 @@ func SetupLogging() {
return
}
var mw io.Writer
l := createLogWriter(path, 10, 3)
if l != nil {
mw = io.MultiWriter(zerolog.ConsoleWriter{Out: os.Stdout}, l)
Writer = io.MultiWriter(zerolog.ConsoleWriter{Out: os.Stdout}, l)
} else {
mw = io.MultiWriter(zerolog.ConsoleWriter{Out: os.Stdout})
Writer = os.Stdout
}
logger = zerolog.New(mw).With().Timestamp().Logger()
logger = zerolog.New(Writer).With().Timestamp().Logger()
SetLevelInfo()
// Wine logs
wineLogPath, err := getWineLogfilePath()
if err != nil {
Errorf("Failed to get wine log path: %v", err)
return
}
l = createLogWriter(wineLogPath, 25, 1)
if l != nil {
mw = io.MultiWriter(zerolog.ConsoleWriter{Out: os.Stdout}, l)
} else {
mw = io.MultiWriter(zerolog.ConsoleWriter{Out: os.Stdout})
}
wineLogger = zerolog.New(mw).With().Timestamp().Logger()
wineLogger.Level(zerolog.InfoLevel)
}
func createLogWriter(path string, maxSize int, maxBackups int) io.Writer {
@@ -134,9 +118,9 @@ func Panicf(format string, args ...interface{}) {
}
func WineLoggerStdout(msg string) {
wineLogger.Info().Msgf("STDOUT: %s", msg)
logger.Info().Msgf("WINE STDOUT: %s", msg)
}
func WineLoggerStderr(msg string) {
wineLogger.Info().Msgf("STDERR: %s", msg)
logger.Info().Msgf("WINE STDERR: %s", msg)
}

View File

@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"git.burkey.co/eburk/epochcli/pkg/epoch"
"github.com/go-git/go-git/v6"
"io"
"os"
"os/exec"
@@ -84,29 +85,15 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
log.Debugf("Successfully copied %s to %s", resourceName, destPath)
}
log.Debugf("Preparing rosettax87 directory at: %s", targetRosettaX87Dir)
if err := os.RemoveAll(targetRosettaX87Dir); err != nil {
log.Debugf("Warning: could not remove existing rosettax87 folder '%s': %v", targetRosettaX87Dir, err)
}
if err := os.MkdirAll(targetRosettaX87Dir, 0755); err != nil {
errMsg := fmt.Sprintf("failed to create directory %s: %v", targetRosettaX87Dir, err)
dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug(errMsg)
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
}
rosettaFilesToCopy := map[string]string{
"rosettax87/rosettax87": filepath.Join(targetRosettaX87Dir, "rosettax87"),
"rosettax87/libRuntimeRosettax87": filepath.Join(targetRosettaX87Dir, "libRuntimeRosettax87"),
}
for resourceName, destPath := range rosettaFilesToCopy {
log.Debugf("Processing rosetta resource: %s to %s", resourceName, destPath)
resource, err := fyne.LoadResourceFromPath(resourceName)
if err != nil {
errMsg := fmt.Sprintf("failed to open bundled resource %s: %v", resourceName, err)
if _, err := os.Stat(filepath.Join(paths.EpochPath, "rosettax87")); err == nil {
log.Debugf("rosettax87 path already exists, skipping copy")
} else {
log.Debugf("Preparing rosettax87 directory at: %s", targetRosettaX87Dir)
if err := os.RemoveAll(targetRosettaX87Dir); err != nil {
log.Debugf("Warning: could not remove existing rosettax87 folder '%s': %v", targetRosettaX87Dir, err)
}
if err := os.MkdirAll(targetRosettaX87Dir, 0755); err != nil {
errMsg := fmt.Sprintf("failed to create directory %s: %v", targetRosettaX87Dir, err)
dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug(errMsg)
paths.PatchesAppliedEpoch = false
@@ -114,40 +101,58 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
return
}
destinationFile, err := os.Create(destPath)
if err != nil {
errMsg := fmt.Sprintf("failed to create destination file %s: %v", destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug(errMsg)
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
rosettaFilesToCopy := map[string]string{
"rosettax87/rosettax87": filepath.Join(targetRosettaX87Dir, "rosettax87"),
"rosettax87/libRuntimeRosettax87": filepath.Join(targetRosettaX87Dir, "libRuntimeRosettax87"),
}
_, err = io.Copy(destinationFile, bytes.NewReader(resource.Content()))
if err != nil {
destinationFile.Close()
errMsg := fmt.Sprintf("failed to copy bundled resource %s to %s: %v", resourceName, destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug(errMsg)
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
}
destinationFile.Close()
if filepath.Base(destPath) == "rosettax87" {
log.Debugf("Setting execute permission for %s", destPath)
if err := os.Chmod(destPath, 0755); err != nil {
errMsg := fmt.Sprintf("failed to set execute permission for %s: %v", destPath, err)
for resourceName, destPath := range rosettaFilesToCopy {
log.Debugf("Processing rosetta resource: %s to %s", resourceName, destPath)
resource, err := fyne.LoadResourceFromPath(resourceName)
if err != nil {
errMsg := fmt.Sprintf("failed to open bundled resource %s: %v", resourceName, err)
dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug(errMsg)
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
}
destinationFile, err := os.Create(destPath)
if err != nil {
errMsg := fmt.Sprintf("failed to create destination file %s: %v", destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug(errMsg)
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
}
_, err = io.Copy(destinationFile, bytes.NewReader(resource.Content()))
if err != nil {
destinationFile.Close()
errMsg := fmt.Sprintf("failed to copy bundled resource %s to %s: %v", resourceName, destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug(errMsg)
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
}
destinationFile.Close()
if filepath.Base(destPath) == "rosettax87" {
log.Debugf("Setting execute permission for %s", destPath)
if err := os.Chmod(destPath, 0755); err != nil {
errMsg := fmt.Sprintf("failed to set execute permission for %s: %v", destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow)
log.Debug(errMsg)
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
}
}
log.Debugf("Successfully copied %s to %s", resourceName, destPath)
}
log.Debugf("Successfully copied %s to %s", resourceName, destPath)
}
log.Debugf("Checking dlls.txt file at: %s", dllsTextFile)
@@ -266,7 +271,7 @@ func PatchCrossOver(myWindow fyne.Window, updateAllStatuses func()) {
if strings.Contains(err.Error(), "operation not permitted") {
errMsg += "\n\nSolution: Open System Settings, go to Privacy & Security > App Management, and enable EpochSilicon."
}
dialog.ShowError(fmt.Errorf(errMsg), myWindow)
dialog.ShowError(fmt.Errorf("%s", errMsg), myWindow)
paths.PatchesAppliedCrossOver = false
updateAllStatuses()
return
@@ -462,3 +467,46 @@ func isConfigSettingCorrect(configText, setting, expectedValue string) bool {
currentValue := matches[1]
return currentValue == expectedValue
}
func BuildRosetta() (string, string, error) {
tmpDir, err := os.MkdirTemp("", "rosettax87")
if err != nil {
return "", "", fmt.Errorf("failed to create temporary directory: %v", err)
}
clonedDir := filepath.Join(tmpDir, "rosettax87")
_, err = git.PlainClone(clonedDir, &git.CloneOptions{
URL: "https://github.com/fputs/rosettax87",
Progress: log.Writer,
RecurseSubmodules: git.DefaultSubmoduleRecursionDepth,
SingleBranch: true,
})
if err != nil {
return "", "", fmt.Errorf("failed to clone repository: %v", err)
}
cmd := exec.Command("cmake", "-B", "build")
cmd.Dir = clonedDir
cmd.Stdout = log.Writer
cmd.Stderr = log.Writer
err = cmd.Run()
if err != nil {
return "", "", fmt.Errorf("failed to create build files: %v", err)
}
cmd = exec.Command("cmake", "--build", "build")
cmd.Dir = clonedDir
cmd.Stdout = log.Writer
cmd.Stderr = log.Writer
err = cmd.Run()
if err != nil {
return "", "", fmt.Errorf("failed to build rosettax87: %v", err)
}
buildDir := filepath.Join(clonedDir, "build")
rosettax87Path := filepath.Join(buildDir, "rosettax87")
librosettaPath := filepath.Join(buildDir, "libRuntimeRosettax87")
return rosettax87Path, librosettaPath, nil
}

View File

@@ -0,0 +1,15 @@
package patching
import (
"fmt"
"testing"
)
func TestBuildRosetta(t *testing.T) {
rp, lp, err := BuildRosetta()
if err != nil {
t.Error(err)
}
fmt.Println("exe path:", rp)
fmt.Println("lib path:", lp)
}

View File

@@ -137,7 +137,7 @@ func createBottomBar(myWindow fyne.Window) fyne.CanvasObject {
})
// Git button
gitButton := widget.NewButton("Source Code", func() {
gitButton := widget.NewButton("Website", func() {
githubURL := "https://git.burkey.co/eburk/epochsilicon"
parsedURL, err := url.Parse(githubURL)
if err != nil {

View File

@@ -1,15 +1,18 @@
package ui
import (
"epochsilicon/pkg/log"
"epochsilicon/pkg/patching"
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/widget"
"os"
"os/exec"
"path/filepath"
"strings"
"howett.net/plist"
@@ -198,12 +201,83 @@ func showTroubleshootingPopup() {
}, currentWindow).Show()
})
// --- Build Rosettax87 Locally ---
buildRosettaButton = widget.NewButton("Build", func() {
msg := "Building rosettax87 on your computer may speed up launch times. This requires xcode-commandline-tools and Cmake to be installed. See the instructions at https://git.burkey.co/eburk/epochsilicon/README.md"
dialog.NewConfirm("Build rosettax87", msg, func(confirm bool) {
if confirm {
// Check for dependencies
if _, err := exec.LookPath("clang"); err != nil {
m := fmt.Errorf("xcode command line tools are not installed on your computer. Click the Website button in the app and read the instructions on building rosettax87 before trying again")
log.Error(m.Error())
dialog.ShowError(m, currentWindow)
return
}
if _, err := exec.LookPath("cmake"); err != nil {
m := fmt.Errorf("Cmake is not installed on your computer. Click the Website button in the app and read the instructions on building rosettax87 before trying again")
log.Error(m.Error())
dialog.ShowError(m, currentWindow)
return
}
xPath, lPath, err := patching.BuildRosetta()
if err != nil {
m := fmt.Errorf("Error building rosettax87: %v\nClick on File Issue to upload your logs and file a support issue", err)
log.Error(m.Error())
dialog.ShowError(m, currentWindow)
return
}
d := filepath.Join(paths.EpochPath, "rosettax87")
if err = os.RemoveAll(d); err != nil {
m := fmt.Errorf("Error removing existing rosettax87 directory: %v", err)
log.Error(m.Error())
dialog.ShowError(m, currentWindow)
return
}
if err = os.MkdirAll(d, 0755); err != nil {
m := fmt.Errorf("Error creating existing rosettax87 directory: %v", err)
log.Error(m.Error())
dialog.ShowError(m, currentWindow)
return
}
pathMap := map[string]string{
xPath: filepath.Join(paths.EpochPath, "rosettax87", "rosettax87"),
lPath: filepath.Join(paths.EpochPath, "rosettax87", "libRuntimeRosettax87"),
}
for srcPath, destPath := range pathMap {
fBytes, err := os.ReadFile(srcPath)
if err != nil {
errMsg := fmt.Sprintf("failed to read source file %s: %v", srcPath, err)
dialog.ShowError(errors.New(errMsg), currentWindow)
log.Debug(errMsg)
return
}
err = os.WriteFile(destPath, fBytes, 0755)
if err != nil {
errMsg := fmt.Sprintf("failed to write file %s: %v", destPath, err)
dialog.ShowError(errors.New(errMsg), currentWindow)
log.Debug(errMsg)
return
}
log.Debugf("Successfully copied %s to %s", srcPath, destPath)
}
dialog.ShowInformation("Build Successful", "Rosettax87 installed successfully.", currentWindow)
}
}, currentWindow).Show()
})
troubleshootingTitle := widget.NewLabel("Troubleshooting")
troubleshootingTitle.TextStyle = fyne.TextStyle{Bold: true}
rowCrossover := container.NewBorder(nil, nil, widget.NewLabel("CrossOver version:"), crossoverStatusShort, nil)
rowWDB := container.NewBorder(nil, nil, widget.NewLabel("Delete WDB directory (cache):"), wdbDeleteButton, nil)
rowWine := container.NewBorder(nil, nil, widget.NewLabel("Delete Wine prefixes (~/.wine & Epoch/.wine):"), wineDeleteButton, nil)
rowBuildRosetta := container.NewBorder(nil, nil, widget.NewLabel("Build Rosettax87 locally):"), buildRosettaButton, nil)
appMgmtNote := widget.NewLabel("Please ensure EpochSilicon is enabled in System Settings > Privacy & Security > App Management.")
appMgmtNote.Wrapping = fyne.TextWrapWord
appMgmtNote.TextStyle = fyne.TextStyle{Italic: true}
@@ -215,6 +289,7 @@ func showTroubleshootingPopup() {
crossoverStatusDetail,
rowWDB,
rowWine,
rowBuildRosetta,
appMgmtNote,
)

View File

@@ -61,6 +61,7 @@ var (
crossoverVersionStatusLabel *widget.RichText
wdbDeleteButton *widget.Button
wineDeleteButton *widget.Button
buildRosettaButton *widget.Button
appMgmtPermissionButton *widget.Button
troubleshootingCloseButton *widget.Button
)