Lazarus

Free Pascal => General => Topic started by: simone on October 03, 2022, 09:40:49 am

Title: Absolute file path in {$include %file%}
Post by: simone on October 03, 2022, 09:40:49 am
As know, {$include %file%} is expanded by compiler with the name of current source file. As far as I understand, the filename is without the path. Is there any way to get the full path name? Thank you.
Title: Re: Absolute file path in {$include %file%}
Post by: MarkMLl on October 03, 2022, 10:41:51 am
Since your question is OS- and version-specific, I'd suggest putting that info in the body of your message, not in your sig (and in fact, editing your message to include those before anything else). The problem is that at some point your sig will change, and that will appear immediately in all historical messages thus destroying the context of the question for anybody who arrives here via a forum or Google search.

I don't believe there is a way of expanding %FILE% directly to a full path. There's various things you can do in the Lazarus IDE at the build settings level to get more info, but at the compiler level you're going to be restricted to whatever shell/environment variables your OS makes available (and please note my para above).

MarkMLl
Title: Re: Absolute file path in {$include %file%}
Post by: simone on October 03, 2022, 10:50:37 am
My question was OS independent. However, thanks for the reply.
Title: Re: Absolute file path in {$include %file%}
Post by: MarkMLl on October 03, 2022, 11:04:05 am
My question was OS independent. However, thanks for the reply.

Your question is NOT OS-independent since it depends on the shell/environment variables made available, and is NOT version-independent since the $I expansions might change.

MarkMLl
Title: Re: Absolute file path in {$include %file%}
Post by: simone on October 03, 2022, 11:14:10 am
My question is os independent. The solution is os dependent.
Title: Re: Absolute file path in {$include %file%}
Post by: KodeZwerg on October 03, 2022, 12:03:50 pm
Is there any way to get the full path name?
How is that meant?
You want to find out at runtime where the source of {$I} was?
Title: Re: Absolute file path in {$include %file%}
Post by: simone on October 03, 2022, 12:19:38 pm
The following code in the filename "C:\Users\Desktop\test\project1.lpr"

Code: Pascal  [Select][+][-]
  1. program project1;
  2. begin
  3.   writeln({$include %file%});
  4.   readln;
  5. end.

shows project.lpr, while while I would need to have: C:\Users\Desktop\test\project1.lpr
Title: Re: Absolute file path in {$include %file%}
Post by: wp on October 03, 2022, 12:31:59 pm
I think that the IDE changes path to the directory with the project file. So, you could try this:
Code: Pascal  [Select][+][-]
  1. program project2;
  2. uses
  3.   SysUtils;
  4. begin
  5.   writeln(IncludeTrailingPathDelimiter(GetCurrentDir) + {$include %file%});
  6.   readln;
  7. end.
Don't beat me if this is wrong... For example, I could imagine that when a project is structured in subfolders you might not get the subfolder of the file...
Title: Re: Absolute file path in {$include %file%}
Post by: MarkMLl on October 03, 2022, 12:36:27 pm
Don't beat me if this is wrong... For example, I could imagine that when a project is structured in subfolders you might not get the subfolder of the file...

Except that that's an unholy mix of compile- and runtime behaviour :-)

On unix you could possibly use %PWD%

MarkMLl
Title: Re: Absolute file path in {$include %file%}
Post by: simone on October 03, 2022, 12:39:38 pm
I'm trying a similar approach:

Code: Pascal  [Select][+][-]
  1. program project2;
  2. uses
  3.   SysUtils;
  4. begin
  5.   writeln(ExpandFileName({$include %file%}));
  6.   readln;
  7. end.


but i'm not sure if it is correct in all possible cases, for the reasons explained by MarkMLI in the last post.
Title: Re: Absolute file path in {$include %file%}
Post by: MarkMLl on October 03, 2022, 12:58:48 pm
It's a good start /if/ a runtime solution is acceptable. One thing I've found useful- in the context of a larger project- is to save the project name like that as a global in the main unit (i.e. .lpr or main .pas/.pp file) so that a different unit can read it back and decide on the appropriate .ini name... which can actually be a fairly complex decision if the installer has changed it.

If you need it at build time I'm pretty confident you could get it from (Lazarus) predefined values at the build level. However I'm not putting time into this.

MarkMLl
Title: Re: Absolute file path in {$include %file%}
Post by: BrunoK on October 03, 2022, 01:52:38 pm
It could be useful to store the source filepath and filename to the executable for debugging.
It happens very frequently to me to have multiple copies of files/units with the same name but in different directories and in the end not knowing which one was selected  for the compilation.
Title: Re: Absolute file path in {$include %file%}
Post by: PascalDragon on October 03, 2022, 02:18:02 pm
As know, {$include %file%} is expanded by compiler with the name of current source file. As far as I understand, the filename is without the path. Is there any way to get the full path name? Thank you.

No, there is no way.

My question was OS independent. However, thanks for the reply.

Your question is NOT OS-independent since it depends on the shell/environment variables made available, and is NOT version-independent since the $I expansions might change.

The question is OS-independant, because %FILE% is handled by the compiler itself and returns the filename of the currently file being processed and is not fetched from the environment of the OS.

I think that the IDE changes path to the directory with the project file. So, you could try this:
Code: Pascal  [Select][+][-]
  1. program project2;
  2. uses
  3.   SysUtils;
  4. begin
  5.   writeln(IncludeTrailingPathDelimiter(GetCurrentDir) + {$include %file%});
  6.   readln;
  7. end.
Don't beat me if this is wrong... For example, I could imagine that when a project is structured in subfolders you might not get the subfolder of the file...

That suggestion is, to put it simple, absolute nonsense (sorry). What simone tries to retrieve is the path of the currently compiled file, but your code would prepend to that the path at runtime where the source might not even remotely be available.
Title: Re: Absolute file path in {$include %file%}
Post by: Kays on October 03, 2022, 02:20:25 pm
[…] Is there any way to get the full path name? […]
No, not without external help. With bash(1) or zsh(1) you could do something like
Code: Pascal  [Select][+][-]
  1. #!/usr/bin/ifpc
  2. program helloWorld(output);
  3. begin
  4.         writeLn('Hello from ', {$include %_%}, '!');
  5. end.
Code: Bash  [Select][+][-]
  1. chmod a+x helloWorld.pas
  2. ./helloWorld.pas
Code: Text  [Select][+][-]
  1. Hello from /tmp/./helloWorld.pas!
The said shells pass an environment variable _ (a single underscore) containing the full path name of the executable file.
Title: Re: Absolute file path in {$include %file%}
Post by: MarkMLl on October 03, 2022, 09:06:54 pm
No, there is no way.

With respect, I express qualified disagreement: I strongly suspect I could do it on unix provided that the build was handled by Lazarus (a carefully-tailored echo|tr in "Execute before" creating a string in a .inc file).

MarkMLl
Title: Re: Absolute file path in {$include %file%}
Post by: 440bx on October 03, 2022, 09:57:27 pm
No, there is no way.
I could be wrong but, if the program is compiled with debugging symbols, doesn't the full filename end up somewhere in there ?
Title: Re: Absolute file path in {$include %file%}
Post by: balazsszekely on October 03, 2022, 10:31:53 pm
@simone

It is possible if you extend the IDE, but the solution is somewhat convoluted and I'm not sure is worth the effort. The idea is to create a package which will tap into the project openings:
Code: Pascal  [Select][+][-]
  1. function OnProjectOpened(Sender: TObject; AProject: TLazProject): TModalResult;
  2. //...
  3. LazarusIDE.AddHandlerOnProjectOpened(@OnProjectOpened);
Each time a project is opened in the IDE, the package will by notified via the OnProjectOpened event. Now all you have to do, is to loop through the project files, find a specific unit, then update a variable, which represents the path to the source file(see below AProject.Files.Filename):
Code: Pascal  [Select][+][-]
  1.   for I := 0 to AProject.FileCount - 1 do
  2.     if ExtractFileName(LowerCase(AProject.Files[I].Filename)) = 'myUnit.pas' then
  3.       //update variable here

The variable will be compiled into your executable. 
Title: Re: Absolute file path in {$include %file%}
Post by: BobDog on October 03, 2022, 11:25:43 pm

You could do something like
Code: Pascal  [Select][+][-]
  1.  
  2. program project1;
  3.  
  4. {$macro ON}
  5. {$define mypath:= extractfilepath(paramstr(0))+{$include %file%}}
  6. uses
  7. sysutils;
  8.  
  9. begin
  10.   writeln(mypath);
  11.   readln;
  12. end.
maybe.
Title: Re: Absolute file path in {$include %file%}
Post by: balazsszekely on October 04, 2022, 04:28:21 am

You could do something like
Code: Pascal  [Select][+][-]
  1.  
  2. program project1;
  3.  
  4. {$macro ON}
  5. {$define mypath:= extractfilepath(paramstr(0))+{$include %file%}}
  6. uses
  7. sysutils;
  8.  
  9. begin
  10.   writeln(mypath);
  11.   readln;
  12. end.
maybe.

Let's say your project is located in c:\MyProjects\Project1\. Build the application,  copy the executable to d:\test\, the run it. ExtractFilePath(Paramstr(0)) will point to d:\test\, OP needs c:\MyProjects\Project1\.
Title: Re: Absolute file path in {$include %file%}
Post by: PascalDragon on October 04, 2022, 01:34:27 pm
No, there is no way.

With respect, I express qualified disagreement: I strongly suspect I could do it on unix provided that the build was handled by Lazarus (a carefully-tailored echo|tr in "Execute before" creating a string in a .inc file).

There is no built-in way (except maybe using debug information as 440bx hinted at, but that means parsing that whole stuff and including it in the first place which might not be desired).
Title: Re: Absolute file path in {$include %file%}
Post by: MarkMLl on October 04, 2022, 02:48:52 pm
There is no built-in way (except maybe using debug information as 440bx hinted at, but that means parsing that whole stuff and including it in the first place which might not be desired).

