arm64
and x86_64
.These two points combined mean that you might have to upgrade some of your projects. I had to migrate all my websites from Jekyll 3.x on Ruby 2.x to Jekyll 4.3.1 on Ruby 3.1.2.
Fight the urge to try and get your projects running with outdated software. You’ll quickly run into issue number two and be tempted to run your Terminal under Rosetta, like some posts suggest. Please don’t do this. You’ll regret it later.
In this guide I’ll help you install Homebrew, rbenv and a recent version of Ruby all compiled for the arm64
architecture.
Before we get started, make sure you’re not already running your Terminal of choice under Rosetta:
x86_64
installations if necessaryIf you’ve somehow migrated your Homebrew, rbenv or Ruby installations from a previous Intel Mac, you’ll first have to uninstall the x86_64
code.
Just to be sure, check if you have any files present under /usr/local
. That’s was the path Homebrew used before. The new path is /opt/Homebrew
.
brew uninstall rbenv
Check if there’s anything left under ~/.rbenv
. Get rid of the folder if it’s still there.
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)"
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Make sure the following line is present in your ~/.zshrc
(or other shell’s config):
export PATH="/opt/Homebrew/bin:$PATH"
brew install rbenv readline openssl
Add the following lines to your ~/.zshrc
(or other shell’s config):
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
You might already have Xcode and its Command Line Tools installed, but there is a chance that rbenv won’t find it.
You can find the standalone release here: https://developer.apple.com/download/all/.
Add the following to your ~/.zshrc
(or other shell’s config):
local READLINE_PATH=$(brew --prefix readline)
local OPENSSL_PATH=$(brew --prefix openssl)
export LDFLAGS="-L$READLINE_PATH/lib -L$OPENSSL_PATH/lib"
export CPPFLAGS="-I$READLINE_PATH/include -I$OPENSSL_PATH/include"
export PKG_CONFIG_PATH="$READLINE_PATH/lib/pkgconfig:$OPENSSL_PATH/lib/pkgconfig"
export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$OPENSSL_PATH"
export PATH=$OPENSSL_PATH/bin:$PATH
export SDKROOT="$(xcrun --show-sdk-path)"
This makes sure the compiler knows where to find all the dependencies it requires.
Now get a list of the most recent Ruby versions:
rbenv install --list
Output:
2.6.10
2.7.6
3.0.4
3.1.2
jruby-9.3.9.0
mruby-3.1.0
picoruby-3.0.0
rbx-5.0
truffleruby-22.3.0
truffleruby+graalvm-22.3.0
Only latest stable releases for each Ruby implementation are shown.
Use 'rbenv install --list-all / -L' to show all local versions.
Depending on when you run this command the output will be different. Just pick the latest release.
If you need Ruby 2, you might have to install OpenSSL 1.1.x. To do this, change every mention of openssl
to openssl@1.1
. So, brew install openssl@1.1
and local OPENSSL_PATH=$(brew --prefix openssl@1.1)
.
To install Ruby 3.1.2:
rbenv install 3.1.2
Hopefully the command will now complete successfully and you’ll be able to use Ruby. To make it the default on your system use this:
rbenv global 3.1.2
That’s it. All done. 🥳
]]>Microsoft recently released the 2004 version update for Windows 10. It includes a bunch of cool new features, like WSL 2 which integrates Linux even better into the Windows operating system.
I immediately jumped at the opportunity to install the update when it presented itself, only to be disappointed during the installation. It repeatedly failed with a BSOD mentioning cpuz141_x64.sys
caused a PAGE_FAULT_IN_NONPAGED_AREA
.
At first I was confused, because I wasn’t aware a CPU-Z driver was installed at all. After some digging I discovered it’s used by the Corsair Link utility installed on all 2017/2018 Corsair ONE models.
Corsair Link is mandatory as it’s solely responsible for updating the fan speeds while the system is in use. Without it the computer will overheat. A terrible depedency I wasn’t fully aware of when I bought the machine.
It’s pretty though and fast.
The in-app update mechanism for Corsair Link promised me I was running the latest version. That was concerning. It suggested I might not be able to install the 2004 update at all. Luckily I came across this topic on the Corsair forum: CORSAIR LINK 4.4.4.9 for CORSAIR ONE (2017/2018). Posted in 2018 it provides a download link to an updated version of Corsair Link. Why this version isn’t available through the in-app updater is unknown to me.
After installing the newer version, Windows continued the OS update without a hitch. 🥳
]]>It was attached though and I tried everything to get it to work:
The problem manifested over a few weeks, getting worse every day. I thought the ribbon cable had been damaged. Nothing I could do to fix it.
Then I tried bending the magnets that snap the keyboard into place. 🧲
I couldn’t believe it at first, but the problem was resolved instantly. After folding and unfolding it several times it still works. I’m actually typing this article on it.
The trick is to bend the magnets slightly towards where it connects with the iPad. Don’t overdo it, just curve them up a tiny bit. I can’t even see the difference on mine, but the effect is there.
So, if you’ve ruled out all software-related issues, you might want to give this a go. Let me know if you got yours working again too!
Note: I’m not responsible for any damage you cause to your keyboard. Be careful and use common sense.
]]>I use VMWare Fusion 10 to test my apps on previous and future versions of macOS. Since this fall, that’s become problematic. The screen remains blank when I start one of my virtuals on Catalina. Oddly enough the preview in the virtual machine overview works fine.
Catalina requires apps to request permission for various tasks. Recording the screen is one of them. Apparently Fusion uses this feature, but neglects to ask for permission. Thus the screen stays black.
Some people found a way to get around this by granting permission manually. Here’s how that works.
⚠️ Note that this requires running Terminal commands in Recovery Mode. Make sure you’re comfortable with these steps. I don’t offer any support and am not responsible if things don’t go as planned. ⚠️
Create a new script file where you can easily access it. I recommend /tmp/fixfusion.sh
. Paste in the following:
#!/bin/sh
# Change the following to fit your system
root="/Volumes/Macintosh HD"
"$root/usr/bin/sqlite3" "${root}/Library/Application Support/com.apple.TCC/TCC.db" 'insert into access values ("kTCCServiceScreenCapture", "com.vmware.fusion", 0, 1, 1, "", "", "", "UNUSED", "", 0,1565595574)'
Enter Recovery Mode by restarting your Mac and holding down ⌘
+ R
while it boots.
Start a Terminal window by selecting Utilities
→ Terminal
from the menu bar when you’ve reached Recovery Mode.
If your primary drive is encrypted using FileVault (it should be), unlock it first by running the following command:
diskutil apfs unlock "Macintosh HD"
(Again, adjust the command if your disk isn’t called “Macintosh HD”.)
Enter your passphrase when it asks for it.
You can now run the script you created earlier:
sh "/Volumes/Machintosh HD/tmp/fixfusion.sh"
It’s supposed to not show any output. If there’s no error, it worked.
Check System Preferences
→ Security & Privacy
→ Privacy
→ Screen Recording
and you’ll notice VMWare Fusion has the permission it needs.
That’s it. Your virtual machines should properly work again. 🥳
]]>DevMate is the service I use to gather download and install statistics for most of my apps. It also serves the update feeds for all non-Mac App Store apps. Earlier this year DevMate announced its retiring the platform in December.
In this post I’ll outline how I’m preparing my apps to migrate to a new update feed. Christian Tietze mentions asking DevMate to point the Sparkle update feed to a new location. He also recommends to not rely on DevMate’s redirect to work forever. That’s where my approach comes in.
I urge you to take control over the feed URL entirely and redirect it yourself. DevMateKit uses Sparkle under the hood. This means a custom update URL can be specified by implementing a Sparkle delegate method.
class ApplicationCoordinator: NSObject, Coordinator {
...
private func configureUpdates() {
DM_SUUpdater.shared().delegate = self
}
}
extension ApplicationCoordinator: DM_SUUpdaterDelegate_DevMateInteraction {
func feedURLString(for updater: DM_SUUpdater) -> String? {
if Defaults.shared.isEnabled(setting: .betaUpdates) {
return .appcastBetaURLString
} else {
return .appcastURLString
}
}
}
extension String {
static let appcastURLString = "https://updates.dangr.co/\(Bundle.main.bundleIdentifier!)/appcast.xml"
static let appcastBetaURLString = "https://updates.dangr.co/\(Bundle.main.bundleIdentifier!)/beta-appcast.xml"
}
After this change Timeless will check for updates at https://updates.dangr.co/com.dangercove.Timeless.Mac/appcast.xml
. The updates.dangr.co
domain is mine and I can set redirects for it however I want.
I use Netlify to handle the redirects. Here’s what that looks like:
com.dangercove.Timeless.Mac/appcast.xml* https://updates.devmate.com/com.dangercove.Timeless.Mac.xml:splat 301
com.dangercove.Timeless.Mac/beta-appcast.xml* https://updates.devmate.com/beta/com.dangercove.Timeless.Mac.xml:splat 301
As you can see I currently redirect to the feed at DevMate, but I can redirect it anywhere else whenever I want. This allows me to use DevMate for as long as possible and switch to any other service that uses Sparkle. I’m keeping a close eye on App Center by Microsoft. They put Sparkle feeds for macOS on the roadmap for September.
]]>dyld: Library not loaded: @rpath/DCOAboutWindow.framework/Versions/A/DCOAboutWindow
Referenced from: /Users/username/Library/Developer/Xcode/DerivedData/Pipvid-adwfbkaurzovizgaarwkmugeihce/Build/Products/Debug/Pipvid.app/Contents/MacOS/Pipvid
Reason: no suitable image found. Did find:
/Users/username/Library/Developer/Xcode/DerivedData/Pipvid-adwfbkaurzovizgaarwkmugeihce/Build/Products/Debug/Pipvid.app/Contents/MacOS/../Frameworks/DCOAboutWindow.framework/Versions/A/DCOAboutWindow: code signature in (/Users/username/Library/Developer/Xcode/DerivedData/Pipvid-adwfbkaurzovizgaarwkmugeihce/Build/Products/Debug/Pipvid.app/Contents/MacOS/../Frameworks/DCOAboutWindow.framework/Versions/A/DCOAboutWindow) not valid for use in process using Library Validation: mapped file has no Team ID and is not a platform binary (signed with custom identity or adhoc?)
The issue is caused by a new entry in your project.pbxproj
that specifies the signing identity: CODE_SIGN_IDENTITY = "-";
. It’s set to Sign to Run Locally by default.
Changing Signing Certificate to Development under Signing Capabilities in the project settings resolves the issue. You could also manually update the entry to CODE_SIGN_IDENTITY = "Apple Development";
.
As promised, in this second part of the website redesign story I’ll go over the technical details of the changes I made to dangercove.com.
To get a sense of how the website’s built, here’s an overview of what I use to layout and serve its content.
It’s a simple setup. The entire site is statically generated by Jekyll and then served by Netlify. Bulma is a CSS framework that allows me to style templates quickly.
Let’s take a look at the homepage first. The list of apps is generated by including the app/overview.html
template and assigning it a set of apps pages.
{% assign live = site.pages | where: 'layout', 'app/live' %}
{% assign announced = site.pages | where: 'layout', 'app/announced' %}
{% assign apps = announced | concat: live %}
{% include app/overview.html apps=apps %}
I fetch the apps to display by querying site.pages
for pages that use the app/live
and app/announced
layout. Then I concatenate both arrays into a single apps
variable and pass that to the includable app/overview.html
template.
The app/overview.html
template checks if it’s on the homepage (if page.layout == "home"
) and adds the Danger Cove logo accordingly.
...
{% if page.layout == "home" %}
<div class="column is-4-widescreen is-half-desktop is-full-tablet is-full-mobile">
<div class="box is-shadowless has-text-centered">
{% include logo/retro.html %}
<h1 class="title is-size-2-mobile is-1 is-spaced">{{ page.title }}</h1>
<h2 class="subtitle is-size-5-mobile is-4">{{ page.subtitle }}</h2>
</div>
</div>
{% endif %}
...
Then it loops over the provided apps and includes app/introduction.html
for each. This is the actual visual representation of the app, in the form of a card. Pulling it out into a separate include makes it trivial to display the app card anywhere else. I’ll use it again when showing related apps with blog posts. More on that a little further down.
...
{% for app in apps %}
<div class="column is-4-widescreen is-half-desktop is-full-tablet is-full-mobile">
{% include app/introduction.html app=app %}
</div>
{% endfor %}
...
Notice the convenient column CSS classes that Bulma provides. It’s trivial to scale the layout from mobile to widescreen devices.
The app/introduction.html
template pulls the title, subtitle, description and colors from the app’s front matter. This is what the front matter for Timeless looks like:
---
layout: app/announced
site_title: Don't get distracted by time
title: Timeless
subtitle: Reduce time anxiety
description: >-
Get a more subtle sense of what time it is. Reducing time pressure and distraction.
date: 2018-07-18
icon: timeless-clock_512.png
hero:
icon: timeless-clock_512.png
dominant_color:
r: 200
g: 200
b: 200
features:
- Specify several, customizable 'time segments'.
- Indicates the current segment in the menu bar.
- Display the actual time and date with a single click.
tags:
- macOS
- Productivity
topic: timeless
mailchimp:
interests: [2]
permalink: /timeless/
---
Every card shows a specific rainbow of colors in its bottom right corner. Storing this information in the page’s front matter allows me to pull it out in the template and apply per-app design details.
{% assign color = app.hero.dominant_color %}
<div class="box" style="background-image: linear-gradient(135deg,
transparent 80%,
rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.25) 80%,
rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.25) 85%,
rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.5) 85%,
rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.5) 90%,
rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.75) 90%,
rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.75) 95%,
transparent 95%)
;">
...
It’s hard to get around using style=""
for this loop. On the app’s landing pages I apply the colors to a generic CSS class that I can use in the template.
...
{% if page.hero.dominant_color %}
{% assign color = page.hero.dominant_color %}
<style>
.hero-app {
background: linear-gradient(35deg,
transparent 60%,
rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.25) 60%,
rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.25) 70%,
rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.5) 70%,
rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 0.5) 80%,
rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 1) 80%,
rgba({{ color.r }}, {{ color.g }}, {{ color.b }}, 1) 90%,
transparent 90%);
}
...
Setting class="hero-app"
atomatically applies the rainbow background for each app.
Before: After:
Loading all posts on the /news
page would be madness. The first step I took was to implement the jekyll-paginate-v2
plugin:
gem "jekyll-paginate-v2"
to Gemfile
:
group :jekyll_plugins do
...
gem "jekyll-paginate-v2"
end
_config.yml
:
plugins:
...
- jekyll-paginate-v2
pagination:
enabled: true
sort_reverse: true # Required in my setup to order posts from new to old
permalink: "/page/:num/"
news.markdown
front matter:
---
...
pagination:
enabled: true
per_page: 5
---
The pagination plugin is ready to be implemented in _layouts/news/home.html
at this point. It comes down to two things:
{% for post in site.posts %}
with {% for post in paginator.posts %}
in the template.I updated _includes/post/preview.html
to show the entire post instead of just a preview. That’s it.
This new feature uses some front matter magic to allow me to pull in related content with a blog post. Consider the _includes/post/related.html
template:
{% assign tags = include.tags %}
{% for tag in tags %}
{% assign app = site.pages | where: 'topic', tag | first %}
{% if app %}
{% include app/introduction.html app=app %}
{% endif %}
{% endfor %}
Usage: {% include post/related.html tags=post.tags %}
It loops through all tags assigned to a post and then searches site.pages
for a page that has a topic
that matches the tag
.
Imagine I write a post about Timeless and tag it like this:
---
...
tags: [updates, timeless]
...
---
If you look in the front matter for Timeless above, you’ll notice its topic:
---
...
topic: timeless
...
---
The app
variable gets assigned and the app/introduction.html
card template gets included. If the tags include multiple apps, each is shown.
The full source code for dangercove.com is available on GitHub. For a comprehensive list of all changes made for this redesign, take a look at this diff: 3493aae..4518428
I hope you enjoyed this in-depth look at how I keep dangercove.com up-to-date. If you have any feedback, questions or comments let me know on Twitter.
]]>
That’s not a good sign and I decided to open them up and take a look at the circuit boards.
Here’s a picture of an authentic, Nintendo manufactured circuit board for Golden Sun (AGB-AGSP-EUR). It looks neat, tidy and well put together.
The contrast with the boards below is striking.
This is the inside of the Metroid Fusion cart. The board is dirty, the fonts and logos are incorrect, there’s even a label on one of the chips (it says something about a ‘North Star’).
The Final Fantasy VI Advance cart is less dramatic, but a reproduction nonetheless. The Nintendo logo looks awful.
I haven’t decided what I’ll do with these. Either I’ll throw them out, or I’ll drop them off at the local thrift store. Trashing them means somebody else won’t be able to buy (or sell) them anymore.
]]>The clock is one of those distractions for me:
This gets worse when I have appointments throughout the day. The example is a bit extreme, but you catch my drift.
As an experiment, I removed every time indicator from my screen six months ago. The effects are noticeable: I can just sit, work and not care about how the day is progressing. This lack of attachment in turn makes it easier to lose myself in what I’m doing, thus comfortably achieving more.
There are downsides: it also stops me from getting up and do basic things like drink water or getting some fresh air. I work from home and if I’m not careful I skip lunch and scramble to make something for diner because I forgot to buy groceries.
Notifications help with this. My calendar and reminders pop up every now and then so I don’t forget anything important. I could start wearing my Apple Watch again to remind me to get up, set additional reminders to help me take proper care of myself and do mundane tasks during the day.
That’s a bit much, I think. It would make me feel like a robot.
I’m working on a more natural way of getting the most out of my day: it’s an app called Timeless. At its core it gives me a generic sense of what part of the day I’m in: morning, lunch time, noon etc.
Instead of breaking concentration or induce stress it lets me continue working when I’m still in the time range I’m expecting to get stuff done. Then, in a glance, it lets me know that I’ve entered a new part of the day. If it’s between 12pm and 2pm I should probably get lunch.
There’s no notification to ‘get lunch now’, just a hint that when I’m ready I should probably go grab something to eat.
Even when combined with more urgent interruptions, like water breaks, it allows me to comfortably get back to work. I don’t feel any pressure or hesitance because of how much time I have left in the day.
I’m getting ready to let others give this a go as well. If you’d like to be invited to try the beta, subscribe to the mailing list. Thanks!
]]>That’s right: I fit my entire office inside of a cabinet. This includes a monitor, desktop computer, laptop, three game consoles with peripherals and a bunch of binders.
It made me think about where I work on my apps. Currently there are three major workplaces that I alternate between: my closet, a desk at Blendle and random Croissant affiliated coworking places1…
Read the rest of this post over at shorts.boy.sh. For more regular updates and personal notes, consider following me there. →
Full disclosure: Contains an affiliate link for Croissant. Using it is much appreciated. ↩