integralpro / nosleep

The MacOS X kernel extension, preventing sleep when you close the lid.
GNU General Public License v2.0
874 stars 45 forks source link

NoSleep 1.5.1 works perfectly on Apple Silicon (M1), macOS 12 Monterey with no code changes, as long as you compile the kext from source! #52

Open akemin-dayo opened 2 years ago

akemin-dayo commented 2 years ago

I'm glad to report that the latest version of NoSleep (1.5.1) works perfectly on Apple Silicon machines with no code changes required!

Basically, just compiling an additional arm64e (not arm64) binary slice to the NoSleep kext works! @integralpro

Tested on macOS 12.0.1 21A559, "Monterey".

(I do realise that this isn't really an issue per se, but I just felt really bad for all the users complaining about broken functionality here…)

(Plus, speaking from my own personal experience as a fellow developer, I do find it quite helpful when someone else already tested compatibility for me ;P)


If you're a general user coming who just wants to use NoSleep on Apple Silicon right this instant…

Ever since macOS / OS X 10.10 Yosemite, Apple has required kernel extensions (kexts) to be signed by developers who are subscribed to the Apple Developer Program, who also have to apply for a special kext signing privilege.

You're… probably not one of those people. ;P

Luckily, there is a way for you to sign your own kexts using an Xcode feature called ad-hoc signing! But it does require changing some settings first.

Switching to "Reduced Security" mode

If you've already placed your Mac in "Reduced Security" mode before, simply skip this section.

  1. Shut down your Apple Silicon Mac.
  2. Press and hold down the power button until the text under the Apple logo says "Loading startup options…", then let go.
  3. Select "Options".
  4. You are now in recoveryOS — enter your password if it asks.
  5. Go to Utilities → Startup Security Utility.
  6. Select "Reduced Security" and enable Allow user management of kernel extensions from identified developers".
  7. Shut down your Apple Silicon Mac.

Disabling SIP (System Integrity Protection)

IMPORTANT: Disabling SIP in any capacity, even partially, will also disable Apple Pay, as well as any iOS-on-macOS apps you may have downloaded from the App Store. This is a strange (and annoying) decision that Apple has decided to make specifically on Apple Silicon, as Apple Pay actually works fine even when SIP is disabled on x86_64 (Intel) Macs.

  1. Follow steps 2〜4 from above.
  2. Go to Utilities → Terminal.
  3. Type in the following to fully disable SIP: csrutil disable Note: It is possible to only partially disable the part of SIP that enforces kext signature verification (csrutil enable --without kext), but according to Apple, this is apparently an "unsupported configuration". Use it if you wish (as many do already), but please make sure to read and fully understand the warning that csrutil gives if you try.
  4. Reboot your Apple Silicon Mac.

Compiling NoSleep for Apple Silicon (arm64e)

  1. Download and install Xcode.
  2. Install the official version of NoSleep 1.5.1. Ignore the "Oops! NoSleep Kernel Extension is not loaded." message for now.
  3. Run the following in a Terminal session. When it asks for your password, it is normal for no characters to show when when you type!
    git clone --recursive https://github.com/integralpro/nosleep.git
    cd nosleep/NoSleep/
    xcodebuild VALID_ARCHS="x86_64 arm64e" CODE_SIGN_IDENTITY="-" -sdk macosx -configuration Release -target NoSleepKext
    sudo cp -rv ../DerivedData/Release/NoSleep.kext /Library/Extensions/
  4. Go to System Preferences → Security & Privacy and approve the NoSleep kernel extension.
  5. Reboot and enjoy NoSleep!

Regarding sudo pmset disablesleep 1 and sudo pmset disablesleep 0

Interestingly, there appears to be an undocumented pmset setting called disablesleep that seems to pretty much does what NoSleep does (prevent macOS from sleeping when the lid is closed).

Because it's undocumented, it's not really a guarantee that this setting will continue to exist in future macOS versions, but for now, if you don't want to deal with the procedure above and you're comfortable with using the Terminal to toggle your sleep functionality…

sudo pmset disablesleep 1 in a Terminal will prevent macOS from sleeping when the lid is closed. sudo pmset disablesleep 0 will re-enable the default behaviour.

To see the current status, use pmset -g and look for "SleepDisabled".

And yes, this does mean that it is possible to write a NoSleep-like front-end complete with menu bar item to toggle the pmset functionality. If NoSleep is EOL'd by integralpro or broken by Apple to the point of requiring a complete rewrite some day, that's what I'll probably end up doing.

integralpro commented 2 years ago

Hi @akemin-dayo! Wow, that's awesome that you took the whole path of recompiling and checking it for the AS macs! I'll try to find some time to prepare release with AS support.

akemin-dayo commented 2 years ago

Glad to hear that my testing was of some help to you!

Looking forward to the official release c:

integralpro commented 2 years ago

@akemin-dayo if you have some time, could you please try NoSleep-1.5.2.dmg. I don't have m1 mac to verify if everything's fine. Thanks!

cad0p commented 2 years ago

Hi @integralpro, I have been following this conversation because I'm interested as well.

I have tried your .dmg and it correctly asked me to add the kernel extension and allow it in the security preferences, but after the restart it still says that the kernel extension is not loaded unfortunately. Please let me know if there's anything I can do to help you debug this.

cad0p commented 2 years ago

I have an 14" M1 Pro by the way

akemin-dayo commented 2 years ago

Apologies for the extremely late reply, @integralpro — been busy with various things.

I tested your signed copy from the UX flow that a typical user would follow, and ran into some strange behaviour that I'm fairly sure is actually a compatibility issue in the kext installation code with recent (>= 11.0?) macOS versions.

I haven't tested this on an x86_64 machine yet but I'm fairly sure this issue would happen on one as well (basically, any macOS version with the split user kextcache functionality).

Here what happens:

  1. User installs NoSleep by dragging the app to /Applications and running it.
  2. macOS correctly detects the request to install a new kext and prompts the user to accept it in Security and Privacy
  3. Upon acceptance of the kext, the kextcache is rebuilt and the user reboots when prompted
  4. Once the system comes back from reboot, NoSleep.kext is not present in /Library/Extensions, but rather can be found at /Library/StagedExtensions/Applications/Utilities/NoSleep.app/Contents/Resources/NoSleep.kext.

I think something is going horribly wrong here since the expected path would have been /Library/StagedExtensions/NoSleep.kext and upon user kext-consent, would have been moved to /Library/Extensions by macOS.

I think the incorrect path in StagedExtensions is what's breaking the entire process here.

For the record though, manually loading the signed NoSleep kext you built using sudo kextload results in NoSleep working as expected, though that's what I expected anyway since my manually-built copy obviously functions fine as well ;P

For reference, I've reproduced this behaviour on macOS 12.3 beta 21E5206e and also macOS 12.2 21D49.

djsf222 commented 2 years ago

@akemin-dayo if you have some time, could you please try NoSleep-1.5.2.dmg. I don't have m1 mac to verify if everything's fine. Thanks!

1.5.2 says NoSleep Kernel Extension is not loaded on Apple M1 Max !

mdrichter commented 2 years ago

NoSleep is an amazing program, but I had difficulty getting it to work.

As a workaround, you can type caffeinate into your terminal window, and your computer won't sleep as long as you keep the terminal window open. It's not as cool as NoSleep, but works in a pinch.

TonOpener commented 2 years ago

I did as you did, but after turning off SIP and then turned to system preferences, I don't know how to "approve the NoSleep kernel extension" (my English is bad, hope you understand it)

akemin-dayo commented 2 years ago

@TonOpener If you can't find the prompt, run this in Terminal and it should make it appear:

sudo kextload /Library/Extensions/NoSleep.kext
dukenhu commented 2 years ago

Couldn't for the life of me get NoSleep to work, so I tried the pmset method and it still worked just fine. I'm on Ventura beta btw. I think just writing a new front end that uses the pmset functionality would be better at this point.