Skip to content
Draft
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
142 changes: 142 additions & 0 deletions .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: Deploy docs and tutorials website

on:
release:
types: [ published ]
workflow_dispatch:
inputs:
target_repo:
description: >-
Repo to deploy to. Override with a personal fork (e.g.
your-username/halide.github.com) to rehearse a real push
without touching the live site.
default: halide/halide.github.com
required: false
dry_run:
description: >-
Build and diff only -- never push anywhere, even to target_repo
above. Uploads the generated docs/ and tutorials/ as a workflow
artifact instead, for manual inspection. This is the safe default
for testing changes to this workflow or the generator itself.
type: boolean
default: true

permissions:
contents: read

env:
TARGET_REPO: ${{ github.event.inputs.target_repo || 'halide/halide.github.com' }}
# Only ever a real push for `release` events -- any workflow_dispatch run
# defaults to a dry run unless explicitly opted out.
DRY_RUN: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run || 'false' }}

jobs:
deploy:
name: Build and deploy to halide.github.com
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v7

- uses: astral-sh/setup-uv@v7

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libpng-dev libjpeg-dev doxygen gdb

- name: Sync CI environment
run: |
uv sync --group ci-llvm-22 --group tutorial-website --no-install-project
echo "${GITHUB_WORKSPACE}/.venv/bin" >> "$GITHUB_PATH"
echo "VIRTUAL_ENV=${GITHUB_WORKSPACE}/.venv" >> "$GITHUB_ENV"

- name: Configure LLVM
run: echo "Halide_LLVM_ROOT=$(halide-llvm --prefix)" >> "$GITHUB_ENV"

- uses: actions/create-github-app-token@v3
id: app-token
with:
app-id: ${{ secrets.LLVM_UPDATER_ID }}
private-key: ${{ secrets.LLVM_UPDATER_PRIVATE_KEY }}

- name: Get GitHub App user ID
id: get-user-id
run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}

- name: Checkout ${{ env.TARGET_REPO }}
uses: actions/checkout@v7
with:
repository: ${{ env.TARGET_REPO }}
ref: master
token: ${{ steps.app-token.outputs.token }}
path: halide.github.com

- name: Configure CMake
run: >-
cmake --preset ci-linux-x86-64
-DWITH_DOCS=ON
-DWITH_TUTORIAL_WEBSITE=ON
-DHalide_TUTORIAL_WEBSITE_DEBUGGER=GDB
-DHalide_INSTALL_DOXYGENDIR=docs
-DHalide_INSTALL_TUTORIALDIR=tutorials
-DWITH_TESTS=NO
-DWITH_PYTHON_BINDINGS=NO
-DWITH_UTILS=NO

- name: Build docs and tutorials website
run: cmake --build build --target doc --target tutorial_website

- name: Replace docs/ and tutorials/
id: replace
run: |
git config --global user.name "${{ steps.app-token.outputs.app-slug }}[bot]"
git config --global user.email "${{ steps.get-user-id.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com"

# Halide_INSTALL_DOXYGENDIR/Halide_INSTALL_TUTORIALDIR above point
# the Halide_Doxygen/Halide_Tutorial components directly at
# halide.github.com's own docs/ and tutorials/ layout, so no
# staging directory or path-guessing is needed -- clear stale
# content first (so removed/renamed lessons don't linger), then
# install straight into the checkout.
rm -rf halide.github.com/docs halide.github.com/tutorials
cmake --install build --prefix "$GITHUB_WORKSPACE/halide.github.com" --component Halide_Doxygen
cmake --install build --prefix "$GITHUB_WORKSPACE/halide.github.com" --component Halide_Tutorial

cd halide.github.com
git add -A

if git diff --cached --quiet; then
echo "No changes to deploy."
echo "has-changes=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "has-changes=true" >> "$GITHUB_OUTPUT"
git diff --cached --stat

- name: Upload docs/tutorials as an artifact (dry run)
if: steps.replace.outputs.has-changes == 'true' && env.DRY_RUN == 'true'
uses: actions/upload-artifact@v7
with:
name: docs-tutorials-site
path: |
halide.github.com/docs
halide.github.com/tutorials
retention-days: 7

