New solution format and ultra-fast compiler

Benefits of using solution

Ultra-fast compiler

The new solution format (PBSLN) is powered by the ultra-fast compiler, and the workspace format (PBW) is powered by the standard compiler.

So the key benefit of using the new solution format is its ultra-fast compiler.

Compared to the standard compiler, the ultra-fast compiler can significantly reduce compilation time by leveraging the Abstract Syntax Tree (AST), multi-threading, and concurrent processing. The AST, in particular, plays a key role in optimizing the compilation process and enabling efficient incremental builds, through its structured representation of the code. And the separation of source code and Pcode and storing each object's source code in individual file makes concurrent processing possible.

 

Ultra-Fast Compiler

Standard Compiler

Source code in binary format or text format

Plain text format, and one object in one text file

Binary format, and multiple objects in one PBL file

Pcode and Machine code

Supports Pcode only

Note: Machine code is unsupported, which means you cannot build Dynamic Link Libraries (DLL files). If the application project selects to generate machine code, it will be changed to select Pcode automatically after converting to the solution format.

Supports Pcode and Machine code

Syntax tree

Supports Abstract Syntax Tree (AST)

Supports parse tree

PowerScript scan

Only one scan

Five scans

Multi-thread or single-thread

Supports multi-thread and multi-process.

Note: The compiler and the IDE run in separate threads.

Supports single-thread and single-process.

The compiler runs in the same thread as the IDE.


Following outlines the tasks performed by the ultra-fast compiler during a full build:

  1. (Multi-thread) Scan the code to generate AST.

    The compiler performs a multithreaded, concurrent scan of the source code to generate AST files for each object. The AST files represent the parsed structure of the source code.

  2. (Single-thread) Preprocess object types and generate the Pcode structure.

    The compiler processes the AST to handle object types and prepare the objects Pcode structure.

  3. (Single-thread) Preprocess object prototypes and generate intermediate Pcode files.

    The compiler traverses the AST to preprocess object prototypes (such as properties, variables, and function definitions), populates the Pcode structure with this information, and generates intermediate Pcode files.

  4. (Multi-thread) Compile the entire object and generate the final Pcode files.

    The compiler fully compiles the object by traversing the AST in a multi-threaded manner and generates the final Pcode file, which is the output ready for execution.


The incremental build will reuse the existing AST and recompile only the modified or impacted parts of the object to optimize performance. Incremental build will be prompted or start automatically whenever necessary, for example, when running or debugging the solution or project, in order to ensure the Pcode is up-to-date, especially when there are changes to the base class, global function or variable, or object property.

With support for AST, multi-threading, and concurrent execution, full compilation time is greatly reduced, and incremental compilation becomes more efficient, reliable, and proactive.

We conduct performance comparison tests for incremental build, full build, and deployment in the workspace format and solution format, as shown in the table below. The larger the application, the more significant the performance improvement.

App Name

Full Build

Incremental Build

(32-bit, Pcode)

(Modified only app object and one window in another PBL)

Full Deployment

(32-bit, Pcode)

Workspace

Solution

Workspace

Solution

Workspace

Solution

Bigger App

(58 PBL, 370 MB)

816

112

771

115

1055

168

(unit: seconds)

Using PBAutoBuild

If using PBAutoBuild to build the solution, after PBAutoBuild downloads source code from Git/SVN, the step of merging the source code into PBLs is eliminated, reducing the time for importing and building by PBAutoBuild.

Note

For faster builds in the solution format, "PowerScript Build" option can be used instead of "Full Build" option, which skips DataWindow recompilation, speeding up the process.

A "PowerScript Build" refers to a build process that skips recompiling DataWindows which can be time-consuming if they have not changed. This can be useful for optimizing build time, especially when DataWindows have not been modified.

You can right click the solution or project in the system tree, and then select "PowerScript Build" from the popup menu.

Direct interoperability with version control

Another benefit of using the solution format is its direct interoperability with version control. In the new solution format, no intermediate file/folder or Pcode are managed in the version control system any more, because source code is stored separately in plain text format.

  • In workspace, both the source code and Pcode are stored together in the PBL file in binary format, and a single PBL file can contain the source code and Pcode for multiple objects. In such case, PowerBuilder has to use some intermediate file/folder (such as ws_objects folder) to export/import the source code from the PBL file in order to track and manage changes at the object level in the version control system. However, this may cause conflicts or corruption during PBL upload/download/merging or Pcode compilation because intermediate file/folder may get out of sync.

  • In solution, source code is stored as individual text files; and each object (such as windows, user objects, functions, and other components) has its own file. Each file can be managed separately and directly in the version control system, without needing to use any intermediate file/folder. Developers can easily track changes to individual files, and avoid conflicts.

  • In addition, in solution, Pcode is stored separately from the source code. This separation makes version control more precisely by reducing the interference of Pcode changes and focusing on only changes to the source code.

