Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
136 changes: 136 additions & 0 deletions .github/workflows/build-native.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
name: Build LVGL Native Libraries

on:
push:
branches: [main, develop, master]
pull_request:
branches: [main, master]
workflow_dispatch:
workflow_call:

jobs:
build:
name: Build ${{ matrix.rid }}
runs-on: ${{ matrix.os }}
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
# Windows — native and cross-compile via MSVC -A flag
- rid: win-x64
os: windows-latest
cmake_generator: "Visual Studio 17 2022"
cmake_arch: x64
- rid: win-x86
os: windows-latest
cmake_generator: "Visual Studio 17 2022"
cmake_arch: Win32
- rid: win-arm64
os: windows-latest
cmake_generator: "Visual Studio 17 2022"
cmake_arch: ARM64

# Linux — native x64
- rid: linux-x64
os: ubuntu-latest
cmake_extra: ""

# Linux — ARM cross-compile (hard-float)
- rid: linux-arm
os: ubuntu-latest
apt_packages: gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
cmake_extra: >-
-DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/libs/cmake/toolchains/arm-linux-gnueabihf.cmake

# Linux — ARM64 cross-compile
- rid: linux-arm64
os: ubuntu-latest
apt_packages: gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
cmake_extra: >-
-DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/libs/cmake/toolchains/aarch64-linux-gnu.cmake

# Linux — LoongArch64 cross-compile (requires Ubuntu 24.04)
- rid: linux-loongarch64
os: ubuntu-24.04
apt_packages: gcc-loongarch64-linux-gnu g++-loongarch64-linux-gnu
cmake_extra: >-
-DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/libs/cmake/toolchains/loongarch64-linux-gnu.cmake

steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive

# ─── Copy lv_conf.h into the lvgl source tree ─────────────────────────
# LVGL's CMake looks for lv_conf.h inside CMAKE_SOURCE_DIR (libs/lvgl/).
# The file lives one level up at libs/lv_conf.h, so copy it in place.
- name: Copy lv_conf.h into lvgl source directory
shell: bash
run: cp libs/lv_conf.h libs/lvgl/lv_conf.h

# ─── Linux: optional cross-compilation toolchain ───────────────────────
- name: Install cross-compilation toolchain
if: ${{ matrix.apt_packages != '' && runner.os == 'Linux' }}
run: |
sudo apt-get update -qq
sudo apt-get install -y ${{ matrix.apt_packages }}

# ─── Windows build ──────────────────────────────────────────────────────
- name: Configure CMake (Windows)
if: runner.os == 'Windows'
shell: bash
run: |
cmake -S libs/lvgl -B libs/lvgl/build_shared \
-G "${{ matrix.cmake_generator }}" \
-A "${{ matrix.cmake_arch }}" \
-DCONFIG_LV_BUILD_EXAMPLES=OFF \
-DCONFIG_LV_BUILD_DEMOS=OFF \
-DCONFIG_LV_USE_THORVG_INTERNAL=OFF \
-DBUILD_SHARED_LIBS=ON \
-DCONFIG_LV_USE_PRIVATE_API=ON

- name: Build (Windows)
if: runner.os == 'Windows'
shell: bash
run: cmake --build libs/lvgl/build_shared --config Release

# ─── Linux build ────────────────────────────────────────────────────────
- name: Configure CMake (Linux)
if: runner.os == 'Linux'
run: |
cmake -S libs/lvgl -B libs/lvgl/build_shared \
-DCMAKE_BUILD_TYPE=Release \
${{ matrix.cmake_extra }} \
-DCONFIG_LV_BUILD_EXAMPLES=OFF \
-DCONFIG_LV_BUILD_DEMOS=OFF \
-DCONFIG_LV_USE_THORVG_INTERNAL=OFF \
-DBUILD_SHARED_LIBS=ON \
-DCONFIG_LV_USE_PRIVATE_API=ON

- name: Build (Linux)
if: runner.os == 'Linux'
run: cmake --build libs/lvgl/build_shared

