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
101 changes: 101 additions & 0 deletions docs/how/cmake_bgfx/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
cmake_minimum_required(VERSION 3.20)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

project(cmake_bgfx CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(TSLANG_ROOT "" CACHE PATH "TypeScriptCompiler __build folder (contains tslang/, llvm/, gc/)")

include(LocateTSLang)
locate_tslang_compiler()
set(CMAKE_TSLANG_COMPILER "${CMAKE_TSLANG_COMPILER}" CACHE FILEPATH "TSLANG compiler" FORCE)

include(FetchContent)

set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_WAYLAND OFF CACHE BOOL "" FORCE)

FetchContent_Declare(
glfw
GIT_REPOSITORY https://github.com/glfw/glfw.git
GIT_TAG 3.4
GIT_SHALLOW TRUE)

set(BGFX_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(BGFX_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
set(BGFX_INSTALL OFF CACHE BOOL "" FORCE)

FetchContent_Declare(
bgfx
GIT_REPOSITORY https://github.com/bkaradzic/bgfx.cmake.git
GIT_TAG v1.150.9365-558
GIT_SHALLOW TRUE)

FetchContent_MakeAvailable(glfw bgfx)

enable_language(TSLANG)

setup_tslang_link_paths()

if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_TSLANG_FLAGS "--opt --opt_level=3")
else()
set(CMAKE_TSLANG_FLAGS "--di --opt_level=0")
endif()

if(WIN32)
else()
set(CMAKE_TSLANG_FLAGS "${CMAKE_TSLANG_FLAGS} -relocation-model=pic")
endif()

add_executable(${PROJECT_NAME}
src/main.ts
src/application.ts
src/appwindow.ts
native/bgfx_bridge.cpp
native/main_entry.cpp)

target_include_directories(${PROJECT_NAME} PRIVATE native)

set(TSLANG_LINK_LIBS
TypeScriptDefaultLib
TypeScriptAsyncRuntime
gc
LLVMSupport)

if(WIN32)
list(APPEND TSLANG_LINK_LIBS ntdll)
else()
find_library(TSLANG_TINFO_LIB NAMES tinfo)
list(APPEND TSLANG_LINK_LIBS LLVMDemangle stdc++ m pthread dl rt)
if(TSLANG_TINFO_LIB)
list(APPEND TSLANG_LINK_LIBS ${TSLANG_TINFO_LIB})
else()
list(APPEND TSLANG_LINK_LIBS tinfo)
endif()
endif()

target_link_libraries(${PROJECT_NAME}
PRIVATE
glfw
bgfx
bx
bimg
${TSLANG_LINK_LIBS})

if(UNIX AND NOT APPLE)
find_package(X11 REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE X11::X11)
endif()

add_custom_target(run
COMMAND "$<TARGET_FILE:${PROJECT_NAME}>"
DEPENDS ${PROJECT_NAME}
USES_TERMINAL
COMMENT "Running ${PROJECT_NAME}")
41 changes: 41 additions & 0 deletions docs/how/cmake_bgfx/CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 20,
"patch": 0
},
"configurePresets": [
{
"name": "default",
"displayName": "Default (Ninja)",
"description": "TSLANG custom language requires the Ninja generator.",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"TSLANG_ROOT": "${sourceDir}/../../../__build"
}
},
{
"name": "debug",
"displayName": "Debug (Ninja)",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build-debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"TSLANG_ROOT": "${sourceDir}/../../../__build"
}
}
],
"buildPresets": [
{
"name": "default",
"configurePreset": "default"
},
{
"name": "debug",
"configurePreset": "debug"
}
]
}
125 changes: 125 additions & 0 deletions docs/how/cmake_bgfx/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# bgfx + GLFW TypeScript sample

Cross-platform graphics sample for the TypeScript native compiler (`tslang`). Application logic is written in TypeScript; GLFW windowing and bgfx rendering live in a thin C++ bridge exposed through `.d.ts` FFI declarations.

Control flow matches [`cmake_vulkan`](../cmake_vulkan/) and [`cmake_winapp`](../cmake_winapp/): **C++ owns the event loop**, TypeScript creates the window and reacts via an `onMessage` callback.

## What it does

