I'm attempting to properly use Source Code Control (Revision Control) along with Source Distributions or Packed Project Libraries to create re-use libraries that a given software version knows the version of all it's contained re-use libraries. I've run into a few roadblocks that I'd like help knowing the appropriate setup to mitigate.
A bit about my system. I'm running LabVIEW 2020 using Tortoise SVN as my Revision Control. I'm using Semantic Versioning for version numbers. My re-use libraries are usually an actual LabVIEW Library. Normally this would contain some commonly used function or class such as an explicitly defined network protocol or fancy timer interface.
Where I've run into a couple problems. First, I've run into an issue with replacing a versioned packed library with a new version. I have to manually reconnect every instance in every vi until all references point to the new version. This sometimes works, sometimes doesn't, and always takes a huge amount of time. There should be a way I can reference a specific re-use library version and easily update from it to another version. Second, I've run into an issue with using a re-use library in multiple places within a top level application. Example, two re-use libraries both use a third re-use library, now they are conflicted in the top level. Example 2, one re-use library uses a second, the top level application uses both the first and second, this also creates a path conflict.
Any suggestions on how to set up this kind of thing properly? I feel like I'm missing some small detail about how these things are supposed to work.
I presented at NI Week 2019: "Effectively Using Packed Project Libraries. It can be challenging but it is doable. We have over 180 PPLs in our system. First and foremost is that you should be VERY careful as you design your APIs. Use the SOLID principles, especially in terms of modifications. Do not alter your connector pains once your API is established. Extend the library with new calls, don't modify the connector panes of existing, released APIs.
Consider using plugins if you need to support multiple versions concurrently on the same machine. Dynamically loading them will allow you to include a version in the PPL name. This would mean that you would have a base class that all of your applications link to when building and then load the specific instance at runtime.
Use the MGI Solution Explorer for building your PPLs. It helps immensely. Also, determine a static directory structure for your PPLs. We place ours in the c:\ProgramData folder. We also have a mirror of that in our development area that we link the source code to. The built executable links to the common folder. One thing to be aware of is that the path information when you build applications and PPLs can get a bit strange. You have to preserve the relative depth of the folders between your development environment and your distribution PPLs.
Thanks for the reply Mark!
So, I've briefly dug through your presentation and reply, and I want to verify that I understand things correctly. For using PPLs I need to have a hard distinction between Libraries and Plugins. A library would go into C:/Program Data and be a static reference. A library would be re-use code that should "never change" and could be used within other Plugins, Libraries, or Projects. The key is maintaining "level", if it will ever be "nested" it should always be nested at the same depth to maintain relative path depth. A Plugin would be re-use code that tends to change more often that is never ever ever nested under any circumstances. It could contain Libraries and be contained in projects. Dynamic loading would allow selection of version number at runtime instead of at compile time. To do this I should keep my source and compiled codes as separate repositories from each other and from top level projects.
I'm guessing the issues I've had with PPLs in the past have had to do with the relative path depth issue you mentioned before. The structure I've got currently is that my trunk code is one level higher than the built PPL. So as example. I've got a directory of Repository/Trunk/Project.lvproj for the source, that then builds to Repository/Builds/Version/Project.lvlib. I should separate the repositories so I've instead got SourceRepository/Trunk/Project.lvproj building to BuildRepository/Version/Project.lvlib? So that the depth is the same? What I've had happen in the past was I would directly use the Version/Project.lvlib in another project, when I "reconnect" the project to the next version it tells me that the new project is incompatible with my version of labVIEW even if the next version is an identical project build bit for bit.
Say I have a Timer Plugin or Library. I want to use this Timer within another Plugin, and also within a top level project which also uses that other Plugin. From your description, that would mean that it has to be a Timer Library stored someplace such as C:/ProgramData. I think I'm missing what the difference to LabVIEW is between a Library and Plugin, do I compile them differently? But then within the top level project I need to include the Timer Library within a wrapping Library or Plugin to maintain depth? Or should I exclusively reference the Library version contained within the Plugin?
Lastly, do you have any recommended reading for SOLID related to LabVIEW if I wanted to dive deeper than the Wikipedia description?
Thanks and sorry for my hodgepodged understanding of some of these concepts,