Paving the Way to Visual Studio

New features make it easier to move traditional code to Visual Studio

By Jeff Greene, Senior .NET Engineer

In the last issue of Synergy-e-News, we discussed how you can now use one IDE, Visual Studio, to develop both Synergy .NET and traditional Synergy applications. We also discussed how Synergy DBL Integration for Visual Studio (SDI) includes new templates that make it easy to create traditional Synergy projects from scratch. But how do you move existing Workbench projects and other traditional Synergy code into Visual Studio?

A large part of our development effort for this new functionality has been focused on understanding the issues with project migration and on developing tools and features to make this easier. For example, we mentioned in the previous issue of Synergy-e-News that MSBuild provides a dependency-based build process. This has a number of advantages over the less structured build process for Workbench, but there can be issues when moving from a freeform build system to one that has a strong notion of projects, references, and dependencies. In this article we’ll take a look at a few of these issues and some features we’ve implemented to mitigate them.

Migration made easy
In an ideal world, project migration would happen automatically. To get as close as we can to this ideal, we’ve created syn2vs, a utility that takes Workbench projects and other groups of Synergy files and turns them into Visual Studio solutions. You can create a traditional Synergy solution manually in Visual Studio, and then just add your source files to that solution, but in many cases it’s better to let syn2vs do the heavy lifting.

There are three ways to use syn2vs: pass a Workbench workspace file (.vpw), pass a Workbench project file (.vpj), or pass a JSON file with project and file information. Syn2vs imports all the source files, ELB references, and even compiler settings if they’re available. It can also be set to resolve dependencies, which can be complicated. We’ll discuss syn2vs in more detail when we take a look at circular references later in this article.

Don’t fear strong prototyping
Strong prototyping is an important safeguard that goes a long way in preventing runtime errors. It is required and happens automatically for Synergy projects in Visual Studio and for object-oriented Synergy code developed outside Visual Studio. However, for non-object-oriented Synergy code, strong prototyping does not happen automatically outside of Visual Studio, and it’s not required. But it is always beneficial. Unfortunately, because strong prototyping has often resulted in an overwhelming number of errors, many Synergy developers avoid it when possible or prototype only a subset of their code. With version 10.3.3, however, we’ve made strong prototyping much easier to use.

In our search for the ideal Visual Studio build experience for traditional Synergy (which relies on under-the-hood strong prototyping), we worked our way through as many customer projects as we could get our hands on and in the process discovered that a couple of key compiler improvements would make strong prototyping much less painful. These have taken the form of two new qrelaxed settings: paramad and paramst, which can be set on the Compile page of Visual Studio’s Project Designer.

Even without these new settings, qrelaxed generates warnings instead of errors for most minor mismatches between declared parameters and what’s actually being passed. However, these new settings “relax” prototyping even further so that a good percentage of errors reported by the compiler are for “real” bugs that could show up at runtime.

The first, paramad, allows alpha type variables to be passed to parameters declared as decimal. While this isn’t safe, your code will continue to work just as it has in the past with this kind of mismatch. At some point, though (sooner rather than later), you should seek out and resolve these mismatches.

Paramst, on the other hand, allows a structure to be passed to a parameter that is declared to accept a different structure type. We noticed a need for paramst when we examined a large section of code that wrapped functions and subroutines for xfServerPlus. At each function declaration, structures were included from the repository but with different names and in a different namespace than the parameters declared for the functions they were wrapping. Paramst enables this to work in Visual Studio.

Incidentally, mismatched EXTERNAL FUNCTION declarations are also a common source of compiler complaints. This feature, which has long been available in Synergy DBL, enables you to declare the name of an external function and tell the compiler what kind of data to expect as the return type for the function. Unfortunately, as with most manual processes, external function declarations are generally neglected over the years and end up diverging from the actual functions they are describing. However, you can use the extf setting for qrelaxed to instruct the compiler to generate warnings instead of errors when these don’t match. The compiler will then handle these mismatches correctly for runtime behavior.

If you’ve been avoiding strong prototyping because it results in too many inconsequential errors, consider using the options we’ve discussed here to narrow down the results a bit. You might be surprised at the potential runtime issues you’ll find lurking in your code. And if you’re moving your Synergy Code to Visual Studio, there’s no need to use strong prototyping before the move. Instead, set qrelaxed options as needed in Visual Studio and let the automatic prototyping do the work. Because the environment is controlled in Visual Studio, you’ll get better results.

Breaking circular references
The most difficult dependency-related problem when migrating to Visual Studio is circular references—for example, where ELB1 references functions from ELB2, while ELB2 references functions from ELB1.

ELB1 and ELB2 reference functions from each other

Circular references are not supported in Visual Studio because MSBuild (Visual Studio’s dependency-based build system) cannot determine the order projects should be built. But they’re perfectly acceptable when developing traditional Synergy applications with traditional tools, such as Workbench, because the linker resolves references in its final stage when it has all the necessary information. Consequently, none of the traditional Synergy tools alert you to circular references.

To enable Synergy code with circular references to work in Visual Studio, we developed the Add Prototype Reference feature, which enables you to use definitions in a code file without actually including the code file in the project. Instead, you add a prototype reference in the Prototypes folder in Visual Studio’s Solution Explorer.

Add Prototype Reference in Visual Studio

We call this “adding a proto-only file.” With proto-only files, the build system knows enough to rebuild if the code file changes, even though there’s no actual project reference to the code file.

ELB2 references and calls routines from ELB1

Dependency resolution and syn2vs
If you use syn2vs with its dependency analysis option (-da), syn2vs resolves dependencies, using proto-only files to break circular references. This enables syn2vs to create a fully formed Visual Studio solution. Syn2vs prototypes all code, builds each source file, and then generates a list of all the types and routines used in the solution. Once it fully understands the references necessary for the project, it breaks circular references in the best possible way. Imagine a scenario where Project 1 has a single small dependency on Project 2, while Project 2 has hundreds of dependencies on Project 1. If syn2vs didn’t choose the best reference to break, the result would be a mess. Syn2vs uses a greedy algorithm to iteratively break all circular references, resulting in the least possible number of prototype references. But there are limits. If you have two different routines, structures, or classes with the same name in two different files, the last one processed wins. Furthermore, syn2vs will not correctly analyze the dependencies of shadowed routines, structures, or classes. This means that you may need to add items or move items from one project to another.

Link order and logical linking
Another issue that can crop up when you move traditional Synergy code to Visual Studio is the establishment of link order requirements. The build system for Visual Studio doesn’t typically allow you to determine the order projects are built, but with traditional Synergy, link order can be important.

To support scenarios where link order is important (e.g. where link order controls which version of a routine is used, such as a customer-specific version of a routine linked on top of your base distribution), we’ve added a feature that enables you to mark an ELB reference with a priority setting. This priority setting is an integer value that defaults to 0. If you set it to a lower number (a negative number), the ELB will be placed toward the end of the dblink command issued by the build system. If you set it to a higher number, the ELB will be placed closer to the front of the dblink command.

And to support linking to an ELB using a Synergy logical (a common practice with traditional Synergy), we’ve created an implementation of the Add Reference dialog that has support for built-in Synergy-defined locations.

Visual Studio Reference Manager showing Synergy ELB files.

The next step
As you can see, we’ve been hard at work developing features to help you move your traditional Synergy code to Visual Studio. For more information on the features we’ve discussed (syn2vs, creating a Visual Studio project manually, setting link priority, and using proto-only files), check out our migration guide, “Migrating Traditional Synergy Projects to Visual Studio.” And consider giving Synergy/DE Developer Support a call so we can work through the migration process with you.