Lazarus
Installation => macOS / Mac OS X => Topic started by: luigi65 on February 16, 2009, 07:25:39 pm
-
How can I get the current working directory of the application?
GetCurrentDir work fine if I run the application from IDE, but if I launch the application from the bundle file .app (after a compilation) then this function always return the root / directory.
There is a method to have the application directory that work also from bundle file?
Thanks & goodbye
-
I have found this solution:
g_path := ExtractFilePath(Application.ExeName);
{$IFDEF DARWIN}
g_path := LeftStr(g_path, Pos('myapp.app', g_path)-1);
{$ENDIF}
so in g_path I have the application directory, also if I run from bundle file.
There is a better solution?
-
Hi,
What I use are the following function:
Getinstalldir gives you what it is: the path to the executable.
Getbasedir gives you the path to the bundle (Mac), or just the same as getinstalldir for Win.
Hope this helps you out.
Jaco
function slash(value:string):string;
begin
if (value='') then result:=''
else begin
{$IFDEF WINDOWS}
if (value[length(value)]<>'\') then result:=value+'\'
{$ELSE}
if (value[length(value)]<>'/') then result:=value+'/'
{$ENDIF}
else result:=value;
end;
end;
function getinstalldir:string;
begin
result:=slash(extractfiledir(paramstr(0)));
end;
function getbasedir:string;
Begin
{$IFDEF WINDOWS}
result:=getinstalldir;
{$ELSE}
result:=copy(getinstalldir,1,pos(extractfilename(paramstr(0))+'.app/Contents/MacOS',getinstalldir)-1);
{$ENDIF}
end;
-
Instead of the function slash, you can use AppendPathDelim (http://lazarus-ccr.sourceforge.net/docs/lcl/fileutil/appendpathdelim.html).
-
Some confusion and misinformation here:
Luigi: From a terminal command line in your project's folder, start your app like this:
open myapp.app
That should give the same results for GetCurrentDir as double-clicking the .app in Finder. Not sure why you're always seeing / with GetCurrentDir when the app is launched from the Laz IDE. Maybe there's a problem there with how it's launching the app.
Not sure what you mean by "working directory". Normally this is a synonum for "current directory". If you mean the location of the .app, that's not what GetCurrentDir returns.
Why do you need to know that? An .app can be dragged and dropped anywhere in the file system, although typically it will be located under /Applications. So I'm not sure that knowing where it's located is something you would normally be using.
However, if do need to know that for some reason, don't use the supplied code. It won't work if the app bundle is named differently from its executable, which is common. For example "My Program.app" with "myprog" executable. You can just chop off the final 3 folder names, searching back from the end of ParamStr(0) for 3 occurences of PathDelim.
Also, remember that Laz creates your app bundle with a symlink in Contents/MacOs that points back to the actual executable in your project folder. You would never distribute or move an app bundle that's set up like that - it's only done so for convenience. Instead, you would delete the symlink and copy the executable file in its place.
Thanks.
-Phil
-
Sorry for my misinformation, but I am a newbie in Mac OSX.
This is first time that I try to porting an application from Linux to OSX.
Thanks for your precious information.
I now understand that I have to substitute the symlink with the actual executable into .app file.
Excuse me if I'm not clear in my exposition, but GetCurrentDir return / if I launch the application as double-clicking the .app in Finder or as "open myapp.app" in terminal.
If I run from IDE GetCurrentDir return the path where is the executable file (e.g. /Developer/Projects/test).
Now, if I have some auxiliaries files that my executable must use then I put this files into Contents/MacOs of the bundle, is it right?
Thanks
-
Take a look at the structure of other .app bundles on your system. Typically there's a Resources folder in the bundle for additional files. You can reference it from your app via a relative path from ParamStr(0).
Also, be sure to review the extensive Apple documentation on bundles. Essentially a bundle has a place for anything you could possible want to add, including local frameworks, localizations, compiled libraries, etc.
I assume you've looked at this (from this subtopic to the end is essential reading for anyone new to OS X programming):
http://wiki.lazarus.freepascal.org/OS_X_Programming_Tips#Adding_an_icon_to_your_app_bundle
Thanks.
-Phil
-
Sorry for my misinformation, but I am a newbie in Mac OSX.
This is first time that I try to porting an application from Linux to OSX.
You may want to read this information first then: http://developer.apple.com/documentation/Porting/Conceptual/PortingUnix/intro/chapter_1_section_1.html
Excuse me if I'm not clear in my exposition, but GetCurrentDir return / if I launch the application as double-clicking the .app in Finder or as "open myapp.app" in terminal.
That is normal and expected. You may want to read all messages titled "specifying the relative path to a file that is located in the same folder as the application bundle? " at http://lists.freepascal.org/lists/fpc-pascal/2009-February/thread.html (note that there are two separate threads).
Now, if I have some auxiliaries files that my executable must use then I put this files into Contents/MacOs of the bundle, is it right?
No, that is not correct. Where to put which files is described in the Introduction to Bundle Programming Guide (http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFBundles/CFBundles.html), under "Anatomy of a Modern Bundle".
-
ExtractFilePath(ParamStr(0));
Edit: and ExcludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)))+'/../../somefolder' works too.
-
ExtractFilePath(ParamStr(0));
Edit: and ExcludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)))+'/../../somefolder' works too.
Paramstr(0) must only be used on Dos and Windows (and maybe OS/2). On all other platforms the results are unpredictable and it will not work as you expect (in the best case it will never work; in the worst case it will only fail under certain circumstances, resulting in hard-to-find bugs). Read the mailing list thread I quoted above for more information.
-
ExtractFilePath(ParamStr(0));
Edit: and ExcludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)))+'/../../somefolder' works too.
Paramstr(0) must only be used on Dos and Windows (and maybe OS/2). On all other platforms the results are unpredictable and it will not work as you expect (in the best case it will never work; in the worst case it will only fail under certain circumstances, resulting in hard-to-find bugs). Read the mailing list thread I quoted above for more information.
Sorry because of late answer: It's weird, I just finished Win/Mac/Linux project that uses ParamStr(0) and I get proper path everywhere? :-\
-
Sorry because of late answer: It's weird, I just finished Win/Mac/Linux project that uses ParamStr(0) and I get proper path everywhere?
Try it on symlinks.
-
Makes sense, I did not used them and it worked.
-
ExtractFilePath(ParamStr(0));
Edit: and ExcludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)))+'/../../somefolder' works too.
Paramstr(0) must only be used on Dos and Windows (and maybe OS/2). On all other platforms the results are unpredictable and it will not work as you expect (in the best case it will never work; in the worst case it will only fail under certain circumstances, resulting in hard-to-find bugs). Read the mailing list thread I quoted above for more information.
Sorry because of late answer: It's weird, I just finished Win/Mac/Linux project that uses ParamStr(0) and I get proper path everywhere? :-\
As I said: "in the worst case it will only fail under certain circumstances". Once more: please read the threads I mentioned earlier for the details. It contains several examples of cases where it will fail.
-
A new thread for this subject is here: https://forum.lazarus.freepascal.org/index.php/topic,61919.0.html
(Don't continue this thread, use the new thread)