Skip to content
pb-diff Help

Project and build files

A PowerBuilder application is more than its objects. Beside the libraries sit the files that say what the application is made of and what goes into a build: which targets a workspace or a Solution opens, which libraries each target searches and in what order, which resources the executable carries. They are short text files nobody reads until a build goes wrong, and a change to one of them changes the application as surely as a change to a script, without touching a single object. pb-diff reads each of them into the parts a build depends on, so a comparison of two releases shows those changes by name, beside the objects.

File What it is for What pb-diff compares
Workspace .pbw The targets the PowerBuilder IDE opens together, and the one it builds by default Each target, and each setting
Target .pbt One application: its application object, its library search path and the projects that build it The library list library by library, each project, each setting
Solution .pbsln PowerBuilder 2025: the projects a Solution holds - its workspace Each project
Project .pbproj PowerBuilder 2025: one application - its target The library list library by library, each deploy configuration, each setting
Resource file .pbr The pictures, icons and DataWindow objects a build copies into the executable or a PBD Each resource, grouped by kind
PowerGen project .gen E. Crane Computing's PowerGen: the applications it builds, each with its executable, its library list and how each library is built Each application, its settings and its library list (best-effort)

All of them are taken from a folder with the objects beside them: add an application's folder to a File Selection, or name two release folders to pb-diff.exe, and they are listed in the summary with the libraries and exports. Each can also be compared on its own, from New Comparison, the command line or a source-control client, and merged.

Here are two releases of Order Desk's application folder side by side. The library is compared object by object, and beside its objects are the workspace, the target, the resource file and the tools target release 1.5 added:

The pb-diff Compare Summary of two folders, application release 1.4 as Old and release 1.5 as New, showing only changed items. The rows include order_desk.gen, order_desk.pbw, order_desk.pbt and order_desk.pbr marked modified and order_tools.pbt marked new, beside the objects of orders.pbl that changed: windows, user objects, the menu and the DataWindow marked modified, n_invoice_export.sru new and w_print_preview.srw deleted.
The Order Desk application folder of release 1.4 against release 1.5: the workspace, the target, the resource file, the PowerGen project and a new tools target are listed with the objects of the library beside them, so a release compare shows what changed in the build as well as in the code. Select the image to view it at full size.

A merge keeps the file as its tools write it. An object export is saved in UTF-16LE, the form the Library painter imports. These files are not imported: PowerBuilder and the build tools read them where they lie, and write them in ANSI. A merged build file is therefore saved in the encoding it was read in, with its own line endings, and a merge that decided nothing gives back the file byte for byte.

Workspaces (.pbw)

What it is for. A workspace is what the PowerBuilder IDE opens with its Open Workspace command: the list of targets shown in the System Tree, which of them is built by default, and how the IDE exports objects for source control. PowerBuilder writes it as text in what its first line calls Save Format:

Save Format v3.0(19990112)
@begin Targets
 0 "src\\order_desk.pbt";
 1 "tools\\order_tools.pbt";
@end;
DefaultTarget "src\\order_desk.pbt";

What a change does. A target added or removed is an application the team now builds, or no longer builds, from that workspace. A changed default target changes what Deploy and Run act on, and a changed export encoding (DefaultExportEncode) changes how every object is written to source control from then on, which shows as every object changing at the next commit.

What pb-diff shows. Each target is a node under Targets, named by its path, and each setting is a node named for what it holds, such as Default target (DefaultTarget). The number in front of a target is only its place in the System Tree, and PowerBuilder rewrites it: a target is identified by its path, so one whose number changed is the same target, modified, not one deleted and one added.

pb-diff-cli compare application/release-1.4/order_desk.pbw application/release-1.5/order_desk.pbw --format json

(result)

Targets (.pbt)

What it is for. A target is one application in a workspace: the application object and the library it is in (appname, applib), the library list (LibList), and the project objects that build it. The library list is the library search path: when an object is referenced, PowerBuilder looks for it in these libraries in this order and takes the first it finds.

What a change does. The target decides which code the application is made of:

What pb-diff shows. Each setting is a node, named for what it holds. The Library list is one setting with each library beneath it, so a library added or removed is named. A library moved is the list modified with no library added or removed beneath it, and the line shows the order that changed. Each project is a node named by the project and its library, such as p_order_desk (orders.pbl).

In Order Desk, release 1.5 adds invoicing.pbl to the search path:

