Mac: Avoid Apple's Installer requiring Rosetta 2 to install BOINC

Add info to ReadMe about running Intel apps from BOINC projects on arm64 Macs
This commit is contained in:
Charlie Fenton 2021-06-22 23:56:57 -07:00
parent afde389dd9
commit eaa1a93043
4 changed files with 134 additions and 112 deletions

View File

@ -1,6 +1,6 @@
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2020 University of California
// Copyright (C) 2021 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
@ -35,6 +35,7 @@
#include "mac_util.h"
#include "translate.h"
#include "file_names.h"
#include "util.h"
#include "mac_branding.h"
#define boinc_master_user_name "boinc_master"
@ -49,7 +50,11 @@ Boolean IsRestartNeeded();
static void GetPreferredLanguages();
static void LoadPreferredLanguages();
static long GetOldBrandID(void);
static void ShowMessage(const char *format, ...);
static Boolean ShowMessage(Boolean askYesNo, const char *format, ...);
#ifdef __arm64__
int check_rosetta2_installed();
int optionally_install_rosetta2();
#endif // __arm64__
static OSErr QuitAppleEventHandler(const AppleEvent *appleEvt, AppleEvent* reply, UInt32 refcon);
int callPosixSpawn(const char *cmd);
void print_to_log_file(const char *format, ...);
@ -79,6 +84,7 @@ int main(int argc, char *argv[])
char pkgPath[MAXPATHLEN];
char postInstallAppPath[MAXPATHLEN];
char temp[MAXPATHLEN], temp2[MAXPATHLEN];
char savedWD[MAXPATHLEN];
char brand[64], s[256];
char *p;
OSStatus err = noErr;
@ -90,7 +96,7 @@ int main(int argc, char *argv[])
int minor = 0;
if (!check_branding_arrays(temp, sizeof(temp))) {
ShowMessage((char *)_("Branding array has too few entries: %s"), temp);
ShowMessage(false, (char *)_("Branding array has too few entries: %s"), temp);
return -1;
}
@ -100,7 +106,7 @@ int main(int argc, char *argv[])
strncpy(loginName, getenv("USER"), sizeof(loginName)-1);
if (loginName[0] == '\0') {
ShowMessage((char *)_("Could not get user login name"));
ShowMessage(false, (char *)_("Could not get user login name"));
return 0;
}
@ -140,7 +146,7 @@ int main(int argc, char *argv[])
// Write a file containing the project auto-attach key into our temp
// directory because the BOINC Data directory may not yet exist.
// PostInstall.app will copy it into the BOINC Data directory laer
// PostInstall.app will copy it into the BOINC Data directory later
snprintf(temp2, sizeof(temp2), "%s/%s", temp, ACCOUNT_DATA_FILENAME);
if (boinc_file_exists(temp2)) {
// If the project server put account_data.txt file in the same
@ -208,7 +214,20 @@ int main(int argc, char *argv[])
sprintf(temp, "pkgutil --expand \"%s\" /tmp/%s/expanded_BOINC.pkg", pkgPath, tempDirName);
err = callPosixSpawn(temp);
REPORT_ERROR(err);
if (err == noErr) {
getcwd(savedWD, sizeof(savedWD));
snprintf(temp, sizeof(temp), "rm -dfR /tmp/%s/BOINC_payload", tempDirName);
callPosixSpawn(temp);
snprintf(temp, sizeof(temp), "/tmp/%s/BOINC_payload", tempDirName);
mkdir(temp, 0777);
chmod(temp, 0777); // Needed because mkdir sets permissions restricted by umask (022)
chdir(temp);
// Exptract the installer package payload to a temporary location
snprintf(temp, sizeof(temp), "cpio -i -I /tmp/%s/expanded_BOINC.pkg/BOINC.pkg/Payload", tempDirName);
callPosixSpawn(temp);
chdir(savedWD);
GetPreferredLanguages();
}
@ -219,7 +238,7 @@ int main(int argc, char *argv[])
p = strrchr(brand, ' '); // Strip off last space character and everything following
if (p)
*p = '\0';
ShowMessage((char *)_("Sorry, this version of %s requires system %s or higher."), brand, Deployment_target);
ShowMessage(false, (char *)_("Sorry, this version of %s requires system %s or higher."), brand, Deployment_target);
snprintf(temp, sizeof(temp), "rm -dfR /tmp/%s/BOINC_payload", tempDirName);
err = callPosixSpawn(temp);
@ -227,6 +246,15 @@ int main(int argc, char *argv[])
return -1;
}
#ifdef __arm64__
int rosetta_result = check_rosetta2_installed();
printf("check_rosetta2_installed() returned %d\n", rosetta_result);
if (rosetta_result == EBADARCH){
optionally_install_rosetta2();
}
#endif // __arm64__
snprintf(temp, sizeof(temp), "rm -dfR /tmp/%s/BOINC_payload", tempDirName);
err = callPosixSpawn(temp);
REPORT_ERROR(err);
@ -392,7 +420,6 @@ static void GetPreferredLanguages() {
struct dirent *dp;
char temp[MAXPATHLEN];
char searchPath[MAXPATHLEN];
char savedWD[MAXPATHLEN];
struct stat sbuf;
CFMutableArrayRef supportedLanguages;
CFStringRef aLanguage;
@ -403,17 +430,6 @@ static void GetPreferredLanguages() {
char *uscore;
FILE *f;
getcwd(savedWD, sizeof(savedWD));
snprintf(temp, sizeof(temp), "rm -dfR /tmp/%s/BOINC_payload", tempDirName);
callPosixSpawn(temp);
snprintf(temp, sizeof(temp), "/tmp/%s/BOINC_payload", tempDirName);
mkdir(temp, 0777);
chmod(temp, 0777); // Needed because mkdir sets permissions restricted by umask (022)
chdir(temp);
snprintf(temp, sizeof(temp), "cpio -i -I /tmp/%s/expanded_BOINC.pkg/BOINC.pkg/Payload", tempDirName);
callPosixSpawn(temp);
chdir(savedWD);
// Create an array of all our supported languages
supportedLanguages = CFArrayCreateMutable(kCFAllocatorDefault, 100, &kCFTypeArrayCallBacks);
@ -589,7 +605,7 @@ static long GetOldBrandID()
}
static void ShowMessage(const char *format, ...) {
static Boolean ShowMessage(Boolean askYesNo, const char *format, ...) {
// CAUTION: vsprintf will produce undesirable results if the string
// contains a % character that is not a format specification!
// But CFString is OK!
@ -604,7 +620,7 @@ static void ShowMessage(const char *format, ...) {
if (myBundleRef) {
myIconURLRef = CFBundleCopyResourceURL(myBundleRef, CFSTR("MacInstaller.icns"), NULL, NULL);
}
#if 1
va_start(args, format);
vsprintf(s, format, args);
@ -616,19 +632,100 @@ static void ShowMessage(const char *format, ...) {
// If defaultButton is nil or an empty string, a default localized
// button title ("OK" in English) is used.
#if 0
enum {
kCFUserNotificationDefaultResponse = 0,
kCFUserNotificationAlternateResponse = 1,
kCFUserNotificationOtherResponse = 2,
kCFUserNotificationCancelResponse = 3
};
#endif
CFStringRef myString = CFStringCreateWithCString(NULL, s, kCFStringEncodingUTF8);
CFStringRef yes = CFStringCreateWithCString(NULL, (char*)_((char*)"Yes"), kCFStringEncodingUTF8);
CFStringRef no = CFStringCreateWithCString(NULL, (char*)_((char*)"No"), kCFStringEncodingUTF8);
BringAppToFront();
CFUserNotificationDisplayAlert(0.0, kCFUserNotificationPlainAlertLevel,
SInt32 retval = CFUserNotificationDisplayAlert(0.0, kCFUserNotificationPlainAlertLevel,
myIconURLRef, NULL, NULL, CFSTR(" "), myString,
NULL, NULL, NULL,
askYesNo ? yes : NULL, askYesNo ? no : NULL, NULL,
&responseFlags);
if (myIconURLRef) CFRelease(myIconURLRef);
if (myString) CFRelease(myString);
if (yes) CFRelease(yes);
if (no) CFRelease(no);
if (retval) return false;
return (responseFlags == kCFUserNotificationDefaultResponse);
}
#ifdef __arm64__
int check_rosetta2_installed() {
int prog;
char execpath[MAXPATHLEN];
int retval = 0;
snprintf(execpath, sizeof(execpath),
"/tmp/%s/BOINC_payload/Library/Application Support/BOINC Data/%s",
tempDirName, EMULATED_CPU_INFO_EXECUTABLE);
int argc = 1;
char* const argv[2] = {
const_cast<char *>(execpath),
NULL
};
retval = run_program(
"/tmp",
execpath,
argc,
argv,
0,
prog
);
if (retval) {
return retval;
}
retval = get_exit_status(prog);
if (retval) {
if (WIFEXITED(retval)) {
return (WEXITSTATUS(retval));
} else if (WIFSIGNALED(retval)) {
return (WTERMSIG(retval));
} else {
return -1;
}
}
return 0;
}
int optionally_install_rosetta2() {
int err = 0;
const char *cmd = "/usr/sbin/softwareupdate --install-rosetta --agree-to-license";
Boolean answer = ShowMessage(true,
(char *)_("BOINC can run project applications written for intel Macs if Rosetta 2 is installed.\n\n"
"Do you want to install Rosetta 2 now?"
));
printf("User answered %s to installing Rosetta 2\n", answer? "yes" : "no");
if (answer) {
err = callPosixSpawn(cmd);
REPORT_ERROR(err);
printf("%s returned %d\n", cmd, err);
fflush(stdout);
}
return err;
}
#endif // __arm64__
static OSErr QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEvent* reply, UInt32 refcon )
{
gQuitFlag = true;
@ -774,7 +871,7 @@ void print_to_log_file(const char *format, ...) {
// strlcpy(buf, getenv("HOME"), sizeof(buf));
// strlcat(buf, "/Documents/test_log.txt", sizeof(buf));
snprintf(buf, sizeof(buf), "/tmp/%s/BOINC_Installer_Errors", tempDirName);
snprintf(buf, sizeof(buf), "/tmp/%s/BOINC_Installer_Errors.txt", tempDirName);
f = fopen(buf, "a");
if (!f) return;

View File

@ -1,6 +1,6 @@
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2020 University of California
// Copyright (C) 2021 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
@ -131,10 +131,6 @@ static Boolean IsUserLoggedIn(const char *userName);
void FindAllVisibleUsers(void);
long GetBrandID(char *path);
int TestRPCBind(void);
#ifdef __arm64__
int check_rosetta2_installed();
int optionally_install_rosetta2();
#endif // __arm64__
pid_t FindProcessPID(char* name, pid_t thePID);
static void SleepSeconds(double seconds);
static OSErr QuitAppleEventHandler(const AppleEvent *appleEvt, AppleEvent* reply, UInt32 refcon);
@ -349,15 +345,6 @@ int main(int argc, char *argv[])
err = callPosixSpawn (s);
REPORT_ERROR(err);
#ifdef __arm64__
int rosetta_result = check_rosetta2_installed();
printf("check_rosetta2_installed() returned %d\n", rosetta_result);
if (rosetta_result == EBADARCH){
optionally_install_rosetta2();
}
#endif // __arm64__
Success = false;
#ifdef SANDBOX
@ -2189,73 +2176,6 @@ int TestRPCBind()
}
#ifdef __arm64__
int check_rosetta2_installed() {
int prog;
const char * data_dir = "/Library/Application Support/BOINC Data";
char execpath[MAXPATHLEN];
int retval = 0;
// write the EMULATED_CPU_INFO into the BOINC data dir
// the execuable should be in BOINC data dir
strncpy(execpath, data_dir, sizeof(execpath));
strncat(execpath, "/" EMULATED_CPU_INFO_EXECUTABLE, sizeof(execpath) - strlen(execpath) - 1);
int argc = 1;
char* const argv[2] = {
const_cast<char *>(execpath),
NULL
};
retval = run_program(
data_dir,
execpath,
argc,
argv,
0,
prog
);
if (retval) {
return retval;
}
retval = get_exit_status(prog);
if (retval) {
if (WIFEXITED(retval)) {
return (WEXITSTATUS(retval));
} else if (WIFSIGNALED(retval)) {
return (WTERMSIG(retval));
} else {
return -1;
}
}
return 0;
}
int optionally_install_rosetta2() {
int err = 0;
const char *cmd = "/usr/sbin/softwareupdate --install-rosetta --agree-to-license";
Boolean answer = ShowMessage(true,
(char *)_("BOINC can run project applications written for intel Macs if Rosetta 2 is installed.\n\n"
"Do you want to install Rosetta 2 now?"
));
printf("User answered %s to installing Rosetta 2\n", answer? "yes" : "no");
if (answer) {
err = callPosixSpawn(cmd);
REPORT_ERROR(err);
printf("%s returned %d\n", cmd, err);
fflush(stdout);
}
return err;
}
#endif // __arm64__
pid_t FindProcessPID(char* name, pid_t thePID)
{
FILE *f;

View File

@ -18,6 +18,8 @@ Installing BOINC may take several minutes; please be patient.
\b0 \
\
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
\cf2 New for Apple Silicon Macs:\cf0 This version of BOINC can run project applications written only for Intel Macs in addition to ones written for Apple Silicon, but only if Apple's Rosetta 2 translation is installed. (Please do not confuse Apple's Rosetta 2 with the BOINC Rosetta project.) If you have not previously installed Apple's Rosetta 2 translator, the BOINC installer will offer you the option of installing it.\
\
\cf2 New for Mojave\cf0 : If your Mac has more than one user account, each user may see the following dialog upon their first login after you have installed BOINC: "BOINC_Finish_install" wants to control "System Events...." The BOINC installer needs this access to finish adding or removing its login item for each user; please click "OK".\
\
\cf2 CUDA UPGRADE WARNING\cf0 : Do not upgrade to CUDA 6.5 or later if you have an older NVIDIA GPU with Compute Capability 1.3 or less. You can check your GPU\'92s Compute Capability at {\field{\*\fldinst{HYPERLINK "https://developer.nvidia.com/cuda-gpus"}}{\fldrslt https://developer.nvidia.com/cuda-gpus}}. \

View File

@ -1,9 +1,9 @@
{\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf600
{\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf610
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;\red251\green2\blue7;\red0\green0\blue0;\red255\green255\blue255;
\red62\green0\blue63;\red217\green11\blue0;\red56\green110\blue255;}
{\*\expandedcolortbl;;\cssrgb\c100000\c14913\c0;\cssrgb\c0\c0\c0;\cssrgb\c100000\c100000\c100000;
\cssrgb\c31373\c0\c31373;\csgenericrgb\c85098\c4314\c0;\csgenericrgb\c21961\c43137\c100000;}
{\colortbl;\red255\green255\blue255;\red251\green2\blue7;\red217\green11\blue0;\red56\green110\blue255;
}
{\*\expandedcolortbl;;\cssrgb\c100000\c14913\c0;\csgenericrgb\c85098\c4314\c0;\csgenericrgb\c21961\c43137\c100000;
}
\margl1440\margr1440\vieww16760\viewh18800\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\qc\partightenfactor0
@ -30,6 +30,9 @@
\b0 \cf0 \ulnone World Community Grid is enabled by the Berkeley Open Infrastructure for Network Computing (BOINC) open source distributed computing platform.\
\
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
\cf2 New for Apple Silicon Macs:\cf0 This version of BOINC can run project applications written only for Intel Macs in addition to ones written for Apple Silicon, but only if Apple's Rosetta 2 translation is installed. (Please do not confuse Apple's Rosetta 2 with the BOINC Rosetta project.) If you have not previously installed Apple's Rosetta 2 translator, the BOINC installer will offer you the option of installing it.\
\
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
\cf2 New for Mojave\cf0 : If your Mac has more than one user account, each user may see the following dialog upon their first login after you have installed World Community Grid: "World Community Grid_Finish_install" wants to control "System Events...." The World Community Grid installer needs this access to finish adding or removing its login item for each user; please click "OK".\
\
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardeftab720\ri0\partightenfactor0
@ -37,7 +40,7 @@
\b \cf0 \ul GPU Processing
\b0 \ulnone \
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
\cf6 CUDA UPGRADE WARNING\cf0 : Do not upgrade to CUDA 6.5 or later if you have an older NVIDIA GPU with Compute Capability 1.3 or less. You can check your GPU\'92s Compute Capability at {\field{\*\fldinst{HYPERLINK "https://developer.nvidia.com/cuda-gpus"}}{\fldrslt https://developer.nvidia.com/cuda-gpus}}. \
\cf3 CUDA UPGRADE WARNING\cf0 : Do not upgrade to CUDA 6.5 or later if you have an older NVIDIA GPU with Compute Capability 1.3 or less. You can check your GPU\'92s Compute Capability at {\field{\*\fldinst{HYPERLINK "https://developer.nvidia.com/cuda-gpus"}}{\fldrslt https://developer.nvidia.com/cuda-gpus}}. \
\
You can find older CUDA drivers at {\field{\*\fldinst{HYPERLINK "http://www.nvidia.com/object/mac-driver-archive.html"}}{\fldrslt http://www.nvidia.com/object/mac-driver-archive.html}}. Note: after mounting the downloaded disk image, you may need to control-click on the CUDA installer package to open it.\
\
@ -45,7 +48,7 @@ For more options, please see the BOINC Macintosh administrator tools at:\
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
{\field{\*\fldinst{HYPERLINK "http://boinc.berkeley.edu/wiki/Tools_for_Mac_OS_X"}}{\fldrslt \cf0 http://boinc.berkeley.edu/wiki/Tools_for_Mac_OS_X}}\
\
Processing with your graphics card, or GPU, is supported. Please see {\field{\*\fldinst{HYPERLINK "http://boinc.berkeley.edu/wiki/GPU_computing"}}{\fldrslt \cf7 \ul \ulc7 http://boinc.berkeley.edu/wiki/GPU_computing\cf0 \ulnone }}for more information. If you have a CUDA-capable NVIDIA GPU and you wish to run CUDA applications, you will need to download and install the CUDA driver and libraries for your system from {\field{\*\fldinst{HYPERLINK "http://www.nvidia.com/object/mac-driver-archive.html"}}{\fldrslt http://www.nvidia.com/object/mac-driver-archive.html}}. OpenCL applications on NVIDIA and ATI / AMD graphics processors are also supported. OpenCL support is standard as part of Mac OS 10.6 and later.\
Processing with your graphics card, or GPU, is supported. Please see {\field{\*\fldinst{HYPERLINK "http://boinc.berkeley.edu/wiki/GPU_computing"}}{\fldrslt \cf4 \ul \ulc4 http://boinc.berkeley.edu/wiki/GPU_computing\cf0 \ulnone }}for more information. If you have a CUDA-capable NVIDIA GPU and you wish to run CUDA applications, you will need to download and install the CUDA driver and libraries for your system from {\field{\*\fldinst{HYPERLINK "http://www.nvidia.com/object/mac-driver-archive.html"}}{\fldrslt http://www.nvidia.com/object/mac-driver-archive.html}}. OpenCL applications on NVIDIA and ATI / AMD graphics processors are also supported. OpenCL support is standard as part of Mac OS 10.6 and later.\
\
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
@ -106,4 +109,4 @@ You can move (
\b0 ) World Community Grid from your Macintosh, run the
\b Uninstall World Community Grid
\b0 application which is included with the installer in the extras folder.\
}
}