# ─── Collect outputs ────────────────────────────────────────────────────
- name: Collect native library
shell: bash
run: |
mkdir -p native_output
# Windows: copy DLL from the Release subdirectory
find libs/lvgl/build_shared -name "lvgl.dll" | head -1 | xargs -I{} cp {} native_output/ 2>/dev/null || true
# Linux: prefer the unversioned symlink; copy and rename to strip any version suffix
so=$(find libs/lvgl/build_shared -name "liblvgl.so" | head -1)
if [ -n "$so" ]; then
cp "$so" native_output/liblvgl.so
fi
ls -la native_output/

- name: Upload native artifact
uses: actions/upload-artifact@v4
with:
name: native-${{ matrix.rid }}
path: native_output/
if-no-files-found: error
188 changes: 188 additions & 0 deletions .github/workflows/nuget-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
name: Pack and Publish NuGet Packages

on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: "Package version (e.g. 9.3.0)"
required: true
default: "9.3.0"
publish_nuget:
description: "Publish to NuGet.org"
type: boolean
default: true
publish_github:
description: "Publish to GitHub Packages"
type: boolean
default: true

env:
# Derive version: prefer workflow_dispatch input, then release tag, then branch name.
# Strip any leading 'v' so we always get a semver string.
PACKAGE_VERSION: ${{ github.event.inputs.version || github.event.release.tag_name || github.ref_name }}

jobs:
# ──────────────────────────────────────────────────────────────────────────
# 1. Build native libraries for every supported platform
# ──────────────────────────────────────────────────────────────────────────
build-native:
uses: ./.github/workflows/build-native.yml
permissions:
contents: read

# ──────────────────────────────────────────────────────────────────────────
# 2. Assemble the LVGLSharp.Native NuGet package and managed packages
# ──────────────────────────────────────────────────────────────────────────
pack:
needs: build-native
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: false # managed code only — no need to build C

- name: Normalise version (strip leading 'v')
id: ver
run: |
VER="${{ env.PACKAGE_VERSION }}"
VER="${VER#v}"
echo "version=${VER}" >> "$GITHUB_OUTPUT"

# ── Download every native artifact ────────────────────────────────────
- name: Download all native artifacts
uses: actions/download-artifact@v4
with:
pattern: native-*
path: native_artifacts

