Unit name problem lazarus / 21-General ---------------------------------------------------------------------- MarkMLl · 2021-01-15 21:11 I'm looking at applying a linkage methodology that I've used before to invoking libpython, with emphasis on still supporting Python v2 since some stuff I'm looking at is based on it (xref to my whine about Inkscape plugins, Python and Electron). Could somebody please take a look at the attached project and explain why I'm getting "Illegal unit name" errors if DYNAMIC is defined in the main (.lpr) project file, and what I should best do about it? I'm open to constructive suggestions about how to distribute the four possibilities over directories etc. This is using Lazarus "trunk" and FPC 3.2.0. MarkMLl ---------------------------------------------------------------------- marcov · 2021-01-15 21:24 dynamic is a procedure/function directive. if you use objfpc mode, try delphi mode, afaik it doesn't reserve directive as keywords. ---------------------------------------------------------------------- Kays · 2021-01-15 21:55 Quote from: MarkMLl on January 15, 2021, 10:11:11 pm[…] explain why I'm getting "Illegal unit name" errors […]In PythonDemo.lpr you are usingCode: 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  // […]  Python_dynamic in './python3/python3_dynamic'; // […]FPC expects the unit’s name to match file (base) names, but 'python3_dynamic' <> 'Python_dynamic'. In other words, without the explicit in '…' clause you would get a unit not found error. Quote from: MarkMLl on January 15, 2021, 10:11:11 pm[…] what I should best do about it? […]Since the files are already in different directories, just rename them and change the unit’s name (in their first line). I hope that’s it, I haven’t actually looked at your code for circumstances preventing this. ---------------------------------------------------------------------- MarkMLl · 2021-01-15 22:04 Thanks Kai, I'll check that in a few few hours. MarkMLl ---------------------------------------------------------------------- MarkMLl · 2021-01-15 22:12 Quote from: marcov on January 15, 2021, 10:24:41 pmdynamic is a procedure/function directive. if you use objfpc mode, try delphi mode, afaik it doesn't reserve directive as keywords. But that's not given problems in e.g my code at https://github.com/MarkMLl/asound which I'm using as a template. Except that in that case I'm not using the "in" clause. I've tried several combinations of unit name (i.e. in the unit being imported), and find myself wondering whether it is some combination of "in" and "xxx_dynamic" (in the main unit)... emphasising here that "dynamic" does not appear as an isolated token so shouldn't be being recognised as one. MarkMLl ---------------------------------------------------------------------- PascalDragon · 2021-01-16 10:32 Quote from: MarkMLl on January 15, 2021, 10:11:11 pmCould somebody please take a look at the attached project and explain why I'm getting "Illegal unit name" errors if DYNAMIC is defined in the main (.lpr) project file, and what I should best do about it? I'm open to constructive suggestions about how to distribute the four possibilities over directories etc. Would have been nice of you to provide the full error which reads as follows: Code: [Select]python3_dynamic.pas(1,21) Error: Illegal unit name: Python3_dynamic (expecting PYTHON_DYNAMIC) The point is that you're using the unit as Python_dynamic in your main project file, but the unit itself is named Python3_dynamic. You need to use the unit as Python3_dynamic (you could disable this using the -Un switch, but I'm advising against that as that could lead to other troubles down the line). Quote from: marcov on January 15, 2021, 10:24:41 pmdynamic is a procedure/function directive. if you use objfpc mode, try delphi mode, afaik it doesn't reserve directive as keywords. That is completely irrelevant here, especially as the "dynamic" is part of other identifiers. ---------------------------------------------------------------------- MarkMLl · 2021-01-16 12:14 Quote from: PascalDragon on January 16, 2021, 11:32:06 amThe point is that you're using the unit as Python_dynamic in your main project file, but the unit itself is named Python3_dynamic. You need to use the unit as Python3_dynamic (you could disable this using the -Un switch, but I'm advising against that as that could lead to other troubles down the line). I can assure you that I'd already tried changing that, but I am about to dive in again and will report back. QuoteQuote from: marcov on January 15, 2021, 10:24:41 pmdynamic is a procedure/function directive. if you use objfpc mode, try delphi mode, afaik it doesn't reserve directive as keywords. That is completely irrelevant here, especially as the "dynamic" is part of other identifiers. Quite frankly I was hoping it wasn't something like that. MarkMLl ---------------------------------------------------------------------- MarkMLl · 2021-01-16 14:22 OK, I've now gone through the files and removed the embedded version digit and it appears OK. I'm slightly puzzled: I was absolutely sure I'd tried that. Should I assume that when I have something like Python_dynamic in './python2/python_dynamic'; the unit name (to the left of the "in") the file name (after the path) and the unit name in the file should match, and that the only thing allowed to vary is the path (i.e. "./python2/" in the above example)? I've got no objection at all to having the files named the same, in fact it would be my preference. But this is the first time that I've tried putting a program together with this structure covering multiple library versions, so I was being cautious. MarkMLl ---------------------------------------------------------------------- PascalDragon · 2021-01-16 16:04 Quote from: MarkMLl on January 16, 2021, 03:22:30 pmthe unit name (to the left of the "in") the file name (after the path) and the unit name in the file should match, and that the only thing allowed to vary is the path (i.e. "./python2/" in the above example)? Correct. ---------------------------------------------------------------------- Kays · 2021-01-16 16:07 Quote from: MarkMLl on January 16, 2021, 03:22:30 pm[…] Should I assume that when I have something like Python_dynamic in './python2/python_dynamic'; the unit name (to the left of the "in") the file name (after the path) and the unit name in the file should match, and that the only thing allowed to vary is the path (i.e. "./python2/" in the above example)? […]Actually, the requirement is that given 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      moduleName in 'directory/somefile.pas' the file somefile.pas contains one 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 unit moduleName;In theory it is allowed to have multiple modules in one file, although (AFAIK) FPC does not support that. The GPC allows multiple modules in one file, and many older compilers. So you’re right, using FPC all names have to correspond to each other. [And I see, PascalDragon just confirmed that.] I think in this case it’d better to just have a couple conditional {$unitPath …} clauses to deal with multiple library versions, so the uses clause itself does not have any {$ifDef}. ---------------------------------------------------------------------- MarkMLl · 2021-01-16 16:50 Quote from: Kays on January 16, 2021, 05:07:42 pmActually, the requirement is that given 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        moduleName in 'directory/somefile.pas' the file somefile.pas contains one 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 unit moduleName;In theory it is allowed to have multiple modules in one file, although (AFAIK) FPC does not support that. The GPC allows multiple modules in one file, and many older compilers. So you’re right, using FPC all names have to correspond to each other. [And I see, PascalDragon just confirmed that.] No, it doesn't like that. In the main file I've got 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   python_dynamic in './python3/python3_dynamic'; (* Python is an object        *)  and in the imported unit python3_dynamic.pas I've got 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 unit python_dynamic;  and I'm now back at Compile Project, Target: PythonDemo: Exit code 1, Errors: 1, Hints: 2 Hint: Start of reading config file /etc/fpc.cfg Hint: End of reading config file /etc/fpc.cfg python3_dynamic.pas(1,20) Error: Illegal unit name: python_dynamic (expecting PYTHON_DYNAMIC) QuoteI think in this case it’d better to just have a couple conditional {$unitPath …} clauses to deal with multiple library versions, so the uses clause itself does not have any {$ifDef}. I'm inclined to agree. In any event, I think that this does emphasise that using multiple directories is inescapable. MarkMLl ---------------------------------------------------------------------- marcov · 2021-01-16 17:56 Quote from: Kays on January 16, 2021, 05:07:42 pmI think in this case it’d better to just have a couple conditional {$unitPath …} clauses to deal with multiple library versions, so the uses clause itself does not have any {$ifDef}. Unitpath is dangerous that it only activates if the module containing it is compiled, and early in the process. It works if it is in the top of your mainmodule, and exclusively compile via compiling the mainmodule. But if you compile e.g. shared units between two programs, that might already be dangerous. ---------------------------------------------------------------------- MarkMLl · 2021-01-16 18:54 Quote from: marcov on January 16, 2021, 06:56:33 pmUnitpath is dangerous that it only activates if the module containing it is compiled, and early in the process. It works if it is in the top of your mainmodule, and exclusively compile via compiling the mainmodule. I'm afraid I've got there, and it might be worse than that. Neither with "unitpath" nor "in" are rebuilds being done reliably, I suspect that Lazarus is failing to pick up that files have been changed despite the fact that they're members of the project. In both cases "Clean Directory" followed by a build works. I hesitate to say that things are "bad" since I'm sure that I'm abusing the system in ways unintended, but I can't even rely on a rebuild if I change one of these lines in the main unit 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 {$define DYNAMIC }{ define PYTHON2 }  Obviously what I'm doing is more of a proof of concept than anything else, and I suspect that if I were to focus on either Python2 or Python3 and had more files in the main directory everything would be OK. But I can't simply stick everything in the same place since "in" doesn't appear to be behaving as expected. MarkMLl ---------------------------------------------------------------------- howardpc · 2021-01-16 19:07 I don't know how exactly FPC handles the "in" syntax in a uses clause, but AFAIK the Lazarus IDE ignores it altogether, regarding it as a dated and flawed non-cross-platform concept of Delphi, tolerated for compatibility reasons only. ---------------------------------------------------------------------- MarkMLl · 2021-01-16 20:03 Quote from: howardpc on January 16, 2021, 08:07:42 pmI don't know how exactly FPC handles the "in" syntax in a uses clause, but AFAIK the Lazarus IDE ignores it altogether, regarding it as a dated and flawed non-cross-platform concept of Delphi, tolerated for compatibility reasons only. "Half-heartedly" is the phrase that comes to mind :-) The IDE has asked on a couple of occasions whether I want to add one or other of the directories to the unit path, however that's something that I specifically /don't/ want to do in the current case because of the name overlap. And the name overlap is inevitable, at least in the case of the statically-linked units, since in all cases "Python" is the interface to the underlying libraries. MarkMLl ---------------------------------------------------------------------- marcov · 2021-01-16 20:33 Quote from: MarkMLl on January 16, 2021, 07:54:16 pmQuote from: marcov on January 16, 2021, 06:56:33 pmUnitpath is dangerous that it only activates if the module containing it is compiled, and early in the process. It works if it is in the top of your mainmodule, and exclusively compile via compiling the mainmodule. I'm afraid I've got there, and it might be worse than that. Neither with "unitpath" nor "in" are rebuilds being done reliably, The documentation of unitpath says it is local to the current module only. But it doesn't say what relative paths are expanded against. I filed a bug for that  QuoteI suspect that Lazarus is failing to pick up that files have been changed despite the fact that they're members of the project. FPC only sees cmdline parameters and what is in the .lpr.  (and to be complete .cfgs and environment variables, but that is fairly not often the cause of problems) QuoteIn both cases "Clean Directory" followed by a build works. I hesitate to say that things are "bad" since I'm sure that I'm abusing the system in ways unintended, but I can't even rely on a rebuild if I change one of these lines in the main unit I don't know how   xxx in  'yyy' is processed, and if this matters for later references to xxx. If some references have paths, and others not or different, that could cause problems. Since if a second reference is encountered, but the first one was not found (e.g. because that unit wasn't changed and thus not recompiled), the compiler couldn't know about it, even theoretically. The documentation  for the feature is again very sketchy. ---------------------------------------------------------------------- MarkMLl · 2021-01-16 21:30 Quote from: marcov on January 16, 2021, 09:33:56 pmThe documentation of unitpath says it is local to the current module only. But it doesn't say what relative paths are expanded against. I filed a bug for that  Thanks for that, your opinion carries more weight than mine. QuoteFPC only sees cmdline parameters and what is in the .lpr.  (and to be complete .cfgs and environment variables, but that is fairly not often the cause of problems) Well, /something/ appears to not be being picked up if only the $define directives in the main unit are changed, which is odd. And their effect is strictly local, i.e. they're in the main unit rather than the lpi/lps and there isn't an include file in that unit. QuoteI don't know how   xxx in  'yyy' is processed, and if this matters for later references to xxx. If some references have paths, and others not or different, that could cause problems. Since if a second reference is encountered, but the first one was not found (e.g. because that unit wasn't changed and thus not recompiled), the compiler couldn't know about it, even theoretically. The documentation  for the feature is again very sketchy. I suspect there's been a regression. I'm currently copying older projects into my Python v2 interface and will then try v3, so I'd rather not work on test cases right now. (Thinks to self): this is something I've done several times by now, starting off with some MIDI stuff years ago. The description of both the statically- and dynamically-linked libraries is going into a common include file, and in principle the units that make use of it could be generated automatically. MarkMLl ---------------------------------------------------------------------- MarkMLl · 2021-01-19 17:11 Quote from: MarkMLl on January 16, 2021, 10:30:44 pm(Thinks to self): this is something I've done several times by now, starting off with some MIDI stuff years ago. The description of both the statically- and dynamically-linked libraries is going into a common include file, and in principle the units that make use of it could be generated automatically. I thought an update might possibly be of interest, or at least worth getting "into the record". Using a fairly natural format, it's possible to put library definitions into an include file in such a way that they're useful both when a library is being "consumed" but also when it's being created (this is something I've been doing for years, but it tends to be hard work). Descriptive comments placed in this are picked up by the Lazarus IDE as hover-over declaration hints. I now have a program which will parse this file, and generate unit files for both static and dynamic linkage (i.e. interfaces to libsomething.a and libsomething.so respectively). These still need a bit of fettling, e.g. to fill in local functions which replace C macros, but for a moderate-sized library this replaces thousands of lines of systematic edits. Using this, I can now embed a simple Python v2 script using either static or dynamic linking. Extending this to v3 should not be particularly difficult. MarkMLl ---------------------------------------------------------------------- MarkMLl · 2021-02-11 08:37 FPC 3.2.0 doesn't automatically compile units which should be reached via the unitpath directive. Is this as intended? MarkMLl ---------------------------------------------------------------------- marcov · 2021-02-11 10:57 Quote from: MarkMLl on February 11, 2021, 09:37:29 amFPC 3.2.0 doesn't automatically compile units which should be reached via the unitpath directive. Is this as intended? I checked and $unitpath is expanded relative to the path of the source module it is in. (so a $unitpath in a $I'd  file will lead to various expansions depending on which unit imports it). Check with -va what it compiles. (earlier comments based on that $unitpath was not local removed, it is local per documentation and also seems local to the source it is in in the compiler sources) ---------------------------------------------------------------------- MarkMLl · 2021-02-11 13:54 Quote from: marcov on February 11, 2021, 11:57:25 amQuote from: MarkMLl on February 11, 2021, 09:37:29 amFPC 3.2.0 doesn't automatically compile units which should be reached via the unitpath directive. Is this as intended? Check with -va what it compiles. It's gone again. It's a Heisenbug. Dagnabbit: I was pretty sure I'd got something reproducible that time. Bet it only happens if the locale is set so that the current day has an "N" in it. MarkMLl