EtheaDev / SVGIconImageList

Three engines to render SVG (Delphi Image32, Skia4Delphi, Direct2D wrapper) and four components to simplify use of SVG images (resize, fixedcolor, grayscale...)
Apache License 2.0
327 stars 96 forks source link

Packages cannot co-exist with Angus Johnson's original Image32 package #193

Closed tuurke63 closed 3 years ago

tuurke63 commented 3 years ago

The SVGIconImageList packages contain a copy of the original Image32 package by Angus Johnson, but unfortunately they do not publish the original component TImage32Panel in a design time package.

I need that component, but unfortunately it is not possible to install the original Image32 package at the same time as the SVGIconImageList packages. They collide.

Could you please correct that? I love SVGIconImageList but I also need tImage32panel!

carloBarazzetta commented 3 years ago

Yes, it can be possible replacing SVGImage32Package with the original one by Image32 library... I'm working on it.

carloBarazzetta commented 3 years ago

I suppose we need an Img32Rtl.dpk that includes only core units: Img32 Img32.Vector Img32.Transform Img32.Resampler and an Img32_VCL packages (that require Img32Rtl and vcl and includes Img32.Panels)

So, for SVGImage32Package (run-time only) package, I can require Img32Rtl only and can co-exists with Img32Rtl and Img32_VCL.

Another solution is to include Img32.Panels into dclSVGIconImageList_DXX package, but is not a clean solution.

AngusJohnson commented 3 years ago

Hi tuurke63 and carlo.

Although I've been using Delphi since version 1, I'm still not overly familiar with Delphi packages 😱 though of course I have a very basic understanding of runtime and designtime packages. Anyhow, I'm not really sure of the best approach. And having run into this problem myself, and found a satisfactory workaround, I haven't as yet given it a lot of thought.

What I've done as a temporary workaround is:

  1. Compile Img32_VCL package and install it as a designtime package (ie so the TImage32Panel component loads in the IDE).
  2. Add the Img32_VCL.dcp to SVGImage32Package as a required dependency.
  3. Remove any direct references to Image32 from other packages

