Absolute file path in {$include %file%} lazarus / 62-General ---------------------------------------------------------------------- simone · 2022-10-03 07:40 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. ---------------------------------------------------------------------- MarkMLl · 2022-10-03 08:41 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 ---------------------------------------------------------------------- simone · 2022-10-03 08:50 My question was OS independent. However, thanks for the reply. ---------------------------------------------------------------------- MarkMLl · 2022-10-03 09:04 Quote from: simone on October 03, 2022, 10:50:37 amMy 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 ---------------------------------------------------------------------- simone · 2022-10-03 09:14 My question is os independent. The solution is os dependent. ---------------------------------------------------------------------- KodeZwerg · 2022-10-03 10:03 Quote from: simone on October 03, 2022, 09:40:49 amIs 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? ---------------------------------------------------------------------- simone · 2022-10-03 10:19 The following code in the filename "C:\Users\Desktop\test\project1.lpr" 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 program project1;begin  writeln({$include %file%});  readln;end. shows project.lpr, while while I would need to have: C:\Users\Desktop\test\project1.lpr ---------------------------------------------------------------------- wp · 2022-10-03 10:31 I think that the IDE changes path to the directory with the project file. So, you could try this: 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 program project2;uses  SysUtils;begin  writeln(IncludeTrailingPathDelimiter(GetCurrentDir) + {$include %file%});  readln;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... ---------------------------------------------------------------------- MarkMLl · 2022-10-03 10:36 Quote from: wp on October 03, 2022, 12:31:59 pmDon'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 ---------------------------------------------------------------------- simone · 2022-10-03 10:39 I'm trying a similar approach: 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 program project2;uses  SysUtils;begin  writeln(ExpandFileName({$include %file%}));  readln;end. but i'm not sure if it is correct in all possible cases, for the reasons explained by MarkMLI in the last post. ---------------------------------------------------------------------- MarkMLl · 2022-10-03 10:58 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 ---------------------------------------------------------------------- BrunoK · 2022-10-03 11:52 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. ---------------------------------------------------------------------- PascalDragon · 2022-10-03 12:18 Quote from: simone on October 03, 2022, 09:40:49 amAs 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. Quote from: MarkMLl on October 03, 2022, 11:04:05 amQuote from: simone on October 03, 2022, 10:50:37 amMy 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. Quote from: wp on October 03, 2022, 12:31:59 pmI think that the IDE changes path to the directory with the project file. So, you could try this: 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 program project2;uses  SysUtils;begin  writeln(IncludeTrailingPathDelimiter(GetCurrentDir) + {$include %file%});  readln;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. ---------------------------------------------------------------------- Kays · 2022-10-03 12:20 Quote from: simone on October 03, 2022, 09:40:49 am[…] 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 likeCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #!/usr/bin/ifpcprogram helloWorld(output);begin        writeLn('Hello from ', {$include %_%}, '!');end.Code: Bash  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i chmod a+x helloWorld.pas./helloWorld.pasCode: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Hello from /tmp/./helloWorld.pas!The said shells pass an environment variable _ (a single underscore) containing the full path name of the executable file. ---------------------------------------------------------------------- MarkMLl · 2022-10-03 19:06 Quote from: PascalDragon on October 03, 2022, 02:18:02 pmNo, 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 ---------------------------------------------------------------------- 440bx · 2022-10-03 19:57 Quote from: PascalDragon on October 03, 2022, 02:18:02 pmNo, 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 ? ---------------------------------------------------------------------- balazsszekely · 2022-10-03 20:31 @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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function OnProjectOpened(Sender: TObject; AProject: TLazProject): TModalResult; //...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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   for I := 0 to AProject.FileCount - 1 do    if ExtractFileName(LowerCase(AProject.Files[I].Filename)) = 'myUnit.pas' then      //update variable here The variable will be compiled into your executable. ---------------------------------------------------------------------- BobDog · 2022-10-03 21:25 You could do something like 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  program project1; {$macro ON}{$define mypath:= extractfilepath(paramstr(0))+{$include %file%}}usessysutils; begin  writeln(mypath);  readln;end. maybe. ---------------------------------------------------------------------- balazsszekely · 2022-10-04 02:28 Quote from: BobDog on October 03, 2022, 11:25:43 pm You could do something like 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  program project1; {$macro ON}{$define mypath:= extractfilepath(paramstr(0))+{$include %file%}}usessysutils; begin  writeln(mypath);  readln;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\. ---------------------------------------------------------------------- PascalDragon · 2022-10-04 11:34 Quote from: MarkMLl on October 03, 2022, 09:06:54 pmQuote from: PascalDragon on October 03, 2022, 02:18:02 pmNo, 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). ---------------------------------------------------------------------- MarkMLl · 2022-10-04 12:48 Quote from: PascalDragon on October 04, 2022, 01:34:27 pmThere 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 ---------------------------------------------------------------------- BobDog · 2022-10-05 22:17 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 1 VERSIONINFOFILEVERSION     1,0,0,0PRODUCTVERSION  1,0,0,0BEGIN  BLOCK "StringFileInfo"  BEGIN    BLOCK "080904E4"    BEGIN      VALUE "CompanyName", "My own company"      VALUE "FileDescription", "Born in C:\\Users\\computer\\Desktop\\bob"      VALUE "FileVersion", "1.0"    VALUE "InternalName", "Some file name"      VALUE "LegalCopyright", "Some copyright"      VALUE "OriginalFilename", "tester.exe"      VALUE "ProductName", "Some product name"      VALUE "ProductVersion", "1.0"    END  END   BLOCK "VarFileInfo"  BEGIN    VALUE "Translation", 0x809, 1252  ENDEND  And the file using it 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 program mydata; {$R bob.rc}beginwriteln ('Please check file properties to view birthplace');readln;end. Works OK here. Right click the exe,properties/details. ---------------------------------------------------------------------- MarkMLl · 2022-10-06 07:18 Quote from: BobDog on October 06, 2022, 12:17:56 amWhat 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 ---------------------------------------------------------------------- BrunoK · 2022-10-06 14:19 Win x86_64 {$I %sourcefile%}, compiler patch to add %sourcefile%. When run with patch applied, the zipped project with 3 units, will output  : QuoteExeName=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.INCThe code to generate the above result is : 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({$I %CURRENTROUTINE%}, ' SourceFile=', {$I %sourcefile%}); To work, you need to apply the SourceFIle.patch to FPC 3.2.2 and rebuild the  FPC compiler. ---------------------------------------------------------------------- MarkMLl · 2022-10-06 14:33 Quote from: BrunoK on October 06, 2022, 04:19:19 pmWin x86_64 {$I %sourcefile%}, compiler patch to add %sourcefile%. When run with patch applied, the zipped project with 3 units, will output  : QuoteExeName=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.INCThe code to generate the above result is : 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({$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 ---------------------------------------------------------------------- BrunoK · 2022-10-06 14:45 Quote from: MarkMLl on October 06, 2022, 04:33:52 pm... worth having. MarkMLl I think that recompiling application mentionned in QuoteRe: ??? 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. ---------------------------------------------------------------------- SymbolicFrank · 2022-10-14 08:41 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. ---------------------------------------------------------------------- PascalDragon · 2022-10-14 13:31 Quote from: SymbolicFrank on October 14, 2022, 10:41:14 amOr 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)