Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/build-linux-cross.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ env:
NO_FORCE: 1
GA_CI_SECRET: ${{ secrets.CI_SECRET }}
USE_ARTIFACT: false
DISABLE_WORKFLOW: "false"
DISABLE_WORKFLOW: "true"

jobs:
pre-check:
Expand Down
188 changes: 188 additions & 0 deletions .github/workflows/build-vs2026-x64.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
name: build-vs2026

on:
push:
paths-ignore:
- '**/*.md'
pull_request:
paths-ignore:
- '**/*.md'

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

env:
TARGET: "vs"
VS_STUDIO: "2026"
VS_VER: 18
NO_FORCE: 1
GA_CI_SECRET: ${{ secrets.CI_SECRET }}
USE_ARTIFACT: false
DISABLE_WORKFLOW: "false"

jobs:
pre-check:
runs-on: ubuntu-latest
outputs:
workflow_disabled: ${{ steps.check-disabled.outputs.disabled }}
steps:
- name: Check if Workflow is disabled
id: check-disabled
shell: bash
run: |
if [ "${{ env.DISABLE_WORKFLOW }}" == "true" ]; then
echo "disabled=true" >> $GITHUB_ENV
echo "::set-output name=disabled::true"
else
echo "::set-output name=disabled::false"
fi

build-vs2026:
if: needs.pre-check.outputs.workflow_disabled != 'true'
needs: pre-check
runs-on: windows-2025-vs2026
strategy:
matrix:
arch: [64, arm64, arm64ec]
bundle: [1, 2]
defaults:
run:
shell: msys2 {0}

env:
ARCH: ${{ matrix.arch }}

steps:
- name: Check if Workflow is disabled
shell: bash
run: |
if [ "${{ env.DISABLE_WORKFLOW }}" == "true" ]; then
echo "Workflow is disabled. Exiting."
exit 78
fi

- name: Setup msys2
uses: msys2/setup-msys2@v2
with:
update: true
install: >-
base-devel unzip dos2unix gperf git python3
mingw-w64-x86_64-binutils mingw-w64-x86_64-clang
mingw-w64-x86_64-gcc mingw-w64-x86_64-gcc-libs
mingw-w64-x86_64-cmake mingw-w64-x86_64-gdb
mingw-w64-x86_64-make

- name: Clone repository
uses: actions/checkout@v4.2.2

- name: Setup MSBuild
uses: microsoft/setup-msbuild@v2

- name: Determine Release
id: vars
shell: bash
run: |
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
echo "RELEASE=${{ github.ref_name }}" >> $GITHUB_ENV
elif [[ "${{ github.ref }}" == "refs/heads/master" ]]; then
echo "RELEASE=nightly" >> $GITHUB_ENV
elif [[ "${{ github.ref }}" == "refs/heads/bleeding" ]]; then
echo "RELEASE=latest" >> $GITHUB_ENV
else
echo "RELEASE=latest" >> $GITHUB_ENV
fi

- name: Scripts Install
run: ./scripts/vs/install.sh

# ── Download artifacts (if enabled) ─────────────────────────────────────
- name: 'Download artifacts'
uses: actions/github-script@v7
if: env.USE_ARTIFACT == 'true'
with:
script: |
const fs = require('fs');
const path = require('path');
const outputDir = path.join(process.env.GITHUB_WORKSPACE, 'out');
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir);

const artifacts = await github.rest.actions.listArtifactsForRepo({
owner: 'openframeworks', repo: 'apothecary',
sort: 'created_at', direction: 'desc', per_page: 150
});

const target = process.env.TARGET;
const studio = process.env.VS_STUDIO;
const arch = process.env.ARCH;
const release = process.env.RELEASE;

let count = 0;
const max = 1;
for (const artifact of artifacts.data.artifacts) {
const isArtifactMatch = artifact.name.includes(`libs-${release}-${target}-${studio}-${arch}`) && !artifact.expired;
if (isArtifactMatch) {
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner, repo: context.repo.repo,
artifact_id: artifact.id, archive_format: 'zip'
});
const artifactPath = path.join(outputDir, `${artifact.name}.zip`);
fs.writeFileSync(artifactPath, Buffer.from(download.data));
console.log(`Downloaded ${artifact.name}`);
count++;
if (count >= max) break;
}
}

