Homebrew formula how to add lib and other files - ruby

I'm on the process of making a Homebrew tap.
My repo has a bash script, lib directory, and other directories.
When I use the following, only the backpack_install is available in the /opt/homebrew/Cellar/backpack_install/0.5.0 directory.
class BackpackInstall < Formula
desc "Backpack Installer for macOS/Linux"
homepage "https://github.com/shinokada/backpack_install"
url "https://github.com/shinokada/backpack_install/archive/refs/tags/v0.5.0.tar.gz"
sha256 "83f2b1e193446c6da00c59bbb671d820e33af8a8c7fd89bdd6ddcf3c21d31c3b"
license "MIT"
depends_on "composer"
def install
bin.install 'backpack_install'
end
end
I need other directories as well. How can modify the def install so that libraries are available when I use it.

Related

homebrew locate installed files path

I have a homebrew package that I was able to push through GitHub: diagnosticator
This is a simple ruby file (diagnosticator.rb) that points to the actual hosting repository: diagnosticator-mac and provides instructions on how to install files:
class Diagnosticator < Formula
desc "Diagnosticator Mac OS homebrew package"
homepage "https://diagnosticator.com"
url "https://github.com/cccnrc/diagnosticator-mac/archive/refs/tags/v0.1.11.tar.gz"
sha256 "f36987ce96c7be269da12b9dce8186c5245aef4046fe62173a145024b5e88b98"
license "MIT"
depends_on "docker"
depends_on "docker-compose"
depends_on "wget"
depends_on "jq"
def install
bin.install "diagnosticator"
bin.install "diagnosticator-mac.sh"
bin.install Dir["files"]
prefix.install "README.md"
end
end
From the diagnosticator executable I have to refer to diagnosticator-mac.sh executable, I am now referring it as:
MAC_EXE=/usr/local/bin/diagnosticator-mac.sh
but I guess I can simply change it to:
MAC_EXE=diagnosticator-mac.sh
as it will be found on the $PATH after installation.
From diagnosticator-mac.sh I have to refer to files in the files folder that are installed through bin.install Dir["files"], I have now:
DIAGNOSTICATOR_FILES_DIR=/usr/local/opt/diagnosticator/bin/files
but I noticed that in a couple of different Mac machines they ended up in different locations based on how users installed homebrew.
How can I find a way to point the diagnosticator-mac.sh executable to that files folder however homebrew was installed?
If you want to try it:
brew install cccnrc/diagnosticator/diagnosticator
Homebrew determines the path for you, and stores it in the variable HOMEBREW_PREFIX
You could use inreplace to swap your hardcoded prefix with the homebrew prefix.
# Iterate through the files, replacing the prefix
%w[diagnosticator diagnosticator-mac.sh].each do |file|
inreplace file, "/usr/local", HOMEBREW_PREFIX
end

Homebrew formula - renaming files on install

i have the following homebrew formulaL
class Software < Formula
desc "Software"
homepage "https://blabla"
version "1.6.0"
if OS.mac? && Hardware::CPU.intel?
url "https://blabla/releases/download/v1.6.0/software-darwin-10.12-amd64"
sha256 "ce02a97fb95aca9bba44413d4158f5f2c182f5eb2823bedf1400f556bb9b"
end
if OS.mac? && Hardware::CPU.arm?
url "https://blabla/releases/download/v1.6.0/software-darwin-10.12-arm64"
sha256 "1c69849ba82c10d15706d110ae63bd97c387da2a8cf925653e1bb5c6fc"
end
if OS.linux? && Hardware::CPU.intel?
url "https://blabla/releases/download/v1.6.0/software-linux-amd64"
sha256 "9b7245823a60c85e027929b776753848d4fbdaaa333a49ae171684893"
end
def install
bin.install "software*" => "software"
end
test do
system "#{bin}/software --version"
end
end
The problematic part is:
def install
bin.install "software*" => "software"
end
The files that get downloaded depends on which OS a user is on
before installation. I want to automatically find the downloaded file (whatever the name is), hence why I am trying to use a regex as bin.install "software"* with a star to find the downloaded file and install it as software
however, I get an error stating software* cannot be found
please how would I rectify this issue?
Some Suggestions (But See Caveats Below)
Per the Homebrew bin.install documentation, the purpose of bin.install is to rename a file within the formula's location within the Cellar, and the key doesn't seem to accept either a glob or a regex. However, since you have the full power of Ruby available to you in addition to the Homebrew formula DSL, you might consider doing something like the following:
def install
binfile_with_extension =
File.basename(Dir.glob "#{prefix}/bin/software*")
bin.install binfile_with_extension => "software"
end
This of course assumes there's only one software-* executable. If there's more than one, then you may need to do something to return value of the glob (which should be an Array) to select the correct one for your architecture.
Alternatively, rather than renaming the file itself, you may simply want to symlink it so that you aren't changing something the application might expect. The documentation says that you have full access to both FileUtils and the DSL's bin.install_symlink method, so you might consider using some combination of those instead. For example, to create a hardlink in the cellar for your architecture-named file, then symlink it into the correct bin directory using relative symlinks, the following should work:
def install
file = Dir.glob("#{prefix}/bin/software*").first
FileUtils.ln file, "#{prefix}/bin/software"
bin.install_symlink bin/"software"
end
There may be better Homebrew-native options for renaming symlinks differently from the file they link to, but I was unable to find one. That doesn't mean one doesn't exist, though.
Additionally, whether or not hardlinking or symlinking is necessary in the first place depends on the application. Some applications care about the name they are invoked by (think busybox as an example) while others don't. YMMV.
Caveats
I'm not currently a Homebrew developer, so there may be other or better ways to do this. Nevertheless, a combination of Ruby globs and the Hombrew DSL features should get you where you want to go.
Please do note that I haven't tested this myself, so the suggestions above may or may not work without tweaking. I offer it simply as a place to start since I don't think bin.install is intended to do what you want by itself.

