在M1 MacBook上配置开发环境

新 MacBook 采用了 arm 架构的 Apple Silicon 芯片,虽说在能耗比上有了巨大的提升,但新的架构却给开发带来了不少困扰。arm 的开发环境能更好地利用性能,但出于兼容性的考虑,很多情况下仍然需要 x86 的开发环境。因此,本文整理了在新 MacBook 上配置 arm 架构和 x86 架构的开发环境共存的方法。

XCode Command Line Tools和Rosetta 2

安装 CLT:

xcode-select --install

安装 Rosetta 2:

softwareupdate --install-rosetta

Shell工具

iTerm2

iTerm2 是一款拥有许多功能的终端模拟器,可以替代 MacOS 自带的“终端”。

  1. 下载并安装 iTerm2。(可选:iTerm 颜色方案下载);
  2. 打开 Finder,按下 ⌘+⇧+A,找到“iTerm”,右键 > 复制;
  3. 将复制出来的图标重命名为“iTerm (Rosetta)”,右键 > 显示简介,勾选“使用 Rosetta”打开。

这样就可以用“iTerm”进入 arm64 架构的 shell,用“iTerm (Rosetta)”进入 x86_64 架构的 shell 了!

oh-my-zsh

oh-my-zsh 是一款增强 zsh 功能的框架。安装:

sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

powerlevel10k

powerlevel10k 是一款 oh-my-zsh 的主题。安装:

git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k

运行 nano ~/.zshrc,找到 ZSH_THEME 一行并改为:ZSH_THEME="powerlevel10k/powerlevel10k"

显示当前架构

为了方便使用,可以在主题中添加当前架构的显示。运行 nano ~/.p10k.zsh,找到 POWERLEVEL9K_OS_ICON_CONTENT_EXPANSION 一行并改为 typeset -g POWERLEVEL9K_OS_ICON_CONTENT_EXPANSION=$'\uE711 $(uname -m)' 。如果主题被配置为显示系统标志,那么标志右侧就会显示当前架构。

显示NodeJS版本

运行 nano ~/.p10k.zsh,找到 POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS,取消注释 node_version 一行。在有 package.json 的目录下就会显示 Node.js 的版本。

z

z 是 oh-my-zsh 自带的一款插件,能够简化在目录之间跳转的流程。例如,你曾经运行过 cd /Users/YOUR_NAME/MyProjects 来跳转到 MyProjects,那么之后你可以执行 z MyProjects 甚至是 z Projects 来达到同样的目的。

启用插件:运行 nano ~/.zshrc,找到 plugins 一行并改为:plugins=(... z)

zsh-syntax-highlighting

zsh-syntax-highlighting 是一款语法高亮插件,能够用不同的颜色来标识正确和错误的语法。安装:

git clone --depth=1 https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

启用插件:运行 nano ~/.zshrc,找到 plugins 一行并改为:plugins=(... zsh-syntax-highlighting)

zsh-autosuggestions

zsh-autosuggestions 是一款命令提示和补全插件,能够根据历史输入来提供命令提示,按下 即可自动补全。安装:

git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

启用插件:运行 nano ~/.zshrc,找到 plugins 一行并改为:plugins=(... zsh-autosuggestions);并在底部添加一行:bindkey '^O' autosuggest-accept,这样按 ⌃+O 也能接受提示的内容了。

如果在 iTerm 中看不到命令提示的内容,需要按下 ⌘+,,前往 Profiles > Colors,确保 Basic Colors > BackgroundANSI Colors > Bright > Black 是不同的。

zsh-history-substring-search 是一款快速搜索历史输入的插件。例如,你曾经运行过 docker container ls,那么你输入 container 就可以搜索到之前的命令。安装:

git clone --depth=1 https://github.com/zsh-users/zsh-history-substring-search ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-history-substring-search

启用插件:运行 nano ~/.zshrc,找到 plugins 一行并改为:plugins=(... zsh-history-substring-search);并在底部添加两行:bindkey '^P' history-substring-search-upbindkey '^N' history-substring-search-down,这样在输入搜索关键字后,按 ⌃+P 就可以向前搜索,按 ⌃+N 就可以向后搜索。

注意,如果同时使用 zsh-syntax-highlightingzsh-history-substring-search,请确保 pluginszsh-syntax-highlightingzsh-history-substring-search 之前。

添加命令别名

运行 nano ~/.zshrc,找到 alias,可以有选择性地添加一些常用的命令别名:

alias zshconfig="nano ~/.zshrc"
alias p10kconfig="nano ~/.p10k.zsh"
alias native="arch -arm64"
alias rosetta="arch -x86_64"
alias cenvls="conda env list"
alias cenvact="conda activate"
alias showpath="echo \$PATH | sed -e \"s/:/\\n/g\""

Homebrew

Homebrew 是一款很好用的包管理器。安装 arm 架构版本:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

安装 x86 架构版本:

arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

将两个版本的 Homebrew 添加到 PATH:运行 nano ~/.zshrc,在底部添加:

# Initiate Homebrew
if [ "$(uname -m)" = "arm64" ]; then
  eval "$(/opt/homebrew/bin/brew shellenv)"
else
  eval "$(/usr/local/bin/brew shellenv)"
fi

这样在不同架构的 iTerm 中,就会添加对应版本的 Homebrew 到 PATH。

Miniconda

Miniconda 是一款很好用的 Python 环境管理器。安装 arm 架构版本:

curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh
. ./Miniconda3-latest-MacOSX-arm64.sh

安装路径输入:/Users/YOUR_NAME/opt/miniconda3-arm64;最后询问是否需要运行 conda init 初始化输入 no

安装 x86 架构版本:

curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh
. ./Miniconda3-latest-MacOSX-x86_64.sh

安装路径输入:/Users/YOUR_NAME/opt/miniconda3-x86_64;最后询问是否需要运行 conda init 初始化输入 no

最后,将两个版本的 Miniconda 添加到 PATH:运行 nano ~/.zshrc,在底部添加:

# Initiate Miniconda
if [ "$(uname -m)" = "arm64" ]; then
  __conda_setup="$('/Users/YOUR_NAME/opt/miniconda3-arm64/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
  if [ $? -eq 0 ]; then
    eval "$__conda_setup"
  else
    if [ -f "/Users/YOUR_NAME/opt/miniconda3-arm64/etc/profile.d/conda.sh" ]; then
      . "/Users/YOUR_NAME/opt/miniconda3-arm64/etc/profile.d/conda.sh"
    else
      export PATH="/Users/YOUR_NAME/opt/miniconda3-arm64/bin:$PATH"
    fi
  fi
  unset __conda_setup
else
  __conda_setup="$('/Users/YOUR_NAME/opt/miniconda3-x86_64/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
  if [ $? -eq 0 ]; then
    eval "$__conda_setup"
  else
    if [ -f "/Users/YOUR_NAME/opt/miniconda3-x86_64/etc/profile.d/conda.sh" ]; then
      . "/Users/YOUR_NAME/opt/miniconda3-x86_64/etc/profile.d/conda.sh"
    else
      export PATH="/Users/YOUR_NAME/opt/miniconda3-x86_64/bin:$PATH"
    fi
  fi
  unset __conda_setup
fi

这样在不同架构的 iTerm 中,就会添加对应版本的 Miniconda 到 PATH。

C/C++ 和 Node.js

无论是 MacOS 自带的 gcc/g++ 编译器,还是通过 Homebrew 安装的 CMake,都同时支持 arm 和 x86 两个架构,因此 C/C++ 环境的搭建要相对简单一些。Node.js 环境的搭建则可以通过 Homebrew 安装 nvm 之类的工具来解决,而且 Node.js 环境对于架构更加不敏感一些。因此本文不再赘述相关步骤。