- name: Extract Artifacts to /out
if: env.USE_ARTIFACT == 'true'
run: |
mkdir -p out
# (your full extraction logic – kept exactly as you had it)
if ls out/*.zip 1> /dev/null 2>&1; then
for zip in out/*.zip; do unzip -o "$zip" -d out/ && rm "$zip"; done
fi
if ls out/*.tar.bz2 1> /dev/null 2>&1; then
for tarball in out/*.tar.bz2; do tar -xjf "$tarball" -C out/; done
rm -f out/*.tar.bz2
fi

- name: List output directory
if: env.USE_ARTIFACT == 'true'
run: ls -lah out/

# ── Build ───────────────────────────────────────────────────────────────
- name: Build ${{ matrix.arch }}
working-directory: ${{env.GITHUB_WORKSPACE}}
run: scripts/build.sh
env:
BUNDLE: ${{ matrix.bundle }}

# ── Package (always for VS2026 preview) ─────────────────────────────────
- name: Package
working-directory: ${{ env.GITHUB_WORKSPACE }}
run: scripts/package.sh
env:
BUNDLE: ${{ matrix.bundle }}
ALWAYS_BUILD: true

- name: List output directory (post-package)
run: ls -lah out/

# ── Upload & Release (only on push to master/bleeding/tags) ─────────────
- name: Upload binaries as Artifact
if: github.repository == 'openframeworks/apothecary' && github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/bleeding')
uses: actions/upload-artifact@v4
with:
name: libs-${{ env.RELEASE }}-${{ env.TARGET }}-${{ env.VS_STUDIO }}-${{ matrix.arch }}-${{ matrix.bundle }}
path: out/openFrameworksLibs_${{ env.RELEASE }}_${{ env.TARGET }}_${{ env.VS_STUDIO }}_${{ matrix.arch }}_${{ matrix.bundle }}.zip
retention-days: 31

- name: Update GitHub Release
if: github.repository == 'openframeworks/apothecary' && github.event_name == 'push' && (startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/master' || github.ref == 'refs/heads/bleeding')
uses: softprops/action-gh-release@v2.1.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
tag_name: ${{ env.RELEASE }}
draft: false
files: out/openFrameworksLibs_${{ env.RELEASE }}_${{ env.TARGET }}_${{ env.VS_STUDIO }}_${{ matrix.arch }}_${{ matrix.bundle }}.zip
164 changes: 126 additions & 38 deletions apothecary/apothecary
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ WIN10_INSTALLED_SDK_2022=10.0.20348.0
WIN10_INSTALLED_SDK_2022_HEX=0x0A004F5C
WIN11_INSTALLED_SDK_2022=10.0.26100.0
WIN11_INSTALLED_SDK_2022_HEX=0x0A0065F4
WIN10_INSTALLED_SDK_2026=10.0.XXXXX.0
WIN10_INSTALLED_SDK_2026_HEX=0x0AXXXXXX
WIN11_INSTALLED_SDK_2026=10.0.26100.7175
WIN11_INSTALLED_SDK_2026_HEX=0x0A0065F4

if [ -z "${VS_TYPE+x}" ]; then # Professional # Enterprise # Community
VS_TYPE=Community
Expand Down Expand Up @@ -367,7 +371,7 @@ while getopts t:a:b:d:s:j:m:c:hgvxfpewy opt ; do
VERBOSE_MAKEFILE=YES
;;
e) # use visual enterprise
export VS_TYPE=Enterprise ;;
export VS_TYPE=Community ;;
f) # force download
export FORCE_DOWNLOAD=1 ;;
y) # use pthreads
Expand Down Expand Up @@ -625,47 +629,117 @@ if [ "$TYPE" = "vs" ]; then
export EXE_FLAGS="/NODEFAULTLIB:libvcruntime.lib /DEFAULTLIB:ucrt.lib /DEFAULTLIB:msvcrt.lib"
fi

VS_BAT="vcvarsall.bat"
if [ -z "${WSL_DISTRO_NAME+x}" ]; then
export DRIVE=/c
else
export DRIVE=/mnt/c
fi
if [ -z ${VS_HOSTPLATFORM+x} ]; then
if [ ${VS_HOST} == "amd64" ]; then
VS_HOSTPLATFORM=Hostx64
elif [ ${VS_HOST} == "86" ]; then
VS_HOSTPLATFORM=Hostx86

for d in d c e f; do
if [ -d "/${d}/Program Files/Microsoft Visual Studio" ] || \
[ -d "/${d}/Program Files (x86)/Microsoft Visual Studio" ]; then
export DRIVE="/${d}"
echo "Found Visual Studio on ${DRIVE} drive"
break
fi
done

# 2. Fallback to original logic if nothing found
if [ -z "${DRIVE+x}" ]; then
if [ -z "${WSL_DISTRO_NAME+x}" ]; then
export DRIVE=/c
else
export DRIVE=/mnt/c
fi
echo "Using default DRIVE=${DRIVE} (WSL or standard Windows)"
else
#else if arm or arm64 which is same as VS_HOST
VS_HOSTPLATFORM=${VS_HOST}
echo "DRIVE detected as ${DRIVE}"
fi
fi
if [ -z ${VS_BASE_PATH+x} ]; then
if [ "${VS_VER}" = "15" ]; then
VS_BASE_PATH="${DRIVE}/Program Files (x86)/Microsoft Visual Studio/2017/$VS_TYPE"
VS_YEAR=2017
VC_VERSION=140
VS_BAT="vcvars$ARCH.bat"

# Default VS_TYPE to Community (will be overridden by detection if possible)
if [ -z "${VS_TYPE+x}" ]; then
export VS_TYPE="Community"
fi

# Set Host Platform
if [ -z "${VS_HOSTPLATFORM+x}" ]; then
if [ "${VS_HOST}" = "amd64" ]; then
VS_HOSTPLATFORM="Hostx64"
elif [ "${VS_HOST}" = "86" ]; then
VS_HOSTPLATFORM="Hostx86"
else
VS_HOSTPLATFORM="${VS_HOST}" # arm / arm64
fi
fi

echo "Detecting Visual Studio ${VS_VER} edition..."

if [ "${VS_VER}" = "17" ] || [ "${VS_VER}" = "18" ]; then
# VS 2022 / 2026+ → under Program Files\
BASE_DIR="${DRIVE}/Program Files/Microsoft Visual Studio"
if [ "${VS_VER}" = "17" ]; then
YEAR_PATH="2022"
else
YEAR_PATH="${VS_VER}" #18 for 2026+
fi
elif [ "${VS_VER}" = "15" ]; then
BASE_DIR="${DRIVE}/Program Files (x86)/Microsoft Visual Studio"
YEAR_PATH="2017"
elif [ "${VS_VER}" = "16" ]; then
VS_YEAR_PATH=2019
if [ -d "${DRIVE}/Program Files (x86)/Microsoft Visual Studio/$VS_YEAR_PATH/$VS_TYPE" ]; then
VS_YEAR_PATH=2019
VC_VERSION=142
else
VS_YEAR_PATH=2019
VC_VERSION=142
fi
VS_BASE_PATH="${DRIVE}/Program Files (x86)/Microsoft Visual Studio/$VS_YEAR_PATH/$VS_TYPE"
VS_YEAR=$VS_YEAR_PATH
elif [ "${VS_VER}" = "17" ]; then
VS_BASE_PATH="${DRIVE}/Program Files/Microsoft Visual Studio/2022/$VS_TYPE"
export VS_BASE_PATH_CLANG="${DRIVE}/Program Files/Microsoft Visual Studio/2022/"
VS_YEAR=2022
VC_VERSION=143
VS_BAT="vcvars$ARCH.bat"
BASE_DIR="${DRIVE}/Program Files (x86)/Microsoft Visual Studio"
YEAR_PATH="2019"
else
BASE_DIR="${DRIVE}/Program Files (x86)/Microsoft Visual Studio"
YEAR_PATH="${VS_VER}"
fi
fi

# Check editions in priority order
if [ -d "${BASE_DIR}/${YEAR_PATH}/Enterprise" ]; then
export VS_TYPE="Enterprise"
elif [ -d "${BASE_DIR}/${YEAR_PATH}/Professional" ]; then
export VS_TYPE="Professional"
elif [ -d "${BASE_DIR}/${YEAR_PATH}/Community" ]; then
export VS_TYPE="Community"
else
echo "Warning: No Visual Studio ${VS_VER} edition found. Defaulting to Community."
export VS_TYPE="Community"
fi

echo "→ Using Visual Studio ${VS_VER} ${VS_TYPE}"

if [ -z ${VS_BASE_PATH+x} ]; then
case "${VS_VER}" in
15)
VS_BASE_PATH="${DRIVE}/Program Files (x86)/Microsoft Visual Studio/2017/${VS_TYPE}"
VS_YEAR=2017
VC_VERSION=140
VS_BAT="vcvars${ARCH}.bat"
;;

16)
VS_BASE_PATH="${DRIVE}/Program Files (x86)/Microsoft Visual Studio/2019/${VS_TYPE}"
VS_YEAR=2019
VC_VERSION=142
VS_BAT="vcvars${ARCH}.bat"
;;

17)
VS_BASE_PATH="${DRIVE}/Program Files/Microsoft Visual Studio/2022/${VS_TYPE}"
export VS_BASE_PATH_CLANG="${DRIVE}/Program Files/Microsoft Visual Studio/2022/"
VS_YEAR=2022
VC_VERSION=143
VS_BAT="vcvars${ARCH}.bat"
;;

18)
VS_BASE_PATH="${DRIVE}/Program Files/Microsoft Visual Studio/18/${VS_TYPE}"
export VS_BASE_PATH_CLANG="${DRIVE}/Program Files/Microsoft Visual Studio/18/"
VS_YEAR=2026
VC_VERSION=145
VS_BAT="vcvars${ARCH}.bat"
;;

*)
echo "Error: Unsupported Visual Studio version: ${VS_VER}"
;;
esac
fi

if [ $ARCH == 32 ] ; then
export PLATFORM="Win32"
export BUILD_PLATFORM="x86"
Expand Down Expand Up @@ -743,6 +817,20 @@ if [ "$TYPE" = "vs" ]; then
export CMAKE_WIN_SDK_HEX=${WIN10_INSTALLED_SDK_2022_HEX}
fi

if [ $VS_COMPILER == "LLVM" ]; then
export CMAKE_WIN_SDK="${CMAKE_WIN_SDK} -DCMAKE_CXX_COMPILER=${VS_BIN_PATH}/clang++ -DCMAKE_C_COMPILER=${VS_BIN_PATH}/clang -T ClangCL -DLLVM_ENABLE_RUNTIMES=libcxx -DLIBCXX_ENABLE_SHARED=NO -DLIBCXX_ENABLE_STATIC=YES"
fi
elif [ $VS_VER == "18" ]; then
export VS_YEAR=2026
export VS_VER=18
export VS_VER_GEN="$VS_VER $VS_YEAR"
if [ $ARCH == "arm64ec" ] || [ $TARGET_WIN_11 == 1 ]; then
export CMAKE_WIN_SDK="-DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=${WIN11_INSTALLED_SDK_2026} -DCMAKE_SYSTEM_VERSION=${WIN11_INSTALLED_SDK_2026} "
export CMAKE_WIN_SDK_HEX=${WIN11_INSTALLED_SDK_2026_HEX}
else
export CMAKE_WIN_SDK="-DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=${WIN10_INSTALLED_SDK_2026} -DCMAKE_SYSTEM_VERSION=${WIN10_INSTALLED_SDK_2026} "
export CMAKE_WIN_SDK_HEX=${WIN10_INSTALLED_SDK_2026_HEX}
fi
if [ $VS_COMPILER == "LLVM" ]; then
export CMAKE_WIN_SDK="${CMAKE_WIN_SDK} -DCMAKE_CXX_COMPILER=${VS_BIN_PATH}/clang++ -DCMAKE_C_COMPILER=${VS_BIN_PATH}/clang -T ClangCL -DLLVM_ENABLE_RUNTIMES=libcxx -DLIBCXX_ENABLE_SHARED=NO -DLIBCXX_ENABLE_STATIC=YES"
fi
Expand Down
Loading
Loading