Skip to content

Build refactor + Windows #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2c4a9b9
Adds windows support
MichealReed Jul 18, 2024
3b7c8e6
windows support
MichealReed Jul 18, 2024
cb67989
fix python for linux builds
MichealReed Jul 18, 2024
36f031d
no need to copy object other than windows
MichealReed Jul 18, 2024
e02b241
fix debug makefiles
MichealReed Jul 18, 2024
4d55073
Windows_NT not Windows
MichealReed Jul 18, 2024
1730a65
abstract to example.cmake
MichealReed Jul 18, 2024
7d1c255
fix OS detection
MichealReed Jul 18, 2024
3e09549
Increase version and fix min max usage for Windows
MichealReed Jul 18, 2024
8b660c9
algorithm not needed
MichealReed Jul 18, 2024
3936258
fix standard for all examples
MichealReed Jul 18, 2024
422094c
CMake from root folder builds library
MichealReed Jul 18, 2024
1f8eee9
Don't forget to link the libraries to the object dude
MichealReed Jul 18, 2024
ebf4565
Merge remote-tracking branch 'origin/main' into build_refactor_windows
MichealReed Jul 19, 2024
00257a1
fix conflicts, set properties before link
MichealReed Jul 19, 2024
427ea77
Unify the example makefiles!
MichealReed Jul 19, 2024
ec934b3
rule to cleanup specific examples
MichealReed Jul 19, 2024
e50a1e2
Fix run rules
MichealReed Jul 19, 2024
e39d859
Fix linux run
MichealReed Jul 19, 2024
3803f39
Use CPP 17
MichealReed Jul 19, 2024
679faed
Update README.md
MichealReed Jul 19, 2024
d4452ee
Update README.md
MichealReed Jul 19, 2024
0d630b7
Fix matmul
MichealReed Jul 19, 2024
15c5415
fix clean matmul
MichealReed Jul 19, 2024
8e24753
Fix example standard
MichealReed Jul 19, 2024
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
5 changes: 2 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ examples/raymarch/build/*
docs/html
source
.DS_Store
third_party/lib/libdawn.*
third_party/lib/*.so
third_party/lib/*.dylib
third_party/lib/*
NUL
68 changes: 17 additions & 51 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,52 +1,19 @@
cmake_minimum_required(VERSION 3.11)
cmake_minimum_required(VERSION 3.28)
project(gpu)

include(FetchContent)
message(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
set(FETCHCONTENT_BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/fetchcontent")
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/webgpu.cmake")

set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # export compile_commands.json to use with LSP
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

option(USE_LOCAL_LIBS "Use local libraries instead of fetching from the internet" OFF)

# Define paths for local and remote repositories
set(WEBGPU_DIST_LOCAL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/third_party/local/WebGPU-distribution")

# Conditional assignment based on USE_LOCAL_LIBS
if(USE_LOCAL_LIBS)
set(WEBGPU_DIST_GIT_REPO ${WEBGPU_DIST_LOCAL_PATH})
message(STATUS "Using local WebGPU distribution: ${WEBGPU_DIST_LOCAL_PATH}")
else()
set(WEBGPU_DIST_GIT_REPO "https://github.com/eliemichel/WebGPU-distribution")
# Ensure the build type is set
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build: Debug or Release" FORCE)
endif()


option(WEBGPU_TAG "WebGPU distribution tag to use")
IF (NOT WEBGPU_TAG)
set(WEBGPU_TAG "dawn")
ENDIF()
message(STATUS "Using WebGPU distribution tag: ${WEBGPU_TAG}")

if (WEBGPU_TAG STREQUAL "dawn")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWEBGPU_BACKEND_DAWN")
# use specific commit
# set(WEBGPU_TAG "1025b977e1927b6d0327e67352f90feb4bcf8274")
# set(WEBGPU_TAG "acf972b7b909f52e183bdae3971b93bb13d4a29e")
# add_compile_options(-UABSL_INTERNAL_AT_LEAST_CXX20)
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -UABSL_INTERNAL_AT_LEAST_CXX20")
message(STATUS "Using Dawn backend")
endif()

FetchContent_Declare(
webgpu
GIT_REPOSITORY ${WEBGPU_DIST_GIT_REPO}
GIT_TAG ${WEBGPU_TAG}
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(webgpu)

option(FASTBUILD "Option to enable fast builds" OFF)
if(FASTBUILD)
set(CMAKE_BUILD_TYPE None) # Avoid default flags of predefined build types
Expand All @@ -59,19 +26,18 @@ if(DEBUG)
set(CMAKE_CXX_FLAGS "-O0 -g")
endif()

# dl for dlopen/dlysm/dlclose
find_library(LIBDL dl REQUIRED)
if(LIBDL)
message(STATUS "Found libdl: ${LIBDL}")
else()
message(FATAL_ERROR "libdl not found")
exit()
if(WIN64)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWEBGPU_BACKEND_DAWN")
endif()

include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/gpu.cmake")

# Build the library target (libgpu)

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(SRC_LIB gpu.h utils/shaders.h utils/array_utils.h utilslogging.h)
add_library(gpu SHARED ${SRC_LIB})
set_target_properties(gpu PROPERTIES LINKER_LANGUAGE CXX)
message(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
message(STATUS "Include directories for wgpu: ${CMAKE_CURRENT_SOURCE_DIR}/third_party/headers")

add_library(gpud SHARED gpu.h)
set_target_properties(gpud PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(gpud PRIVATE wgpu)
target_link_libraries(gpud PRIVATE webgpu)
target_link_libraries(gpud PRIVATE gpu)
install(TARGETS gpud)
225 changes: 158 additions & 67 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,104 +1,195 @@
NUM_JOBS=$(shell nproc)
NUM_JOBS=$(shell nproc 2>/dev/null || echo 1)
CXX=clang++

.PHONY: default examples/hello_world/build/hello_world tests libgpu debug build check-clang clean-build clean all watch-tests docs

GPUCPP ?= $(PWD)
LIBDIR ?= $(GPUCPP)/third_party/lib
LIBSPEC ?= . $(GPUCPP)/source

default: examples/hello_world/build/hello_world

pch:
mkdir -p build && $(CXX) -std=c++17 -I$(GPUCPP) -I$(GPUCPP)/third_party/headers -x c++-header gpu.h -o build/gpu.h.pch

# TODO(avh): change extension based on platform
lib:
mkdir -p build && $(CXX) -std=c++17 -I$(GPUCPP) -I$(GPUCPP)/third_party/headers -L$(LIBDIR) -ldawn -ldl -shared -fPIC gpu.cpp -o build/libgpucpp.dylib

examples/hello_world/build/hello_world: check-clang dawnlib examples/hello_world/run.cpp check-linux-vulkan
$(LIBSPEC) && cd examples/hello_world && make build/hello_world && ./build/hello_world

dawnlib: $(if $(wildcard third_party/lib/libdawn.so third_party/lib/libdawn.dylib),,run_setup)
.PHONY: default examples_hello_world_build_hello_world tests libgpu debug build check-entr check-clang clean-build clean clean-dawnlib clean-all all watch-tests docs
.PHONY: $(addprefix run_, $(TARGETS))

# List of targets (folders in your examples directory)
TARGETS := gpu_puzzles hello_world matmul physics render shadertui

# Set up variables for cross-platform compatibility
ifeq ($(OS),Windows_NT)
DETECTED_OS := Windows
MKDIR_CMD := if not exist build mkdir build
RMDIR_CMD := rmdir
SLASH := \\
LS_CMD := dir
LDLIB_SUFFIX := dll
EXPORT_CMD := set
else
DETECTED_OS := $(shell uname)
MKDIR_CMD := mkdir -p build
RMDIR_CMD := rm -rf
SLASH := /
LS_CMD := ls
LDLIB_SUFFIX := so
EXPORT_CMD := export
endif

# Determine the architecture
ifeq ($(OS),Windows_NT)
ifeq ($(PROCESSOR_ARCHITECTURE),AMD64)
ARCH := x64
else
ARCH := x86
endif
else
ARCH := $(shell uname -m)
ifeq ($(ARCH), x86_64)
ARCH := x64
else ifneq (,$(findstring arm, $(ARCH)))
ARCH := arm
endif
endif

# Determine the build type
BUILD_TYPE ?= Release
LOWER_BUILD_TYPE ?= $(shell python3 -c "print('$(BUILD_TYPE)'.lower())")

# Paths
GPUCPP ?= $(shell pwd)
LIBDIR ?= $(GPUCPP)$(SLASH)third_party$(SLASH)lib
LIBSPEC ?= . $(GPUCPP)$(SLASH)source

default: run_hello_world

# Define Run Rules
define RUN_RULES
run_$(1):
@cd examples && $(MAKE) run_$(1)
endef
# Apply Run Rules to each target in $(TARGETS)
$(foreach target,$(TARGETS),$(eval $(call RUN_RULES,$(target))))

# Build rules for specific targets
define BUILD_RULES
build_$(1):
ifeq ($(OS),Windows_NT)
cd examples && $(MAKE) $(1)_$(LOWER_BUILD_TYPE)
else
cd examples&& $(MAKE) $(1)_$(LOWER_BUILD_TYPE)
endif
endef
$(foreach target, $(TARGETS), $(eval $(call BUILD_RULES,$(target))))

# We use the custom "shell" based condition to check files cross-platform
dawnlib:
ifeq ($(OS),Windows_NT)
@if not exist "$(LIBDIR)$(SLASH)libdawn_$(ARCH)_$(BUILD_TYPE).dll" if not exist "$(LIBDIR)$(SLASH)libdawn.dll" $(MAKE) run_setup
else
@if [ ! -f "$(LIBDIR)$(SLASH)libdawn_$(ARCH)_$(BUILD_TYPE).so" ] && [ ! -f "$(LIBDIR)$(SLASH)libdawn.so" ] && [ ! -f "$(LIBDIR)$(SLASH)libdawn_$(ARCH)_$(BUILD_TYPE).dylib" ]; then \
$(MAKE) run_setup; \
fi
endif

run_setup: check-python
ifeq ($(OS),Windows_NT)
python3 setup.py
else
python3 >/dev/null 2>&1 && python3 setup.py
endif

all: dawnlib check-clang check-linux-vulkan lib pch
cd examples/gpu_puzzles && make build/gpu_puzzles
cd examples/hello_world && make build/hello_world
cd examples/matmul && make build/mm
cd examples/physics && make build/physics
cd examples/render && make build/render
all: dawnlib check-clang check-linux-vulkan
cd examples$(SLASH)gpu_puzzles && make build$(SLASH)gpu_puzzles
cd examples$(SLASH)hello_world && make build$(SLASH)hello_world
cd examples$(SLASH)matmul && make build$(SLASH)mm
cd examples$(SLASH)physics && make build$(SLASH)physics
cd examples$(SLASH)render && make build$(SLASH)render

docs: Doxyfile
doxygen Doxyfile

################################################################################
# cmake targets (optional - precompiled binaries is preferred)
################################################################################

CMAKE_CMD = mkdir -p build && cd build && cmake ..
# Add --trace to see the cmake commands
FLAGS = -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_CXX_COMPILER=$(CXX) -DABSL_INTERNAL_AT_LEAST_CXX20=OFF
FASTBUILD_FLAGS = $(FLAGS) -DFASTBUILD:BOOL=ON
DEBUG_FLAGS = $(FLAGS) -DDEBUG:BOOL=ON
RELEASE_FLAGS = $(FLAGS) -DFASTBUILD:BOOL=OFF
TARGET_LIB=gpu

libgpu-cmake: check-clang check-cmake
$(CMAKE_CMD) $(RELEASE_FLAGS) && make -j$(NUM_JOBS) gpu

debug-cmake: check-clang check-cmake
$(CMAKE_CMD) $(DEBUG_FLAGS) && make -j$(NUM_JOBS) $(TARGET_ALL)

all-cmake: check-clang check-cmake
$(CMAKE_CMD) $(RELEASE_FLAGS) && make -j$(NUM_JOBS) $(TARGET_ALL)

################################################################################
# Cleanup
################################################################################

# Clean rules for cleaning specific targets
define CLEAN_RULES
clean_$(1):
ifeq ($(OS),Windows_NT)
@if exist examples$(SLASH)$(1)$(SLASH)build ( $(RMDIR_CMD) /s examples$(SLASH)$(1)$(SLASH)build )
else
find examples$(SLASH)$(1) -name build -type d | xargs rm -rf
endif
endef
$(foreach target,$(TARGETS),$(eval $(call CLEAN_RULES,$(target))))

clean-dawnlib:
rm -f third_party/lib/libdawn.so third_party/lib/libdawn.dylib
$(RMDIR_CMD) $(LIBDIR)$(SLASH)libdawn*.*

clean:
read -r -p "This will delete the contents of build/*. Are you sure? [CTRL-C to abort] " response && rm -rf build/*
rm -rf examples/gpu_puzzles/build/*
rm -rf examples/hello_world/build/*
ifeq ($(OS),Windows_NT)
@if exist build $(RMDIR_CMD) build /s /q
@if exist examples$(SLASH)gpu_puzzles$(SLASH)build $(RMDIR_CMD) examples$(SLASH)gpu_puzzles$(SLASH)build /s /q
@if exist examples$(SLASH)hello_world$(SLASH)build $(RMDIR_CMD) examples$(SLASH)hello_world$(SLASH)build /s /q
@if exist examples$(SLASH)matmul$(SLASH)build $(RMDIR_CMD) examples$(SLASH)matmul$(SLASH)build /s /q
@if exist examples$(SLASH)physics$(SLASH)build $(RMDIR_CMD) examples$(SLASH)physics$(SLASH)build /s /q
@if exist examples$(SLASH)render$(SLASH)build $(RMDIR_CMD) examples$(SLASH)render$(SLASH)build /s /q
@if exist build$(SLASH)gpu.h.pch del build$(SLASH)gpu.h.pch
$(MKDIR_CMD)
else
@command read -r -p "This will delete the contents of build/*. Are you sure? [CTRL-C to abort] " response && rm -rf build*
rm -rf examples/gpu_puzzles/build*
rm -rf examples/hello_world/build*
rm -rf examples/matmul/build/mm
rm -rf examples/physics/build/*
rm -rf examples/render/build/*
rm -f build/gpu.h.pch
rm -f build/libgpucpp.so
endif

clean-all:
read -r -p "This will delete the contents of build/* and third_party/*. Are you sure? [CTRL-C to abort] " response && rm -rf build/* third_party/fetchcontent/* third_party/gpu-build third_party/gpu-subbuild third_party/gpu-src third_party/lib/libdawn.so third_party/lib/libdawn.dylib
ifeq ($(OS),Windows_NT)
@if exist build $(RMDIR_CMD) build /s /q
$(RMDIR_CMD) third_party$(SLASH)fetchcontent /s /q
$(RMDIR_CMD) third_party$(SLASH)gpu-build /s /q
$(RMDIR_CMD) third_party$(SLASH)gpu-subbuild /s /q
$(RMDIR_CMD) third_party$(SLASH)gpu-src /s /q
$(RMDIR_CMD) third_party$(SLASH)lib /s /q
$(MKDIR_CMD)
else
read -r -p "This will delete the contents of build/* and third_party/*. Are you sure? [CTRL-C to abort] " response && rm -rf build* third_party/fetchcontent* third_party/gpu-build third_party/gpu-subbuild third_party/gpu-src third_party/lib/libdawn* third_party/lib/libdawn_$(ARCH)_$(BUILD_TYPE).*
endif

################################################################################
# Checks
################################################################################

# check for the existence of clang++ and cmake
# check for the existence of clang++
check-clang:
ifeq ($(OS),Windows_NT)
@if not exist "$(shell where clang++.exe 2>NUL)" (echo "Please install clang++ with 'sudo apt-get install clang' or 'brew install llvm'" & exit 1)
else
@command -v clang++ >/dev/null 2>&1 || { echo >&2 "Please install clang++ with 'sudo apt-get install clang' or 'brew install llvm'"; exit 1; }
endif

# check for the existence of entr
check-entr:
ifeq ($(OS),Windows_NT)
@if not exist "$(shell where entr.exe 2>NUL)" (echo "Please install entr with 'brew install entr' or 'sudo apt-get install entr'" & exit 1)
else
@command -v entr >/dev/null 2>&1 || { echo >&2 "Please install entr with 'brew install entr' or 'sudo apt-get install entr'"; exit 1; }
endif

# check for the existence of cmake
check-cmake:
ifeq ($(OS),Windows_NT)
@if not exist "$(shell where cmake.exe 2>NUL)" (echo "Please install cmake with 'sudo apt-get install cmake' or 'brew install cmake'" & exit 1)
else
@command -v cmake >/dev/null 2>&1 || { echo >&2 "Please install cmake with 'sudo apt-get install cmake' or 'brew install cmake'"; exit 1; }
endif

# check for the existence of python3
check-python:
@command -v python3 >/dev/null 2>&1 || { echo >&2 "Python needs to be installed and in your path."; exit 1; }
ifeq ($(OS),Windows_NT)
@if not exist "$(shell where python3.exe 2>NUL)" (echo "Python needs to be installed and in your path." & exit 1)
else
@command -v python3 >/dev/null 2>&1 || { echo >&2 "Python needs to be installed and in your path."; exit 1; }
endif

# check the existence of Vulkan (Linux only)
check-linux-vulkan:
@echo "Checking system type and Vulkan availability..."
@if [ "$$(uname)" = "Linux" ]; then \
if command -v vulkaninfo >/dev/null 2>&1; then \
echo "Vulkan is installed."; \
vulkaninfo; \
else \
echo "Vulkan is not installed. Please install Vulkan drivers to continue. On Debian / Ubuntu: sudo apt install libvulkan1 mesa-vulkan-drivers vulkan-tools"; \
exit 1; \
fi \
else \
echo "Non-Linux system detected. Skipping Vulkan check."; \
fi
ifeq ($(OS),Linux)
@command -v vulkaninfo >/dev/null 2>&1 && { echo "Vulkan is installed."; vulkaninfo; } || { echo "Vulkan is not installed. Please install Vulkan drivers to continue. On Debian / Ubuntu: sudo apt install libvulkan1 mesa-vulkan-drivers vulkan-tools"; exit 1; }
else
@echo "Non-Linux system detected. Skipping Vulkan check.";
endif
Loading
Loading