@@ -810,6 +810,59 @@ template tryExceptOSErrorMessage(conf: ConfigRef; errorPrefix: string = "", body
810810 (ose.msg & " " & $ ose.errorCode))
811811 raise
812812
813+ proc createMacAppBundle (conf: ConfigRef ; exefile: AbsoluteFile ) =
814+ let (dir, name, _) = splitFile (exefile.string )
815+ let appBundleName = name & " .app"
816+ let appBundlePath = dir / appBundleName
817+ let contentsPath = appBundlePath / " Contents"
818+ let macosPath = contentsPath / " MacOS"
819+
820+ createDir (macosPath)
821+
822+ let bundleExePath = macosPath / name
823+ copyFileWithPermissions (exefile.string , bundleExePath)
824+
825+ let infoPlistPath = contentsPath / " Info.plist"
826+
827+ proc xmlEscape (s: string ): string =
828+ result = newStringOfCap (s.len)
829+ for c in items (s):
830+ case c:
831+ of '<' : result .add (" <" )
832+ of '>' : result .add (" >" )
833+ of '&' : result .add (" &" )
834+ of '"' : result .add (" "" )
835+ of '\' ' : result .add (" '" )
836+ else :
837+ if ord (c) < 32 :
838+ result .add (" &#" & $ ord (c) & ';' )
839+ else :
840+ result .add (c)
841+
842+ let escapedName = xmlEscape (name)
843+ let infoPlistContent = """ <?xml version="1.0" encoding="UTF-8"?>
844+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
845+ <plist version="1.0">
846+ <dict>
847+ <key>CFBundleExecutable</key>
848+ <string>$1</string>
849+ <key>CFBundleIdentifier</key>
850+ <string>com.nim.$1</string>
851+ <key>CFBundleName</key>
852+ <string>$1</string>
853+ <key>CFBundlePackageType</key>
854+ <string>APPL</string>
855+ <key>LSUIElement</key>
856+ <string>1</string>
857+ </dict>
858+ </plist> """ % [escapedName]
859+
860+ writeFile (infoPlistPath, infoPlistContent)
861+
862+ removeFile (exefile.string )
863+
864+ rawMessage (conf, hintUserRaw, " Created Mac app bundle: " & appBundlePath)
865+
813866proc getExtraCmds (conf: ConfigRef ; output: AbsoluteFile ): seq [string ] =
814867 result = @ []
815868 when defined (macosx):
@@ -994,6 +1047,10 @@ proc callCCompiler*(conf: ConfigRef) =
9941047 preventLinkCmdMaxCmdLen (conf, linkCmd)
9951048 for cmd in extraCmds:
9961049 execExternalProgram (conf, cmd, hintExecuting)
1050+ # create Mac app bundle for GUI apps on macOS
1051+ when defined (macosx):
1052+ if conf.globalOptions * {optGenGuiApp, optGenDynLib, optGenStaticLib} == {optGenGuiApp}:
1053+ createMacAppBundle (conf, mainOutput)
9971054 else :
9981055 linkCmd = " "
9991056 if optGenScript in conf.globalOptions:
0 commit comments