3

I am trying to write a shell script to automate installation of a bunch of dependencies for a project on macOS which will be an equivalent script for the same that works on EL6/EL7 and uses the yum package manager. This script will try to leverage HomeBrew to do the same.

A few of the tools/dependencies/packages that I want to automate installation are gcc, wget, make, cmake and git and so forth. I want to first check if any of these exist already, then update them or else install them. As you can see in this following snippet I am first trying to check if brew exists already, then update it or else simply install it.

#!/bin/sh

echo Checking brew
#Check if Homebrew is already installed else prompt the user to do so.

BREW_INSTALLED="/usr/local/bin/brew"


#Variables to check if dependencies exist.
HOMEBREW=$(which brew)

echo $HOMEBREW

if [ "$HOMEBREW" == "$BREW_INSTALLED" ]; then
    echo "Brew is already installed."
    echo "Update Brew"
    brew update
else
    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
fi

Now, my questions are (multipart question!)

  1. Is it the right way to use which brew or which X where X can be gcc, make etc. and then compare them with hardcoded /usr/bin/X to check their existence? Since I have quite a list of them I need to check and install so declaring variables for all and cross checking with paths somehow doesn't seem appropriate to me.
  2. How to handle the situation where the user has these packages installed but at some different location for whatever reason they might have? (This seems a bit objective but to ensure the project compiles and builds upon these dependencies should I force these paths only?)
  3. Also, one or more packages might be git repos and need to be cloned, compiled, make installed on the fly. What should be the proper place to put the generated .dylibs and create symlinks to make sure all these interdependent packages can find one another and work in peace?
  4. Is there anything equivalent to virtual_env or jenv to isolate all these installations (of course using HomeBrew they end up in /usr/local/Cellar)? But, as macOS does come with at least a few of them (git, gcc etc.) I don't want to duplicate installations.

P.S. Any help in terms of a direction, resource or an example project working with large amount of dependencies will help. I just can't figure out the right keywords or the right resources to look for a solution or a partial solution. Thanks. :)

  • The code you have showed us does not work. The parameter OUTPUT is undefined. – fd0 May 27 '18 at 17:46
  • @fd0 Oops, forgot to change the variable name. :) – Jashan Singh May 27 '18 at 18:39
  • There is no need to check the text returned by which, just check the exit code ($?). This also solves the "binary installed in a random location" problems. But: if you use Homebrew anyway, why not package your whole application that way and let Homebrew handle dependencies? – nohillside May 27 '18 at 18:52
  • @nohillside Thank you! But honestly it is a bit abstract for me. Could you please elaborate on packaging the app with brew or point me to a resource with similar example/s? – Jashan Singh May 27 '18 at 18:56
  • I'm not a brew hacker, but I'm quite sure that they already solved all the problems you are facing. Links to documentation on how to write your own formulas etc can be found at the bottom of brew.sh. – nohillside May 27 '18 at 19:16
1

To piggyback off nohillside, I was gonna say you might be able to just achieve a lot of that by creating your own tap! You can even tap a repo hosted elsewhere (say like a private one, bitbucket, or anything) as long as you specify the git url after brew tap

0

Homebrew knows what packages you installed already, so even if you install gcc twice (by running brew install gcc), it will just install once. So you can safely put a bunch of brew install <package> commands in you scripts without needing to worry about wasting much time.

What's better is Homebrew support Brewfile, which allows you to define all the dependency in a single file and install all of them by running brew bundle --file=<path/to/brewfile>

Here is a example brewfile:

brew "ack"
brew "git"
brew "python3"

this is equivalent to running:

brew install ack git python3

You can find more example of brewfile, just google it.

We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations. Answers that don't include explanations may be removed.

  • Please don‘t send people to Google for answers, include them in your post – nohillside Feb 17 at 5:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .