Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Add manual MSI packaging documentation using WiX Toolset #153

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion app.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import streamlit as st
from pathlib import Path
import json
# For some reason the windows version only works if this is imported here
import pyopenms

if "settings" not in st.session_state:
with open("settings.json", "r") as f:
st.session_state.settings = json.load(f)

if __name__ == '__main__':
pages = {
"OpenMS Web App" : [
str(st.session_state.settings["app-name"]) : [
st.Page(Path("content", "quickstart.py"), title="Quickstart", icon="👋"),
st.Page(Path("content", "documentation.py"), title="Documentation", icon="📖"),
],
Expand Down
261 changes: 214 additions & 47 deletions docs/win_exe_with_embed_py.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,51 @@ Here's a step-by-step guide:

1. Download a suitable Python embeddable version. For example, let's download Python 3.11.9:

```bash
# use curl command or manually download
curl -O https://www.python.org/ftp/python/3.11.9/python-3.11.9-embed-amd64.zip
```
```bash
# use curl command or manually download
curl -O https://www.python.org/ftp/python/3.11.9/python-3.11.9-embed-amd64.zip
```

2. Extract the downloaded zip file:

```bash
mkdir python-3.11.9
```bash
mkdir python-3.11.9

unzip python-3.11.9-embed-amd64.zip -d python-3.11.9
unzip python-3.11.9-embed-amd64.zip -d python-3.11.9

rm python-3.11.9-embed-amd64.zip
```
rm python-3.11.9-embed-amd64.zip
```

### Install pip

1. Download `get-pip.py`:

```bash
# use curl command or manually download
curl -O https://bootstrap.pypa.io/get-pip.py
```
```bash
# use curl command or manually download
curl -O https://bootstrap.pypa.io/get-pip.py
```

2. Install pip:

```bash
./python-3.11.9/python get-pip.py --no-warn-script-location
```bash
./python-3.11.9/python get-pip.py --no-warn-script-location

# no need anymore get-pip.py
rm get-pip.py
```
# no need anymore get-pip.py
rm get-pip.py
```

### Configure Python Environment

1. Uncomment 'import site' in the `._pth` file:

```bash
# Uncomment to run site.main() automatically
# Remove hash from python-3.11.9/python311._pth file
import site
```bash
# Uncomment to run site.main() automatically
# Remove hash from python-3.11.9/python311._pth file
import site

# Or use command
sed -i '/^\s*#\s*import\s\+site/s/^#//' python-3.11.9/python311._pth
```
# Or use command
sed -i '/^\s*#\s*import\s\+site/s/^#//' python-3.11.9/python311._pth
```

### Install Required Packages

Expand All @@ -65,45 +65,212 @@ Install all required packages from `requirements.txt`:

1. Test by running app

```batch
.\python-3.11.9\python -m streamlit run app.py
```
```batch
.\python-3.11.9\python -m streamlit run app.py
```

2. Create a Clickable Shortcut

Create a `run_app.bat` file to make running the app easier:
```batch
echo @echo off > run_app.bat
echo .\\python-3.11.9\\python -m streamlit run app.py >> run_app.bat
```
Create a `run_app.bat` file to make running the app easier:

```batch
echo @echo off > run_app.bat
echo .\\python-3.11.9\\python -m streamlit run app.py >> run_app.bat
```

### Create one executable folder

1. Create a folder for your Streamlit app:

```bash
mkdir ../streamlit_exe
```
```bash
mkdir ../streamlit_exe
```

2. Copy environment and app files:

```bash
# move Python environment folder
mv python-3.11.9 ../streamlit_exe
```bash
# move Python environment folder
mv python-3.11.9 ../streamlit_exe

# move run_app.bat file
mv run_app.bat ../streamlit_exe

# move run_app.bat file
mv run_app.bat ../streamlit_exe
# copy streamlit app files
cp -r src pages .streamlit assets example-data ../streamlit_exe
cp app.py ../streamlit_exe
```

# copy streamlit app files
cp -r src pages .streamlit assets example-data ../streamlit_exe
cp app.py ../streamlit_exe
```

#### 🚀 After successfully completing all these steps, the Streamlit app will be available by running the run_app.bat file.

:pencil: You can still change the configuration of Streamlit app with .streamlit/config.toml file, e.g., provide a different port, change upload size, etc.

## Build executable in github action automatically

Automate the process of building executables for your project with the GitHub action example [Test streamlit executable for Windows with embeddable python](https://github.com/OpenMS/streamlit-template/blob/main/.github/workflows/test-win-exe-w-embed-py.yaml)
</br>

## Create MSI Installer using WiX Toolset

After creating your executable folder, you can package it into an MSI installer using WiX Toolset. Here's how:

### 1. Set Environment Variables

Set these variables for consistent naming throughout the process:

```batch
APP_NAME=OpenMS-StreamlitTemplateApp
APP_UpgradeCode=4abc2e23-3ba5-40e4-95c9-09e6cb8ecaeb
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set should be not used here. will make life hard. later APP_NAME needed in .wxs file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i got your point , it will surely make . these are the changes i will make -

APP_NAME=OpenMS-StreamlitTemplateApp
APP_UpgradeCode=4abc2e23-3ba5-40e4-95c9-09e6cb8ecaeb

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@achalbajpai important how to create GUID? for example this 4abc2e23-3ba5-40e4-95c9-09e6cb8ecaeb? user should know. please provide.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i will be adding this

 -  PowerShell: `[guid]::NewGuid().ToString()`
 -  Online GUID generator: https://www.guidgen.com/
 -  Windows Command Prompt: `powershell -Command "[guid]::NewGuid().ToString()"`

Copy link
Contributor Author

@achalbajpai achalbajpai Mar 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once all the changes are validated, I will pull the final changes file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes please request me to review. thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Arslan-Siraj
I’ve implemented all the suggested changes in my final commit. Hope it is good to go


To create a new GUID for your application's UpgradeCode, you can use:

- PowerShell: `[guid]::NewGuid().ToString()`
- Online GUID generator: https://www.guidgen.com/
- Windows Command Prompt: `powershell -Command "[guid]::NewGuid().ToString()"`

### 2. Install WiX Toolset

1. Download WiX Toolset binaries:
```batch
curl -LO https://github.com/wixtoolset/wix3/releases/download/wix3111rtm/wix311-binaries.zip
unzip wix311-binaries.zip -d wix
```

### 3. Prepare Installation Files

1. Create a SourceDir structure:

```batch
mkdir SourceDir
move streamlit_exe\* SourceDir
```

2. Create Readme.txt:

```batch
# Create a Readme.txt file in the SourceDir folder with instructions
# for launching the application
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of these commands, just write create Readme.txt file in SourceDir?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it will be much better to create a Readme.txt file in the SourceDir

Updates I will give -

  1. Create a SourceDir structure:

    mkdir SourceDir
    move streamlit_exe\* SourceDir
  2. Create Readme.txt:

    # Create a Readme.txt file in the SourceDir folder with instructions
    # for launching the application


3. Add necessary assets:
- Copy license file: `copy assets\openms_license.rtf SourceDir\`
- Copy app icon: `copy assets\openms.ico SourceDir\`
- Create success message script:
```vbscript
' ShowSuccessMessage.vbs
MsgBox "The " & "%APP_NAME%" & " application is successfully installed.", vbInformation, "Installation Complete"
```

### 4. Generate WiX Source Files

1. Generate component list from your files:

```batch
wix\heat.exe dir SourceDir -gg -sfrag -sreg -srd -template component -cg StreamlitExeFiles -dr AppSubFolder -out streamlit_exe_files.wxs
```

2. Create main WiX configuration file (streamlit_exe.wxs):

```xml
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="$(env.APP_NAME)" Language="1033" Version="1.0.0.0"
Manufacturer="OpenMS Developer Team" UpgradeCode="$(env.APP_UpgradeCode)">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$(env.APP_NAME) $(env.APP_UpgradeCode) its still available?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it is still available.

<Package Id="*" InstallerVersion="300" Compressed="yes" InstallPrivileges="elevated" Platform="x64" />
<Media Id="1" Cabinet="streamlit.cab" EmbedCab="yes" />

<!-- Directory structure -->
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="$(env.APP_NAME)">
<Directory Id="AppSubFolder" Name="$(env.APP_NAME)" />
<Component Id="CreateAppFolder" Guid="95dbfa06-d36a-427f-995c-e87769ac2e59">
<CreateFolder>
<Permission User="Everyone" GenericAll="yes" />
</CreateFolder>
</Component>
</Directory>
</Directory>
<Directory Id="DesktopFolder" />
</Directory>

<!-- Features -->
<Feature Id="MainFeature" Title="Main Application" Level="1">
<ComponentGroupRef Id="StreamlitExeFiles" />
<ComponentRef Id="CreateAppFolder" />
<ComponentRef Id="DesktopShortcutComponent" />
<ComponentRef Id="InstallDirShortcutComponent" />
</Feature>

<!-- Desktop Shortcut -->
<Component Id="DesktopShortcutComponent" Guid="3597b243-9180-4d0b-b105-30d8b0d1a334" Directory="DesktopFolder">
<Shortcut Id="DesktopShortcut" Name="$(env.APP_NAME)"
Description="Launch $(env.APP_NAME)"
Target="[AppSubFolder]$(env.APP_NAME).bat"
WorkingDirectory="AppSubFolder"
Icon="AppIcon" />
<RegistryValue Root="HKCU" Key="Software\OpenMS\$(env.APP_NAME)"
Name="DesktopShortcut" Type="integer" Value="1" KeyPath="yes" />
</Component>

<!-- Installation Directory Shortcut -->
<Component Id="InstallDirShortcutComponent" Guid="c2df9472-3b45-4558-a56d-6034cf7c8b72" Directory="AppSubFolder">
<Shortcut Id="InstallDirShortcut" Name="$(env.APP_NAME)"
Description="Launch $(env.APP_NAME)"
Target="[AppSubFolder]$(env.APP_NAME).bat"
WorkingDirectory="AppSubFolder"
Icon="AppIcon" />
<RegistryValue Root="HKCU" Key="Software\OpenMS\$(env.APP_NAME)"
Name="InstallFolderShortcut" Type="integer" Value="1" KeyPath="yes" />
</Component>

<!-- UI and Icon -->
<Icon Id="AppIcon" SourceFile="SourceDir/openms.ico" />
<UI>
<UIRef Id="WixUI_InstallDir" />
<UIRef Id="WixUI_ErrorProgressText" />
</UI>

<!-- Success Message -->
<Binary Id="ShowMessageScript" SourceFile="SourceDir/ShowSuccessMessage.vbs" />
<CustomAction Id="ShowSuccessMessage" BinaryKey="ShowMessageScript" VBScriptCall="" Execute="immediate" Return="check" />

<!-- Custom Actions Sequence -->
<InstallExecuteSequence>
<Custom Action="ShowSuccessMessage" After="InstallFinalize">NOT Installed</Custom>
</InstallExecuteSequence>

<!-- License -->
<WixVariable Id="WixUILicenseRtf" Value="SourceDir/openms_license.rtf" />
</Product>
</Wix>
```

### 5. Build the MSI

1. Compile WiX source files:

```batch
# Generate wixobj files from the WiX source files
wix\candle.exe streamlit_exe.wxs streamlit_exe_files.wxs
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what will the outcome of this command? write the wixobj files will created.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes , the wixobj files will be created via this command - for linking by light.exe to produce the final MSI installer

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add this as comment in documentation that user should be able to generate wixobj file with this command.


2. Link and create MSI:
```batch
# Create the MSI installer from the wixobj files
# The -sice:ICE60 flag stops a warning about duplicate component GUIDs, which can happen when heat.exe auto-generates components
wix\light.exe -ext WixUIExtension -sice:ICE60 -o %APP_NAME%.msi streamlit_exe_files.wixobj streamlit_exe.wixobj
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-sice:ICE60 (because not always we use) why this important short comment please?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The -sice:ICE60 stops a warning about duplicate component GUIDs, which can happen when heat.exe auto-generates components

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes please add to documentation as comment.


### 6. Additional Notes

- The generated MSI will create desktop and start menu shortcuts
- Installation requires elevated privileges
- A success message will be shown after installation
- The installer includes a proper license agreement page
- All files will be installed in Program Files by default

For more detailed customization options, refer to the [WiX Toolset documentation](https://wixtoolset.org/documentation/).

:warning: The `APP_UpgradeCode` GUID should be unique for your application. Generate a new one if you're creating a different app.
1 change: 1 addition & 0 deletions settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"app-name": "OpenMS WebApp Template",
"github-user": "OpenMS",
"version": "1.0.2",
"repository-name": "streamlit-template",
"analytics": {
"google-analytics": {
Expand Down
22 changes: 22 additions & 0 deletions src/common/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,28 @@ def change_workspace():
)
else:
st.session_state["spectrum_num_bins"] = 50

# Display OpenMS WebApp Template Version from settings.json
with st.container():
st.markdown(
"""
<style>
.version-box {
border: 1px solid #a4a5ad;
padding: 10px;
border-radius: 0.5rem;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
</style>
""",
unsafe_allow_html=True
)
version_info = st.session_state.settings["version"]
app_name = st.session_state.settings["app-name"]
st.markdown(f'<div class="version-box">{app_name}<br>Version: {version_info}</div>', unsafe_allow_html=True)
return params


Expand Down
Loading