- Opens an 800x600 GLFW window (no client API — bgfx owns rendering)
- Initializes bgfx with the native window handle (Win32, X11, or Cocoa)
- C++ `run_loop()` polls GLFW and dispatches `Messages.Frame` each iteration
- TypeScript `onMessage` calls `run_bgfx_frame()` on Frame (like `run_vulkan()` on Paint)
- Renders an animated clear color and on-screen debug text: "Hello from tslang"
- Quits on Escape or window close

## Prerequisites

1. **Built `tslang`** — follow the main [README](../../../README.md) to build the compiler and install the default library (`tslang --install-default-lib`).
2. **CMake 3.20+** and **Ninja** (required for the custom `TSLANG` CMake language).
3. **C++20** toolchain (GCC, Clang, or MSVC).
4. **Graphics drivers** — bgfx auto-selects an available backend (OpenGL, Vulkan, DirectX on Windows).

### Linux packages (Fedora example)

```bash
sudo dnf install cmake ninja-build gcc-c++ ncurses-devel \
libX11-devel libXcursor-devel libXi-devel libXrandr-devel \
libXinerama-devel libXxf86vm-devel mesa-libGL-devel
```

### Windows

- Visual Studio 2022+ with C++ workload, CMake, and Ninja.
- Ensure `tslang.exe` is on `PATH` or pass `-DTSLANG_ROOT=...` pointing at the folder that contains `bin/tslang.exe`.

## Layout

```
cmake_bgfx/
├── CMakeLists.txt # FetchContent GLFW + bgfx, mixed TS/C++ target
├── CMakePresets.json
├── cmake/ # TSLANG custom language modules
├── src/
│ ├── main.ts # entry point (Main)
│ ├── application.ts # constructs AppWindow only
│ ├── appwindow.ts # onMessage handler (Frame / KeyDown / Close / Destroy)
│ └── bgfx_glfw.d.ts # FFI declarations
└── native/
├── bgfx_bridge.cpp # extern "C" GLFW + bgfx glue + run_loop()
└── main_entry.cpp # main() -> Main() -> run_loop()
```

## Build and run

### Linux

```bash
cd docs/how/cmake_bgfx

cmake --preset default
# or explicitly:
# cmake --preset default -DTSLANG_ROOT=/path/to/TypeScriptCompiler/__build

cmake --build --preset default
cmake --build --target run
```

Binary: `build/cmake_bgfx`

If CMake reports `tslang compiler not found`, build the compiler from the repo root first:

```bash
./prepare_3rdParty_release.sh
cd tslang && ./config_tslang_release.sh && ./build_tslang_release.sh
./bin/tslang --install-default-lib
```

Then re-run `cmake --preset default` from `docs/how/cmake_bgfx`.

### Windows

```bat
cd docs\how\cmake_bgfx

cmake --preset default -DTSLANG_ROOT=C:\path\to\TypeScriptCompiler\__build
cmake --build --preset default
cmake --build --target run
```

Binary: `build\cmake_bgfx.exe`

### macOS

Same CMake flow as Linux. Requires Xcode command-line tools and a working OpenGL/Metal backend for bgfx.

### Debug build

```bash
cmake --preset debug
cmake --build --preset debug
```

## How it works

