From eaa1a930431296ee1ffc414748f087f15800c74d Mon Sep 17 00:00:00 2001 From: Charlie Fenton Date: Tue, 22 Jun 2021 23:56:57 -0700 Subject: [PATCH] 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 --- mac_installer/Installer.cpp | 143 +++++++++++++++++++++++++++----- mac_installer/PostInstall.cpp | 82 +----------------- mac_installer/ReadMe.rtf | 2 + mac_installer/wcgrid-ReadMe.rtf | 19 +++-- 4 files changed, 134 insertions(+), 112 deletions(-) diff --git a/mac_installer/Installer.cpp b/mac_installer/Installer.cpp index 167cdf0a9a..cb22fc39bd 100644 --- a/mac_installer/Installer.cpp +++ b/mac_installer/Installer.cpp @@ -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(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; diff --git a/mac_installer/PostInstall.cpp b/mac_installer/PostInstall.cpp index 2a10320989..87862d7fa8 100644 --- a/mac_installer/PostInstall.cpp +++ b/mac_installer/PostInstall.cpp @@ -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(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; diff --git a/mac_installer/ReadMe.rtf b/mac_installer/ReadMe.rtf index 65779adf76..ca3446efeb 100644 --- a/mac_installer/ReadMe.rtf +++ b/mac_installer/ReadMe.rtf @@ -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}}. \ diff --git a/mac_installer/wcgrid-ReadMe.rtf b/mac_installer/wcgrid-ReadMe.rtf index 425e69c876..d0f2a66960 100644 --- a/mac_installer/wcgrid-ReadMe.rtf +++ b/mac_installer/wcgrid-ReadMe.rtf @@ -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.\ -} +} \ No newline at end of file