1- name : Build
1+ name : Build and Release
22
33on :
44 push :
55 branches : [ "master" ]
66 pull_request :
77 branches : [ "master" ]
8+ workflow_dispatch :
9+ inputs :
10+ create_release :
11+ description : ' Create a new release'
12+ required : false
13+ type : boolean
14+ default : false
15+ schedule :
16+ - cron : ' 0 2 * * *'
817
918env :
10- BUILD_TYPE : RelWithDebInfo
19+ BUILD_TYPE : Release
20+ MIN_BUILD_NUMBER : 7290
1121
1222jobs :
23+ check-versions :
24+ runs-on : ubuntu-latest
25+ outputs :
26+ should_build : ${{ steps.check.outputs.should_build }}
27+ versions_matrix : ${{ steps.check.outputs.versions_matrix }}
28+ steps :
29+ - uses : actions/checkout@v4
30+ with :
31+ submodules : ' true'
32+ fetch-depth : 0
33+
34+ - name : Check for new versions
35+ id : check
36+ run : |
37+ cd binaryninjaapi
38+ git fetch --tags origin
39+
40+ VERSIONS_JSON='[{"name": "dev", "filename": "dev", "short_name": "dev", "full_version": "dev"}]'
41+
42+ ALL_TAGS=$(git tag -l 'v*-stable' 'stable/*' | sort -V)
43+
44+ for tag in $ALL_TAGS; do
45+ if [[ $tag == v*-stable ]]; then
46+ VERSION=$(echo $tag | sed 's/^v//' | sed 's/-stable$//')
47+ elif [[ $tag == stable/* ]]; then
48+ VERSION=$(echo $tag | sed 's|stable/||')
49+ else
50+ continue
51+ fi
52+
53+ BUILD_NUM=$(echo $VERSION | grep -oE '[0-9]{4}$')
54+
55+ if [[ ! -z "$BUILD_NUM" ]] && [[ $BUILD_NUM -ge $MIN_BUILD_NUMBER ]]; then
56+ echo "Including version: $tag (build $BUILD_NUM)"
57+ VERSIONS_JSON=$(echo $VERSIONS_JSON | jq -c --arg name "$tag" --arg filename "v$VERSION-stable" --arg short "$BUILD_NUM" --arg fullver "$VERSION" '. += [{"name": $name, "filename": $filename, "short_name": $short, "full_version": $fullver}]')
58+ fi
59+ done
60+
61+ echo "versions_matrix<<EOF" >> $GITHUB_OUTPUT
62+ echo "$VERSIONS_JSON" >> $GITHUB_OUTPUT
63+ echo "EOF" >> $GITHUB_OUTPUT
64+
65+ if [[ "${{ github.event_name }}" == "schedule" ]] || [[ "${{ inputs.create_release }}" == "true" ]]; then
66+ echo "should_build=true" >> $GITHUB_OUTPUT
67+ else
68+ echo "should_build=false" >> $GITHUB_OUTPUT
69+ fi
70+
1371 build :
14- runs-on : ${{matrix.config.os}}
72+ needs : check-versions
73+ if : needs.check-versions.outputs.should_build == 'true' || github.event_name == 'push' || github.event_name == 'pull_request'
74+ runs-on : ${{ matrix.config.os }}
1575 strategy :
1676 matrix :
1777 config :
18- - {
19- os : windows-2025,
20- name : windows
21- }
22- - {
23- os : macos-13,
24- name : macos
25- }
26- - {
27- os : ubuntu-24.04,
28- name : ubuntu
29- }
30- version :
31- - name : v5.0.7290-stable
32- use-patch : false
33- - name : v5.0.7648-stable
34- use-patch : false
35- - name : dev
36- use-patch : false
78+ - { os: windows-latest, name: windows, ext: dll }
79+ - { os: macos-15, name: macos, ext: dylib }
80+ - { os: ubuntu-24.04, name: ubuntu, ext: so }
81+ version : ${{ fromJson(needs.check-versions.outputs.versions_matrix) }}
82+
3783 steps :
38- - uses : actions/checkout@v3
84+ - uses : actions/checkout@v4
3985 with :
4086 submodules : ' true'
87+
4188 - uses : seanmiddleditch/gha-setup-ninja@master
89+
4290 - uses : ilammy/msvc-dev-cmd@v1
91+ if : matrix.config.name == 'windows'
92+
93+ - name : Setup Python
94+ uses : actions/setup-python@v6
95+ with :
96+ python-version : ' 3.13'
97+
4398 - name : Update submodule
4499 run : |
45100 cd binaryninjaapi
46101 git fetch --tags
47- git checkout --force ${{matrix.version.name}}
102+ git checkout --force ${{ matrix.version.name }}
48103 git submodule update --init --recursive
49- - name : Patch api to allow building headlessly
50- if : ${{ matrix.version.use-patch }}
51- shell : bash
52- run : |
53- cd binaryninjaapi
54- git apply --verbose ${{matrix.version.patch-file}}
104+
55105 - name : Configure CMake
56- run : cmake -B ${{github.workspace}}/build -G Ninja -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
106+ run : cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBN_ALLOW_STUBS=ON
107+
57108 - name : Build
58- run : cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
109+ run : cmake --build build --config ${{env.BUILD_TYPE}}
110+
111+ - name : Rename artifacts (Windows)
112+ if : matrix.config.name == 'windows'
113+ shell : pwsh
114+ run : |
115+ cd build
116+ $original = Get-ChildItem -Recurse -Filter "*NativePredicateSolver*.dll" | Select-Object -First 1
117+
118+ if ($null -eq $original) {
119+ Write-Error "Built library not found"
120+ exit 1
121+ }
122+
123+ if ("${{ matrix.version.full_version }}" -eq "dev") {
124+ $newName = "NativePredicateSolver-dev.dll"
125+ } else {
126+ $newName = "NativePredicateSolver-${{ matrix.version.full_version }}.dll"
127+ }
128+
129+ Copy-Item -Path $original.FullName -Destination $newName
130+ echo "artifact_name=$newName" >> $env:GITHUB_ENV
131+
132+ - name : Rename artifacts (Unix)
133+ if : matrix.config.name != 'windows'
134+ shell : bash
135+ run : |
136+ cd build
137+
138+ if [[ "${{ matrix.config.ext }}" == "so" ]]; then
139+ ORIGINAL=$(find . -type f -name "libNativePredicateSolver.so*" | head -n 1)
140+ else
141+ ORIGINAL=$(find . -type f -name "libNativePredicateSolver.dylib*" | head -n 1)
142+ fi
143+
144+ if [[ -z "$ORIGINAL" ]]; then
145+ echo "Built library not found"
146+ exit 1
147+ fi
148+
149+ if [[ "${{ matrix.version.full_version }}" == "dev" ]]; then
150+ NEW_NAME="NativePredicateSolver-dev.${{ matrix.config.ext }}"
151+ else
152+ NEW_NAME="NativePredicateSolver-${{ matrix.version.full_version }}.${{ matrix.config.ext }}"
153+ fi
154+
155+ cp "$ORIGINAL" "$NEW_NAME"
156+ echo "artifact_name=$NEW_NAME" >> $GITHUB_ENV
157+
59158 - name : Upload artifact
60159 uses : actions/upload-artifact@v4
61160 with :
62- name : ${{matrix.config.name}}-${{matrix.version.name}}
63- path : ${{github.workspace}}/build/*NativePredicateSolver*
161+ name : ${{ matrix.config.name }}-${{ matrix.version.filename }}
162+ path : build/${{ env.artifact_name }}
163+
164+ create-release :
165+ needs : [check-versions, build]
166+ if : needs.check-versions.outputs.should_build == 'true' || github.event.inputs.create_release == 'true' || github.event_name == 'push'
167+ runs-on : ubuntu-latest
168+ permissions :
169+ contents : write
170+
171+ steps :
172+ - uses : actions/checkout@v4
173+
174+ - name : Download all artifacts
175+ uses : actions/download-artifact@v4
176+ with :
177+ path : artifacts
178+
179+ - name : Organize artifacts
180+ run : |
181+ mkdir -p release_files
182+ find artifacts -type f \( -name "*.dll" -o -name "*.so" -o -name "*.dylib" \) -exec cp {} release_files/ \;
183+
184+ - name : Generate release notes
185+ run : |
186+ RELEASE_DATE=$(date +'%Y-%m-%d')
187+
188+ cat > release_notes.md <<EOF
189+ ## Build Information
190+
191+ **Date:** ${RELEASE_DATE}
192+ **Commit:** \`${GITHUB_SHA:0:7}\`
193+
194+ ### Supported Binary Ninja Versions
195+
196+ EOF
197+
198+ echo '${{ needs.check-versions.outputs.versions_matrix }}' > versions.json
199+ jq -r '.[] | "- \(.full_version) (build \(.short_name))"' versions.json >> release_notes.md
200+
201+ cat >> release_notes.md <<EOF
202+
203+ ### Installation
204+
205+ **Option 1 (Recommended):** Use the [loader plugin](https://github.com/ScriptWare-Software/native-predicate-solver_loader) which automatically downloads and updates the correct binary for your Binary Ninja version.
206+
207+ **Option 2:** Manual installation - download the appropriate binary for your platform and Binary Ninja version, then place it in your Binary Ninja plugins directory.
208+
209+ **Naming format:**
210+ - Stable: \`NativePredicateSolver-<version>.<ext>\`
211+ - Dev: \`NativePredicateSolver-dev.<ext>\`
212+
213+ Where \`<ext>\` is \`dll\` (Windows), \`so\` (Linux), or \`dylib\` (macOS).
214+ EOF
215+
216+ - name : Create Release
217+ uses : softprops/action-gh-release@v1
218+ with :
219+ tag_name : build-${{ github.run_number }}
220+ name : Build ${{ github.run_number }}
221+ body_path : release_notes.md
222+ files : release_files/*
223+ env :
224+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
0 commit comments