nanotech / hs-sdl-mac

A sample project using cabal-macosx to package a Haskell SDL2 app
Other
0 stars 0 forks source link

Command line creation of OSX app bundles #1

Open nanotech opened 7 years ago

nanotech commented 7 years ago

Modify or create a method so that a programmer can compile to a Mac app bundle from the command line simply by modifying their .cabal, Setup.hs, and stack.yaml files on a mac with a fresh install of OSX Sierra and XCode 8.2. It cannot rely on deprecated frameworks like Carbon. The project must be able to integrate common libraries such as SDL2 and OpenCL, add resources to the package and the resulting package must launch from the finder and from the command line open command. It must integrate into a stack based as well as cabal based workflow. (link)

cabal-macosx does almost all of this already, so that's what I've used in this sample project. It works with both cabal and stack. The missing pieces were:

Continuing with the requirements:

biglambda commented 7 years ago

I think your theory about the different environment is most likely correct. I load some openCL kernel code from a file for example. How can I see the normal error output of my code when I run it with open? How can I detect that I'm running from inside an app bundle and find the proper resources from within haskell?

biglambda commented 7 years ago

I cloned your repository and I get the following output from stack build

`hs-sdl-mac-0.1.0.0: configure [1 of 1] Compiling Main ( /Users/biglambda/Software/hs-sdl-mac/Setup.hs, /Users/biglambda/Software/hs-sdl-mac/.stack-work/dist/x86_64-osx/Cabal-1.24.0.0/setup/Main.o ) Linking /Users/biglambda/Software/hs-sdl-mac/.stack-work/dist/x86_64-osx/Cabal-1.24.0.0/setup/setup ... Configuring hs-sdl-mac-0.1.0.0... hs-sdl-mac-0.1.0.0: build Preprocessing executable 'hs-sdl-mac' for hs-sdl-mac-0.1.0.0... [1 of 1] Compiling Main ( src/Main.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac/hs-sdl-mac-tmp/Main.o ) Linking .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac/hs-sdl-mac ... error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/install_name_tool: can't open input file: .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac.app/Contents/Frameworks/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib for writing (Permission denied) error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/install_name_tool: can't lseek to offset: 0 in file: .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac.app/Contents/Frameworks/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib for writing (Bad file descriptor) error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/install_name_tool: can't write new headers in file: .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac.app/Contents/Frameworks/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib (Bad file descriptor) error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/install_name_tool: can't close written on input file: .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac.app/Contents/Frameworks/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib (Bad file descriptor) Creating application bundle directory .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac.app setup: Pattern match failure in do expression at Copying executable hs-sdl-mac into place from .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac/hs-sdl-mac to .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac.app/Contents/MacOS/hs-sdl-mac Distribution/MacOSX/Dependencies.hs:219:6-16 Copying icon.icns to app's icon Building dependency graph Copying /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib to .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac.app/Contents/Frameworks/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib Copying /usr/lib/libiconv.2.dylib to .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac.app/Contents/Frameworks/usr/lib/libiconv.2.dylib Updating .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac.app/Contents/MacOS/hs-sdl-mac's dependency on /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib to @executable_path/../Frameworks/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib Updating .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac.app/Contents/MacOS/hs-sdl-mac's dependency on /usr/lib/libiconv.2.dylib to @executable_path/../Frameworks/usr/lib/libiconv.2.dylib Updating .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac.app/Contents/Frameworks/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib's dependency on /usr/lib/libiconv.2.dylib to @executable_path/../Frameworks/usr/lib/libiconv.2.dylib Completed 29 action(s).

-- While building package hs-sdl-mac-0.1.0.0 using: /Users/biglambda/Software/hs-sdl-mac/.stack-work/dist/x86_64-osx/Cabal-1.24.0.0/setup/setup --builddir=.stack-work/dist/x86_64-osx/Cabal-1.24.0.0 build exe:hs-sdl-mac --ghc-options " -ddump-hi -ddump-to-file" Process exited with code: ExitFailure 1`

