@@ -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)
|
||||
}
|
||||
|
@@ -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,42 @@ 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: os.Stdout,
|
||||
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
|
||||
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
|
||||
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
|
||||
}
|
||||
|
15
pkg/patching/patching_test.go
Normal file
15
pkg/patching/patching_test.go
Normal 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)
|
||||
}
|
@@ -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 {
|
||||
|
@@ -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,84 @@ 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\n\n"
|
||||
msg += "Click YES to start the build process. This could take up to a minute depending on the the speed of your Mac. A popup will let you know when the files have been built and copied to the right place."
|
||||
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 Website for information on getting help", 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 +290,7 @@ func showTroubleshootingPopup() {
|
||||
crossoverStatusDetail,
|
||||
rowWDB,
|
||||
rowWine,
|
||||
rowBuildRosetta,
|
||||
appMgmtNote,
|
||||
)
|
||||
|
||||
@@ -223,11 +299,11 @@ func showTroubleshootingPopup() {
|
||||
troubleshootingCloseButton = widget.NewButton("Close", func() {})
|
||||
|
||||
popupContent := container.NewBorder(
|
||||
nil, // top
|
||||
nil, // top
|
||||
container.NewCenter(troubleshootingCloseButton), // bottom
|
||||
nil, // left
|
||||
nil, // right
|
||||
container.NewPadded(scrollContainer), // center
|
||||
nil, // left
|
||||
nil, // right
|
||||
container.NewPadded(scrollContainer), // center
|
||||
)
|
||||
|
||||
windowSize := currentWindow.Content().Size()
|
||||
|
@@ -61,6 +61,7 @@ var (
|
||||
crossoverVersionStatusLabel *widget.RichText
|
||||
wdbDeleteButton *widget.Button
|
||||
wineDeleteButton *widget.Button
|
||||
buildRosettaButton *widget.Button
|
||||
appMgmtPermissionButton *widget.Button
|
||||
troubleshootingCloseButton *widget.Button
|
||||
)
|
||||
|
Reference in New Issue
Block a user