Homebrew | Utilisez un package manager sous macOS

Homebrew - Package manager macOS

Situation classique : votre société ou votre client vient de vous confier un MacBook flambant neuf pour exercer vos talents. Parfait, mais il vous reste le plus long à faire : installer tous vos outils pour pouvoir l’exploiter. Sous Linux, vous auriez un gestionnaire de formulas qui ferait bien l’affaire pour aller plus vite. Mais sous macOS, pas de apt-get, pas de yum : si on ne se renseigne pas, on se retrouve rapidement à tout faire à la main. Alors que ces craintes sont infondées ! Des gestionnaires de formulas existent aussi pour macOS, comme Homebrew (ou MacPorts). Et nous allons voir comment s’en servir pour se faciliter la vie.

Commençons par le plus important ! Installer homebrew, ce qui se fait en une ligne de commande ➜

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

NOTE : Homebrew est un gestionnaire basé sur des formulas d’installation de formula (en Ruby) et utilise des repositories git comme conteneurs de ces dernières.

Après une simple installation, vous avez à votre disposition une nouvelle commande, petit tour du propriétaire :

La commande “brew” vous montre les commandes les plus courantes.

$ brew
Example usage:
  brew search [TEXT|/REGEX/]
  brew (info|home|options) [FORMULA...]
  brew install FORMULA...
  brew update
  brew upgrade [FORMULA...]
  brew uninstall FORMULA...
  brew list [FORMULA...]

Troubleshooting:
  brew config
  brew doctor
  brew install -vd FORMULA

Dans ces commandes, on trouve notamment celles pour gérer les outils installés.

  brew install FORMULA...
  brew update
  brew upgrade [FORMULA...]
  brew uninstall FORMULA...

TIP : En exécutant “brew doctor”, vous vérifiez que votre installation de Homebrew est correcte. La commande vous indiquera les différents problèmes de votre installation (s’il y en a).

Maintenant que homebrew est installé, vous souhaitez installer vos premiers outils.

Commençons par les besoins de votre projet. Imaginons qu’il est en Java, sous Gradle, avec des outils écrits en Go et que l’ensemble est géré par Ansible. Il va donc vous falloir :

  • Ansible
  • Java
  • Go
  • Gradle

Installez vos formulas hors java

$ brew install ansible go gradle
$ ansible --version
ansible 2.2.0.0

$ go version
go version go1.7.4 darwin/amd64

$ gradle -v
Gradle 3.3

Traitons Java à part, pour installer en toute sécurité Java 8, en cherchant les formulas nommées « java ».

$ brew search java
app-engine-java
google-java-format
javarepl
jslint4java
libreadline-java
homebrew/emacs/javaimp
Caskroom/cask/eclipse-java
Caskroom/cask/java
Caskroom/cask/netbeans-java-ee
Caskroom/cask/netbeans-java-se
Caskroom/cask/yourkit-java-profiler
Caskroom/versions/charles-applejava
Caskroom/versions/charles-beta-applejava
Caskroom/versions/java-beta
Caskroom/versions/java6
Caskroom/versions/java7
Caskroom/versions/java9-beta

Oups, il n’y a pas de formula nommée Java ou Java8. En revanche, la recherche vous propose les formulas contenant le mot java. Parmi les formulas, ceux avec un chemin (a/b/formula) sont des formulas contenues dans des taps. Mais qu’est-ce qu’un tap ? Il s’agit d’un autre repository git, contenant des formulas dédiées ou des nouvelles commandes.

Note : On installe un tap via la commande brew tap utilisateur/nom_tap.

Avec le tap utilisateur/nom_tap, brew installera le repository git associé à l’url https://github.com/utilisateur/homebrew-nom_tap.

Pour les autres possibilités, utilisez brew tap -h.

TIP : brew install a/b/formula installera le tap et la formula en même temps.

Parmis les taps officiels, on peut trouver :

Tous ces taps sont gérés par la communauté Homebrew, mais certains taps officiels ne sont pas de Homebrew mais sont bien intégrés comme Caskroom/cask. Les formulas de Caskroom/cask sont dédiés aux installations d’applications macOS.

Maintenant, installons Java 8

$ brew install Caskroom/cask/java
==> brew cask install Caskroom/cask/java
...

$ java -version
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.112-b16, mixed mode)