# ── Place native libs under runtimes/{rid}/native/ ─────────────────────
- name: Organise native libs into runtimes layout
shell: bash
run: |
declare -A LIB_NAME=(
[win-x64]="lvgl.dll"
[win-x86]="lvgl.dll"
[win-arm64]="lvgl.dll"
[linux-x64]="liblvgl.so"
[linux-arm]="liblvgl.so"
[linux-arm64]="liblvgl.so"
[linux-loongarch64]="liblvgl.so"
)
missing=()
for rid in "${!LIB_NAME[@]}"; do
src_dir="native_artifacts/native-${rid}"
dst_dir="src/LVGLSharp.Native/runtimes/${rid}/native"
mkdir -p "$dst_dir"
lib="${LIB_NAME[$rid]}"
placed=false
if [ -f "${src_dir}/${lib}" ]; then
cp "${src_dir}/${lib}" "${dst_dir}/"
echo "Placed ${lib} -> ${dst_dir}/"
placed=true
else
# Fall back to the first .so or .dll found in the artifact folder
first=$(find "$src_dir" \( -name "*.dll" -o -name "*.so" \) | head -1)
if [ -n "$first" ]; then
cp "$first" "${dst_dir}/${lib}"
echo "Placed (fallback) $(basename "$first") -> ${dst_dir}/${lib}"
placed=true
fi
fi
if [ "$placed" = "false" ]; then
echo "ERROR: No native library found for ${rid} in ${src_dir}"
missing+=("$rid")
fi
done
if [ ${#missing[@]} -ne 0 ]; then
echo "The following RIDs have missing native libraries: ${missing[*]}"
exit 1
fi

# ── Pack LVGLSharp.Native ──────────────────────────────────────────────
- name: Pack LVGLSharp.Native
run: |
dotnet pack src/LVGLSharp.Native/LVGLSharp.Native.csproj \
-c Release \
-p:Version=${{ steps.ver.outputs.version }} \
--output nupkgs

# ── Pack LVGLSharp.Interop ─────────────────────────────────────────────
- name: Pack LVGLSharp.Interop
run: |
dotnet pack src/LVGLSharp.Interop/LVGLSharp.Interop.csproj \
-c Release \
-p:Version=${{ steps.ver.outputs.version }} \
--output nupkgs

# ── Pack LVGLSharp.Forms ───────────────────────────────────────────────
- name: Pack LVGLSharp.Forms
run: |
dotnet pack src/LVGLSharp.WinForms/LVGLSharp.Forms.csproj \
-c Release \
-p:Version=${{ steps.ver.outputs.version }} \
--output nupkgs

# ── Upload packed NuGet packages as artifacts ──────────────────────────
- name: Upload NuGet packages
uses: actions/upload-artifact@v4
with:
name: nuget-packages
path: nupkgs/*.nupkg

# ──────────────────────────────────────────────────────────────────────────
# 3. Publish
# ──────────────────────────────────────────────────────────────────────────
publish:
needs: pack
runs-on: ubuntu-latest
permissions:
packages: write
# Only publish on real releases (not manual dry-runs that disabled both)
if: |
github.event_name == 'release' ||
github.event.inputs.publish_nuget == 'true' ||
github.event.inputs.publish_github == 'true'

steps:
- name: Download NuGet packages
uses: actions/download-artifact@v4
with:
name: nuget-packages
path: nupkgs

# ── Publish to NuGet.org ──────────────────────────────────────────────
- name: Publish to NuGet.org
if: |
github.event_name == 'release' ||
github.event.inputs.publish_nuget == 'true'
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
run: |
dotnet nuget push nupkgs/*.nupkg \
--source https://api.nuget.org/v3/index.json \
--api-key "$NUGET_API_KEY" \
--skip-duplicate

# ── Publish to GitHub Packages ────────────────────────────────────────
- name: Publish to GitHub Packages
if: |
github.event_name == 'release' ||
github.event.inputs.publish_github == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
dotnet nuget add source \
"https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" \
--name github \
--username "${{ github.actor }}" \
--password "$GITHUB_TOKEN" \
--store-password-in-clear-text
dotnet nuget push nupkgs/*.nupkg \
--source github \
--skip-duplicate
21 changes: 21 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project>
<PropertyGroup>
<!-- Shared NuGet metadata inherited by every project in the repo. -->
<Authors>IoTSharp</Authors>
<Company>IoTSharp</Company>
<Copyright>Copyright © IoTSharp contributors</Copyright>
<PackageProjectUrl>https://github.com/IoTSharp/LVGLSharp.Forms</PackageProjectUrl>
<RepositoryUrl>https://github.com/IoTSharp/LVGLSharp.Forms</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>lvgl;embedded;ui;winforms;cross-platform</PackageTags>
<!-- Default version; overridden by CI via -p:Version=... -->
<Version>9.3.0</Version>
</PropertyGroup>

<!-- Include the repo-level README in every NuGet package. -->
<ItemGroup Condition="'$(IsPackable)' != 'false' And Exists('$(MSBuildThisFileDirectory)README.md')">
<None Include="$(MSBuildThisFileDirectory)README.md" Pack="true" PackagePath="\" Visible="false" />
</ItemGroup>
</Project>
11 changes: 11 additions & 0 deletions libs/cmake/toolchains/aarch64-linux-gnu.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
set(CMAKE_STRIP aarch64-linux-gnu-strip)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
11 changes: 11 additions & 0 deletions libs/cmake/toolchains/arm-linux-gnueabihf.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_STRIP arm-linux-gnueabihf-strip)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
11 changes: 11 additions & 0 deletions libs/cmake/toolchains/loongarch64-linux-gnu.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR loongarch64)

set(CMAKE_C_COMPILER loongarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER loongarch64-linux-gnu-g++)
set(CMAKE_STRIP loongarch64-linux-gnu-strip)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
Loading
Loading