The source code structure in the solution format is more compatible with modern version control systems like Git/SVN.

Note

The PBNative and SCC API are not supported with the new solution format.

Optimized workflow with scripts

By using the new solution format, you can also benefit from a more efficient process when working with the script.

  • When editing scripts

    In the solution format, you can perform an incremental build or full build when the object is being edited in the painter window. In the workspace format, you will have to close all of the painter windows before building the application.

  • When saving scripts

    When a script is saved (or when you select Compile or press Ctrl+L), the entire object (not just the script being edited) is automatically compiled.

    The compilation results of the entire object are displayed in the "Output" window (any error/warning will display in the "Errors" or "Warnings" tab respectively), rather than in the message window below the script. And when there are compilation errors, the line number, column number, and error message will be displayed, and you can double click an entry in the "Output" window to jump to that line of code and fix the code in the code editor.

    Changes made to the script are saved directly, regardless of whether the code compiles successfully. In other words, compilation errors or warnings no longer prevent you from saving the associated object, closing the script view, or opening a different script in the same view.

Working with solution

Unsupported features of solution

The solution format and its ultra-fast compiler does not support all of the features that are supported by the workspace format and its standard compiler. For example, the following features are NOT supported in the ultra-fast compiler and solution:

  • PBNative in source control

  • SCC API

  • Machine-code compilation

  • ORCA/OrcaScript compilation

  • PowerServer cursory (ultra-fast) build mode

  • A few PB functions (view more details).

Converting workspace to solution

To create a new solution, you can select the File > New menu, and then click the Workspace tab to select to create a new workspace or solution.

To convert the existing workspace (PBW) to the solution (PBSLN), you can right-click the workspace and then select Convert Workspace to Solution, in which,

  • .pbw will be converted to .pbsln

  • .pbt will be converted to .pbproj

  • PBL file will be converted to PBL folder, and they will have the same name (the file extension ".pbl" will be part of the folder name), for example, if the PBL file name is a.pbl, then the PBL folder is named as "a.pbl". The objects' source code in the PBL file will be split and stored as individual files (in text format) under the PBL folder, and Pcode in the PBL file will be split and stored as individual files (in binary format) under separate folders.

  • .pbw, .pbt, .pbl, and .user.opt files will be backed up to a sub-folder named "BackupFiles" under each file's location. If the .pbl file is located outside the directory of the .pbt file, the .pbl file will be backed up with a .bak suffix in its original location.

    You can remove these BackupFiles folders after converting to solution successfully, or keep these folders in case you want to go back to the workspace.

    The workspace can be converted to the solution, but the solution cannot be converted back to the workspace. To work with the original workspace, you can get files back from these BackupFiles folders or the .bak file.

    Note

    After converting to the solution, the comments of the PBL are stored in the .pblmeta file (each PBL folder has a .pblmeta file), and the comments of objects are stored with the source code.

    Note

    If the application project selects to generate machine code (which is unsupported in the solution), it will be changed to select Pcode automatically after conversion.

After converting to the new solution, all project types (including traditional C/S Application projects, PowerClient projects, and PowerServer projects) can support the ultra-fast compiler.

Before converting the workspace to the solution, you are strongly recommended to:

  • Rename PBLs or objects with the same name to avoid duplication during conversion.

  • Optimize the PBL and then full build the target (PBT).

Note

If the workspace is under source control, you cannot directly convert the workspace to solution (the Convert Workspace to Solution menu is greyed out). You can make a copy of the entire workspace, remove source control from this copy, convert this copy to solution, and then add it (as a branch) to the source control. Notice that the change logs will not be carried over to the new branch unless you manually adjust the repo content.

Importing target (.pbt) or library (.pbl) individually

When converting a workspace to a solution, the target (.pbt) and library file (.pbl) included in the workspace will be automatically converted to the project (.pbproj) and library folder.

After the conversion, you can also import individual target file (.pbt) to the solution, or import individual library file (.pbl) to the project (.pbproj), or import objects from the library file (.pbl) to the library folder.

To import the target (.pbt) files to the solution,

  • Right-click the solution and then select Convert & Add Target.

    The selected target (.pbt) file will be converted to the project (.pbproj) and the library (.pbl) files included in the selected target will be converted to the corresponding library folders.

    If the library (.pbl) file is located under the directory or subdirectory of the selected target (.pbt) file, the original target file and library file will be backed up to the "BackupFiles" sub-folder under the original location.

    If the library (.pbl) file is located outside the directory of the selected target (.pbt) file, the original target file will be backed up to the "BackupFiles" sub-folder under its original location while the library file will be backed up with a .bak suffix in its original location.