pb-diff comparing two versions of the target order_desk.pbt. The tree shows the Library list (LibList) setting marked modified, expanded to its libraries, with invoicing.pbl marked new. The setting is selected, and the panes show the old and new LibList lines, the new one with invoicing.pbl marked between orders.pbl and the shared PFC library.
Order Desk's target in release 1.5 adds invoicing.pbl to the library search path. The library list is one setting, modified, with each library beneath it; the library added is named, and the line marks it. Select the image to view it at full size.
pb-diff-cli compare application/release-1.4/src/order_desk.pbt application/release-1.5/src/order_desk.pbt --format json

(result)

Merging a workspace or a target. Each target, project and setting is a unit a merge takes or leaves, so two developers who each added a target to a workspace merge cleanly. The library list is taken or left whole, because its order is its meaning: two developers who each changed it meet in a conflict, and the person merging decides the order.

A workspace or a target is compared as a file. Opening one does not compare the libraries it names: add those libraries, or the folder that holds them, to compare the objects. Named after @ on a command line, a workspace or a target is refused, because it is not a list of arguments.

PowerBuilder 2025 Solutions and projects (.pbsln, .pbproj)

What they are for. A PowerBuilder 2025 Solution is the new form of a workspace: Convert Workspace to Solution turns the .pbw into a .pbsln and each .pbt into a .pbproj. They hold what the workspace and the targets held, written as XML:

What a change does. The same as for a workspace and a target: a project added or removed is an application built or no longer built; a library added, removed or moved changes which code the application is made of and which object it finds first; a deploy configuration added or removed changes what a build produces. Appeon's guidance for moving PBL folders is to update the paths in both the .pbproj and the .pbsln, which is the kind of change worth reviewing before a commit.

What pb-diff shows. Each project of a solution is a node under Projects, named by its path; the Projects node itself shows the default project. A project's settings are nodes, each deploy configuration is a node named with its project object, and the Library list is one node with the application library and each library beneath it. The list is compared line by line: every element with all its attributes, and every comment, so only an element's spacing is not a change. A library moved is the list modified with every library beneath it unchanged: in Order Desk, Solution release 1.6 searches the shared PFC library before invoicing.pbl, and builds through a new deploy configuration:

pb-diff comparing two versions of the PowerBuilder 2025 project order_desk.pbproj. The tree shows the Deploy configurations node marked new and the Library list (Libraries) node marked modified; the library list is selected, and the panes show its lines, with invoicing.pbl and the shared PFC library in swapped places.
Order Desk's project in Solution release 1.6 builds through a deploy configuration and searches the shared PFC library before invoicing.pbl. No library was added or removed, so the library list is modified with every library unchanged beneath it: the order changed, and with it which object the application finds first. Select the image to view it at full size.
pb-diff-cli compare solution/release-1.5/order_desk.pbproj solution/release-1.6/order_desk.pbproj --format json

(result)

Merging. Projects, settings and deploy configurations are units a merge takes or leaves, and the library list is taken or left whole, as for a target. A merged solution or project stays UTF-8, with its byte-order mark or without one exactly as it was, and every line the merge did not decide is copied, so the result opens and builds in PowerBuilder 2025. Being a PowerBuilder 2025 file, it is certified with the Solution's sources (see PowerBuilder 2025 Solutions).

Resource files (.pbr)

What it is for. When PowerBuilder builds an executable or a dynamic library (PBD or DLL), it copies in the pictures and icons the objects name in their properties. It cannot see the ones a script assigns at run time, p_logo.PictureName = "logo.bmp", nor a DataWindow object assigned only through a string, dw_1.DataObject = ls_name. A resource file lists them: one per line, a file name with the path the script uses, or a DataWindow object written as its library followed by the object in parentheses, orders.pbl(d_order_lines). The Project painter attaches one to the executable and one to each dynamic library, and PowerGen names one for each library it builds.

What a change does. The PBR decides what the delivered application carries:

What pb-diff shows. Each line is a resource node, grouped as DataWindow objects, Pictures, Icons, Pointers and Other resources. A DataWindow object is named by the object and then its library, d_order_lines (orders.pbl). The order of the lines means nothing to PowerBuilder, so a reordered PBR compares identical, and blank lines and the blanks around a name are ignored. A name whose case changed is paired with its other spelling and reported modified, with the letters that changed marked.

