GetAppConfigDir on MAC OSX lazarus / 15-macOS - Mac OS X ---------------------------------------------------------------------- tintinux · 2014-02-06 21:06 Hi Using Lazarus 1.0.14, I have now an application working on Windows, Linux and Mac. It has to write some data in a configuration file. I used GetAppConfigDir(false) to obtain the filename of the inifile. Before writing, I call ForceDirectories to be sure that all parent directories exist. It works fine on Windows and Linux. On MAC OSX, when the app is launched from the EDI, the returned path is /Users/my_user/.config/my_application_name which is may be not perfect for OSX policy, but it works. If I create an app bundle, and run it from a terminal, the path returned by GetAppConfigDir is  : -psn_0_311372 !  And then, ForceDirectories raises a strange error "Cannot create empty directory" I'm afraid that I will need to use something else than GetAppConfigDir to find the config path, but before I'd like to know if someone has already encountered this issue and fixed it in  another way. Thanks Tintinux ---------------------------------------------------------------------- jwdietrich · 2014-02-06 21:10 This is an old issue. In my applications I use the following function to get the correct location of the preferences folder: Code: [Select]function GetPreferencesFolder: String; {platform-independend method to search for the location of preferences folder} const   kMaxPath = 1024; var   {$IFDEF DARWIN}   theError: OSErr;   theRef: FSRef;   {$ENDIF}   pathBuffer: PChar; begin   {$IFDEF DARWIN} {standard method for Mac OS X}     try       pathBuffer := Allocmem(kMaxPath);     except on exception do       begin         GetPreferencesFolder := '';         exit;       end     end;     try       Fillchar(pathBuffer^, kMaxPath, #0);       Fillchar(theRef, Sizeof(theRef), #0);       theError := FSFindFolder(kOnAppropriateDisk, kPreferencesFolderType, kDontCreateFolder, theRef);       if (pathBuffer <> nil) and (theError = noErr) then       begin         theError := FSRefMakePath(theRef, pathBuffer, kMaxPath);         if theError = noErr then GetPreferencesFolder := UTF8ToAnsi(StrPas(pathBuffer)) + '/';       end;     finally       Freemem(pathBuffer);     end   {$ELSE}     GetPreferencesFolder := GetAppConfigDir(false); {standard method for Linux and Windows}   {$ENDIF} end; ---------------------------------------------------------------------- tintinux · 2014-02-07 08:31 Hi Thanks for your confirmation. However, portability would be enforced if we could use GetAppConfigDir in any platform, and minimize the usage of compilation directives in applications. So I filed a bug, since it was not done before. Regards ---------------------------------------------------------------------- jwdietrich · 2014-02-07 08:50 Quote from: tintinux on February 07, 2014, 09:31:50 amSo I filed a bug, since it was not done before. Well, the fact that GetAppConfigDir delivers ~/.config/my_application_name is not wrong from a Unix-centric perspective. It is, however, anyway a good idea that you filed a bug, since - despite of its Unix nature - Mac OS X expects configuration files usually at ~/Library/Preferences or /Library/Preferences (for local and global preferences, respectively). ---------------------------------------------------------------------- tintinux · 2014-02-11 20:07 Hi Could you tell which units you uses, to find kMaxPath and GetPreferencesFolder ? Thanks Tintinux ---------------------------------------------------------------------- jwdietrich · 2014-02-11 20:19 Quote from: tintinux on February 11, 2014, 09:07:46 pmCould you tell which units you uses, to find kMaxPath and GetPreferencesFolder ? Sorry, I forgot to post this information as well. You only need the MacOSAll unit. You could write at the beginning of your preferences unit something like Code: [Select]uses   Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,   StdCtrls, DOM, XMLRead, XMLWrite, StrUtils, Math, ...   {$IFDEF win32}   , Windows   {$ELSE}     {$IFDEF LCLCarbon}       , MacOSAll     {$ENDIF}   {$ENDIF}; ---------------------------------------------------------------------- tintinux · 2014-02-13 21:25 Thanks ! ---------------------------------------------------------------------- jwdietrich · 2014-02-13 23:31 You are welcome. To be correct, kMaxPath and GetPreferencesFolder are defined in the code fragment itself, they don't need any external unit. The MacOSAll unit is needed, however, to define the types OSErr and FSRef, the functionsFSFindFolder and FSRefMakePath and some constants. To be even more exact, they are not defined there, but the MacOSAll unit includes the units, where they are defined. ---------------------------------------------------------------------- tintinux · 2014-02-19 07:56 Hi It works fine now with your code to get a correct path for the configuration directory... when requested. However, I was completely wrong : I was not actually calling getAppConfigDir but I coded to call instead ParamStr(1) when it was not an empty string. It was expected that ParamStr(1) was empty, and I even do not know how to set it to any value in the OSX application bundle (I can, of course, with Windows and Linux). How could, at least, make sure it is empty, to enforce portability ? Is someone using ParamStr(1) on OSX and has any idea about this issue ?  Regards ---------------------------------------------------------------------- Zoran · 2014-02-19 11:34 Quote from: jwdietrich on February 06, 2014, 10:10:59 pmThis is an old issue. In my applications I use the following function to get the correct location of the preferences folder: JWDietrich, Why don't you send this function as a patch to standard GetAppConfigDir function. If it does not work as it should in Mac, then it should be fixed. ---------------------------------------------------------------------- tintinux · 2014-02-19 12:46 Hi To send a patch you must use the trunk version and maintain it up to date. I can't do that for 2 reasons : 1) I can't access to the repository from where I work "for security reasons". I would have to update with copies on an USB key and it is very long. 2) I have enough issues to make my apps working with a stable branch, and I must be able to correct quickly in case of problem, it would be too difficult with an unstable trunk. That's why I use only stable versions, sorry for this. I can post the procedure I have made, thanks to jwdietrich work, which is now working fine on 1.0.14 OSX. But last time I did something like that, I was said that it was not useful. Regards ---------------------------------------------------------------------- jwdietrich · 2014-02-19 18:50 Quote from: Zoran on February 19, 2014, 12:34:28 pmQuote from: jwdietrich on February 06, 2014, 10:10:59 pmThis is an old issue. In my applications I use the following function to get the correct location of the preferences folder: JWDietrich, Why don't you send this function as a patch to standard GetAppConfigDir function. If it does not work as it should in Mac, then it should be fixed. I would like to do so, but since I use a PPC-based Mac I cannot use the trunk version on this platform, therefore I can't write a patch. Unfortunately, I don't have enough spare time to compile the sources on myself. ---------------------------------------------------------------------- Zoran · 2014-02-20 17:57 Okay. Myself, I do not use Mac at all, so I cannot make a patch, but, as this should not be forgotten, I have just created a bug report. See: http://bugs.freepascal.org/view.php?id=25746 ---------------------------------------------------------------------- Zoran · 2014-02-20 18:03 Oh, now I see that there was already a bug report, where JWDietrich already posted his solution: http://bugs.freepascal.org/view.php?id=20706.