10-08-2021 08:56 AM
Hi, I have been using LV Actors for many years, but the early years generated a lot of bad habits and poor use of OO principles, It was all very new to me. Therefore over the last few months I have tried to re-work my System with new interface classes leveraging 2020 to reduce coupling and correct some of the evolved mess I had created.
However, I needed to do a fair bit of work to get comfy with the interfaces and new structure and have not dedicated the time to deployment AGAIN... FYI Long term I want to develop a CI pipeline using Jenkins to automate build and test. We currently use Tagged code in the Dev environment on test machines, which is costly and prone to errors and potential for issues during testing.
Now I understand PPLs are the best route to a build, my real question is how to best organise the project(s), libraries etc to get functional PPLs. I have found and used LVSolutionBuilder which is awesome and works well... so far.
I have created a library for each interface (or group) and each actor in a main project, I have then created several sub projects for dynamic elements such as UIs and Tests etc. I have correctly handled these locations in the code too to distinguish PPL for source locations.
But I keep hitting a road block of PPLs not building Error 1003 or getting it to build but issues running, not to mention the whole PPL of Actor FW.
So long question, long... am I doing things right or is this a stupid path and should change my plan/strategy and embrace EXE and Data folder concept etc?
Many Thanks in advance for any help!!
Neil 👍
10-11-2021 11:21 AM
Hey Neil,
I have not used PPLs with Actors. But in a recent project when dealing with PPLs, I have found it to be much easier using LVSolutionBuilder for dealing with PPLs. On the issue that you are facing with Actor PPLs, I would suggest posting this in the LVSolutionBuilder's github issues page, preferably with a simple reproducible example.
10-12-2021 03:13 AM
Hi,
Thanks for the reply. I appreciate the help. I don't think this is an issue with LVSolution Builder more my code. I think I tracked down my problem to be circular dependencies in my PPL structure. I really am struggling to resolve them as I have interfaces (new proper labVIEW ones) that are used by Actors for messaging but they use Classes to encapsulate data which are shared by the Actors due to the interface messages so LVSolution builder cant resolve the build order.
I am wondering if this is my understanding of which items should be in what library/PPL to start with or a major design fault by using classes to encapsulate the message data etc.
Whatever it is I'm tearing my hair out and spending a lot of time failing to build 😓, that I should perhaps be spending on my code 🤔 .
Its all part of the process but this is mainly why I haven't had a proper build strategy with Actor before, along with the destruction of the IDE by having to pack the main Actor classes in to PPL too 😩.
Thanks again,
Neil.
10-12-2021 04:24 AM
Hi Neil,
I've had some 'fun' with this issue in the past too, for me (in hindsight...) one of the best aspects of PPLs is that to build them you have to fix dependencies and figure out what needs what and break any circles.
I'm currently building my PPLs in 2019 (I started with Jenkins using LV2017) but I don't think your use of Interfaces is inherently the problem.
Guessing blindly, I'd say you probably need more libraries 😉
You can have some luck just building your PPLs 'by hand' to start with (using the LabVIEW Build Specifications and the right click > Build option) and then making sure that each next library depends on the .lvlibp instead of the .lvlib of its "upstream" libraries.
Take care to check the "Exclude Dependent PPLs" box (or whatever the actual label is).
In my case, I build all my PPLs into a single directory ("C:\LabVIEW Sources\PPLs\Current\blahblah.lvlibp").
I use the "Current" directory part to allow directory junctions (not symlinks on Windows) for multiple bitnesses, but since I designed this system AQ has published information about platform-dependent load path resolution, so if you want to run code in 32/64-bit on the same computer, I recommend reading that first and doing that instead (basically, put your PPLs in <vi.lib>/MyAwesomeCompany/PPLs/blahblah.lvlibp instead).
If this all sounds like a lot of trouble and you're not interested in it (at least now), you can ignore it all. But consider if <vi.lib> is a suitable destination for your PPLs anyway, it might make migration in the future easier. Maybe.. 😕
To have a bit more control over your builds on Jenkins, you might take a look at the Application Builder API. It seems this is an unpopular choice, but I really like it. The documentation(?) is a little hit and miss (/guesswork based on file name), but it allows you to generate the build specs during build time on Jenkins, and change whichever values you like to get stuff set up how you want.
I found it vital to building cRIO PPLs without pulling out all of my hair (but I'm not sure there aren't better solutions, just that this works for me and other things seemed very trying).
For me, the "easiest" solution to building the Actor Framework libraries whilst retaining some of the original decisions (split out Reply messages, etc) was to ditch AF_Debug entirely.
I copied all of the Actor Framework code out of vi.lib into a separate directory and made changes there, this involved cut/pasting the vi.lib stuff if I remember correctly to force it to relink and search, it was quite a pain but now it works nicely. (Obviously copy the original code back into vi.lib once you've finished).
I have two PPLs, "Actor Framework.lvlibp" and "AF_Messages.lvlibp", where the first is just the contents of the Actor Framework library, and AF_Messages is the rest (Reply, Time-Delayed, Batch, Self-Addressed and Report Error Msgs).
A more popular (as I guess from reading the forums) approach is to throw everything inside one library, and build that instead. You can keep AF_Debug in that case, but you still have to fight the library membership if I understand correctly.
I have a git repository with the two libraries I've created, and so I can easily rebuild it using Jenkins as desired.
If you build Actor Framework.lvlibp outside of vi.lib, you must (I think 😉 ) adjust "<LabVIEW 20xx>\resource\Framework\Providers\MessageMakerProvider\_Message Maker\_support\Inherits from an Actor.vi" in order to retain the scripting tools in the IDE.
My modified version is shown below:
This is because when you build the PPL in vi.lib, it has a mangled path but includes "vi.lib\ActorFramework\Actor\Actor.lvclass" at the end of the path for the Actor.lvclass class.
If you build it somewhere else, it doesn't!
If you show an example of your dependencies and libraries/classes, we might be able to give some suggestions about how they could be rearranged to remove circular dependencies (apologies if you already know how to do this, and are instead looking for motivation not to!)
Hopefully at least the point in this post about the VI modifications for the search path can fix the thing you describe as "destruction of the IDE". But maybe that's something else, in which case please explain it and I'll try figure out a solution.
10-12-2021 05:49 AM
Thanks cbutcher,
You have really given me a lot to think about and really appreciate the time you have taken to respond.
Can I ask for a few extra bits for clarification?
@cbutcher wrote:
Guessing blindly, I'd say you probably need more libraries 😉
I have a library for each Actor, Interface, Support Class (or group) I currently only have one main project for my Main Program and additional Projects for Dynamic elements UI and Tests etc.
@cbutcher wrote:
You can have some luck just building your PPLs 'by hand' to start with (using the LabVIEW Build Specifications and the right click > Build option) and then making sure that each next library depends on the .lvlibp instead of the .lvlib of its "upstream" libraries.
Based on this statement though I think I will need to create a project for each and re-work post build of each upstream PPL, which is kind of why I tried to use LVsolution Builder to avoid this, am I taking this statement correctly?
@cbutcher wrote:
In my case, I build all my PPLs into a single directory ("C:\LabVIEW Sources\PPLs\Current\blahblah.lvlibp").
Is there value in the flat structure? I tried to maintain the Actor, plugin, support and interface segregation in the output, does it matter or will I cause more issues than I prevent lol?
@cbutcher wrote:
I copied all of the Actor Framework code out of vi.lib into a separate directory and made changes there, this involved cut/pasting the vi.lib stuff if I remember correctly to force it to relink and search, it was quite a pain but now it works nicely. (Obviously copy the original code back into vi.lib once you've finished).
I have two PPLs, "Actor Framework.lvlibp" and "AF_Messages.lvlibp", where the first is just the contents of the Actor Framework library, and AF_Messages is the rest (Reply, Time-Delayed, Batch, Self-Addressed and Report Error Msgs).
When you say relink and search do you mean in each project that referenced the new Actor framework? or something else?
I don't know if this will help much but here is a snip of my project explorer view.
I have highlighted a potential concern of a support Class utilised in messages (interface class) and Actor, since thinking about all of this I am wondering if this sort of problem/structure would be better resolved using an actor for Parameters and handling each parameter request as individual values? I will try with this link first to pre-build manually to see if it is a problem.
My design revolves around Parameters needing to be immutable so the class ingests the XML and stores in variant attributes, it is then supplied to the launched tests for reading. I could not figure out how to do this without send and wait messages for a centralised actor?!?
I haven't even got to the point of using Jenkins etc, I thought thought I knew how to program in LaBVIEW I know even less about Batch file, Jenkins and all that... I am at the stage of doubting the whole lot, top to bottom and my skills/understanding as a whole lol.
I have been here before, it is just know which is the route out not picking up a different spade and digging deeper Haha!
Thanks again 🙂
Really appreciate it.
Neil.
10-12-2021 06:12 AM
Hi,
Further to the last I have tried as you described to create an Actor PPL from a completely different folder and cant get past the first issue adding it to a empty project.
I created a copy and new project and added the Actor Framework Library to be struck by conflict that create an un correctable locked link to vi.lib.
Attempting to resolve conflicts doesnt have a selectable option
All of the referenced items are in vi.lib...
Any Advice? Again fallen at the first hurdle lol!
10-12-2021 09:11 PM
@NeilA wrote:
@cbutcher wrote:
You can have some luck just building your PPLs 'by hand' to start with (using the LabVIEW Build Specifications and the right click > Build option) and then making sure that each next library depends on the .lvlibp instead of the .lvlib of its "upstream" libraries.
Based on this statement though I think I will need to create a project for each and re-work post build of each upstream PPL, which is kind of why I tried to use LVsolution Builder to avoid this, am I taking this statement correctly?
Yes, that's my approach. I haven't got any personal experience with the LVSolutionBuilder, but I have heard some good things, so that might be an alternative.
However, if it never updates libraries in source to depend on upstream lvlibps, then I suspect it might not make it so obvious where you have dependency cycles, which might make it harder to solve your original issue.
In my case, the workflow (originally went like) goes something like:
@NeilA wrote:
@cbutcher wrote:
In my case, I build all my PPLs into a single directory ("C:\LabVIEW Sources\PPLs\Current\blahblah.lvlibp").
Is there value in the flat structure? I tried to maintain the Actor, plugin, support and interface segregation in the output, does it matter or will I cause more issues than I prevent lol?
The most critical aspect of PPL paths is that the relative path between PPLs must remain the same.
Mark Yedinak and Yinhui Chen gave a presentation about this in some detail at NIWeek 2019. NIWeek 2019/Effectively Using Packed Project Libraries (wiki link)
For me, a flat structure is a simple way to avoid this, but their presentation details a relative structure that they maintained at Zebra Technologies, if I remember correctly.
In any case, it isn't a requirement, just a simplification for me. If you like a more complicated structure, it's certainly possible. Just evaluate if it adds some value for you.
@NeilA wrote:
@cbutcher wrote:
I copied all of the Actor Framework code out of vi.lib into a separate directory and made changes there, this involved cut/pasting the vi.lib stuff if I remember correctly to force it to relink and search, it was quite a pain but now it works nicely. (Obviously copy the original code back into vi.lib once you've finished).
I have two PPLs, "Actor Framework.lvlibp" and "AF_Messages.lvlibp", where the first is just the contents of the Actor Framework library, and AF_Messages is the rest (Reply, Time-Delayed, Batch, Self-Addressed and Report Error Msgs).
When you say relink and search do you mean in each project that referenced the new Actor framework? or something else?
I mean when you try and create an Actor Framework.lvlib (not p) by copying out of vi.lib, everything will be a pain in the neck. From your next post, I'd guess you've already discovered this!
I'm going to respond to that one too after I've had a go at repeating the process, so I can write down which things I did in what order. Then you can try repeating it if you like.
Alternatively, copies of my PPLs (source from 2017 LabVIEW, built in 2019 LabVIEW, compatible with that and later versions via the build checkbox, 32-bit and debug enabled but no AF_Debug library) are attached.
Different approaches are described by Stefan Lemmens here: How to build a PPL including Actor classes, messages and AF Debug
and an overview is in this KB article: How to Inherit from an Actor That Is Inside a Packed Project Library? (see the first section, "Create a PPL from the Actor Framework").
The KB article also has some good points about using the PPL, probably worth a read if you haven't seen it before.
Regarding your image and description, I'm not quite sure which libraries contain which bits, so I'll guess and you can correct me...
From that description, a few thoughts:
Re Jenkins, I think it's useful, but it adds complexity and if you're having problems with the PPLs alone (and the problems aren't related to multiple platforms) then I'd suggest the manual approach first, then move to Jenkins once the basic process is fixed.
You can also write VIs to build your PPLs, and run them manually on your computer, and then when you're happy use those directly on Jenkins-based workflows (I did this for a little bit, but it didn't last that long, the cRIO stuff kept messing me (well, my source libraries) up so had to "go big or go home", sort of thing).
10-12-2021 11:29 PM - edited 10-13-2021 09:55 PM
And the promised list of my steps to extract a pair of PPLs without building in vi.lib.
Apologies for the lack of nice writing style, these are basically the notes I made whilst carrying out the process and I haven't made many adjustments to post here, except adding the bullets and some spacing + images (edited to add these, realise I forgot before) + headings.
I've used numbers in places to make it easier to ask questions if you want.
Prep
Actor Framework.lvlibp
The next few steps are probably very sub-optimal, but anyway...
Continued... (let's call this section 3?)
Save project again. Celebrate, you're halfway done.
AF_Messages
This basically involves opening broken VIs (in the classes, not the ones that get added outside the class), resolving the conflicts that pop up, ignoring the Browse search dialog (ignore all), then selecting items and choosing the equivalent item from the PPL using Quick-Drop and Ctrl+P to replace. An easily forgotten item is the message priority in Send Blah.vi
Having Context Help open and visible is useful, you're looking for items with the same name, but from the PPL.
When each is done, move it into the library (AF_Messages.lvlib)
I did them in the following order:
Time-Delayed Send Message (previously done).
Batch Msg (in Do.vi, you need the Message.lvclass:Do.vi in the loop. I couldn't get the Batch Msg class to replace at first, needed to go to class properties and fix inheritance)
Reply Msg
Report Error Msg (same issue as Batch with the class constant and control, retried after reload)
Self-Addressed Msg
Save all, close, reopen (just to be safe for me, actually it seemed fine at this point).
Only Actor Framework.lvlibp (PPL) and the Error Cluster from Error Code (in vi.lib) should be in Dependencies.
Move the classes out of the virtual folders (optional, but imo looks nicer). Not sure if it adjusts the load paths... I think only directory changes matter (not virtual folders).
Add the Packed Library build spec. Make sure to tick the exclusion box (now it matters). Set the destination appropriately (same directory for me, easiest option).
Build.
???
Profit!
I had to fiddle with the original Actor Framework library after the first build of the Messages library, I'd accidentally broken some of the source VIs and linked them into the Actor Framework.lvlibp when adjusting the message priorities. So just open the two projects a couple of times and check you can repeatedly build both without problems. If not, figure out where they're mislinked (Why is this item in Dependencies?) and fix those call sites.
Finally, copy your backed-up ActorFramework and AFDebug directories back into vi.lib and resources, so that your installation isn't weird. Overwrite the AFDebug stuff (or just remove and replace, whichever).