- name: Commit and push
if: steps.replace.outputs.has-changes == 'true' && env.DRY_RUN != 'true'
working-directory: halide.github.com
run: |
if [ -n "${{ github.event.release.tag_name }}" ]; then
MESSAGE="Deploy docs and tutorials for Halide ${{ github.event.release.tag_name }}"
else
MESSAGE="Deploy docs and tutorials (manual run from halide/Halide@${{ github.sha }})"
fi

git commit -m "$MESSAGE"
# actions/checkout leaves a detached HEAD, so push explicitly by
# refspec rather than relying on a tracked branch.
git push origin HEAD:master
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,12 @@ Halide_feature(
)
Halide_feature(WITH_TESTS "Halide's unit test suite" TOP_LEVEL)
Halide_feature(WITH_TUTORIALS "Halide's tutorial code" TOP_LEVEL)
Halide_feature(
WITH_TUTORIAL_WEBSITE
"Generate the Halide tutorials website (requires gdb or lldb, and Python's pygments)"
OFF
DEPENDS WITH_TUTORIALS
)
Halide_feature(
WITH_UTILS "Optional utility programs for Halide, including HalideTraceViz" TOP_LEVEL
)
Expand Down
34 changes: 33 additions & 1 deletion packaging/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ set(Halide_INSTALL_TOOLSDIR "${CMAKE_INSTALL_DATADIR}/tools"
CACHE STRING "Path to Halide build-time tools and sources"
)

set(Halide_INSTALL_TUTORIALDIR "${CMAKE_INSTALL_DATADIR}/tutorial"
CACHE STRING "Path to Halide's generated tutorial website"
)

set(Halide_INSTALL_DOXYGENDIR "${CMAKE_INSTALL_DOCDIR}/html"
CACHE STRING "Path to Halide's generated Doxygen documentation"
)

##
# RPATH patching helper
##
Expand Down Expand Up @@ -187,6 +195,14 @@ if (WITH_TUTORIALS)
)
endif ()

if (WITH_TUTORIAL_WEBSITE)
install(
DIRECTORY ${Halide_BINARY_DIR}/tutorial/website/site/
DESTINATION ${Halide_INSTALL_TUTORIALDIR}
COMPONENT Halide_Tutorial
)
endif ()