1. **`main_entry.cpp`** calls TypeScript `Main()`, then C++ `run_loop()`.
2. **`Main()`** constructs `AppWindow`, which registers `onMessage` and calls `create_bgfx`.
3. **`run_loop()`** polls GLFW, dispatches `Messages.Frame` each tick, then `Messages.Destroy` on exit.
4. **CMake `TSLANG` language** compiles `.ts` sources to object files with `tslang --emit=obj`.
5. **`bgfx_bridge.cpp`** implements the flat `extern "C"` API declared in `bgfx_glfw.d.ts`.
6. **FetchContent** downloads GLFW 3.4 and [bgfx.cmake](https://github.com/bkaradzic/bgfx.cmake) on first configure.

## Platform notes

| Platform | Window backend | Notes |
|----------|----------------|-------|
| Windows | Win32 (`glfwGetWin32Window`) | bgfx D3D11/D3D12/OpenGL/Vulkan |
| Linux | X11 (`glfwGetX11Display` / `glfwGetX11Window`) | Wayland disabled (`GLFW_BUILD_WAYLAND=OFF`) |
| macOS | Cocoa (`glfwGetCocoaWindow`) | OpenGL/Metal via bgfx |

## Related samples

- [`cmake_winapp`](../cmake_winapp/) — Win32 window only (C++ message loop)
- [`cmake_vulkan`](../cmake_vulkan/) — Win32 + Vulkan cube (same onMessage pattern)
- [`cmake_tslang`](../cmake_tslang/) — mixed C++/TypeScript with custom CMake language
- [`c-cpp-header-import.md`](../../c-cpp-header-import.md) — FFI / native binding design
23 changes: 23 additions & 0 deletions docs/how/cmake_bgfx/cmake/CMakeDetermineTSLANGCompiler.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
include(${CMAKE_CURRENT_LIST_DIR}/LocateTSLang.cmake)

if(NOT CMAKE_TSLANG_COMPILER OR NOT EXISTS "${CMAKE_TSLANG_COMPILER}")
locate_tslang_compiler()
set(CMAKE_TSLANG_COMPILER "${CMAKE_TSLANG_COMPILER}" CACHE FILEPATH "TSLANG compiler" FORCE)
endif()

cmake_path(GET CMAKE_TSLANG_COMPILER PARENT_PATH CMAKE_TSLANG_DIR)

mark_as_advanced(CMAKE_TSLANG_COMPILER)
mark_as_advanced(CMAKE_TSLANG_DIR)

set(CMAKE_TSLANG_SOURCE_FILE_EXTENSIONS ts)
if(NOT WIN32)
set(CMAKE_TSLANG_OUTPUT_EXTENSION .o)
else()
set(CMAKE_TSLANG_OUTPUT_EXTENSION .obj)
endif()
set(CMAKE_TSLANG_COMPILER_ENV_VAR "TSLANG")

configure_file(
${CMAKE_CURRENT_LIST_DIR}/CMakeTSLANGCompiler.cmake.in
${CMAKE_PLATFORM_INFO_DIR}/CMakeTSLANGCompiler.cmake @ONLY)
6 changes: 6 additions & 0 deletions docs/how/cmake_bgfx/cmake/CMakeTSLANGCompiler.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
set(CMAKE_TSLANG_COMPILER "@CMAKE_TSLANG_COMPILER@")
set(CMAKE_TSLANG_DIR "@CMAKE_TSLANG_DIR@")
set(CMAKE_TSLANG_SOURCE_FILE_EXTENSIONS @CMAKE_TSLANG_SOURCE_FILE_EXTENSIONS@)
set(CMAKE_TSLANG_OUTPUT_EXTENSION @CMAKE_TSLANG_OUTPUT_EXTENSION@)
set(CMAKE_TSLANG_COMPILER_LOADED 1)
set(CMAKE_TSLANG_COMPILER_WORKS TRUE)
20 changes: 20 additions & 0 deletions docs/how/cmake_bgfx/cmake/CMakeTSLANGInformation.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# bx propagates -msse4.2 via PUBLIC compile options on GCC/Clang. tslang does
# not accept those flags, so filter them through a small wrapper on Unix.
get_filename_component(_TSLANG_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
set(_TSLANG_COMPILE_TEMPLATE
"<CMAKE_TSLANG_COMPILER> <FLAGS> --default-lib-path=${CMAKE_TSLANG_DIR} --emit=obj --export=none -o=<OBJECT> <SOURCE>")
if(NOT CMAKE_TSLANG_COMPILE_OBJECT)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
set(CMAKE_TSLANG_COMPILE_OBJECT
"${_TSLANG_CMAKE_DIR}/tslang_compile.sh ${_TSLANG_COMPILE_TEMPLATE}")
else()
set(CMAKE_TSLANG_COMPILE_OBJECT "${_TSLANG_COMPILE_TEMPLATE}")
endif()
endif()

if(NOT CMAKE_TSLANG_LINK_EXECUTABLE)
set(CMAKE_TSLANG_LINK_EXECUTABLE
"<CMAKE_CXX_COMPILER> <FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
endif()

set(CMAKE_TSLANG_INFORMATION_LOADED 1)
1 change: 1 addition & 0 deletions docs/how/cmake_bgfx/cmake/CMakeTestTSLANGCompiler.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
set(CMAKE_TSLANG_COMPILER_WORKS TRUE)
Loading
Loading