Создать аппликацию под macOS довольно таки просто.
Так же, как и аппликацию под Windows или под Linux.
Но если ваша аппликация включает в себя дополнительную библиотеку от стороннего производителя или вашу, то тут уже возникает проблема.
И не все так просто, как кажется.
Так как под Macintosh аппликация это как "упакованная папка", то все библиотеки лежат в папке под названием Library.
Об этом должен знать компайлер во время компиляции.
Для этого нужна какая-то специальная программа или специальная функция, и она есть, которую написал mk-soft
;-TOP
; Comment : Module Path Helper v1.05.2 by mk-soft
; Link : https://www.purebasic.fr/english/viewtopic.php?p=562634#p562634
DeclareModule PathHelper
; Change names
CompilerIf Defined(CompanyName, #PB_Constant) = 0
#CompanyName = "mk-soft"
CompilerEndIf
CompilerIf Defined(ApplicationName, #PB_Constant) = 0
#ApplicationName = "MyApplication"
CompilerEndIf
Declare.s GetProgramPath()
Declare.s GetResourcePath()
Declare.s GetLibraryPath()
Declare.s GetProgramDataPath()
Declare.s GetAllUserDataPath()
EndDeclareModule
; ----
Module PathHelper
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
Macro CocoaString(NSString)
PeekS(CocoaMessage(0, NSString, "UTF8String"), -1, #PB_UTF8)
EndMacro
CompilerEndIf
Procedure.s GetProgramPath()
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
Static bundlePath.s
Protected bundlePathPtr
If Not Bool(bundlePath)
bundlePathPtr = CocoaMessage(0,CocoaMessage(0,0,"NSBundle mainBundle"),"bundlePath")
If bundlePathPtr
bundlePath = CocoaString(bundlePathPtr) + "/"
EndIf
EndIf
ProcedureReturn bundlePath
CompilerElse
ProcedureReturn GetPathPart(ProgramFilename())
CompilerEndIf
EndProcedure
; ----
Procedure.s GetResourcePath()
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
Static resourcePath.s
Protected resourcePathPtr
If Not Bool(resourcePath)
resourcePathPtr = CocoaMessage(0,CocoaMessage(0,0,"NSBundle mainBundle"),"resourcePath")
If resourcePathPtr
resourcePath = CocoaString(resourcePathPtr) + "/"
EndIf
EndIf
ProcedureReturn resourcePath
CompilerElse
ProcedureReturn GetProgramPath() + "Resources" + #PS$
CompilerEndIf
EndProcedure
; ----
Procedure.s GetLibraryPath()
Protected librayPath.s
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
librayPath = GetProgramPath() + "Contents/Library/"
CompilerElse
librayPath = GetProgramPath() + "Library" + #PS$
CompilerEndIf
ProcedureReturn librayPath
EndProcedure
; ----
Procedure.s GetProgramDataPath()
Protected basePath.s, subPath.s, dataPath.s
CompilerIf #PB_Compiler_OS = #PB_OS_Linux
basePath = GetHomeDirectory()
subPath = basePath + "." + #CompanyName + #PS$
CompilerElse
basePath = GetUserDirectory(#PB_Directory_ProgramData)
subPath = basePath + #CompanyName + #PS$
CompilerEndIf
dataPath = subPath + #ApplicationName + #PS$
If FileSize(dataPath) <> -2
If FileSize(subPath) <> -2
CreateDirectory(subPath)
EndIf
If FileSize(dataPath) <> -2
CreateDirectory(dataPath)
EndIf
EndIf
ProcedureReturn dataPath
EndProcedure
; ----
Procedure.s GetAllUserDataPath()
Protected basePath.s, subPath.s, dataPath.s
basePath = GetUserDirectory(#PB_Directory_AllUserData)
subPath = basePath + #CompanyName + #PS$
dataPath = subPath + #ApplicationName + #PS$
If FileSize(dataPath) <> -2
If FileSize(subPath) <> -2
CreateDirectory(subPath)
EndIf
If FileSize(dataPath) <> -2
CreateDirectory(dataPath)
EndIf
EndIf
ProcedureReturn dataPath
EndProcedure
; ----
EndModule
UseModule PathHelper
; ****
CompilerIf #PB_Compiler_IsMainFile
Debug "Program Path: " + GetProgramPath()
Debug "Program Resources Path: " + GetResourcePath()
Debug "Program Libraries Path: " + GetLibraryPath()
Debug "Program Data Path: " + GetProgramDataPath()
Debug "Program Alluser Data Path: " + GetAllUserDataPath()
CompilerEndIf
Можете назвать ее PathHelperp.pbi включить ее в ваш проект(XIncludeFile "PathHelper.pbi") и перед открытием вашей библиотеки сделать следующее:
UseModule PathHelper LibId.i = OpenLibrary(#PB_Any, GetLibraryPath() + "Ваша_библиотека.dylib")
Теперь будет скомпилировано все правильно и запускаемый файл будет правильно обращаться к библиотеке, которая находится в директории Library.
Теперь можно открыть аппликацию посредством нажатия правой клавиши мышки на ней и выбрать Show Package Contents, зайти в Contents, создать папку Library и переписать туда вашу библиотеку.
Но можно этот процесс автоматизировать:
Берем у того же автора прогу MyAppData
;-TOP
; Tool : MyAppData - Copied the folder MyAppData in the APP folder \Contents
; Author : mk-soft
; Version : 1.04.0
; Create : 10.02.2015
; Update : 16.01.2022
;
; Commpilermode : Console
;
; Info.plist
;
; PLIST <key>CFBundleSignature</key>
; PLIST <string>PB-TOOL</string>
; PLIST <key>CFBundleShortVersionString</key>
; PLIST <string>1.2.0.2</string>
; PLIST <key>CFBundleName</key>
; PLIST <string>PB-Tool MyAppData</string>
; PLIST <key>NSHumanReadableCopyright</key>
; PLIST <string>Copyright © 2022 mk-soft. All rights reserved.</string>
;
; ***************************************************************************************
; Configure Tool 1
;
; Commandline:
; MyAppData
;
; Arguments:
; "%FILE"
;
; Working Directorory
; Nothing
;
; Name:
; MyAppData Run
;
; Event to trigger the tool:
; After Compile/Run
;
; Option:
; Wait until tools quits
;
; ---------------------------------------------------------------------------------------
;
; Configure Tool 2
;
; Commandline:
; MyAppData
;
; Arguments:
; "%FILE"
;
; Working Directorory
; Nothing
;
; Name:
; MyAppData Executable
;
; Event to trigger the tool:
; After Create Executable
;
; Option:
; Nothing
;
; ---------------------------------------------------------------------------------------
;
; Format for new info.plist
;
; Begin without space '; PLIST {keys and values}
;
; Example
; ; PLIST <key>CFBundleSignature</key>
; ; PLIST <string>PBAPP</string>
; ; PLIST <key>CFBundleShortVersionString</key>
; ; PLIST <string>1.0.1.0</string>
; ; PLIST <key>NSHumanReadableCopyright</key>
; ; PLIST <string>Copyright © 2018 mk-soft. All rights reserved.</string>
; **********************************************
EnableExplicit
Structure udtDict
key.s
List value.s()
EndStructure
Global NewList plist.s()
Global NewList dict.udtDict()
Global file_code.s
Global file_app.s
Global path_contents.s
; ---------------------------------------------------------------------------------------
Procedure InitParameters()
; Parameter source file
file_code = ProgramParameter()
If file_code = ""
ProcedureReturn 0
EndIf
; Parameter execute file
file_app = GetEnvironmentVariable("PB_TOOL_Executable")
If file_app = ""
ProcedureReturn 0
EndIf
If GetExtensionPart(file_app) <> "app"
ProcedureReturn 0
EndIf
; Set path to contents
path_contents = file_app + "/Contents/"
ProcedureReturn 1
EndProcedure
; ---------------------------------------------------------------------------------------
;- Copy folder MyAppData to Contents
Procedure CopyAppData()
Protected path_data.s
path_data = GetPathPart(file_code) + "MyAppData"
If FileSize(path_data) <> -2
ProcedureReturn 0
EndIf
If CopyDirectory(path_data, path_contents, "*", #PB_FileSystem_Recursive) = 0
MessageRequester("MyAppData", "Error copy data" + #CR$ + path_data + " to " + path_contents)
ProcedureReturn 0
EndIf
ProcedureReturn 1
EndProcedure
; ---------------------------------------------------------------------------------------
;- Read info.plist from Application
Procedure ReadPList()
Protected file_plist.s, text.s, dict.i, key.s, value.s, newkey.i, pos
file_plist.s = path_contents + "info.plist"
If ReadFile(0, file_plist)
While Not Eof(0)
text.s = ReadString(0, #PB_UTF8)
If Bool(text)
If FindString(text, "<dict>")
AddElement(plist())
plist() = text
dict = #True
ElseIf FindString(text, "</dict>")
AddElement(plist())
plist() = text
dict = #False
ElseIf Not dict
AddElement(plist())
plist() = text
EndIf
If dict
pos = FindString(text, "<key>")
If pos >= 1 And pos <= 3
AddElement(dict())
dict()\key = Trim(text)
newkey = #True
ElseIf newkey
AddElement(dict()\value())
dict()\value() = Trim(text)
EndIf
EndIf
EndIf
Wend
CloseFile(0)
EndIf
EndProcedure
;- Read new info.plist from source
Procedure ReadInfo()
Protected r1, text.s, key.s, lkey.s, value.s, newkey, addkey
If ReadFile(0, file_code)
While Not Eof(0)
text.s = ReadString(0, #PB_UTF8)
If Bool(text)
If FindString(text, "; PLIST ", 1, #PB_String_NoCase) = 1
r1 = #True
text = RTrim(Mid(text, 9))
If FindString(text, "<key>") = 1 ; New key only with first place
key = Trim(text)
lkey = LCase(key)
newkey = #True
addkey = #True
ForEach dict()
If LCase(dict()\key) = lkey
ClearList(dict()\value())
addkey = #False
Break
EndIf
Next
If addkey
ResetList(dict())
AddElement(dict())
dict()\key = key
EndIf
ElseIf newkey
AddElement(dict()\value())
dict()\value() = text
EndIf
EndIf
EndIf
Wend
CloseFile(0)
EndIf
ProcedureReturn r1
EndProcedure
;- Write new info.plist
Procedure WritePList()
Protected file_plist.s
file_plist.s = path_contents + "info.plist"
If CreateFile(0, file_plist)
ForEach plist()
WriteStringN(0, plist(), #PB_UTF8)
If FindString(plist(), "<dict>") = 1
ForEach dict()
WriteStringN(0, #TAB$ + dict()\key, #PB_UTF8)
ForEach dict()\value()
WriteStringN(0, #TAB$ + dict()\value(), #PB_UTF8)
Next
Next
EndIf
Next
EndIf
EndProcedure
; ---------------------------------------------------------------------------------------
;-Main
If InitParameters()
CopyAppData()
ReadPList()
If ReadInfo()
WritePList()
EndIf
EndIf
Компилируем его и создаем консольное приложение.
Создаем два инструмента для PureBasic, один для запуска, другой для создания аппликации. Так как написано в исходникe у автора.
В папке своего проекта создаем папку MyAppData, в ней папки Library и Resource
В Library помещаем библиотеку, ту которая находится в папке проекта.
Запускаем Compile -> Create Executable и получаем готовую аппликацию, которая может запуститься на любом Маке.
Также аппликация MyAppData может изменить некоторые параметры P-листа, в которой может быть указано название программы, автор и так далее.
Надо только в начале исходника вашей программы добавить несколько строк.
Как пример:
; Info.plist ; ; PLIST <key>CFBundleSignature</key> ; PLIST <string>PB-TOOL</string> ; PLIST <key>CFBundleShortVersionString</key> ; PLIST <string>1.2.0.2</string> ; PLIST <key>CFBundleName</key> ; PLIST <string>PB-Tool MyAppData</string> ; PLIST <key>NSHumanReadableCopyright</key> ; PLIST <string>Copyright © 2022 mk-soft. All rights reserved.</string>
Успехов!
Отредактировано dibor (18.04.2025 20:27:18)