Lors du lancement de la commande, brew a transféré votre demande à brew cask install pour son installation. Avec Cask, vous pouvez, en plus de vos formulas, installer votre navigateur, votre éditeur de code, etc.

$ brew cask install google-chrome intellij-idea docker slack

TIP : brew tap caskroom/drivers vous permet d’installer les drivers pour macOS. Les fonts s’installent via brew tap caskroom/fonts.

Certains outils sont gérées comme des services via macOS launchd. Pour cela, brew propose, via homebrew/services, la commande brew services pour faciliter leur utilisation.

Pour votre projet, vous avez aussi besoin d’une base de données MySQL. Installons donc MySQL qui possède un service sous macOS.

$ brew install mysql

$ brew services list
Name           Status  User Plist
mysql          stopped

$ brew services start mysql
==> Successfully started `mysql` (label: homebrew.mxcl.mysql)

$ brew services list
Name           Status  User            Plist
mysql          started <your_username> ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist

Votre installation de poste est terminée. Vous pouvez commencer à travailler !

Pour la mise à jour des commandes et outils de homebrew, la procédure se fait en deux commandes : update + upgrade. Avec ces 2 commandes, vous pouvez aussi utiliser deux autres commandes outdated et cleanup qui sont bien utiles.

  • update met à jour les repositories git des taps,
$ brew update
Updated 2 taps (caskroom/cask, homebrew/core).
==> New Formulae
==> Updated Formulae
go <img draggable="false" data-mce-resize="false" data-mce-placeholder="1" data-wp-emoji="1" class="emoji" alt="✔" src="https://s.w.org/images/core/emoji/2.2.1/svg/2714.svg">
  • upgrade met à jour les formulas,
$ brew upgrade
==&gt; Upgrading 1 outdated formula, with result:
go 1.7.4_1
==&gt; Upgrading go
==&gt; Downloading https://homebrew.bintray.com/bottles/go-1.7.4_1.sierra.bottle.tar.gz
...
<img draggable="false" data-mce-resize="false" data-mce-placeholder="1" data-wp-emoji="1" class="emoji" alt="🍺" src="https://s.w.org/images/core/emoji/2.2.1/svg/1f37a.svg">  /usr/local/Cellar/go/1.7.4_1: 6,438 files, 250.7M
  • outdated liste les formulas qui doivent être mis à jour,
$ brew outdated
go (1.6) &lt; 1.7.4_1
  • cleanup supprime les anciennes versions des formulas (car Homebrew les garde indéfiniment).
$ brew cleanup
Removing: /usr/local/Cellar/go/1.6... (6,438 files, 250.7M)
==&gt; This operation has freed approximately 250.7M of disk space.

TIP : Définissez un alias bubu (déjà disponible par défaut dans zsh) pour `brew update && brew outdated && brew upgrade && brew cleanup`, et ainsi en une commande gérer vos formulas plus simplement.

Vous venez d’apprendre qu’un des mécanismes par défaut de Homebrew est de conserver toutes les versions installées de vos formulas. Ceci dans le but de vous permettre de facilement switcher entre ces versions.

WARNING : brew install ne permet d’installer que la version courante du formula, jamais une ancienne version.

Comment passer à une version go 1.6 puis revenir sur une version go 1.7 ? Facile.

$ brew switch go 1.6
Cleaning /usr/local/Cellar/go/1.6
Cleaning /usr/local/Cellar/go/1.7.4_1
3 links created for /usr/local/Cellar/go/1.6

$ brew switch go 1.7.4_1
Cleaning /usr/local/Cellar/go/1.6
Cleaning /usr/local/Cellar/go/1.7.4_1
3 links created for /usr/local/Cellar/go/1.7.4_1

TIP : Le tap homebrew/versions vous permet d’accéder à d’anciennes versions.

Sur ce projet, votre voisin de bureau commence sa première journée et vous demande de lui passer votre liste de formulas et d’applications pour faire l’installation rapidement.

Vous appliquez la méthode KISS

$ brew list &gt; brew-formulas.txt
$ brew cask list &gt; brew-applications.txt

Là encore, Homebrew a pensé à faciliter ce genre d’actions via brew bundle.

Vous créez un Brewfile de votre poste via brew bundle dump

$ brew bundle dump
$ cat Brewfile
tap 'caskroom/cask'
tap 'homebrew/bundle'
tap 'homebrew/core'
tap 'homebrew/services'
brew 'ansible'
brew 'go'
brew 'mysql', restart_service: true
brew 'gradle'
cask 'docker'
cask 'google-chrome'
cask 'intellij-idea'
cask 'java'
cask 'slack'

