How to deploy ONLY .EXE and custom .BPL files? - plugins

I would like to develop GUI application with plugins. The plugins contains VCL Forms which are inherited from Base Forms in the Plugin-Core library. The main application can select which plugin to load dynamically, and then which Form subclasses to display.
In the users side, I would like to deploy main .EXE, the Plugin-Core library, and many plugin libraries for different models. I could release new or modify existed plugin libraries to users to display new Forms for new devices without modifying the main .EXE and the Plugin-Core library.
The first version I developed uses DLL approach, namely both the Plugin-Core library and the plugins are in DLL form. Everything is just fine on the users side. However, in the developers side, the plugin DLL project can not be linked without Base Forms defined in the Plugin-Core DLL project. It means that the Base Forms are actually statically linked in each plugin DLL project, and if someday I modify the Base Forms and rebuild the Plugin-Core DLL project, I have to rebuild all plugin DLL projects and re-release plugin .DLL s to users, too.
After searching and asking in StackOverflow, I realized the limitation that VCL Forms can NOT be inherited across DLL boundary is due to RTTI conflict(?). The suggested solution is to modify the libraries from DLL to BPL form, which is the second version I developed. Everything is also fine except the following two:
The dynamic loaded Form from plugin BPL is separated from the main .EXE in Windows taskbar. It is not what I desired. The solution is that I enabled "Build with runtime packages" in the .EXE project.
After I enabled "Build with runtime packages" in the .EXE project, I have to release other .BPLs to the users, such as vcl.bpl and rtl.bpl. This is not perfectly what I desired.
I would like to know that the above two issues can be resolved at the same time? In my thought, I could resolve both two issues if I:
Disable "Build with runtime packages" in .EXE project.
Enable "Build with runtime packages" in all .BPL projects.
In this way, the .EXE can run without vcl.bpl and rtl.bpl bundled, and the plugin .BPL s can be loaded successfully because the dependent units are already part of the main .EXE? Am I correct? However, the "Build with runtime packages" checkbox is disabled in all .BPL project options. As a result I don't have a chance to check whether the solution works or not. I am sorry for the lengthy description and I can not attach picture due to company's Internet security policy.

The dynamic loaded Form from plugin BPL is separated from the main .EXE in Windows taskbar. It is not what I desired. The solution is that I enabled "Build with runtime packages" in the .EXE project.
After loading a BPL, pass the EXE's Application.Handle to the BPL and assign it to the BPL's own Application.Handle before it creates any Form instances.
Alternatively, on Windows 7+, you can have the EXE call SetCurrentProcessExplicitAppUserModelID() to establish a App ID for its taskbar button. Then each Form in the BPLs can use SHGetPropertyStoreForWindow() and IPropertyStore.SetValue(PKEY_AppUserModel_ID) to set the same App ID for their windows. Multiple windows with the same App ID are grouped together under a single taskbar button.
See MSDN for more details: Application User Model IDs (AppUserModelIDs)
I would like to know that the above two issues can be resolved at the same time? In my thought, I could resolve both two issues if I:
Disable "Build with runtime packages" in .EXE project.
Enable "Build with runtime packages" in all .BPL projects.
In this way, the .EXE can run without vcl.bpl and rtl.bpl bundled, and the plugin .BPL s can be loaded successfully because the dependent units are already part of the main .EXE? Am I correct?
No. BPLs cannot use the EXE's built-in units like that.
If you disable "Build with Runtime Packages", the RTL/VCL units will be statically linked into the executable file. The problem with doing that is multiple copies of a given unit cannot be loaded in memory at the same time, so you wouldn't be able to load multiple BPLs together (or even at all) if the same RTL/VCL units are statically linked into multiple BPLs, or even the EXE itself.
If you enable "Build with Runtime Packages", the executable file will be dependent on the RTL/VCL BPLs, which must then be deployed.
So, if your EXE and BPLs share common units, those units must be loaded via shared BPL(s) so only one copy of the units exist in memory. There is no avoiding that when writing custom BPLs. Which means at a minimum you usually have to deploy RTL.BPL if you are using basic RTL functionalities, and VCL.BPL for UIs.

Related