In Order Desk, release 1.5 dropped the print preview window and its picture, added an Export invoices picture for the new menu item, and retyped customer.bmp with a capital C. The tree shows one picture deleted, one new and one modified:

pb-diff comparing two versions of the resource file order_desk.pbr. With Only Changed Items on, the tree shows the Pictures group alone: Customer.bmp marked modified, print_preview.bmp deleted and export_invoices.png new. Customer.bmp is selected, and the panes show the old line with customer in lower case and the new line with Customer capitalised, the name marked on both sides.
Order Desk's resource file in release 1.5 drops the print preview picture, adds the export invoices picture and spells customer.bmp with a capital C. Each resource is a node, grouped by kind; the case-only change is reported, because PowerBuilder finds a resource by its name as written. Select the image to view it at full size.
pb-diff-cli compare application/release-1.4/src/order_desk.pbr application/release-1.5/src/order_desk.pbr --format json

(result)

Merging. Each resource is a unit a merge takes or leaves: restore a deleted resource in a two-way merge, or let a three-way merge carry the resources each developer added into the Base.

PowerGen projects (.gen)

PowerGen, by E. Crane Computing, is a tool many PowerBuilder teams build their applications with. It is not part of PowerBuilder, and pb-diff reads its files best-effort: they are compared and merged, and they are not part of what pb-diff certifies. pb-diff never runs PowerGen.

What it is for. A PowerGen project lists the applications PowerGen builds, in the order it builds them. For each one it holds the application library, the executable to write and how, the icon and the resource file, where the PBDs or DLLs go, and the library list: one $Library line per library, saying whether the library is regenerated, whether its objects go into the executable, a PBD or a DLL, and which resource file it is built with. The format is documented in PowerGen's own help, under Understanding Project files:

$PowerGenVersion=17
$ApplicationName="order_desk",0,0,0,0,0,1707259592,1,0,1
$EXEPath=".\order_desk.exe","",1,1,"","",""
$Library=".\orders.pbl","",0,0,0,""
$Library=".\invoicing.pbl","",0,2,0,""

What a change does. The PowerGen project decides what the build delivers: a library moved from the executable into a PBD is a new file to install, a library added or removed changes the code of the application, a library moved in the list changes which object the application finds first, and the runtime named in the header is the PowerBuilder runtime every user needs.

What pb-diff shows. Each application is a node, with each setting beneath it, named as PowerGen's help names it, such as Executable ($EXEPath), and its Library list. Each library beneath the list is named by its path and, from the two fields the help documents, where its objects go and its resource file: .\invoicing.pbl (PBD). A library whose build options changed is that library modified, and a library moved is the list modified with no library added or removed. Other fields, which later versions of the format add, are compared as written and not named.

A PowerGen project must open with its $PowerGenVersion= line. A file called .gen that does not is not one, and a PowerGen project saved under another name - a target's .pbt, say - is not read as PowerGen: see When a file is not what its name says.

In Order Desk, release 1.5 builds with the PowerBuilder 2025 runtime and adds invoicing.pbl, built into a PBD:

pb-diff comparing two versions of the PowerGen project order_desk.gen. The tree shows the Project ($ProjectName) setting marked modified and, under Application order_desk, the Library list ($Library) marked modified, expanded to the new library invoicing.pbl (PBD). The library list is selected, and the New pane shows the added $Library line for invoicing.pbl in green.
Order Desk's PowerGen project in release 1.5 builds with the PowerBuilder 2025 runtime and adds invoicing.pbl to the library list, built into a PBD. Each application is a node, with its settings and its library list beneath it; each library is named with where its objects go. Select the image to view it at full size.
pb-diff-cli compare application/release-1.4/src/order_desk.gen application/release-1.5/src/order_desk.gen --format json

(result)

Merging. Applications and settings are units a merge takes or leaves, so an application one side added arrives whole, and the library list of an application is taken or left whole, as for a target. A merged project is written in the encoding PowerGen wrote it in.

When a file is not what its name says

pb-diff reads a file as the format its extension names, and never guesses another one from its content. A file whose content is not that format is reported, not quietly read as something else:

Each format is checked on what it must open with: a workspace or a target on its Save Format line, a PowerGen project on its $PowerGenVersion= line, a Solution on its root <Solution>, a project on its root <Project> holding <Type Name="pb"/>, and an export on its $PBExportHeader$ line. A file whose name says nothing at all, such as the temporary files Git hands a diff tool, is the one case where pb-diff reads the content to tell what it is.