Un fichier Brewfile commence par lister les taps installés, puis les formulas installés, ainsi que les applications. Il garde même en mémoire les statuts des services (ici, mysql est lancé).

Vous transmettez le fichier Brewfile à votre voisin et il n’a plus qu’à l’utiliser.

Brewfile en action :

$ brew bundle
Tapping caskroom/cask
Tapping homebrew/bundle
Using homebrew/core
Tapping homebrew/services
Installing ansible
Installing go
Installing gradle
Installing mysql
Installing docker
Installing google-chrome
Installing intellij-idea
Installing java
Installing slack

TIP : Par défaut, brew bundle utilise le fichier Brewfile depuis le dossier courant. L’option --file=path permet de définir un autre chemin vers le fichier Brewfile. L’option --global ira lire un fichier .Brewfile depuis votre $HOME.

Après la découverte de brew bundle, vous vous dites autant partager la liste des formulas nécessaires pour ce projet. Pour cela, il suffit de créer un fichier Brewfile dans vos sources de projet et de le commiter. Comme ça, un nouveau développeur n’a qu’à lancer brew bundle pour être sûr d’avoir le nécessaire pour travailler sur le projet en question. Ça tombe bien, vous avez un nouveau projet en Java sous Gradle à faire, qui servira comme outil aux autres développeurs.

Vous créez un Brewfile dans votre nouveau projet avec Java et Gradle :

$ cd project-tool
$ vim Brewfile
$ cat Brewfile
tap 'caskroom/cask'
brew 'gradle'
cask 'java'

Après la première version du projet, vous souhaitez que les autres développeurs l’utilisent. Pour faciliter sa distribution, vous l’avez publié dans votre repository manager de votre client (ex. Nexus). Un de vos collègues teste l’installation du nouvel outil ➜

$ tool_url='https://nexus.client.tld/content/repositories/releases/tld/client/project/tool/1.0.0/tool-1.0.0-distribution.zip'
$ wget $tool_url
$ unzip tool-1.0.0-distribution.zip
$ tree
tool-1.0.0-distribution
├── bin
│   └── tool
└── lib
    └── tool-1.0.0.jar
$ chmod u+x tool-1.0.0-distribution/bin/tool
$ echo "export PATH=\"$(pwd)/tool-1.0.0-distribution/bin:\$PATH\"" &gt;&gt; ~/.bashrc
$ . ~/.bashrc
$ tool --version
1.0.0

Malheureusement, la procédure d’installation n’est pas aussi simple que d’écrire brew install project-tool. Pourquoi ne pas créer une formula aussi pour ce projet ? Avant de la créer, vous vous demandez comment la sauvegarder ? Homebrew vous propose déjà des taps pour avoir plus de formulas disponibles.

Vous pouvez créer un tap privé qui est un simple repository git. Par défaut, un tap ajouté via brew tap utilisateur/nom_tap corresponds à l’url https://github.com/utilisateur/homebrew-nom_tap.git

Si vous voulez le stocker ailleurs, l’ajout se fait par brew tap utilisateur/nom_tap git@git.client.tld:utilisateur/homebrew-nom_tap.git.

NOTE : Dans un Brewfile, ajouter la ligne tap 'utilisateur/nom_tap', 'git@git.client.tld:utilisateur/homebrew-nom_tap.git' pour déclarer ce tap.

Une fois que vous avez créé et ajouté ce tap privé, vous pouvez passer à la création de la formula via la commande create.

$ brew create $tool_url --set-name project-tool --set-version 1.0.0 --tap utilisateur/nom_tap
==&gt; Downloading https://nexus.client.tld/content/repositories/releases/tld/client/project/tool/1.0.0/tool-1.0.0-distribution.zip
######################################################################## 100,0%
Please `brew audit --new-formula project-tool` before submitting, thanks.
Editing /usr/local/Homebrew/Library/Taps/utilisateur/nom_tap/project-tool.rb

Suite à la création de votre formula, homebrew ouvre automatiquement le fichier associé ➜

# Documentation: http://docs.brew.sh/Formula-Cookbook.html #
# http://www.rubydoc.info/github/Homebrew/brew/master/Formula
# PLEASE REMOVE ALL GENERATED COMMENTS BEFORE SUBMITTING YOUR PULL REQUEST!