Trying to use Eclipse (Mars) with Linked Folders for ESP8266 project

I have successfully built a number of projects with eclipse (mars) under windows 10 with copied common source and header files. I now want to refactor these projects to use the eclipse 'linked folder' facility.
linked folders
I have successfully created the common project and the linked source folders to it in the target project.
However when I try to compile the project the compiler can't see the linked folders...
compiler error messages
I'd appreciate any help with this, or is it that the xtensa compiler under windows doesn't support linked folders??
IMHO "linked folders" is a slightly borked feature as it raises expectations it can't fulfill. The folders are only linked within the Eclipse context. That means that as soon as you leave the safe Eclipse haven those links are gone.
What you actually want/need are links on OS level that also work on the command line i.e. you need them on the file system. Such symlinks are native on Unix(-like) systems but there are ways to create them on Windows as well.

Can I get eclipse gwt devmode to always recompile all my modules

I have two modules, the Main module and the Included module.
If I start the Main module it will show an interface with an iFrame which contains the Included module with some additional controls around it. I can also start the Included module separately.
I have solved this by having two separate .gwt.xml files and two separate entrypoints and the result is then placed in the same war folder.
If I use GWT Compile in eclipse I can add both my entrypoints to the list and it will compile both modules and everything will work correctly.
However if I click the "Run" button in eclipse to have my application run in devmode, then it will only recompile the entrypoint that I access in my browser. If I access the Main entrypoint then I will get a popup saying "gwt module may need to be recompiled" and devmode will not automatically recompile my Include entrypoint.
Is there someway that I can get devmode in eclipse to -always- recompile all of my modules?
As I understand it, you use an IFrame that contains the host page of a secondary GWT module. This frame's content must also be loaded using the gwt.codesvr=127.0.0.1:9997 parameter, or it would just load the latest compiled version of the GWT javascript without using the devmode server.
You should also make sure the debug configuration in Eclipse contains both modules. You can verify that by not clicking the button directly, but using the menu to open the "Debug Configurations" menu. Assuming you clicked on the "Debug" button before, you should find an existing GWT debug configuration there. Make sure that both modules are listed in the "GWT" tab.
If you have your modules in two different projects, you might have to use two instances of the dev mode server. (remember to use different ports)
Add you included module to your main module.
You can do this by adding
<inherits name="fully qualified name of your module"/>
this code in your main.gwt.xml file.
I would contend that this is more of a "project setup" problem, than "how can I get Eclipse to compile all my modules" problem. The reason I say this is, I have yet to see a GWT project where two entry points were necessary/made sense. The main reason to have separate entry points is for reuse (Dev Guide, Dividing code into multiple modules).
The way I would approach the problem is to have your Main module, which includes the controls and iFrame (and have it inherit your Included module), so the same as you are now. Where I would differ is I would set up the Included module to not have an entry point. Instead, if you have a reason to run it separately from the Main module, I would create a "drive"/"launcher" module that also inherits the Included module. However, instead of controls and an iFrame like the Main module, this driver module would consist merely of an entry point and a place to attach your Included module.
You might also check out this question for more discussion in this same vein: Multiple Entry Points in GWT.

How to share a common customBuildCallbacks script between multiple Eclipse plug-ins

I am trying to avoid duplicating customBuildCallbacks.xml for all my plug-ins, when called from either PDE's headless build or the Eclipse GUI. I have in customBuildCallbacks.xml steps to generate code or modify the plug-in packaging that I:
obviously want to run with the headless build
would also like to run either when I export this plug-in from the GUI or from an external builder watching specific files in my plug-in
The headless build runs in a well defined environment, so I can set customBuildCallbacks.buildpath or even use a relative path in each plug-in's build.properties to point at my common customBuildCallbacks.xml. However, this is trickier from the GUI: that path is different for every developers since we do not have sources in the Eclipse workspace (we import projects from various locations due to our internal build process). I was hoping for every project to have an associated ant property holding its path on disk, similar to the ${workspace} variables exposed in various dialogs. I couldn't find anything useful though.
Does anyone have any experience doing this kind of things?
Thanks,
Romain

VSTO addin dependency resolution

