Re: Designing LabVIEW NXG: Linking

When oneLabVIEW VI needs to call another VI, LabVIEW makes that “just work” without asking the user to specify additional information. This is great for the domain user who doesn’t want to be distracted by the noise of file management. To make it “just work,” the linker inside LabVIEW may store an absolute path to the called subVIs inside the VI itself. This often makes it simple and fast to load dependencies.

However, things get complicated when a dependency isn’t found where it is expected to be.During the process of loading a VI, LabVIEW may launch various helpers to locate the missing dependencies.

The first helper searches the VI Search Path for files that match the expected name:

If that helper finds a VI with a matching name, another helper informs you about the path discrepancy:

We’ve observed users struggle to keep their VI dependencies from getting cross-linked when going down this path, so we evolved the linker in LabVIEW NXG to prevent encountering missing dependencies at VI load time in the first place.

We did this with a few key design decisions:

VIs hold only names, not paths.

As long as your VIs are part of a Project or Component, creating VIs that call other VIs still “just works.”

The Project and its Components serve as the Linker, resolving names to paths and loading SubVI dependencies as needed. This is done without user intervention.

Project files hierarchy mirrors project disk folder hierarchy 1:1.

The LabVIEW NXG Project is required for loading and editing VIs.

By consolidating dependency resolution responsibilities into LabVIEW NXG Projects and Components, they’re the only things responsible for knowing the paths to the files they “own.” If a project expects a VI to be at a certain location on disk and it’s not there, you don’t search disk looking for the missing file or files. Instead, you look at the navigation pane on the left side of the IDE to identify errors displayed directly on any missing project items:

By hovering over a broken item, you’ll see a tool tip that should help you diagnose what went wrong.

This should help you take corrective action by either:

Deleting the broken project item and creating a new project item that points to the file in its new location.

We’re excited to hear what you think about the LabVIEW NXG project and linking strategy we’ve described here. Will you miss writing code outside a project? Have you struggled with missing dependencies in the past and look forward to LabVIEW NXG ending those struggles?

Your feedback is essential to influencing our plans, as we are committed to do our best to deliver an IDE that stays out of the way while you do the heavy lifting writing code.

I always thought that subVI paths are stored as relative (not absolute) paths inside the caller. Can you clarify?

(Typically, If I move the entire folder hierarchy to a new location and open the toplevel, there is no observable searching for dependencies as long as everything remains in the same relative location)

I have run into linking issues in the past, so moves toward mitigating those types of errors are welcome. The strategy described for NXG makes sense, though is little bit too hands-off in helping fix dependency issues. Some more streamlined workflows would be useful.

For example, I can easily crash NXG when moving files around the project with the same name into the same namespace (e.g. from a library into a subfolder, where the top level already has the same named file). In these cases the files on disk have moved, but the project didn't get a chance to save those changes, so now everything is out of sync. Opening the project shows missing files, even though they exist within the project folder on disk in a different location.

So in the above scenario it'd be useful if the linker were able to resolve the moved files, or provide a simple component replacement wizard which steps through each missing component and lets me either pick a replacement or just remove the missing file from the project. It's a quick fix in this example, but for very large projects a little bit of help would be nice.

Another related workflow for which some help would be nice is "orphaned" GVIs in .gcomp folders. Any directory ending with .gcomp doesn't actually show up under the project tree (not without a .gcomp definition file). In my crash example I have some of these GVIs left under a .gcomp folder, but the project thinks are part of another library. The orphaned gvi is not not visible in the project tree, so now I'm back to hunting on disk to find my files. A component replacement wizard should help in finding these files.

Unless otherwise stated, all code snippets and examples providedby me are "as is", and are free to use and modify without attribution.

Thanks for the concrete feedback! This type of discussion is exactly what we were hoping would come from this blog series.

These types of usability helpers for dealing with bad situations are things that are on our backlog. While we are currently focusing on bringing some key functionality into the product around building libraries and applications, I am cataloging opportunities for increased usability. Examples, like the ones you have pointed out, are exactly the type of use cases that fall into this category.

"How does LabVIEW store [information about the subVI, particularly where it is on disk]?

As an absolute path (e.g. C:\Project1\Sub1.vi)? Not if there’s any other choice. Imagine how brittle it would be if we always stored absolute paths. If you renamed your Proj1 folder, LabVIEW wouldn't be able to find any subVI of main.VI. However, in some cases, it is not possible to use a relative path (such as when the subVI is on a different network drive), so LabVIEW has to store an absolute path.

As a relative path (e.g. .\Sub1.vi)? Sometimes. In fact, this is how the path is stored in most cases, except when the subVI is in certain “special” locations.

As a pseudo path (e.g.\Sub3.vi)? Sometimes. If the VI is in one of the “special” locations defined by pseudo paths."

We’re excited to hear what you think about the LabVIEW NXG project and linking strategy we’ve described here... Have you struggled with missing dependencies in the past and look forward to LabVIEW NXG ending those struggles?

I think everyone who has used LabVIEW for anything more than simple tasks has run into problems with missing dependencies and cross-linking and is looking forward to seeing improvements. It sounds like your proposal is a step in the right direction, though I don't have enough direct experience with NXG to say whether or not it solves the problems I typically run into.

The most common scenarios for me running into cross-linking problems are:

Refactoring. Moving things around on disk, changing library memberships, renaming classes/libraries/vis, etc. If LabVIEW crashes while I'm doing this I'm virtually guaranteed to have cross-linking when I reopen the project. Sometimes I run into cross-linking when reopening the project even if I've saved everything and closed the project normally. This happens often enough that "close and reopen the project to make sure everything is still linked correctly" is part of my standard workflow before making major commits.

Replacing an existing class/library with a different implementation of the same thing. Usually this occurs during the development of code that is targeted as a potential reuse component.

Buildtime and/or runtime. At my last job we had a relatively complex RT application with many components loaded at runtime. Runtime linking errors were a nightmare to track down. Buildtime linking errors were only slightly less annoying.

The latest versions of NXG still don't support enough functionality to justify me spending a huge amount of time in it, so I can't promise I'll explore the linking any time soon. However, it does sound like we have better solutions for scenarios 1 and 2--if nothing else I assume we could edit the project or component file directly?

That said, I don't see anything in your post related to linking at buildtime or runtime. Can you tell us what the current thinking is?

Refactoring code (which is something that basically needs to happen all the time) involves frequently renaming vi's and classes. This is god awful in LabVIEW if you're using Perforce (perhaps it's better with Git which picks up changes and automatically checks out files). My work flow is: rename a class or vi, make sure every referencing thing is checked out, save all, close labview, reload everything, discover that for some reason 20 items didn't update, sort out that mess, exit, reload everything, it all looks good, commit my change, have my co workers tell me I broke the build. Delete everything and force sync everything, load it up, see that I indeed broke the build.

One time there was a class (which was renamed) that we were asked to find for an entire year when we loaded our code. It wasn't until some hail mary mass compile on all 6000 vis that it stopped doing that.

I think it's a critical flaw to have a 1:1 coupling of a vi name and the name of the file on disk. Renaming vis should be sort of like renaming google docs. The link isn't broken, and the name is just a property of the linked item, not intrinsically linked to the file name on disk requiring file name changes everytime I want to refactor.