class ProjectTool &lt; Formula
 desc ""
 homepage ""
 url "https://nexus.client.tld/content/repositories/releases/tld/client/project/tool/1.0.0/tool-1.0.0-distribution.zip" #
 version "1.0.0"
 sha256 "12259beb7c5a0954f2193f581a0c11ec63ff4a573ffeb35efba4b6389d36fad7"

 # depends_on "cmake" =&gt; :build #

 def install
 # ENV.deparallelize # if your formula fails when building in parallel

 # Remove unrecognized options if warned by configure
 system "./configure", "--disable-debug",
 "--disable-dependency-tracking",
 "--disable-silent-rules",
 "--prefix=#{prefix}"
 # system "cmake", ".", *std_cmake_args
 system "make", "install" # if this fails, try separate make/make install steps
 end

 test do
 # `test do` will create, run in and delete a temporary directory.
 #
 # This test will fail and we won't accept that! It's enough to just replace
 # "false" with the main program this formula installs, but it'd be nice if you
 # were more thorough. Run the test with `brew test project-tool`. Options passed
 # to `brew install` such as `--HEAD` also need to be provided to `brew test`.
 #
 # The installed folder is not in the path, so use the entire path to any
 # executables being tested: `system "#{bin}/program", "do", "something"`.
 system "false"
 end
end

On voit dans cet exemple que la formula vous fournie le lien vers la documentation pour finir sa création, qu’elle contient déjà les informations données (ex. url, version) ou générées (ex. sha256) et le reste du code est un template par défaut.

Vous pouvez auditer la formula pour savoir par où commencer

$ brew audit --new-formula project-tool
utilisateur/nom_tap/project-tool:
  * Formula should have a desc (Description).
  * The homepage should start with http or https (URL is ).
  * The homepage  is not reachable (HTTP status code 000)
  * Please remove default template comments
  * Please remove default template comments
  * Commented-out dep "cmake" =&gt; :build
  * Please remove default template comments
  * Please remove default template comments
  * Commented cmake call found
  * Please remove default template comments
Error: 10 problems in 1 formula

Vous devez donc définir la description et la homepage de la formula (ex. l’url du repository git). Et comme il ne s’agit pas d’un build cmake, vous pouvez enlever les commentaires ainsi que le code lié à cmake.

Vous faites les premiers changements afin que l’audit passe ➜

class ProjectTool &lt; Formula
  desc "Installer l'outil 'tool' pour le projet"
  homepage "https://git.client.tld/project/tool"
  url "https://nexus.client.tld/content/repositories/releases/tld/client/project/tool/1.0.0/tool-1.0.0-distribution.zip"
  version "1.0.0"
  sha256 "12259beb7c5a0954f2193f581a0c11ec63ff4a573ffeb35efba4b6389d36fad7"

  def install
    # Il ne reste plus qu'à faire la procédure d'installation
  end

  test do
    # Et tester la formula
    system "false"
  end
end

Puis vous auditez et tentez d’installer la formula ➜

$ brew audit --new-formula project-tool #
$ brew install project-tool
==&gt; Installing project-tool from utilisateur/nom_tap
==&gt; Downloading https://nexus.client.tld/content/repositories/releases/tld/client/project/tool/1.0.0/tool-1.0.0-distribution.zip
Already downloaded: /Users/utilisateur/Library/Caches/Homebrew/project-tool-1.0.0.zip
Error: Empty installation #

L’audit est bien passé, mais l’installation de la formula vous indique que la procédure d’installation reste à faire. La procédure d’installation manuelle vous sert de guide dans l’écriture de votre formula :

  • Télécharger le zip
  • Décompresser le zip
  • Aller dans le dossier décompressé,
  • Rendre exécutable le script bin/too
  • Ajouter le dossier bin au PATH
  • Tester que tool --version donne bien le numéro de version de l’outil

Homebrew téléchargera et décompressera le zip du projet automatiquement (via url et sha256) réalisant les étapes 1 et 2. Pour l’étape 3, la fonction install s’exécute dans le dossier décompressé. Par contre, ce dossier est temporaire, vous devez demander à garder les dossiers bin et lib dans libexec.

Une formula propose plusieurs répertoires pour stocker des fichiers utiles. Le dossier libexec sert à stocker des fichiers uniquement nécessaires à la formula. Via libexec.install, vous pouvez demander qu’un dossier y soit stocké. Afin de réaliser l’étape 4, vous devez demander à lier le script libexec/bin/tool au PATH via bin.install_symlink. Cette action réalise également l’étape 5 car bin.install_symlink gère aussi les permissions.

Le test de l’étape 6 se fera par brew test, ceci une fois la fonction test remplie dans la formula. Ce test peut simplement être que l’exécution de tool --version fonctionne.

De plus, une formula peut définir des prérequis. Par exemple que Java 8 (ou plus) soit installé. Via depends_on :java => "1.8+" vous définissez un tel prérequis.

Vous ajoutez les différentes étapes dans la formula ➜

&lt;/pre&gt;
&lt;pre&gt;class ProjectTool &lt; Formula
  desc "Installer l'outil 'tool' pour le projet"
  homepage "https://git.client.tld/project/tool"
  url "https://nexus.client.tld/content/repositories/releases/tld/client/project/tool/1.0.0/tool-1.0.0-distribution.zip"
  version "1.0.0"
  sha256 "12259beb7c5a0954f2193f581a0c11ec63ff4a573ffeb35efba4b6389d36fad7"

  depends_on :java =&gt; "1.8+"

  def install
    libexec.install %w[bin lib]
    bin.install_symlink Dir["#{libexec}/bin/*"]
  end

  test do
    system "#{bin}/tool", "--version"
  end
end

Afin de correctement tester cette formula, vous devez :

  • l’auditer avec brew audit
  • l’installer avec brew install
  • la tester avec brew test
$ brew audit --new-formula project-tool
$ brew install project-tool
==&gt; Installing project-tool from utilisateur/nom_tap
==&gt; Downloading https://nexus.client.tld/content/repositories/releases/tld/client/project/tool/1.0.0/tool-1.0.0-distribution.zip
Already downloaded: /Users/utilisateur/Library/Caches/Homebrew/project-tool-1.0.0.zip
<img draggable="false" data-mce-resize="false" data-mce-placeholder="1" data-wp-emoji="1" class="emoji" alt="🍺" src="https://s.w.org/images/core/emoji/2.2.1/svg/1f37a.svg">  /usr/local/Cellar/project-tool/1.0.0: 4 files, 100K, built in 0 seconds
 $ brew test project-tool
Testing utilisateur/nom_tap/project-tool
==&gt; Using the sandbox
==&gt; /usr/local/Cellar/project-tool/1.0.0/bin/tool --version

NOTE : Vous pouvez aussi vérifier le style de la formula via brew style.

Comme tout s’est bien passé, vous souhaitez maintenant la commiter pour que vos collègues puissent l’installer plus simplement.

$ cd $(brew --repo utilisateur/nom_tap)
$ git add Formula/project-tool.rb
$ git commit

Votre collègue apprécie la nouvelle procédure ➜

$ brew tap utilisateur/nom_tap git@git.client.tld:utilisateur/homebrew-nom_tap.git
$ brew install project-tool

NOTE : le système de formula permet également de gérer l’installation depuis les sources (–HEAD) ou les versions bêta (–devel). La documentation des formulas vous permettra d’approfondir vos connaissances.

Maintenant que vous savez créer des formulas pour votre client, vous pouvez aussi en créer et les maintenir sur les taps officiels.Pour contribuer, la formula da ns les taps officiels (comme homebrew-core) doit respecter certaines conditions pour être acceptable.

Le projet installé par la formula doit être :

  • open-source
  • stable, maintenu, connu, et utilisé
  • installable depuis ces sources

Une fois la formula créée ou modifiée, vous pouvez créer une pull-request vers le project homebrew-core. Votre pull-request sera automatiquement analysée et validée par bot.brew.sh. Dans le but d’aider les mainteneurs du projet, bot.brew.sh traite toutes pull-requests en testant la formula sur les trois dernières versions supportées de macOS (yosemite, el capitan, et sierra).

Concernant votre projet tool, il ne vous reste plus qu’à le rendre open-source et proposer votre formula sur homebrew-core quand le projet sera plus connu. En attendant ce jour, n’hésitez pas à contribuer sur les formulas existantes et rejoindre les 6200 contributeurs de homebrew-core !

Partagez vos expériences avec Homebrew (ou autre) en commentaire ! Je serais ravi de voir ce que vous en pensez.

Vous aimerez aussi...