Create symlink to /usr/local/lib/cmake from Homebrew Formula

I wrote a custom Homebrew Formula to distribute some library. I'm happy with the result, but there's an outstanding problem. I would like to install the cmake config file (YORPLibConfig.cmake) in /use/local/lib/cmake.
Unfortunately, this location appears to be out of reach from within the Formula. I had no problems to install the library and its headers thanks to the nifty lib.install and include.install functions, but I'm out of luck since there's no lib/cmake.install equivalent.
I also tried to manually create the symlink by doing
ln_sf "YORPLibConfig.cmake", "/usr/local/lib/cmake/"
but the install fails upon throwing
Error: Operation not permitted # rb_file_s_symlink - (YORPLibConfig.cmake, /usr/local/lib/cmake/YORPLibConfig.cmake)
How can I install this cmake file in /usr/local/lib/cmake from within the Formula?
The formula itself:
class Yorplib < Formula
desc "A library for the computation of the Fourier decomposition of YORP forces and moments"
homepage "https://github.com/bbercovici/YORPLib"
url "https://github.com/bbercovici/YORPLib/archive/1.0.0.tar.gz"
sha256 "45fb9a2969368e76e472a39afa8feb32c27cbe17032371e06fd283f3d70bb7c7"
depends_on "cmake" => :build
def install
# Compile
system "cmake . -DBREW:BOOL=TRUE && make"
prefix.install "YORPLibConfig.cmake"
# Create symlink to library
ln_sf "YORPLibConfig.cmake", "/usr/local/lib/cmake/"
lib.install "libYORPLib.dylib"
include.install "include/"
end
end
I ended up modifying both the formula and the CMakeLists.txt file so as to install a symlink to the configuration file in /usr/local/share. The configuration file pointed at by the symlink resides in the Cellar.

Use Ruby command line tool out of the box upon gem install

I made a bash command line tool that I'd like to convert to Ruby.
I know that I'd have to use OptionParser and stuff to write the program, but I look at programs like rake and see that once you install the gem, it's ready to use immediately. Why is this? When I make a program with optparse I have to put it in my bin and give it access.
How can I have the user use it out of the box with mac or windows if I make it into a gem?
Thank you
Gems can include executable files which are added to the user's PATH by RubyGems when installing the gem.
Usually, those scripts are put into the bin directory (or exe nowadays) of your gem. You can then specify in your gemspec that scripts in this directory should be treated as executables:
In your gemspec file, you can thus put something like this:
Gem::Specification.new do |spec|
spec.name = 'my_awesome_gem'
spec.version = '0.0.1'
spec.bindir = 'bin'
spec.executables = ['my_script']
# ...
end
As for the script itself, you should make sure that it is marked as executable (i.e. chmod +x bin/my_script on Linux/Mac) and that it has the right shebang as its first line. Usually, it looks like this:
#!/usr/bin/env ruby
puts 'Hello World'
You can learn more about adding executables to your gem in the RubyGems guide.
Finally, if you are creating your basic gem structure with the bundle gem my_awesome_gem command, it will automatically create a reasonable gemspec file and basic structure. Just put your scripts into the exe directory and everything should just work.

Access downloaded files in a formula's test block

I'm creating a Homebrew formula for a C library that includes its own test suite. As part of the test block for the formula, I'd like to run the tests that are included with the downloaded files. The tests run as a make target (make test). However, Homebrew test blocks run in their own temporary directory and the downloaded files are not in the path. That is, the following doesn't work because it can't find the files:
test do
system "make", "test"
end
How can I access the location into which the files were originally downloaded and unpacked? I haven't been able to find any information about that in the docs. Or is there a better solution for Homebrew tests in this case?
The test do block is meant to test if a formula has correctly been installed, not to run test suits. If the tests don’t take too long you can run them as part of the install:
def install
# ...
system "make", "test"
# ...
end
To answer your question there’s no reliable way to get the original unpacked directory because it’s destroyed after install and the user may have deleted the cached tarball (with e.g. brew cleanup) so you’d have to re-download it.
A solution is to copy the necessary test files somewhere during the install step then use them directly or copy them in the current directory when testing, e.g.:
def install
# ...
libexec.install "tests"
end
test do
cp_r (libexec/"tests"), "."
cd "tests" do
# I’m assuming the Makefile's paths can be given
# as variables here.
system "make", "test", "LIB=#{lib}", "INCLUDE=#{include}"
end
end

Resources