##
# CMake scripts
##
Expand Down Expand Up @@ -335,7 +351,11 @@ _Halide_install_pkgdeps(
##

if (WITH_DOCS)
install(DIRECTORY ${Halide_BINARY_DIR}/doc/html TYPE DOC COMPONENT Halide_Documentation)
install(
DIRECTORY ${Halide_BINARY_DIR}/doc/html/
DESTINATION ${Halide_INSTALL_DOXYGENDIR}
COMPONENT Halide_Doxygen
)
endif ()

##
Expand Down Expand Up @@ -405,3 +425,15 @@ cpack_add_component(
DISPLAY_NAME "Halide documentation"
DESCRIPTION "Documentation for Halide"
)

cpack_add_component(
Halide_Doxygen
DISPLAY_NAME "Halide Doxygen documentation"
DESCRIPTION "Generated Doxygen API documentation (WITH_DOCS)"
)

cpack_add_component(
Halide_Tutorial
DISPLAY_NAME "Halide tutorial website"
DESCRIPTION "Generated HTML tutorial website (WITH_TUTORIAL_WEBSITE)"
)
6 changes: 6 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ tools = [
"ruff>=0.12",
"tbump>=6.11",
]
tutorial-website = [
# for tutorial/website -- generates the tutorials website via gdb/lldb
"jinja2>=3.1",
"markupsafe>=3.0",
"pygments>=2.17",
]

ci-base = [
{ include-group = "dev" },
Expand Down
38 changes: 38 additions & 0 deletions tutorial/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,27 @@ function(add_tutorial source_file)
if (args_WITH_IMAGE_IO)
target_link_libraries(${name} PRIVATE Halide::ImageIO)
endif ()

_Halide_register_tutorial_website_target("${source_file}" "${name}")
endfunction()

# Registers a lesson source file's corresponding executable target so that
# tutorial/website can locate its built binary (by way of a generate-time
# manifest, since executable output paths aren't known until then), and
# builds it unoptimized with debug info, regardless of build type, so that
# single-line stepping/breakpoints are reliable (matches
# test/debugger/CMakeLists.txt's debugger_fixture, which needs the same thing
# for the same reason: at -O2/-O3, reordered/merged line-table entries make
# `next`/one-shot breakpoints land on the wrong statement).
function(_Halide_register_tutorial_website_target source_file target)
if (NOT WITH_TUTORIAL_WEBSITE)
return()
endif ()
target_compile_options(
${target}
PRIVATE $<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-g;-O0;-fno-omit-frame-pointer>
)
set_property(GLOBAL APPEND PROPERTY HALIDE_TUTORIAL_SOURCE_TARGETS "${source_file}=${target}")
endfunction()

# Declare tutorials
Expand Down Expand Up @@ -107,6 +128,10 @@ if ("NVPTX" IN_LIST Halide_LLVM_COMPONENTS)
PRIVATE "${CMAKE_CURRENT_BINARY_DIR}"
)

_Halide_register_tutorial_website_target(
lesson_10_aot_compilation_run.cpp lesson_10_aot_compilation_run
)

add_test(NAME tutorial_lesson_10_aot_compilation_run COMMAND lesson_10_aot_compilation_run)
set_tests_properties(
tutorial_lesson_10_aot_compilation_run
Expand All @@ -125,6 +150,7 @@ add_tutorial(lesson_14_types.cpp)
# Lesson 15
add_executable(lesson_15_generate lesson_15_generators.cpp)
target_link_libraries(lesson_15_generate PRIVATE Halide::Generator)
_Halide_register_tutorial_website_target(lesson_15_generators.cpp lesson_15_generate)

## Hack to build the libraries

Expand Down Expand Up @@ -217,6 +243,7 @@ if (Halide_TARGET MATCHES "wasm")
else ()
add_executable(lesson_16_rgb_generate lesson_16_rgb_generate.cpp)
target_link_libraries(lesson_16_rgb_generate PRIVATE Halide::Generator)
_Halide_register_tutorial_website_target(lesson_16_rgb_generate.cpp lesson_16_rgb_generate)

add_halide_library(
brighten_planar
Expand Down Expand Up @@ -254,6 +281,7 @@ else ()
brighten_planar brighten_interleaved brighten_either brighten_specialized Halide::ImageIO
Halide::Tools
)
_Halide_register_tutorial_website_target(lesson_16_rgb_run.cpp lesson_16_rgb_run)

add_test(NAME tutorial_lesson_16_rgb_run COMMAND lesson_16_rgb_run)
set_tests_properties(tutorial_lesson_16_rgb_run PROPERTIES LABELS tutorial)
Expand All @@ -269,6 +297,9 @@ add_tutorial(lesson_20_cloning_funcs.cpp)
if (TARGET Halide::Mullapudi2016)
add_executable(lesson_21_auto_scheduler_generate lesson_21_auto_scheduler_generate.cpp)
target_link_libraries(lesson_21_auto_scheduler_generate PRIVATE Halide::Generator)
_Halide_register_tutorial_website_target(
lesson_21_auto_scheduler_generate.cpp lesson_21_auto_scheduler_generate
)

add_halide_library(
auto_schedule_false
Expand All @@ -293,6 +324,9 @@ if (TARGET Halide::Mullapudi2016)
lesson_21_auto_scheduler_run
PRIVATE auto_schedule_false auto_schedule_true Halide::Tools
)
_Halide_register_tutorial_website_target(
lesson_21_auto_scheduler_run.cpp lesson_21_auto_scheduler_run
)

add_test(NAME tutorial_lesson_21_auto_scheduler_run COMMAND lesson_21_auto_scheduler_run)
set_tests_properties(
Expand All @@ -307,3 +341,7 @@ endif ()
add_tutorial(lesson_22_jit_performance.cpp)
add_tutorial(lesson_23_serialization.cpp WITH_IMAGE_IO)
add_tutorial(lesson_24_async.cpp GROUPS multithreaded)

if (WITH_TUTORIAL_WEBSITE)
add_subdirectory(website)
endif ()
Loading
Loading