Skip to content

Commit

Permalink
Use WiX 5 (#66)
Browse files Browse the repository at this point in the history
* Make product code automatically random

Instead of externally generating it and using it explicitly.

* Componentize the merge module

This prevents upgrades from leaving files from the previous version
behind that are not in the new version.

* Configure drivers on x64 The Way It Should Be Done

Use the ODBCDriver element only, without additional Registry settings.
This works, although it does not solve the file name issue and therefore
still requires removing the short file names from the File table.

It also works for installing the x86 driver on an x64 system. Whether it
works on an x86 system remains unknown.

* Configure drivers on x86 In The Exact Same Way

Tested on Windows 10 x86; the driver installs correctly and works
at first glance (in Access, to be precise). Registry and file system
look good.

The comment saying it "probably would be safe" is probably correct.

* Use candle's -arch option to select build platform

According to docs, using Package/@platform "is discouraged". The -arch
option also provides the default bitness for components, making the
Component/@win64 attribute unnecessary in single-architecture packages.

* Reindent

* Save some attributes

* Replace upgrade logic with MajorUpgrade element

This element compiles into approximately the same entries in the
Upgrade, CustomAction, and InstallExecuteSequence tables.

* Remove unused GUID

I think this was the product code, a long time ago.

* Make MSI file smaller

By about 20 percent.

* Better select where to remove short file names

Use the FileName column itself instead of the file ID. This is less
susceptible to changes in file IDs (and component IDs) that may happen
when relying more on default behaviors in future WiX versions.

* Build with WiX 5

This is a preview. It appears to build a working x64 installer; I have
tested nothing else yet.

* Clean up modify_msi.vbs

Also, put blame where it belongs, which is Windows Installer. If this
was a bug in WiX, then the fix would be to enforce 8.3 file names for
ODBC drivers, and we wouldn't like that very much either, would we?

* Increase WiX-5-ness

- Remove most Component elements in favor of naked files
- Replace PGFOLDER variable with ProgramFiles6432Folder

The Condition element on Component has become an attribute in WiX 5, and
the combination of preprocessor and component condition (i.e. include
a non-x64 condition only in a non-x64 package) to install PGXA only from
a package native to the underlying OS does not work anymore. Replace it
with a pure component condition that includes the package architecture.

The Template summary property has this information already, but it is
not available from within the installation, and I'm not about to start
writing custom actions.

* Update build workflow for WiX 5
  • Loading branch information
chrullrich authored Oct 14, 2024
1 parent 62ef077 commit 7da4711
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 300 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,12 @@ jobs:
with:
arch: x86

- name: Install WiX
shell: cmd
run: |
dotnet tool install --global wix
wix extension add --global WixToolset.UI.wixext
- name: build psqlodbc standard
shell: powershell
working-directory: psqlodbc
Expand Down
12 changes: 8 additions & 4 deletions installer/README.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
This directory contains the psqlODBC installer for Windows. To build the
installer, you will need a copy of WiX installed somewhere in your system
path. The installer has been tested with WiX version 3.0.2420 and WiX 3.8 at
the time writing.
installer, you will need a copy of WiX installed. The installer has been
tested with WiX version 5.0.2 at the time of writing.

WiX may be downloaded from:

http://wix.codeplex.com/
http://wixtoolset.org/

In addition to the base package, the UI extension is required:

dotnet tool install --global wix
wix extension add --global WixToolset.UI.wixext


HOW TO BUILD
Expand Down
21 changes: 3 additions & 18 deletions installer/buildInstallers.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -256,46 +256,31 @@ function buildInstaller([string]$CPUTYPE)

[string []]$libpqRelArgs=@()
for ($i=0; $i -lt $maxmem; $i++) {
$libpqRelArgs += ("-dLIBPQMEM$i=" + $libpqmem[$i])
$libpqRelArgs += "-d", ("LIBPQMEM$i=" + $libpqmem[$i])
}

if (-not(Test-Path -Path $CPUTYPE)) {
New-Item -ItemType directory -Path $CPUTYPE | Out-Null
}

$PRODUCTCODE = [GUID]::NewGuid()
Write-Host "PRODUCTCODE: $PRODUCTCODE"

try {
pushd "$scriptPath"

Write-Host ".`nBuilding psqlODBC/$SUBLOC merge module..."
$BINBASE = GetObjbase ".."
$INSTBASE = GetObjbase ".\$CPUTYPE" "installer\$CPUTYPE"
candle -nologo $libpqRelArgs "-dPlatform=$CPUTYPE" "-dVERSION=$VERSION" "-dSUBLOC=$SUBLOC" "-dLIBPQBINDIR=$LIBPQBINDIR" "-dLIBPQMSVCDLL=$LIBPQMSVCDLL" "-dLIBPQMSVCSYS=$LIBPQMSVCSYS" "-dPODBCMSVCDLL=$PODBCMSVCDLL" "-dPODBCMSVPDLL=$PODBCMSVPDLL" "-dPODBCMSVCSYS=$PODBCMSVCSYS" "-dPODBCMSVPSYS=$PODBCMSVPSYS" "-dNoPDB=$NoPDB" "-dBINBASE=$BINBASE" -o $INSTBASE\psqlodbcm.wixobj psqlodbcm_cpu.wxs
wix build --nologo -arch $CPUTYPE $libpqRelArgs -d "VERSION=$VERSION" -d "SUBLOC=$SUBLOC" -d "LIBPQBINDIR=$LIBPQBINDIR" -d "LIBPQMSVCDLL=$LIBPQMSVCDLL" -d "LIBPQMSVCSYS=$LIBPQMSVCSYS" -d "PODBCMSVCDLL=$PODBCMSVCDLL" -d "PODBCMSVPDLL=$PODBCMSVPDLL" -d "PODBCMSVCSYS=$PODBCMSVCSYS" -d "PODBCMSVPSYS=$PODBCMSVPSYS" -d "NoPDB=$NoPDB" -d "BINBASE=$BINBASE" -o $INSTBASE\psqlodbc_$CPUTYPE.msm psqlodbcm_cpu.wxs
if ($LASTEXITCODE -ne 0) {
throw "Failed to build merge module"
}

Write-Host ".`nLinking psqlODBC merge module..."
light -sval -nologo -o $INSTBASE\psqlodbc_$CPUTYPE.msm $INSTBASE\psqlodbcm.wixobj
if ($LASTEXITCODE -ne 0) {
throw "Failed to link merge module"
}

Write-Host ".`nBuilding psqlODBC installer database..."

candle -nologo "-dPlatform=$CPUTYPE" "-dVERSION=$VERSION" "-dSUBLOC=$SUBLOC" "-dPRODUCTCODE=$PRODUCTCODE" "-dINSTBASE=$INSTBASE" -o $INSTBASE\psqlodbc.wixobj psqlodbc_cpu.wxs
wix build --nologo -arch $CPUTYPE -ext WixToolset.UI.wixext -d "VERSION=$VERSION" -d "SUBLOC=$SUBLOC" -d "INSTBASE=$INSTBASE" -o $INSTBASE\psqlodbc_$CPUTYPE.msi psqlodbc_cpu.wxs
if ($LASTEXITCODE -ne 0) {
throw "Failed to build installer database"
}

Write-Host ".`nLinking psqlODBC installer database..."
light -sval -nologo -ext WixUIExtension -cultures:en-us -o $INSTBASE\psqlodbc_$CPUTYPE.msi $INSTBASE\psqlodbc.wixobj
if ($LASTEXITCODE -ne 0) {
throw "Failed to link installer database"
}

Write-Host ".`nModifying psqlODBC installer database..."
cscript modify_msi.vbs $INSTBASE\psqlodbc_$CPUTYPE.msi
if ($LASTEXITCODE -ne 0) {
Expand Down
54 changes: 26 additions & 28 deletions installer/modify_msi.vbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,51 @@
' When the dll name of the driver is not of 8.3-format
' the modification of the FileName is needed
'
' This is to work-around a bug in the WiX Toolset, see
' This is to work-around an oversight in Windows Installer, see
' http://wixtoolset.org/issues/1422/
'
' We remove the short name from the filename field in the File-table
' of the two DLLs that need to be registered as ODBC drivers. Strictly
' speaking, that makes the contents of the table invalid, because a short
' name is mandatory, but Windows Installer seems nevertheless install it
' just fine.
'
option Explicit

Const msiOpenDatabaseModeTransact = 1
Option Explicit

Const msiOpenDatabaseModeTransact = 1
Const msiViewModifyInsert = 1
Const msiViewModifyUpdate = 2
Const query = "SELECT * FROM File"

Dim msiPath : msiPath = Wscript.Arguments(0)
Dim installer, database
Dim view, record
Dim pos, filename

Dim installer
Set installer = Wscript.CreateObject("WindowsInstaller.Installer")
Dim database
Set database = installer.OpenDatabase(msiPath, msiOpenDatabaseModeTransact)

Dim query
query = "Select * FROM File"
Dim view
Set database = installer.OpenDatabase(WScript.Arguments(0), _
msiOpenDatabaseModeTransact)
Set view = database.OpenView(query)
view.Execute
Dim record

Set record = view.Fetch
Dim gFile, pos
Do While not record Is Nothing
gFile = record.StringData(1)
If Left(gFile, 8) = "psqlodbc" Then
gFile = record.StringData(3)
' Check if the FileName field is ShortName|LongName
pos = InStr(record.StringData(3), "|")
If pos > 0 Then
' Omit the ShortName part
gFile = Mid(record.StringData(3), pos + 1)
WScript.echo record.StringData(3) & " -> " & gFile
' And update the field
record.StringData(3) = gFile
Do While Not record Is Nothing

filename = record.StringData(3)
pos = InStr(filename, "|psqlodbc")

If (pos > 0) Then

' Remove the ShortName part
filename = Mid(filename, pos + 1)
WScript.echo record.StringData(3) & " -> " & filename

record.StringData(3) = filename
view.Modify msiViewModifyUpdate, record

End If
End If
Set record = view.Fetch

Set record = view.Fetch

Loop

database.Commit
173 changes: 65 additions & 108 deletions installer/psqlodbc_cpu.wxs
Original file line number Diff line number Diff line change
@@ -1,107 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">

<!-- Default to x86 platform -->
<?ifndef var.Platform ?>
<?define Platform = "x86" ?>
<?else?>
<?if $(var.Platform) != x64 and $(var.Platform) != x86 ?>
<?error Invalid Platform variable ?>
<?endif?>
<?endif?>

<?ifndef var.INSTBASE ?>
<?define INSTBASE = $(var.Platform) ?>
<?endif?>

<?if $(var.Platform) = x64 ?>
<?if $(sys.BUILDARCH) = x64 ?>
<?define Platform = "x64" ?>
<?define PKGNAME = "psqlODBC_x64" ?>
<?define BIT64 = "yes" ?>
<?define PGFOLDER = "ProgramFiles64Folder" ?>
<?define PRODID = "3E42F836-9204-4c42-B3C3-8680A0434875" ?>
<?define CIDREG = "4D361F28-8F75-4c86-9A37-6C279967413D" ?>
<?define CIDDOC = "0C745A85-4E55-4bab-BBF1-DCF51D92FCC5" ?>
<?define CIDSMD = "{E6410EE8-96DC-4d84-8D07-94F8093BF3EF}" ?>
<?define UPGCOD = "BBD29DF5-89F6-4b8b-BDC9-C3EA3A4AFDBB" ?>
<?define ALLUSERS = "1" ?>
<?else?>
<?elseif $(sys.BUILDARCH) = x86 ?>
<?define Platform = "x86" ?>
<?define PKGNAME = "psqlODBC" ?>
<?define BIT64 = "no" ?>
<?define PGFOLDER = "ProgramFilesFolder" ?>
<?define PRODID = "838E187D-8B7A-473d-B93C-C8E970B15D2B" ?>
<?define CIDREG = "4F0C04EB-ADCB-4fa8-B6A3-E9F74EA693F8" ?>
<?define CIDDOC = "89DDBC52-9F0D-4846-91DC-09EECC87E42E" ?>
<?define CIDSMD = "{22288E09-B3B6-4181-907F-676099C20125}" ?>
<?define UPGCOD = "24BCA538-75A2-4a7f-B236-C99EFC2145DE" ?>
<?define ALLUSERS = "1" ?>
<?else?><!-- sys.BUILDARCH -->
<?error Invalid build architecture ?>
<?endif?>

<?ifndef var.INSTBASE ?>
<?define INSTBASE = $(Platform) ?>
<?endif?>

<?define MERGEM = "$(var.INSTBASE)\psqlodbc_$(var.Platform).msm" ?>
<?define MERGEM = "$(INSTBASE)\psqlodbc_$(Platform).msm" ?>

<!-- Product details -->

<Product
<Package
Manufacturer="PostgreSQL Global Development Group"
Id="$(var.PRODUCTCODE)"
UpgradeCode="$(var.UPGCOD)"
Name="$(var.PKGNAME)"
Version="$(var.VERSION)"
UpgradeCode="$(UPGCOD)"
Name="$(PKGNAME)"
Version="$(VERSION)"
Codepage="1252"
InstallerVersion="300"
Compressed="yes"
Language="1033">

<!-- Package details -->

<Package
<SummaryInformation
Codepage="1252"
Keywords="PostgreSQL, ODBC"
Comments="PostgreSQL ODBC Driver"
Manufacturer="PostgreSQL Global Development Group"
InstallerVersion="300"
Platform="$(var.Platform)"
Languages="1033"
Compressed="yes"
SummaryCodepage="1252" />
Comments="PostgreSQL ODBC Driver" />

<!-- Directories -->

<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="$(var.PGFOLDER)" Name="PFiles">
<Directory Id="BASEDIR" Name="psqlODBC">
<Directory Id="SUBLOC" Name="$(var.SUBLOC)">
<Directory Id="BINDIR" Name="bin">
<Component Id="registration" Guid="$(var.CIDREG)" Win64="$(var.BIT64)">
<RegistryValue KeyPath="yes" Type="string" Root="HKLM" Key="Software\$(var.PKGNAME)" Name="Version" Value="$(var.VERSION)" />
</Component>
<Merge Id="psqlodbcm" DiskId="1" Language="1033" SourceFile="$(var.MERGEM)" />
</Directory>
<Directory Id="DOCSDIR" Name="docs">
<Component Id="docs" Guid="$(var.CIDDOC)" Win64="$(var.BIT64)">
<File Id="docs.README.txt" Name="README.txt" DiskId="1" Source="../docs/README.txt" KeyPath="yes" />
<File Id="docs.config.html" Name="config.html" DiskId="1" Source="../docs/config.html" />
<File Id="docs.config_opt.html" Name="config-opt.html" DiskId="1" Source="../docs/config-opt.html" />
<File Id="docs.release.html" Name="release.html" DiskId="1" Source="../docs/release.html" />
<File Id="docs.release_7.3.html" Name="release-7.3.html" DiskId="1" Source="../docs/release-7.3.html" />
<File Id="docs.unix_compilation.html" Name="unix-compilation.html" DiskId="1" Source="../docs/unix-compilation.html" />
<File Id="docs.win32_compilation.html" Name="win32-compilation.html" DiskId="1" Source="../docs/win32-compilation.html" />
<File Id="docs.editConfiguration.jpg" Name="editConfiguration.jpg" DiskId="1" Source="../docs/editConfiguration.jpg" />

<!-- <Shortcut Id="docs.index.html" Directory="SMDir" Name="Documentation index" Description="psqlODBC documentation, HOWTOs and FAQs" Advertise="yes" Show="normal" /> -->
</Component>
</Directory>
<StandardDirectory Id="ProgramFiles6432Folder">
<Directory Id="BASEDIR" Name="psqlODBC">
<Directory Id="SUBLOC" Name="$(SUBLOC)">
<Directory Id="BINDIR" Name="bin">
<Component Id="registration" Guid="$(CIDREG)">
<RegistryValue KeyPath="yes" Type="string" Root="HKLM" Key="Software\$(PKGNAME)" Name="Version" Value="$(VERSION)" />
</Component>
<Merge Id="psqlodbcm" DiskId="1" Language="1033" SourceFile="$(MERGEM)" />
</Directory>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder" Name="." SourceName="Programs">
<Directory Id="SMDir" Name="$(var.PKGNAME)">
<Component Id="smdir" Guid="$(var.CIDSMD)" Win64="$(var.BIT64)">
<RegistryValue KeyPath="yes" Type="string" Root="HKCU" Key="Software\$(var.PKGNAME)\SMDir Created" Value="y" />
<RemoveFolder Id="SMDir" On="uninstall" />
<Directory Id="DOCSDIR" Name="docs" FileSource="../docs">
<Component Id="docs" Guid="$(CIDDOC)">
<File Name="README.txt" KeyPath="yes" />
<File Name="config.html" />
<File Name="config-opt.html" />
<File Name="release.html" />
<File Name="release-7.3.html" />
<File Name="unix-compilation.html" />
<File Name="win32-compilation.html" />
<File Name="editConfiguration.jpg" />

<!-- <Shortcut Id="docs.index.html" Directory="SMDir" Name="Documentation index" Description="psqlODBC documentation, HOWTOs and FAQs" Advertise="yes" Show="normal" /> -->
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
</StandardDirectory>
<StandardDirectory Id="ProgramMenuFolder">
<Directory Id="SMDir" Name="$(PKGNAME)">
<Component Id="smdir" Guid="$(CIDSMD)">
<RegistryValue KeyPath="yes" Type="string" Root="HKCU" Key="Software\$(PKGNAME)\SMDir Created" Value="y" />
<RemoveFolder Id="SMDir" On="uninstall" />
</Component>
</Directory>
</StandardDirectory>

<!-- Features -->

<Feature Id="psqlodbc" Title="$(var.PKGNAME)" Level="1" Description="psqlODBC - The PostgreSQL ODBC Driver" ConfigurableDirectory="BASEDIR" Display="expand">
<Feature Id="psqlodbc" Title="$(PKGNAME)" Level="1" Description="psqlODBC - The PostgreSQL ODBC Driver" ConfigurableDirectory="BASEDIR" Display="expand">
<Feature Id="binaries" Title="ODBC Driver" Level="1" Description="The ODBC driver and supporting libraries.">
<ComponentRef Id="registration" />
<MergeRef Id="psqlodbcm" />
Expand All @@ -113,47 +98,19 @@
</Feature>

</Feature>
<Media Id="1" EmbedCab="yes" Cabinet="psqlodbc.cab"/>

<!-- Properties -->

<Property Id="ALLUSERS">$(var.ALLUSERS)</Property>
<Property Id="WIXUI_INSTALLDIR" Value="BASEDIR" />
<Media Id="1" EmbedCab="yes" Cabinet="psqlodbc.cab" CompressionLevel="high"/>

<!-- UI -->

<UIRef Id="WixUI_FeatureTree" />
<WixVariable Id="WixUILicenseRtf" Value="lgpl.rtf" />
<WixVariable Id="WixUIDialogBmp" Value="background.bmp" />
<WixVariable Id="WixUIBannerBmp" Value="banner.bmp" />
<ui:WixUI Id="WixUI_FeatureTree" InstallDirectory="BASEDIR" />
<WixVariable Id="WixUILicenseRtf" Value="lgpl.rtf" />
<WixVariable Id="WixUIDialogBmp" Value="background.bmp" />
<WixVariable Id="WixUIBannerBmp" Value="banner.bmp" />

<!-- Upgrade -->
<Upgrade Id="$(var.UPGCOD)">
<UpgradeVersion OnlyDetect='yes' Property='SELFFOUND'
Minimum="$(var.VERSION)" IncludeMinimum='yes'
Maximum="$(var.VERSION)" IncludeMaximum='yes' />
<UpgradeVersion OnlyDetect='yes' Property='NEWERFOUND'
Minimum="$(var.VERSION)" IncludeMinimum='no' />
<UpgradeVersion OnlyDetect='no' Property='UPGRADEFOUND'
Minimum='8.3.0' IncludeMinimum='yes'
Maximum="$(var.VERSION)" IncludeMaximum='no' />
</Upgrade>

<CustomAction Id='AlreadyUpdated'
Error="the same version of [ProductName] is already installed" />
<CustomAction Id='NoDowngrade'
Error="a new version of [ProductName] is already installed" />
<CustomAction Id='NoMinorUpgrade'
Error="REINSTALL unavailable. Major upgrade is needed." />
<CustomAction Id='NoReinstall'
Error="REINSTALL unavailable. Install the package first." />

<InstallExecuteSequence>
<Custom Action='AlreadyUpdated' After='FindRelatedProducts'>SELFFOUND AND NOT Installed</Custom>
<Custom Action='NoDowngrade' After='FindRelatedProducts'>NEWERFOUND AND NOT Installed</Custom>
<Custom Action='NoReinstall' Before='ValidateProductID'>REINSTALLMODE AND NOT Installed</Custom>
<Custom Action='NoMinorUpgrade' After='FindRelatedProducts'>UPGRADEFOUND AND REINSTALLMODE</Custom>
<RemoveExistingProducts After='InstallFinalize'>UPGRADEFOUND AND NOT Installed</RemoveExistingProducts>
</InstallExecuteSequence>
</Product>
</Wix>

<MajorUpgrade
DowngradeErrorMessage="A newer version of [ProductName] is already installed"
Schedule="afterInstallInitialize" />
</Package>
</Wix>
Loading

0 comments on commit 7da4711

Please sign in to comment.