To import the library (.pbl) files to the project (.pbproj),

  • Right-click the project (.pbproj) and then select Library List, and in the dialog box select Convert & Add, or right-click the project (.pbproj) and then select Properties, and in the dialog box select Convert & Add.

    The selected library (.pbl) file will be converted to the library folder. The library (.pbl) file will be backed up with a .bak suffix in its original location.

    You can also use Convert & Add to add the PB dynamic library (.pbd) to the library list and reference the PBD file in the application.

To import objects from the library (.pbl) file to the library folder,

  • Right-click the library folder and then select Import From Library.

    The objects will be imported from the selected library file (.pbl) to the current library folder. The library (.pbl) file remains unchanged in its original location.

Working with PBL folder

The biggest difference between a workspace and a solution is their approach to source code management and structure.

PBL folder

In the Workspace format, the source code and Pcode for multiple objects are stored in the same PBL file.

In the Solution format, the PBL file is converted to a folder structure, with each folder containing source code files for multiple objects.

  • The original .pbl file is converted into a folder with the same name. The folder stores the source code for each object (such as .sr* files). This structure is similar to the folder and project structure in modern development environments, where each object has its own representation in the file system.

  • The source code for each object is stored as a separate file. Each PowerBuilder object (such as window, user object, datawindow, etc.) is split into individual source code files, which are stored in text format (usually .sr* files). Each file corresponds to a specific PowerBuilder object and contains its source code. For example, a window object named w_main would have a corresponding w_main.srw (window source code file), instead of storing all object source codes in a single large PBL file.

  • Pcode is stored in a separate directory. The compiled Pcode for each object is stored as a binary file and is kept in its own directory (typically under ".pb" and "build" directories) separate from the source code files.

This approach makes the management of source code and Pcode more independent, allowing the source code to be tracked and updated separately in version control systems, while the Pcode is only generated and stored during the build process and does not need to be managed.

.pb and build folders

The ".pb" folder is used to store intermediate files generated during the compilation process, such as Abstract Syntax Trees (AST) and intermediate Pcode files. During incremental build and save operations, the .pb folder updates only the files that have changed. However, during a full build, the .pb folder is completely regenerated.

All Pcode files are stored in the .pb/xxx/obj directory, which is used for compiling the final Pcode, and the AST files are stored in the .pb/xxx/ast directory.

The "build" folder stores the final Pcode files. The final Pcode files will be loaded when the user edits or runs the object in the IDE.

These two folders will be automatically ignored when the solution is added to Git/SVN in IDE.

Adding a file to the PBL folder

In the solution format, it is unsupported to import objects into PBL via ORCA because ORCA is NOT supported.

To add a file/object to the PBL folder, you must right-click on the PBL folder in the System Tree and use the "Import From Library" option.

Or add the source file such as a .sr* file (which represents the PowerBuilder object) directly to the PBL folder. The object will be shown in the System Tree when PowerBuilder IDE is re-opened.

Reorganizing the PBL folders

If you want to reorganize the PBL folders, for example, moving PBL folders into a new folder called src, make sure the path changes are reflected correctly in both the .pbproj and .pbsln files.

There are two recommended approaches for changing the PBL folder structure:

  • #1: Place the .pbsln, .pbproj, and main PBL folders in one directory, and other PBL folders in the src subdirectory. Update the paths in the .pbproj and .pbsln files accordingly.

  • #2: Place the .pbsln in one directory, and the .pbproj, main PBLs, and other PBL folders inside the src subdirectory. Then, update the paths in the .pbsln file.

There are some general guidelines for the project structure:

  1. Keep the .pbproj file in the same directory as the application's PBL folders: The .pbproj file should be in the same folder as the PBL folders to avoid issues with resolving paths and managing objects.

  2. Use relative paths for images: The path to the image (such as the application icon) should be relative to the location of the .pbproj fie, not the root directory or elsewhere in the project structure.

  3. Check the other folder structures: Ensure that the "build" and ".pb" folders are in the same location as the .pbproj file to avoid issues.

Referencing shared PBL

In the solution format, multiple projects can share the same PBL folder, similar to how PBL files are shared in the workspace format. And changes (such as adding or deleting objects) in one project will be synchronized to the other projects.

However, the best practice is to separate the PBL folder for each project, or generate and reference PBD in the projects.

Referencing PBD file

In the solution format, referencing PBD (PowerBuilder Dynamic Libraries) is supported. To do this, go to the Project Properties, select "Convert & Add," and choose the option to add a PB Dynamic Library (*.pbd). This allows users to include PBD files in their solution, similar to how they were used in the workspace format.

