1

Delphi 10 Seattle introduces Winapi.Security.pas. The project (a package) I'm trying to upgrade already has a Security.pas file. Short of removing Winapi from the list of scope names for the project (huge undesirable ripple effect), is there a way to tell the IDE and compiler to use the project's Security.pas file instead of Winapi.Security.pas?

I already tried renaming the projects Security.pas, but that caused even more problems with the compiler generating errors that have nothing to do with the code it was complaining about, so that's a rathole I'd rather not go down right now. This project builds just fine unchanged in XE7, FWIW, so this isn't due to any code changes in the project.

Updates:

  • Renaming the file and using a unit alias doesn't work.
  • The compiler behavior for a package differs from an application.
John Kaster
  • 2,509
  • 1
  • 33
  • 40
  • Did you add Security.pas to the project? – David Heffernan Sep 23 '15 at 22:47
  • No, I didn't add it to the project because it's already in the project. – John Kaster Sep 23 '15 at 23:54
  • If you list the file name in the .dpr file then won't it find your file. Anyway, you are asking for trouble trying to use the same name and hope that the compiler can read your mind. Be explicit. – David Heffernan Sep 24 '15 at 00:31
  • If the compiler was finding the referenced file I wouldn't be asking this question. I have edited the title to state the correct question because that would be a better solution than having to rename project files that may happen to conflict with some aliased namespace in the future. This behavior is currently breaking file location precedence rules, so before I file a bug report I was looking for some directive to correct the compiler's confusion. – John Kaster Sep 24 '15 at 03:32
  • Give the file a different name and move on – David Heffernan Sep 24 '15 at 03:57
  • 1
    Thanks for the suggestion but it's not the right thing to do. This isn't a one-off project with a single developer. I'd rather find a way to direct the compiler to do the correct thing instead having to change potentially hundreds of source code files dozens of versions of a long-term project. – John Kaster Sep 24 '15 at 04:09
  • 1
    As everybody else is saying you need to rename your Security unit. Compile you project in an older version of Delphi, and do the rename there. Then you know for sure which Security unit then compiler chooses (because there is only yours). After the rename you can go back to Delphi 10 – Jens Borrisholt Sep 24 '15 at 05:30
  • Thanks for the feedback Jens. This isn't a popular vote or an opinion poll. This is a bug in the implementation of default namespace resolution. Otherwise, any time ..pas gets introduced and someone already has .pas in their project, it will break their project and cause major undesirable and unnecessary code changes. I'm checking with someone from Embarcadero on it now, since it's clear I'm not getting help here. – John Kaster Sep 24 '15 at 21:29
  • You have received help but you clearly don't want to heed it. What you observe is by design. There is no bug. You need to fix your code. You cannot expect to use a namespace alias here and then have the compiler read your mind. – David Heffernan Sep 25 '15 at 16:38
  • I clearly disagree with your opinion, that much is true. – John Kaster Sep 25 '15 at 22:40
  • What about using a [Unit Alias](http://docwiki.embarcadero.com/RADStudio/Seattle/en/Delphi_Compiler)? Rename the `Security.pas` file, then define a Unit Alias in the project options that maps `Security` to the new name. Any code that wants to use the `Winapi.Security` unit would have to specify that full unit name in their `uses` clause, but any `uses` clause that references just `Security` by itself should resolve to the other unit instead. – Remy Lebeau Sep 26 '15 at 00:02
  • Thanks for the suggestion, Remy. Tried that as well. For a package, it just doesn't work. I haven't tried it in an application project. – John Kaster Sep 26 '15 at 00:22
  • All you need to do is rename your unit. – David Heffernan Sep 28 '15 at 05:15
  • I wonder: could you not just use a different namespace? Unless it also needs to compile for versions of Delphi that do not support them, I think in that case the compiler would use yours. – Andrea Raimondi Sep 29 '15 at 00:27
  • @AndreaRaimondi That's just another file rename, wherein you have to change to Foo.Security.* everywhere you might previously have had nothing, or just Security.* – John Kaster Sep 29 '15 at 00:30
  • 1
    Renaming the app unit appears to be the way to go. The Delphi unit will always be there, and your unit name is now retroactively a bad idea. – Warren P Sep 29 '15 at 01:39
  • @WarrenP it's a bug. To work around it for now, I'll have to rename the unit. Requiring customers to make major changes to their code base any time a "default" namespace tertiary file name conflicts with a file already in their project is wrong. That's the bug Embarcadero acknowledges and needs to fix. – John Kaster Sep 29 '15 at 16:17
  • Ok. Did you log it in Quality portal? – Warren P Sep 29 '15 at 17:47
  • @John You claim that Embarcadero acknowledges a bug. But I can't see that is so. With all due respect Jim doesn't appear to understand the problem in his answer and what's more he's not on the engineering staff and so not in a position to make that call. But yes, log it. – David Heffernan Sep 29 '15 at 18:08
  • 1
    When I asked Jim if I should file the bug, he told me he'd be escalating it since the behavior was peculiar and inconsistent. I'll follow up on it in a couple days. – John Kaster Sep 29 '15 at 21:15
  • 1
    If you file the bug, we can see it. We can search for it. Others can find it. Plus you can link to all the research that I did. – David Heffernan Sep 29 '15 at 21:20
  • 2
    Thanks. As the creator of QualityCentral, I'm quite familiar with that concept ;) – John Kaster Sep 29 '15 at 21:21

4 Answers4

5

Looks like this might actually be related to the Winapi.Security unit rather than something as generic as you suggest in the question. For instance, the following package compiles just fine:

package Package1;

requires
  rtl;

contains
  Windows in 'Windows.pas'; // blank unit named Windows.pas in project folder

end.

Note that I have, like you, included Winapi in the project's list of unit scope names.

On the other hand, this package does not compile:

package Package1;

requires
  rtl;

contains
  Security in 'Security.pas'; // blank unit named Security.pas in project folder

end.

The compiler fails with:

[dcc32 Error] Package1.dpk(7): E2200 Package 'rtl' already contains unit 'Winapi.Security'

If the issue was purely related to unit scope names then either both packages would compile, or both would fail. Hence my conclusion that there is something out of whack with Winapi.Security.

I can find no source code for Winapi.Security. I wonder what it actually is. [Nicholas Ring located the source for me, inside the rtl\win\winrt directory.]

Anyway, I think it's time to submit a QP report. The package below that fails to compile is probably the starting point for that QP report. [Your submitted report is here RSP-12469.]

It seems clear to me that in the short term you must rename your unit if you wish to adopt Seattle.

FWIW, here are some other units that behave the same way as Winapi.Security:

  • Winapi.ApplicationModel
  • Winapi.CommonTypes
  • Winapi.Devices
  • Winapi.Foundation
  • Winapi.Gaming
  • Winapi.Globalization
  • Winapi.GraphicsRT
  • Winapi.Management
  • Winapi.Media
  • Winapi.Networking
  • Winapi.Storage
  • Winapi.UI
  • Winapi.WebRT

These are all newly added WinRT units which I expect is important.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    Others may benefit from your explanation, so I appreciate your effort even though I don't need it. In a dream world, it would be feasible to completely refactor all existing source code to address this bug and prevent it from appearing when another new default namespace file is introduced in the future. However, taking these steps on this particular project does nothing to address breaking the vast majority of legacy Delphi code. That is the issue that needs to be addressed. – John Kaster Sep 29 '15 at 16:16
  • 1
    I just tried to answer the question that you asked, as I saw it. Maybe it's a bug. Maybe it's not. I just tried to answer the question. – David Heffernan Sep 29 '15 at 16:26
  • 1
    Agreed. To fix the immediate problem, renaming the unit is the only way to get it building. Unit aliases don't work. Removing winapi as a default namespace causes even more problems. Renaming the unit doesn't address the issue the next time a newly introduced file in a default namespace obscures a project file, and is like using a bazooka to kill a fly for any non-trivial application that relies on the existing unit name. – John Kaster Sep 29 '15 at 16:39
  • Jim's report was internal. I've made a public report so he can link the internal one to it. You may want to add https://quality.embarcadero.com/browse/RSP-12469 to your answer, then I'll accept it. Thanks again for your efforts. – John Kaster Sep 29 '15 at 21:52
  • 1
    FYI: I have it in $(BDS)source\rtl\win\winrt\WinAPI.Security.pas – Nicholas Ring Sep 30 '15 at 07:45
0

If you put both Winapi.Security and your local Security in the same uses clause then you are able to access the members of both of them without issue. If you put them in separate uses clauses (Interface vs. Implementation) then you will get the error:

E2004 Identifier redeclared: 'Winapi.Security'

If I only include Security.pas in the uses clause (and it is included in the project) then it accesses its members just fine.

Perhaps I need more information about what error you are running into? I'll send you a sample project that shows this working.

Jim McKeeth
  • 38,225
  • 23
  • 120
  • 194
  • 1
    This project does not use Winapi.Security – John Kaster Sep 25 '15 at 22:37
  • @JohnKaster Are you getting an error or what is happening? In my tests only including Security.pas works fine. – Jim McKeeth Sep 25 '15 at 22:38
  • I'm getting around 60 compilation errors in about 30 different files because the declarations in Security.pas are not compiled into the project. – John Kaster Sep 25 '15 at 22:43
  • Turns out it is a package and the error "E2200 Package 'rtl' already contains unit 'Winapi.Security'" was being hidden. – Jim McKeeth Sep 25 '15 at 23:41
  • Jim, thanks for looking at this. As a follow-up to your comment, we saw in the package that references to Security.pas were always resolving to Winapi.Security.pas, so the uses clause discussion above was for an application project. – John Kaster Sep 25 '15 at 23:56
-1

I might well be wrong, but I believe that if Security.pas is in the uses clause of the dpr file, along with its full path, it will be preferred over whichever file can be found via the namespaces and search paths.

OBones
  • 310
  • 2
  • 13
-2

Open project settings, in the Delphi Compiler section remove "Winapi" from "Unit scope names".

This way, when you need the Security unit shipped with Delphi, you'll have to write Winapi.Security, and if you write Security, it will use your custom Security unit.

djsoft
  • 1,051
  • 8
  • 19
  • Read the first paragraph of the question. The poster is asking how to do it **without removing WinAPI from "Unit scope names"**. How does explaining how to remove it answer the question of how **not** to have to remove it? – Ken White Sep 28 '15 at 18:17
  • Somehow I missed that part of the question :) My bad. – djsoft Sep 28 '15 at 18:18
  • Thanks for the attempt, @djsoft. At least you were trying to help resolve the problem. – John Kaster Sep 28 '15 at 23:37