Skip to content

Commit 1f5c75f

Browse files
authored
Merge pull request #16 from MichealReed/build_refactor_windows
Build refactor + Windows
2 parents 476c5cf + 8e24753 commit 1f5c75f

File tree

26 files changed

+751
-362
lines changed

26 files changed

+751
-362
lines changed

.gitignore

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,5 @@ examples/raymarch/build/*
66
docs/html
77
source
88
.DS_Store
9-
third_party/lib/libdawn.*
10-
third_party/lib/*.so
11-
third_party/lib/*.dylib
9+
third_party/lib/*
10+
NUL

CMakeLists.txt

Lines changed: 17 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,19 @@
1-
cmake_minimum_required(VERSION 3.11)
1+
cmake_minimum_required(VERSION 3.28)
22
project(gpu)
33

4-
include(FetchContent)
5-
message(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
6-
set(FETCHCONTENT_BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/fetchcontent")
4+
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/webgpu.cmake")
75

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

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

14-
# Define paths for local and remote repositories
15-
set(WEBGPU_DIST_LOCAL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/third_party/local/WebGPU-distribution")
16-
17-
# Conditional assignment based on USE_LOCAL_LIBS
18-
if(USE_LOCAL_LIBS)
19-
set(WEBGPU_DIST_GIT_REPO ${WEBGPU_DIST_LOCAL_PATH})
20-
message(STATUS "Using local WebGPU distribution: ${WEBGPU_DIST_LOCAL_PATH}")
21-
else()
22-
set(WEBGPU_DIST_GIT_REPO "https://github.com/eliemichel/WebGPU-distribution")
12+
# Ensure the build type is set
13+
if(NOT CMAKE_BUILD_TYPE)
14+
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build: Debug or Release" FORCE)
2315
endif()
2416

25-
26-
option(WEBGPU_TAG "WebGPU distribution tag to use")
27-
IF (NOT WEBGPU_TAG)
28-
set(WEBGPU_TAG "dawn")
29-
ENDIF()
30-
message(STATUS "Using WebGPU distribution tag: ${WEBGPU_TAG}")
31-
32-
if (WEBGPU_TAG STREQUAL "dawn")
33-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWEBGPU_BACKEND_DAWN")
34-
# use specific commit
35-
# set(WEBGPU_TAG "1025b977e1927b6d0327e67352f90feb4bcf8274")
36-
# set(WEBGPU_TAG "acf972b7b909f52e183bdae3971b93bb13d4a29e")
37-
# add_compile_options(-UABSL_INTERNAL_AT_LEAST_CXX20)
38-
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -UABSL_INTERNAL_AT_LEAST_CXX20")
39-
message(STATUS "Using Dawn backend")
40-
endif()
41-
42-
FetchContent_Declare(
43-
webgpu
44-
GIT_REPOSITORY ${WEBGPU_DIST_GIT_REPO}
45-
GIT_TAG ${WEBGPU_TAG}
46-
GIT_SHALLOW TRUE
47-
)
48-
FetchContent_MakeAvailable(webgpu)
49-
5017
option(FASTBUILD "Option to enable fast builds" OFF)
5118
if(FASTBUILD)
5219
set(CMAKE_BUILD_TYPE None) # Avoid default flags of predefined build types
@@ -59,19 +26,18 @@ if(DEBUG)
5926
set(CMAKE_CXX_FLAGS "-O0 -g")
6027
endif()
6128

62-
# dl for dlopen/dlysm/dlclose
63-
find_library(LIBDL dl REQUIRED)
64-
if(LIBDL)
65-
message(STATUS "Found libdl: ${LIBDL}")
66-
else()
67-
message(FATAL_ERROR "libdl not found")
68-
exit()
29+
if(WIN64)
30+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWEBGPU_BACKEND_DAWN")
6931
endif()
7032

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

72-
# Build the library target (libgpu)
73-
74-
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
75-
set(SRC_LIB gpu.h utils/shaders.h utils/array_utils.h utilslogging.h)
76-
add_library(gpu SHARED ${SRC_LIB})
77-
set_target_properties(gpu PROPERTIES LINKER_LANGUAGE CXX)
35+
message(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
36+
message(STATUS "Include directories for wgpu: ${CMAKE_CURRENT_SOURCE_DIR}/third_party/headers")
37+
38+
add_library(gpud SHARED gpu.h)
39+
set_target_properties(gpud PROPERTIES LINKER_LANGUAGE CXX)
40+
target_link_libraries(gpud PRIVATE wgpu)
41+
target_link_libraries(gpud PRIVATE webgpu)
42+
target_link_libraries(gpud PRIVATE gpu)
43+
install(TARGETS gpud)

Makefile

Lines changed: 158 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,195 @@
1-
NUM_JOBS=$(shell nproc)
1+
NUM_JOBS=$(shell nproc 2>/dev/null || echo 1)
22
CXX=clang++
33

4-
.PHONY: default examples/hello_world/build/hello_world tests libgpu debug build check-clang clean-build clean all watch-tests docs
5-
6-
GPUCPP ?= $(PWD)
7-
LIBDIR ?= $(GPUCPP)/third_party/lib
8-
LIBSPEC ?= . $(GPUCPP)/source
9-
10-
default: examples/hello_world/build/hello_world
11-
12-
pch:
13-
mkdir -p build && $(CXX) -std=c++17 -I$(GPUCPP) -I$(GPUCPP)/third_party/headers -x c++-header gpu.h -o build/gpu.h.pch
14-
15-
# TODO(avh): change extension based on platform
16-
lib:
17-
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
18-
19-
examples/hello_world/build/hello_world: check-clang dawnlib examples/hello_world/run.cpp check-linux-vulkan
20-
$(LIBSPEC) && cd examples/hello_world && make build/hello_world && ./build/hello_world
21-
22-
dawnlib: $(if $(wildcard third_party/lib/libdawn.so third_party/lib/libdawn.dylib),,run_setup)
4+
.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
5+
.PHONY: $(addprefix run_, $(TARGETS))
6+
7+
# List of targets (folders in your examples directory)
8+
TARGETS := gpu_puzzles hello_world matmul physics render shadertui
9+
10+
# Set up variables for cross-platform compatibility
11+
ifeq ($(OS),Windows_NT)
12+
DETECTED_OS := Windows
13+
MKDIR_CMD := if not exist build mkdir build
14+
RMDIR_CMD := rmdir
15+
SLASH := \\
16+
LS_CMD := dir
17+
LDLIB_SUFFIX := dll
18+
EXPORT_CMD := set
19+
else
20+
DETECTED_OS := $(shell uname)
21+
MKDIR_CMD := mkdir -p build
22+
RMDIR_CMD := rm -rf
23+
SLASH := /
24+
LS_CMD := ls
25+
LDLIB_SUFFIX := so
26+
EXPORT_CMD := export
27+
endif
28+
29+
# Determine the architecture
30+
ifeq ($(OS),Windows_NT)
31+
ifeq ($(PROCESSOR_ARCHITECTURE),AMD64)
32+
ARCH := x64
33+
else
34+
ARCH := x86
35+
endif
36+
else
37+
ARCH := $(shell uname -m)
38+
ifeq ($(ARCH), x86_64)
39+
ARCH := x64
40+
else ifneq (,$(findstring arm, $(ARCH)))
41+
ARCH := arm
42+
endif
43+
endif
44+
45+
# Determine the build type
46+
BUILD_TYPE ?= Release
47+
LOWER_BUILD_TYPE ?= $(shell python3 -c "print('$(BUILD_TYPE)'.lower())")
48+
49+
# Paths
50+
GPUCPP ?= $(shell pwd)
51+
LIBDIR ?= $(GPUCPP)$(SLASH)third_party$(SLASH)lib
52+
LIBSPEC ?= . $(GPUCPP)$(SLASH)source
53+
54+
default: run_hello_world
55+
56+
# Define Run Rules
57+
define RUN_RULES
58+
run_$(1):
59+
@cd examples && $(MAKE) run_$(1)
60+
endef
61+
# Apply Run Rules to each target in $(TARGETS)
62+
$(foreach target,$(TARGETS),$(eval $(call RUN_RULES,$(target))))
63+
64+
# Build rules for specific targets
65+
define BUILD_RULES
66+
build_$(1):
67+
ifeq ($(OS),Windows_NT)
68+
cd examples && $(MAKE) $(1)_$(LOWER_BUILD_TYPE)
69+
else
70+
cd examples&& $(MAKE) $(1)_$(LOWER_BUILD_TYPE)
71+
endif
72+
endef
73+
$(foreach target, $(TARGETS), $(eval $(call BUILD_RULES,$(target))))
74+
75+
# We use the custom "shell" based condition to check files cross-platform
76+
dawnlib:
77+
ifeq ($(OS),Windows_NT)
78+
@if not exist "$(LIBDIR)$(SLASH)libdawn_$(ARCH)_$(BUILD_TYPE).dll" if not exist "$(LIBDIR)$(SLASH)libdawn.dll" $(MAKE) run_setup
79+
else
80+
@if [ ! -f "$(LIBDIR)$(SLASH)libdawn_$(ARCH)_$(BUILD_TYPE).so" ] && [ ! -f "$(LIBDIR)$(SLASH)libdawn.so" ] && [ ! -f "$(LIBDIR)$(SLASH)libdawn_$(ARCH)_$(BUILD_TYPE).dylib" ]; then \
81+
$(MAKE) run_setup; \
82+
fi
83+
endif
2384

2485
run_setup: check-python
86+
ifeq ($(OS),Windows_NT)
2587
python3 setup.py
88+
else
89+
python3 >/dev/null 2>&1 && python3 setup.py
90+
endif
2691

27-
all: dawnlib check-clang check-linux-vulkan lib pch
28-
cd examples/gpu_puzzles && make build/gpu_puzzles
29-
cd examples/hello_world && make build/hello_world
30-
cd examples/matmul && make build/mm
31-
cd examples/physics && make build/physics
32-
cd examples/render && make build/render
92+
all: dawnlib check-clang check-linux-vulkan
93+
cd examples$(SLASH)gpu_puzzles && make build$(SLASH)gpu_puzzles
94+
cd examples$(SLASH)hello_world && make build$(SLASH)hello_world
95+
cd examples$(SLASH)matmul && make build$(SLASH)mm
96+
cd examples$(SLASH)physics && make build$(SLASH)physics
97+
cd examples$(SLASH)render && make build$(SLASH)render
3398

3499
docs: Doxyfile
35100
doxygen Doxyfile
36101

37-
################################################################################
38-
# cmake targets (optional - precompiled binaries is preferred)
39-
################################################################################
40-
41-
CMAKE_CMD = mkdir -p build && cd build && cmake ..
42-
# Add --trace to see the cmake commands
43-
FLAGS = -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_CXX_COMPILER=$(CXX) -DABSL_INTERNAL_AT_LEAST_CXX20=OFF
44-
FASTBUILD_FLAGS = $(FLAGS) -DFASTBUILD:BOOL=ON
45-
DEBUG_FLAGS = $(FLAGS) -DDEBUG:BOOL=ON
46-
RELEASE_FLAGS = $(FLAGS) -DFASTBUILD:BOOL=OFF
47-
TARGET_LIB=gpu
48-
49-
libgpu-cmake: check-clang check-cmake
50-
$(CMAKE_CMD) $(RELEASE_FLAGS) && make -j$(NUM_JOBS) gpu
51-
52-
debug-cmake: check-clang check-cmake
53-
$(CMAKE_CMD) $(DEBUG_FLAGS) && make -j$(NUM_JOBS) $(TARGET_ALL)
54-
55-
all-cmake: check-clang check-cmake
56-
$(CMAKE_CMD) $(RELEASE_FLAGS) && make -j$(NUM_JOBS) $(TARGET_ALL)
57-
58-
################################################################################
59102
# Cleanup
60103
################################################################################
61104

105+
# Clean rules for cleaning specific targets
106+
define CLEAN_RULES
107+
clean_$(1):
108+
ifeq ($(OS),Windows_NT)
109+
@if exist examples$(SLASH)$(1)$(SLASH)build ( $(RMDIR_CMD) /s examples$(SLASH)$(1)$(SLASH)build )
110+
else
111+
find examples$(SLASH)$(1) -name build -type d | xargs rm -rf
112+
endif
113+
endef
114+
$(foreach target,$(TARGETS),$(eval $(call CLEAN_RULES,$(target))))
115+
62116
clean-dawnlib:
63-
rm -f third_party/lib/libdawn.so third_party/lib/libdawn.dylib
117+
$(RMDIR_CMD) $(LIBDIR)$(SLASH)libdawn*.*
64118

65119
clean:
66-
read -r -p "This will delete the contents of build/*. Are you sure? [CTRL-C to abort] " response && rm -rf build/*
67-
rm -rf examples/gpu_puzzles/build/*
68-
rm -rf examples/hello_world/build/*
120+
ifeq ($(OS),Windows_NT)
121+
@if exist build $(RMDIR_CMD) build /s /q
122+
@if exist examples$(SLASH)gpu_puzzles$(SLASH)build $(RMDIR_CMD) examples$(SLASH)gpu_puzzles$(SLASH)build /s /q
123+
@if exist examples$(SLASH)hello_world$(SLASH)build $(RMDIR_CMD) examples$(SLASH)hello_world$(SLASH)build /s /q
124+
@if exist examples$(SLASH)matmul$(SLASH)build $(RMDIR_CMD) examples$(SLASH)matmul$(SLASH)build /s /q
125+
@if exist examples$(SLASH)physics$(SLASH)build $(RMDIR_CMD) examples$(SLASH)physics$(SLASH)build /s /q
126+
@if exist examples$(SLASH)render$(SLASH)build $(RMDIR_CMD) examples$(SLASH)render$(SLASH)build /s /q
127+
@if exist build$(SLASH)gpu.h.pch del build$(SLASH)gpu.h.pch
128+
$(MKDIR_CMD)
129+
else
130+
@command read -r -p "This will delete the contents of build/*. Are you sure? [CTRL-C to abort] " response && rm -rf build*
131+
rm -rf examples/gpu_puzzles/build*
132+
rm -rf examples/hello_world/build*
69133
rm -rf examples/matmul/build/mm
70134
rm -rf examples/physics/build/*
71135
rm -rf examples/render/build/*
72136
rm -f build/gpu.h.pch
73137
rm -f build/libgpucpp.so
138+
endif
74139

75140
clean-all:
76-
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
141+
ifeq ($(OS),Windows_NT)
142+
@if exist build $(RMDIR_CMD) build /s /q
143+
$(RMDIR_CMD) third_party$(SLASH)fetchcontent /s /q
144+
$(RMDIR_CMD) third_party$(SLASH)gpu-build /s /q
145+
$(RMDIR_CMD) third_party$(SLASH)gpu-subbuild /s /q
146+
$(RMDIR_CMD) third_party$(SLASH)gpu-src /s /q
147+
$(RMDIR_CMD) third_party$(SLASH)lib /s /q
148+
$(MKDIR_CMD)
149+
else
150+
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).*
151+
endif
77152

78-
################################################################################
79153
# Checks
80154
################################################################################
81155

82-
# check for the existence of clang++ and cmake
156+
# check for the existence of clang++
83157
check-clang:
158+
ifeq ($(OS),Windows_NT)
159+
@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)
160+
else
84161
@command -v clang++ >/dev/null 2>&1 || { echo >&2 "Please install clang++ with 'sudo apt-get install clang' or 'brew install llvm'"; exit 1; }
162+
endif
163+
164+
# check for the existence of entr
165+
check-entr:
166+
ifeq ($(OS),Windows_NT)
167+
@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)
168+
else
169+
@command -v entr >/dev/null 2>&1 || { echo >&2 "Please install entr with 'brew install entr' or 'sudo apt-get install entr'"; exit 1; }
170+
endif
85171

172+
# check for the existence of cmake
86173
check-cmake:
174+
ifeq ($(OS),Windows_NT)
175+
@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)
176+
else
87177
@command -v cmake >/dev/null 2>&1 || { echo >&2 "Please install cmake with 'sudo apt-get install cmake' or 'brew install cmake'"; exit 1; }
178+
endif
88179

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

188+
# check the existence of Vulkan (Linux only)
92189
check-linux-vulkan:
93190
@echo "Checking system type and Vulkan availability..."
94-
@if [ "$$(uname)" = "Linux" ]; then \
95-
if command -v vulkaninfo >/dev/null 2>&1; then \
96-
echo "Vulkan is installed."; \
97-
vulkaninfo; \
98-
else \
99-
echo "Vulkan is not installed. Please install Vulkan drivers to continue. On Debian / Ubuntu: sudo apt install libvulkan1 mesa-vulkan-drivers vulkan-tools"; \
100-
exit 1; \
101-
fi \
102-
else \
103-
echo "Non-Linux system detected. Skipping Vulkan check."; \
104-
fi
191+
ifeq ($(OS),Linux)
192+
@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; }
193+
else
194+
@echo "Non-Linux system detected. Skipping Vulkan check.";
195+
endif

0 commit comments

Comments
 (0)