Tip

Referencing PBL file (as an external file) is also supported in the solution format.

Differences in PB functions when using PBL file vs. PBL folder

Due to the change from PBL file to PBL folder in the solution format, some functions will behave differently.

Function

Workspace

Solution

If runs from IDE

If runs as EXE

1) If runs from IDE;

2) Works against external PBL file

1) If runs as EXE;

2) Works against external PBL file

1) If runs from IDE;

2) Works against PBL folder

1) If runs as EXE;

2) Works against PBL folder (This is rare scenario because no one would deploy PBL folders to the client)

AddToLibraryList

No

Yes

No

Yes

No

Yes

GetLibraryList

Yes

Yes

Yes

Yes

Yes

Yes

SetLibraryList

No

Yes

No

Yes

No

Yes

FindClassDefinition

Yes

Yes

Yes

Yes

Yes

No

FindFunctionDefinition

Yes

Yes

Yes

Yes

Yes

No

FindTypeDefinition

Yes

Yes

Yes

Yes

Yes

No

LibraryCreate

Yes

Yes

Yes

Yes

Yes (creates a PBL file not folder)

Yes (creates a PBL file not folder)

LibraryDelete

Yes

Yes

Yes

Yes

Yes

Yes

LibraryDirectory

Yes

Yes

Yes

Yes

Yes

Yes

LibraryDirectoryEx

LibraryExport

Yes

Yes

Yes

Yes

Yes

Yes

LibraryImport

Yes

Yes

Yes

Yes

Yes

Yes

Unsupported: FindGroup, FindClass, FindMatchingFunction, CreateSession, and RunApplication

You can use the system function IsRunningAsSolution to implement conditional logic depending on whether the application is running as a solution or workspace. For example, if certain functions are only applicable in one format, you can write code to handle the differences appropriately.

Source files in UTF-8 encoding

The source files generated during migration to the solution and the .pbsln/.pbproj/.pblmeta files are encoded using UTF-8 instead of the Unicode 16LE encoding. UTF-8 was chosen because the compiler only supports this encoding format and it is more space-efficient.

You can use the Import/Export option to transfer source files between UTF-8 and Unicode 16LE encodings.

You can specify whether UTF-8 includes BOM or not in the PB.INI file:

[library]
DefaultEncoding=64 // 4 (default) indicates UTF-8 with BOM, 64 indicates UTF-8 without BOM, other values will be processed as 4.

Version control

PBNative and SCC API are not supported

The PBNative and SCC API are not supported with the new solution format. Users who wish to continue using PBNative must stick with the workspace format. Although transition to Git/SVN and the solution format is encouraged, users who prefer to use PBLs with PBNative can still do so.

Add to version control

If the workspace is under version control, you cannot directly convert the workspace to solution (the "Convert Workspace to Solution" menu is grayed out). You can make a copy of the entire workspace, remove version control from this copy, convert this copy to solution, and then add it (as a branch) to the version control. Notice that the change logs will not be carried over to the new branch unless you manually adjust the repo content.

When adding a solution to the version control, the following files and folders need to be uploaded:

  • Source code files such as .sr* in the PBL folder, .bin (for OLE object), .ini, images, theme, etc.

  • Solution and project configuration files and files related to the structure of the solution and project such as .pbsln, .pbproj, .pblmeta, etc.

The following files/folders will be ignored automatically:

  • ".pb" folder

  • "build" folder

The following folders and menus are not needed any more (they are required only in the workspace):

  • ws_objects folder

  • "Upload PBL" and "Refresh" right-click menus

Troubleshooting tips

Error: "Fatal C0247: Exception occurred while generating Pcode"

Each project in a solution has an independent syntax tree and Pcode; each time when the project is opened, it will check whether the Pcode and source code match with each other. When a mismatch is detected, it prompts for a "Request Compilation." This is expected behavior, but when incremental builds are performed, it may lead to errors, such as C0247, due to exceptions during Pcode generation.

The C0247 error typically occurs during Pcode generation, and it is common in incremental builds when there are mismatches between the code and the compiled data. This error does not appear in full builds because full builds regenerate everything, ensuring consistency between the source code and Pcode.

Database connection popping up multiple times during full build

During the full build process, multiple PBCC.exe processes may start simultaneously due to support for multi-threading. These processes run independently; and when they execute SQL queries, they will each need to connect to the database. This leads to the data connection window popping up multiple times, and developers have to enter the connection information repeatedly to continue the build process.

This behavior occurs because of concurrent compilation. Developers can reduce the connection windows by selecting the "Disable database connection when compiling and building" option from the Tools menu > System Options menu > General tab.