What I suspect is a better approach will be for Image32 to have 2 packages, a runtime and a designtime package. All the library units would be included in the runtime package. The designtime package would install the TImage32Panel component while also linking with the runtime package. That way other libraries including SVGIconImageList could link with the runtime package without encountering these conflicts. (This seems to be what carlo is suggesting above too, now that I've read his post again 😜.)

Does that sound sensible to all you package experts?

Edit: Perhaps better yet for Image32 packages:

  1. All library units except Img32.Panels in the runtime package
  2. Just Img32.Panels in the designtime package (with the runtime as a dependency).

Also, what's the best way to manage FMX and VCL? Should I avoid including units in the runtime that have specific FMX or VCL dependencies, or should I have 2 runtimes, one for FMX and another for VCL?

As I understand things, the implementation of Borland's CodeGear's Embercadero's Idera's runtime packages was and still is flawed, and we should have stuck with DLLs. But as I stated above, I've never really spent much time investigating the intricacies of these things.

Edit 4: Try this: Image32_Packages.zip

tuurke63 commented 3 years ago

Two packages makes perfect sense to me and it would certainly work. Maybe also create a little "project group" that contains both packages.

By the way, in GIT it is possible to simply reference external libraries as "submodules", so SVGIconImageList needs not come with a copy of Image32. It should rather reference image32 as a submodule. When a user pulls SVGIconImageList, he can then subsequently update the submodule which will automatically pull the original Image32 from Github. That way both repositories can stay "pure" and be maintained independently.

AngusJohnson commented 3 years ago

@tuurke63

Maybe also create a little "project group" that contains both packages.

That sounds like a good idea 😁.

which will automatically pull the original Image32 from Github

Except that Image32 isn't on GitHub 😜.

carloBarazzetta commented 3 years ago

The perfect solution is to separate design-time from run-time packages. For cross-platform libraries like Image32 it's recommended to make an rtl based run-time-only package and a separate run-time-only package for both vcl and fmx, so other libraries can include correctly those packages, like into SVGIconImageList. Finally another good practise is to add LibSuffix so the dcp and bpl file names are different from Delphi versions, so it's possible to have more copies of the same bpl package in the same library folder for different Delphi applications... I'm working on this structure of packages and commit them into this repo, so you can see if could be a solution for us. bye Carlo

AngusJohnson commented 3 years ago

@carlo.

Finally another good practise is to add LibSuffix so the dcp and bpl file names are different from Delphi versions, so it's possible to have more copies of the same bpl package in the same library folder for different Delphi applications...

I don't understand what you're saying here, would you mind explaining with an example?

carloBarazzetta commented 3 years ago

Look at the Package SVGImage32Package into this project, you can see that for every Delphi version LibSuffix is defined (like _D10_4) and placed in different folders. image Compiling this packages you obtain SVGImage32Package_D10_4.bpl for example. normally those bpl stays in different folders: image But if you deploy some different applications that needs run-time packages you can place the "same" SVGIconImage3Package.bpl in the same library folder because the have different file name. Into code you continue to refer to the required package without the suffix: require SVGImage32Package

tuurke63 commented 3 years ago

Except that Image32 isn't on GitHub 😜.

Ah yes, that's true. That reminds me, the download link on your homepage points to "https://sourceforge.net/projects/img32/", which does not exist. Shouldn't it be https://sourceforge.net/projects/image32/files/ ?

carloBarazzetta commented 3 years ago

I don't like to use SubProject if not maintained by the same author because of the risk of misalignment between libraries... It will be my responsibility to keep the versions aligned periodically ;-) For example for some days SVGIconImageList uses ver.2.0 with older filenames, when Image32 was updated to ver.3.0.

luebbe commented 3 years ago

Except that Image32 isn't on GitHub 😜.

It would be possible to set up a GitHub mirror of the Sourceforge Repo and pull that mirror in.

AngusJohnson commented 3 years ago

@carloBarazzetta Look at the Package SVGImage32Package into this project, you can see that for every Delphi version LibSuffix is defined (like _D10_4) and placed in different folders.

Thanks. That makes sense to me now. However, do many Delphi developers deploy runtime packages? Is there really an advantage of that over compiling the code into the execuable?

@tuurke63. Shouldn't it be https://sourceforge.net/projects/image32/files/ ?

Thanks. Yes, it needs fixing.

luebbe commented 3 years ago

In newer Versions of Delphi (don't know since when), there is also an $(Auto) option for the libsuffix, so you basically don't have to provide different packages anymore and will get the correct libsuffix for each new enough version of Delphi.

grafik

When I set this to $(Auto), the project name automatically changed from MPCommonLibD250.bpl to MPCommonLibD270.bpl

carloBarazzetta commented 3 years ago

Thanks. That makes sense to me now. However, do many Delphi developers deploy runtime packages? Is there really an advantage of that over compiling the code into the execuable?

Not many, but looking at the content of many Delphi libraries this is the approach, especially when the library has many components and component editors that are not needed at runtime ... In this case we would not need them... I am looking for an elegant solution that requires few files...

carloBarazzetta commented 3 years ago

In newer Versions of Delphi (don't know since when), there is also an $(Auto) option for the libsuffix, so you basically don't have to provide different packages anymore and will get the correct libsuffix for each new enough version of Delphi.

I'will test this solution for older versions. I can do it with D7, DXE3, DXE6, DXE8, D10.1 to the lastest... It is a solution that I have never adopted because I have always used non-numeric suffixes, like D10_4 instead of 270...

tuurke63 commented 3 years ago

I don't like to use SubProject if not maintained by the same author because of the risk of misalignment between libraries... It will be my responsibility to keep the versions aligned periodically ;-) For example for some days SVGIconImageList uses ver.2.0 with older filenames, when Image32 was updated to ver.3.0.

We use open source C# projects that reference many dozen other open-source projects by various authors. Correct compilation is ensured by specifying a specific commit of a subproject. It needs not be the most recent master that may or may not compile correctly.

BTW, companies like Intraweb also bundle some external open source libraries with their stuff. They solved the problem by re-naming the original units. That may be awkward to do but it avoids all pitfalls.

luebbe commented 3 years ago

In newer Versions of Delphi (don't know since when), there is also an $(Auto) option for the libsuffix, so you basically don't have to provide different packages anymore and will get the correct libsuffix for each new enough version of Delphi.

I'will test this solution for older versions. I can do it with D7, DXE3, DXE6, DXE8, D10.1 to the lastest... It is a solution that I have never adopted because I have always used non-numeric suffixes, like D10_4 instead of 270...

Just found out that it's pretty new and at least in 10.4.1 it didn't work correctly yet: https://en.delphipraxis.net/topic/3427-delphi-1041-libsuffix-auto/

carloBarazzetta commented 3 years ago

The simple way to permit to use SVGIconImageList and TImage32Panel, without the creation of many packages into Image32 is to add Img32.Panels unit to SVGIconImageList (run-time) and dclSVGIconImageList (design-time package) for every Delphi version, so It's possible to use bpl runtime packages of SVGIconImageList to include all the functionality of Image32 lib. Image32 is a graphic library with a single component and I think is not necessary to create multiple packages for every Delphi version into this library. If a developer needs both SVGIconImageList and TImage32Panel can uninstall Image32 package and install all SVGIconImageList packages. Do you agree with me? I'm working to this solution...

AngusJohnson commented 3 years ago

If a developer needs both SVGIconImageList and TImage32Panel can uninstall Image32 package and install all SVGIconImageList packages. Do you agree with me? I'm working to this solution...

I would very much like to avoid multiple packages for every version of Delphi, especially where the library currently supports all versions back to Delphi 7. Once I've split the current package into design and runtime packages, is there a compelling need for Image32 to provide packages for each version of Delphi?

I'm presuming that where SVGIconImageList becomes dependent on the Image32 runtime, the Image32 package will have to be installed first. (I'm not aware of packages being able to install other (missing) packages which would be a neater solution.) Surely this wouldn't preclude users from optionally installing the Image32 designtime package at any time after its runtime package (+/- SVGIconImageList) is/are installed?

tuurke63 commented 3 years ago

I think multiple packages for multiple Delphi versions can be avoided.

By default, Delphi installs the compiled packages in C:\Users\Public\Documents\Embarcadero\Studio\version\Bpl so even if a user has multiple Delphi versions on his machine the compiled packages will not collide, they land in different directories.

Only if a user has the desire to deploy compiled software with packages and also wishes to store those packages in a common directory (such as c:\windows\syswow64) then there could be a name conflict (a.k.a. "dll hell") . But hey, "polluting" a Windows directory with one's own DLL's is a highly frowned upon practice anyway.

One issue is that .dproj files aren't backwards compatible. Newer Delphi versions can cope pretty well with older .dproj formats or they are converted "on the fly". So if one wishes to distribute just one *.dproj file for multiple compiler versions, it should either be created with an older Delphi version or at least one should manually strip off the stuff that older Delphi versions don't understand. I have read about a tool called "Project magician" that can supposedly do this, but I haven't tested it.

On the other hand, DPROJ files are just XML sidecar files that give the compiler some extra information such as search paths and some settings. The file is not needed if all the information is already contained in the *.DPK file.

In other words: one needs not deploy any *.dproj files if the DPK files themselves contain the (relative) paths of all units that they need to compile. It's a little bit more work, but the result is a wonderfully compatible package.

AngusJohnson commented 3 years ago

@tuurke63 Thanks. That's very helpful advice.

Edit: However, it seems that in removing the *.proj files, I'm no longer able to specify target platforms, or default to the Release build. Is this an issue?

luebbe commented 3 years ago

So IIUC the hardcoded {$LIBSUFFIX 'XXX'} in the .dpk wouldn't be a problem, because the compiled packages end up in different directories. I didn't know that and I remember seeing non matching libsuffixes in the ...\\bpl folders, but this was then probably caused by .dpk files that weren't updated.

carloBarazzetta commented 3 years ago

Now I've pushed a new copy of all packages, including Img32.Panels.pas in SVGImage32Package (runtime only) and registered component into dclSVGIconImageList (design-time only). @tuurke63 you can continue to use TImage32Panel and SVGiconImageList togheter.

tuurke63 commented 3 years ago

Super, I'll try it today! Grazie mille per lo sforzo!

PS do you bundle Angus' image32 demos as well?

carloBarazzetta commented 3 years ago

PS do you bundle Angus' image32 demos as well?

No, in my library there is only a copy of the Image32\Source folder and the readme.txt. No Examples, no Clipper, no Packages folder.

carloBarazzetta commented 3 years ago

Please @tuurke63 give me a feed-back about this problem, if I can close it.

tuurke63 commented 3 years ago

Hi Carlo,

I could install the packages without problems. I can also compile Angus' demos. Thanks again!