nanotech commented 7 years ago

How can I see the normal error output of my code when I run it with open?

From my first post:

Standard output and error are written to the Console app when run from launch services, which may help debug this.

The console app is at /Applications/Utilities/Console.app. Select your Mac in the sidebar (or All Messages prior to 10.12), and filter by the name of your app.

How can I detect that I'm running from inside an app bundle and find the proper resources from within haskell?

Use getExecutablePath from executable-path to build a path to your resources. If you need to check if the program is running from inside a bundle, check if something like getExecutablePath >>= \exePath -> doesDirectoryExist (takeDirectory (takeDirectory exePath) </> "MacOS") is true.

error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/install_name_tool: can't open input file: .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/hs-sdl-mac.app/Contents/Frameworks/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib for writing (Permission denied)

Homebrew removes write access to the files it installs, and cabal-macosx is copying permissions when it copies the files in (it probably shouldn't). As a workaround, run

chmod +w /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib

and re-run stack build. I'll have a look at patching cabal-macosx to not copy permissions.

nanotech commented 7 years ago

I've patched cabal-macosx to set the writable bit before running install_name_tool on libraries, and updated the dependency here.

biglambda commented 7 years ago

Ok, that's working. I'm working on the executable-path stuff, I'll let you know how that goes.

biglambda commented 7 years ago

I think I almost have this working, unfortunately the when I try to add a file to the resources list field of the MacApp structure it does not seem to be able to find that file regardless of trying multiple places including the root directory of my project. Any ideas on this?

nanotech commented 7 years ago

What's the error message? As a test, when I add README.md to the resources field for this project,

import Distribution.MacOSX
import Distribution.Simple

main :: IO ()
main = defaultMainWithHooks $ simpleUserHooks {
         postBuild = appBundleBuildHook guiApps -- no-op if not MacOS X
       }

guiApps :: [MacApp]
guiApps = [MacApp "hs-sdl-mac"
                  (Just "icon.icns")
                  Nothing -- Build a default Info.plist for the icon.
                  ["README.md"] -- Resources.
                  [] -- No other binaries.
                  ChaseWithDefaults
          ]

it builds as

Configuring hs-sdl-mac-0.1.0.0...
Building hs-sdl-mac-0.1.0.0...
Preprocessing executable 'hs-sdl-mac' for hs-sdl-mac-0.1.0.0...
Creating application bundle directory dist/build/hs-sdl-mac.app
Copying executable hs-sdl-mac into place from dist/build/hs-sdl-mac/hs-sdl-mac to dist/build/hs-sdl-mac.app/Contents/MacOS/hs-sdl-mac
Copying icon.icns to app's icon
Copying resource README.md to dist/build/hs-sdl-mac.app/Contents/Resources/README.md
Building dependency graph
Copying /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib to dist/build/hs-sdl-mac.app/Contents/Frameworks/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib
Copying /usr/lib/libiconv.2.dylib to dist/build/hs-sdl-mac.app/Contents/Frameworks/usr/lib/libiconv.2.dylib
Updating dist/build/hs-sdl-mac.app/Contents/MacOS/hs-sdl-mac's dependency on /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib to @executable_path/../Frameworks/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib
Updating dist/build/hs-sdl-mac.app/Contents/MacOS/hs-sdl-mac's dependency on /usr/lib/libiconv.2.dylib to @executable_path/../Frameworks/usr/lib/libiconv.2.dylib
Updating dist/build/hs-sdl-mac.app/Contents/Frameworks/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib's dependency on /usr/lib/libiconv.2.dylib to @executable_path/../Frameworks/usr/lib/libiconv.2.dylib

In particular,

Copying resource README.md to dist/build/hs-sdl-mac.app/Contents/Resources/README.md

And opening the Resources directory shows README.md being there.

biglambda commented 7 years ago

Got it, whitespace at the end of the string was tripping it up. Do you have a minute to get on Skype to talk about completing the bounty?

nanotech commented 7 years ago

Great! I don't use Skype, but you can email me at nanotech@nanotechcorp.net and we can talk there.