alan-turing-institute / meet

schedule meetings
MIT License
1 stars 0 forks source link

Homebrew v0.2.0.2 binaries broken #16

Closed penelopeysm closed 3 months ago

penelopeysm commented 3 months ago
$ meet [emails]
meet: /private/tmp/meet-20240710-39031-vili7o/.brew_home/.local/state/cabal/store/ghc-9.4.8/tzdt-0.2.20240201.0-36c401bd/share/Europe/London.zone: openBinaryFile: does not exist (No such file or directory)

https://github.com/alan-turing-institute/meet/pull/13 includes a dependency on the tzdata package, which ships with a database of time zones. Apparently, when Homebrew compiles the codebase during the bottle building process, it uses a sandboxed home directory (see above) and this database gets saved there. The path to this database is then baked into this binary and once Homebrew cleans up, the path is no longer valid.

Not sure how to get around it. We could modify the Homebrew build process to copy the files to the real home directory, but the binary would still have the wrong paths encoded inside. A solution that might work might be to fork/modify the tzdata package to use data hosted on the Internet (and self host the data, specifically the London file).

Even instructing Homebrew to install from source doesn't work.

penelopeysm commented 3 months ago

Eventual solution was to replace loadTZFromDB with loadTZFromFile; then instead of reading from a named file I inlined the contents of the London.zone file which it needs. (I obtained the relevant file via cloning https://github.com/ysangkok/haskell-tzdata/ and then USE_CABAL=yes ./build-tzdata.sh inside there.)

Now the London data is included into the binary itself!

penelopeysm commented 3 months ago

Some questions for future pondering:

  1. Can we realistically prevent this sort of bug from being deployed? Is there a way to test a Homebrew release without changing the actual formula itself? I think it's worth noting that I thought I tested the new brew install version; however, very unfortunately I had run cabal install . before this and so when I ran meet I got the version in ~/.cabal/bin rather than Homebrew's binary.
  2. Is myBs = BS.pack [...] the most computationally efficient way of creating a constant ByteString? I'll ask this on /r/haskell or something
penelopeysm commented 3 months ago

Is myBs = BS.pack [...] the most computationally efficient way of creating a constant ByteString? I'll ask this on /r/haskell or something

I found this: https://www.reddit.com/r/haskell/comments/m4t9xm/distributing_a_binary_that_imports_a_library_that/ and the corresponding file-embed package, which does the same thing via Template Haskell.

penelopeysm commented 3 months ago

Presumably we can do something like:

{-# LANGUAGE TemplateHaskell #-}
import Data.Time.Zones.Files (timeZonePathFromDB)
import Data.FileEmbed (embedFile)

{-# NOINLINE londonTZFilePath #-}
londonTZFilePath :: FilePath
londonTZFilePath = unsafePerformIO (timeZonePathFromDB "Europe/London")

londonTZBs :: Data.ByteString.ByteString
londonTZBs = $(embedFile londonTZFilePath)