I have a VSTO addin, which works fine. I am trying to give it a plugin-loading mechanism so that others can add plugins to my plugin. I sounds horrific, I know, but it seems to best option for now.
I publish my addin to a folder called 'Published'. This creates the application manifest (Symbols.application) and also a folder called Symbols_x.y.xx.yy with the actual addin assemblies in it. Visual Studio increments this version number each time I publish, so the assemblies are never in the same place twice.
The plugins are in a folder Published\Plugins. I load the plugin assemblies using Assembly.LoadFile(string) and this works OK. The plugins are all in folder which stays in the same place no matter how many times I publish it and I can scan that folder for DLLs and load them.
What doesn't work is when those plugin DLLs have dependencies. In particular, one depends on a COM object. Visual Studio builds an automatic Interop DLL which it puts in the Published\Plugins folder, alongside the corresponding plugin DLL. An exception is thrown as soon as any attempt is made to access the COM object, saying that the interop assembly could not be found.
Putting the interop DLL into the folder Published\Symbols_x.y.xx.yy folder works, but that requires manually putting it there each time. I've tried adding the plugins to the AppDomain's PrivateBinPath, but the documentation says that anything outside the ApplicationBase will be ignored and it seems this is indeed the case - it doesn't work. ApplicationBase is set to Published\Symbols_x.y.xx.yy.
It seems to me I have four options:
Figure out how to change the ApplicationBase, moving it up one level, and then add the Published\Plugins folder to the AppDomain's PrivateBinPath.
Make some change to the application manifest to indicate that assemblies can be loaded automatically from Published\Plugins.
Find some other way of explicitly loading an assembly into the AppDomain, not just into memory using Assembly.LoadFile.
Anything else anyone wants to suggest!
But I can't find any way to get any of these options to work. Help!
The solution was provided by the MSDN forums:
I've added an event handler to AppDomain.CurrentDomain.AssemblyResolve. This gives you a chance to load the assembly in whatever way you like, including by loading it from my plugins directory.

Managing dependencies with Eclipse and CVS

I have a bit of code for a dll that is needed by two or more projects in eclipse. Currently each project has a copy of the code and builds the DLL separately. I want to separate the dll code into a separate eclipse project so there is a common location. But I want to avoid the situation where we have to build the dll in the one project, then copy the dll back to the other projects and check the dll to each respective project. This will create a dll for each project that isn't traceable to the exact code that it was built with.
Is there a way to somehow symbolically link the dlls to another eclipse project that is using CVS as the version control system so that it is possible to tell which version of the code was used to create the dll? Am I making this too complicated or missing something obvious?
I thought about working sets in the package manager for eclipse, but I have to investigate more on how to use them with CVS to avoid making it a nightmare for the next person who checks it out and can't figure out why their project won't compile.
Thanks.
What about creating a new folder in a separate project. In the advanced section of creating a new folder there is an option to link to another location on the file system.
Or you could also create a container project that makes use of a projectset.psf file. Have the projectset file link to the different projects in your repository. When you want to check out that project, check out the container instead and right click on the projectset file and select Import Project Set...
If you are working with one workspace, you end up with three projects, each mirrored in CVS: One is the dll, the others are the projects using the dll (configured as a project dependency of these projects upon the dll project).
With three projects I wouldn't aim for working sets - they are good for managing a lot of projects within one workspace, for three projects, I'd consider them overkill. I usually tend to aim for several workspaces instead of working sets.
Regarding the next person working with these projects: You need to keep some kind of documentation about how to setup your projects. You might say that your eclipse project files do just that (as they define a project dependency upon another project) but this is for the machine - humans tend to like other communication means.
If you are worried about changes to the dll being incompatible to one project (because the person applying these changes doesn't care about the other project), aim for a build server. This will build all projects and dependent projects whenever something under version control changes, run all tests, provide a build number and package it all ready for use. This way you can be sure that - whatever is in your deliverable - can be reproduced, because the buildserver is not able to make local (uncommitted) changes to the code. Also a buildserver will signal failure (either broken API or broken tests) at the moment of the last commit (well - a few minutes later) and place the burden of repairing the damage on the one causing the damage.