File path to ${HOME} lazarus / 66-Unix ---------------------------------------------------------------------- cryppyrc · 2023-05-01 06:16 I am new to this forum (and new to pascal) so I hope this question is in the appropriate sub section. I am trying to compile an app for macOS that was written with a focus on Windows users and I don't understand how I need to adjust the code to make it work on Darwin. If executed on Linux or Windows from CLI, the app creates two folders (wallet and data) in the app directory. On Darwin this obviously does not work because apps have no permission to write to the app bundle. Therefore I am trying to find a way to adjust the paths of the code snippet below to point to the respective user's home directory ${HOME} in Darwin. Path definition: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i CONST  WalletDirectory   = 'wallet'+directoryseparator;  // Wallet folder  DataDirectory     = 'data'+directoryseparator;  WalletFileName    = WalletDirectory+'wallet.pkw';  // Wallet keys file  I would be very happy for any hints. ---------------------------------------------------------------------- simone · 2023-05-01 08:23 I have no experience in developing under Mac OS, but about environment variables, maybe this wiki can help: https://wiki.freepascal.org/Command_line_parameters_and_environment_va riables#Environment_variables ---------------------------------------------------------------------- KodeZwerg · 2023-05-01 09:23 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$mode objfpc}{$H+}{$modeswitch objectivec1}  ... uses  CocoaAll; // for NSBundle ... function GetBundlePath: string;begin  Result := NSBundle.mainBundle.bundlePath.UTF8String;end;Taken from https://wiki.lazarus.freepascal.org/macOS_Programming_Tips ---------------------------------------------------------------------- dbannon · 2023-05-01 10:42 On the Mac, only files that would be discareded in the even, eg, of an update would be kept in the bundle.  Given we don't see Trev very often these days, here is how I do it ("tomboy-ng" being the name of my app, you will need to set your own !)- Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function TSett.GetDefaultNoteDir : string;begin    {$IFDEF UNIX}    Result := GetEnvironmentVariable('HOME') + '/.local/share/tomboy-ng/';    {$ENDIF}    {$IFDEF DARWIN}    Result := GetEnvironmentVariable('HOME') + '/Library/Application Support/Tomboy- ng/Notes/';    {$ENDIF}    {$IFDEF WINDOWS}    Result := GetEnvironmentVariable('APPDATA') + '\tomboy-ng\notes\';    {$ENDIF}end; Yes, I know, the UNIX line will be activated in Cocoa too but it will be overwritten by the correct one. There is a historical reason .... Davo ---------------------------------------------------------------------- WayneSherman · 2023-05-20 02:47 Quote from: dbannonYes, I know, the UNIX line will be activated in Cocoa too but it will be overwritten by the correct one. Possibly a better way (?) using newer {$IF} and {$ELSEIF} directives: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function TSett.GetDefaultNoteDir : string;begin  {$IF DEFINED(DARWIN)}    Result := GetEnvironmentVariable('HOME') + '/Library/Application Support/Tomboy-ng/Notes/';  {$ELSEIF DEFINED(UNIX)}    Result := GetEnvironmentVariable('HOME') + '/.local/share/tomboy-ng/';  {$ELSEIF DEFINED(WINDOWS)}    Result := GetEnvironmentVariable('APPDATA') + '\tomboy-ng\notes\';  {$ENDIF}end; Reference: https://wiki.freepascal.org/Conditional_compilation#.24else_and_.24els eif https://wiki.freepascal.org/$IF ---------------------------------------------------------------------- colo · 2023-05-20 07:42 Sorry for raising this maybe slightly off-topic remark, but since I've seen something along the lines of Code: [Select]GetEnvironmentVariable('HOME') to determine a user's home directory on GNU/Linux and other UNIX-like OSes quite often, I would like to remind everyone that it's not a given this environment variable exists or is set to the proper value. Most interactive shell sessions will have it set, but not all commonly encountered (and even less so, all possible) execution environments will have it. Even getuserdir seems to get it wrong, at least per its docs, and if you call it with an empty HOME value in the env, it will return "/tmp", which is its own can of worms entirely. Only getpwnam(3) or getpwuid(3) from the host's C library will always yield the right thing (even in the face of more exotic circumstances, like the user database not living in /etc/passwd due to nsswitch, for example), which is what you should call from any fpc code to get this right. Unfortunately, it escapes me how to do that, since the only reference I could find is to the deprecated libc stuff in https://www.freepascal.org/daily/packages/libc/index-8.html#SECTIONG - but if anyone else can chime in, I'd be eager to learn! ---------------------------------------------------------------------- marcov · 2023-05-20 12:05 Maybe the "users" unit as mentioned in the libc article as alternative ? https://wiki.freepascal.org/libc_unit ---------------------------------------------------------------------- colo · 2023-05-21 09:34 Yes! Excellent, this led me to the right thing The procedures buried in the related `pwd` module call `getpwnam` and friends, as it should be. For demonstration purposes (I'm on GNU/Linux here, with a boring passwd/shadow-based NSS user and group database), consider this program: Code: [Select]program userhomedir(output); uses sysutils, baseunix, pwd; var     pwrec: PPasswd; begin  { Sometimes wrong, don't use }  writeLn('GetUserDir: ' + GetUserDir);  { Correct way to determine the current user's home directory }  pwrec := fpgetpwuid(FpGetUid);  writeLn('FpGetPwUid: ' + pwrec^.pw_dir ); end. The struct that contains pw_dir also carries other useful per-account data, as documented here. Demo shell session output: Code: [Select]$ fpc userhomedir.pas Free Pascal Compiler version 3.2.2 [2023/05/07] for x86_64 Copyright (c) 1993-2021 by Florian Klaempfl and others Target OS: Linux for x86-64 Compiling userhomedir.pas Linking userhomedir 12 lines compiled, 0.1 sec # "happy" path $ ./userhomedir GetUserDir: /home/colo/ FpGetPwUid: /home/colo # where GetUserDir gets it wrong $ HOME= ./userhomedir GetUserDir: /tmp/ FpGetPwUid: /home/colo A soon as a program that uses GetUserDir ends up being run as a system service, chances are its notion of home will be off. So I would encourage anyone to use the `pwd` module instead, and if the value of HOME is to be accounted for, maybe handle this in custom code. ---------------------------------------------------------------------- Raskaton · 2023-07-03 19:58 Maybe just use: ExpandFileName https://lazarus- ccr.sourceforge.io/docs/rtl/sysutils/expandfilename.html Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses SysUtils; ExpandFileName('.');  //app directoryExpandFileName('~/');  //home absolute path like: /home/username/  or /root/ExpandFileName('~/.local/');  // /home/username/.localExpandFileName('~/..');  // /home/ or  / Never use it by myself  Upd. Test it in Linux (KDE) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   writeln('ExpandFileName(''.'') = ', ExpandFileName('.'));  writeln('ExpandFileName(''~/'') = ', ExpandFileName('~/'));  writeln('ExpandFileName(''~/.local/'') = ', ExpandFileName('~/.local/'));  writeln('ExpandFileName(''~/..'') = ', ExpandFileName('~/..')); Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ExpandFileName('.') = /home/raskaton/Projects/Lazarus- Projects/TestConsoleAppExpandFileName('~/') = /home/raskaton/ExpandFileName('~/.local/') = /home/raskaton/.local/ExpandFileName('~/..') = /home wrong slashes also converted Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ExpandFileName('~\..') = /homeExpandFileName('~\..\') = /home/