Yes, agreed. That was why I was very careful to qualify what I said in terms of development environment and OS.

MarkMLl
Title: Re: Absolute file path in {$include %file%}
Post by: BobDog on October 06, 2022, 12:17:56 am

What about a resource file with the file's (birthplace) written in, for member GetMem, who reckons this is what is required.
bob.rc
Code: Pascal  [Select][+][-]
  1. 1 VERSIONINFO
  2. FILEVERSION     1,0,0,0
  3. PRODUCTVERSION  1,0,0,0
  4. BEGIN
  5.   BLOCK "StringFileInfo"
  6.   BEGIN
  7.     BLOCK "080904E4"
  8.     BEGIN
  9.       VALUE "CompanyName", "My own company"
  10.       VALUE "FileDescription", "Born in C:\\Users\\computer\\Desktop\\bob"
  11.       VALUE "FileVersion", "1.0"
  12.       VALUE "InternalName", "Some file name"
  13.       VALUE "LegalCopyright", "Some copyright"
  14.       VALUE "OriginalFilename", "tester.exe"
  15.       VALUE "ProductName", "Some product name"
  16.       VALUE "ProductVersion", "1.0"
  17.     END
  18.   END
  19.  
  20.   BLOCK "VarFileInfo"
  21.   BEGIN
  22.     VALUE "Translation", 0x809, 1252
  23.   END
  24. END
  25.  
And the file using it
Code: Pascal  [Select][+][-]
  1. program mydata;
  2.  
  3. {$R bob.rc}
  4. begin
  5. writeln ('Please check file properties to view birthplace');
  6. readln;
  7. end.
  8.  
Works OK here.
Right click the exe,properties/details.
Title: Re: Absolute file path in {$include %file%}
Post by: MarkMLl on October 06, 2022, 09:18:38 am
What about a resource file with the file's (birthplace) written in, for member GetMem, who reckons this is what is required.

Better if the location could be generated automatically by whatever VCS OP's using (svn, git or whatever).

MarkMLl
Title: Re: Absolute file path in {$include %file%}
Post by: BrunoK on October 06, 2022, 04:19:19 pm
Win x86_64 {$I %sourcefile%}, compiler patch to add %sourcefile%.
When run with patch applied, the zipped project with 3 units, will output  :
Quote
ExeName=C:\FPC_SourceName\SourceName.exe
$main SourceFile=C:\FPC_SourceName\SourceName.pas
DoProjUnit C:\FPC_SourceName\SubDir\projunit.pas
DoProjUnit C:\FPC_SourceName\SubDir\SubSubDir\projuniti.INC
The code to generate the above result is :
Code: Pascal  [Select][+][-]
  1.   WriteLn({$I %CURRENTROUTINE%}, ' SourceFile=', {$I %sourcefile%});

To work, you need to apply the SourceFIle.patch to FPC 3.2.2 and rebuild the  FPC compiler.
Title: Re: Absolute file path in {$include %file%}
Post by: MarkMLl on October 06, 2022, 04:33:52 pm
Win x86_64 {$I %sourcefile%}, compiler patch to add %sourcefile%.
When run with patch applied, the zipped project with 3 units, will output  :
Quote
ExeName=C:\FPC_SourceName\SourceName.exe
$main SourceFile=C:\FPC_SourceName\SourceName.pas
DoProjUnit C:\FPC_SourceName\SubDir\projunit.pas
DoProjUnit C:\FPC_SourceName\SubDir\SubSubDir\projuniti.INC
The code to generate the above result is :
Code: Pascal  [Select][+][-]
  1.   WriteLn({$I %CURRENTROUTINE%}, ' SourceFile=', {$I %sourcefile%});

To work, you need to apply the SourceFIle.patch to FPC 3.2.2 and rebuild the  FPC compiler.

Thanks for that, I've been thinking through a different issue ** during the day and have concluded that it's well worth having.

** security-related, which I might raise separately

MarkMLl
Title: Re: Absolute file path in {$include %file%}
Post by: BrunoK on October 06, 2022, 04:45:55 pm
... worth having.
MarkMLl
I think that recompiling application mentionned in
Quote
Re: ??? How is this possible ???
with the {$I %sourcefile%} in the units in correct places might show exactly what units are included and whether it is what it is expected.

I have been doing a bit of patching to JCF these days and know how it becomes difficult to not mix-up various iterations of same named sources simultaneously opened.
Title: Re: Absolute file path in {$include %file%}
Post by: SymbolicFrank on October 14, 2022, 10:41:14 am
It might be important to explain what the path is used for. If it is to find resources during runtime, for example, ParamStr(0) would work. And if it is to include files from different locations, the paths property from the project options would work. Or one of the path macros, like $(ProjOutDir). Etc.
Title: Re: Absolute file path in {$include %file%}
Post by: PascalDragon on October 14, 2022, 03:31:27 pm
Or one of the path macros, like $(ProjOutDir). Etc.

Those don't work inside the code (unless you somehow forward them to the code using either defines or environment variables)
TinyPortal © 2005-2018