Skip to content

Commit f96dade

Browse files
feat: add CMake support using cmkr
1 parent 95dde4f commit f96dade

5 files changed

Lines changed: 353 additions & 21 deletions

File tree

.gitignore

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ build/
88
# Idea
99
.idea
1010

11-
# Cmake
12-
CMakeLists.txt
13-
cmake-build-debug
11+
# cmkr
12+
build*/
13+
cmake-build*/
14+
CMakerLists.txt
15+
CMakeLists.txt.user

CMakeLists.txt

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# This file is automatically generated from cmake.toml - DO NOT EDIT
2+
# See https://github.com/build-cpp/cmkr for more information
3+
4+
cmake_minimum_required(VERSION 3.15)
5+
6+
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
7+
message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build")
8+
endif()
9+
10+
set(CMKR_ROOT_PROJECT OFF)
11+
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
12+
set(CMKR_ROOT_PROJECT ON)
13+
14+
# Bootstrap cmkr and automatically regenerate CMakeLists.txt
15+
include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)
16+
if(CMKR_INCLUDE_RESULT)
17+
cmkr()
18+
endif()
19+
20+
# Enable folder support
21+
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
22+
23+
# Create a configure-time dependency on cmake.toml to improve IDE support
24+
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS cmake.toml)
25+
endif()
26+
27+
project(vectorjs
28+
LANGUAGES
29+
CXX
30+
VERSION
31+
0.1.0
32+
)
33+
34+
include(FetchContent)
35+
36+
# Fix warnings about DOWNLOAD_EXTRACT_TIMESTAMP
37+
if(POLICY CMP0135)
38+
cmake_policy(SET CMP0135 NEW)
39+
endif()
40+
message(STATUS "Fetching raylib (6.0)...")
41+
FetchContent_Declare(raylib
42+
GIT_REPOSITORY
43+
"https://github.com/raysan5/raylib.git"
44+
GIT_TAG
45+
6.0
46+
)
47+
FetchContent_MakeAvailable(raylib)
48+
49+
# Target: vectorjs
50+
set(vectorjs_SOURCES
51+
cmake.toml
52+
"src/engine.cpp"
53+
"src/main.cpp"
54+
)
55+
56+
add_executable(vectorjs)
57+
58+
target_sources(vectorjs PRIVATE ${vectorjs_SOURCES})
59+
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${vectorjs_SOURCES})
60+
61+
target_compile_features(vectorjs PRIVATE
62+
cxx_std_23
63+
)
64+
65+
target_link_libraries(vectorjs PRIVATE
66+
raylib
67+
)
68+
69+
get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT)
70+
if(NOT CMKR_VS_STARTUP_PROJECT)
71+
set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT vectorjs)
72+
endif()

cmake.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Reference: https://build-cpp.github.io/cmkr/cmake-toml
2+
[project]
3+
name = "vectorjs"
4+
version = "0.1.0"
5+
languages = ["CXX"]
6+
7+
[fetch-content]
8+
raylib = { git = "https://github.com/raysan5/raylib.git", tag = "6.0"}
9+
10+
[target.vectorjs]
11+
type = "executable"
12+
compile-features = ["cxx_std_23"]
13+
sources = ["src/**.cpp"]
14+
link-libraries = [
15+
"raylib"
16+
]

cmkr.cmake

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
include_guard()
2+
3+
# Change these defaults to point to your infrastructure if desired
4+
set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE)
5+
set(CMKR_TAG "v0.2.46" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
6+
set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE)
7+
8+
# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake
9+
if(CMAKE_SCRIPT_MODE_FILE)
10+
set(CMAKE_BINARY_DIR "${CMAKE_BINARY_DIR}/build")
11+
set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_BINARY_DIR}")
12+
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}")
13+
endif()
14+
15+
# Set these from the command line to customize for development/debugging purposes
16+
set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable")
17+
set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation")
18+
set(CMKR_BUILD_TYPE "Debug" CACHE STRING "cmkr build configuration")
19+
mark_as_advanced(CMKR_REPO CMKR_TAG CMKR_COMMIT_HASH CMKR_EXECUTABLE CMKR_SKIP_GENERATION CMKR_BUILD_TYPE)
20+
21+
# Disable cmkr if generation is disabled
22+
if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION OR CMKR_BUILD_SKIP_GENERATION)
23+
message(STATUS "[cmkr] Skipping automatic cmkr generation")
24+
unset(CMKR_BUILD_SKIP_GENERATION CACHE)
25+
macro(cmkr)
26+
endmacro()
27+
return()
28+
endif()
29+
30+
# Disable cmkr if no cmake.toml file is found
31+
if(NOT CMAKE_SCRIPT_MODE_FILE AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml")
32+
message(AUTHOR_WARNING "[cmkr] Not found: ${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml")
33+
macro(cmkr)
34+
endmacro()
35+
return()
36+
endif()
37+
38+
# Convert a Windows native path to CMake path
39+
if(CMKR_EXECUTABLE MATCHES "\\\\")
40+
string(REPLACE "\\" "/" CMKR_EXECUTABLE_CMAKE "${CMKR_EXECUTABLE}")
41+
set(CMKR_EXECUTABLE "${CMKR_EXECUTABLE_CMAKE}" CACHE FILEPATH "" FORCE)
42+
unset(CMKR_EXECUTABLE_CMAKE)
43+
endif()
44+
45+
# Helper macro to execute a process (COMMAND_ERROR_IS_FATAL ANY is 3.19 and higher)
46+
function(cmkr_exec)
47+
execute_process(COMMAND ${ARGV} RESULT_VARIABLE CMKR_EXEC_RESULT)
48+
if(NOT CMKR_EXEC_RESULT EQUAL 0)
49+
message(FATAL_ERROR "cmkr_exec(${ARGV}) failed (exit code ${CMKR_EXEC_RESULT})")
50+
endif()
51+
endfunction()
52+
53+
# Windows-specific hack (CMAKE_EXECUTABLE_PREFIX is not set at the moment)
54+
if(WIN32)
55+
set(CMKR_EXECUTABLE_NAME "cmkr.exe")
56+
else()
57+
set(CMKR_EXECUTABLE_NAME "cmkr")
58+
endif()
59+
60+
# Use cached cmkr if found
61+
if(DEFINED ENV{CMKR_CACHE})
62+
set(CMKR_DIRECTORY_PREFIX "$ENV{CMKR_CACHE}")
63+
string(REPLACE "\\" "/" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}")
64+
if(CMKR_DIRECTORY_PREFIX MATCHES "^~")
65+
if(WIN32)
66+
string(REGEX REPLACE "^~" "$ENV{USERPROFILE}" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}")
67+
elseif(UNIX)
68+
string(REGEX REPLACE "^~" "$ENV{HOME}" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}")
69+
endif()
70+
endif()
71+
if(NOT CMKR_DIRECTORY_PREFIX MATCHES "\\/$")
72+
set(CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}/")
73+
endif()
74+
# Build in release mode for the cache
75+
set(CMKR_BUILD_TYPE "Release")
76+
else()
77+
set(CMKR_DIRECTORY_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/_cmkr_")
78+
endif()
79+
set(CMKR_DIRECTORY "${CMKR_DIRECTORY_PREFIX}${CMKR_TAG}")
80+
set(CMKR_CACHED_EXECUTABLE "${CMKR_DIRECTORY}/bin/${CMKR_EXECUTABLE_NAME}")
81+
82+
# Helper function to check if a string starts with a prefix
83+
# Cannot use MATCHES, see: https://github.com/build-cpp/cmkr/issues/61
84+
function(cmkr_startswith str prefix result)
85+
string(LENGTH "${prefix}" prefix_length)
86+
string(LENGTH "${str}" str_length)
87+
if(prefix_length LESS_EQUAL str_length)
88+
string(SUBSTRING "${str}" 0 ${prefix_length} str_prefix)
89+
if(prefix STREQUAL str_prefix)
90+
set("${result}" ON PARENT_SCOPE)
91+
return()
92+
endif()
93+
endif()
94+
set("${result}" OFF PARENT_SCOPE)
95+
endfunction()
96+
97+
# Handle upgrading logic
98+
if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE)
99+
cmkr_startswith("${CMKR_EXECUTABLE}" "${CMAKE_CURRENT_BINARY_DIR}/_cmkr" CMKR_STARTSWITH_BUILD)
100+
cmkr_startswith("${CMKR_EXECUTABLE}" "${CMKR_DIRECTORY_PREFIX}" CMKR_STARTSWITH_CACHE)
101+
if(CMKR_STARTSWITH_BUILD)
102+
if(DEFINED ENV{CMKR_CACHE})
103+
message(AUTHOR_WARNING "[cmkr] Switching to cached cmkr: '${CMKR_CACHED_EXECUTABLE}'")
104+
if(EXISTS "${CMKR_CACHED_EXECUTABLE}")
105+
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
106+
else()
107+
unset(CMKR_EXECUTABLE CACHE)
108+
endif()
109+
else()
110+
message(AUTHOR_WARNING "[cmkr] Upgrading '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'")
111+
unset(CMKR_EXECUTABLE CACHE)
112+
endif()
113+
elseif(DEFINED ENV{CMKR_CACHE} AND CMKR_STARTSWITH_CACHE)
114+
message(AUTHOR_WARNING "[cmkr] Upgrading cached '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'")
115+
unset(CMKR_EXECUTABLE CACHE)
116+
endif()
117+
endif()
118+
119+
if(CMKR_EXECUTABLE AND EXISTS "${CMKR_EXECUTABLE}")
120+
message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'")
121+
elseif(CMKR_EXECUTABLE AND NOT CMKR_EXECUTABLE STREQUAL CMKR_CACHED_EXECUTABLE)
122+
message(FATAL_ERROR "[cmkr] '${CMKR_EXECUTABLE}' not found")
123+
elseif(NOT CMKR_EXECUTABLE AND EXISTS "${CMKR_CACHED_EXECUTABLE}")
124+
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
125+
message(STATUS "[cmkr] Found cached cmkr: '${CMKR_EXECUTABLE}'")
126+
else()
127+
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
128+
message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'")
129+
130+
message(STATUS "[cmkr] Fetching cmkr...")
131+
if(EXISTS "${CMKR_DIRECTORY}")
132+
cmkr_exec("${CMAKE_COMMAND}" -E rm -rf "${CMKR_DIRECTORY}")
133+
endif()
134+
find_package(Git QUIET REQUIRED)
135+
cmkr_exec("${GIT_EXECUTABLE}"
136+
clone
137+
--config advice.detachedHead=false
138+
--branch ${CMKR_TAG}
139+
--depth 1
140+
${CMKR_REPO}
141+
"${CMKR_DIRECTORY}"
142+
)
143+
if(CMKR_COMMIT_HASH)
144+
execute_process(
145+
COMMAND "${GIT_EXECUTABLE}" checkout -q "${CMKR_COMMIT_HASH}"
146+
RESULT_VARIABLE CMKR_EXEC_RESULT
147+
WORKING_DIRECTORY "${CMKR_DIRECTORY}"
148+
)
149+
if(NOT CMKR_EXEC_RESULT EQUAL 0)
150+
message(FATAL_ERROR "Tag '${CMKR_TAG}' hash is not '${CMKR_COMMIT_HASH}'")
151+
endif()
152+
endif()
153+
message(STATUS "[cmkr] Building cmkr (using system compiler)...")
154+
cmkr_exec("${CMAKE_COMMAND}"
155+
--no-warn-unused-cli
156+
"${CMKR_DIRECTORY}"
157+
"-B${CMKR_DIRECTORY}/build"
158+
"-DCMAKE_BUILD_TYPE=${CMKR_BUILD_TYPE}"
159+
"-DCMAKE_UNITY_BUILD=ON"
160+
"-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}"
161+
"-DCMKR_GENERATE_DOCUMENTATION=OFF"
162+
)
163+
cmkr_exec("${CMAKE_COMMAND}"
164+
--build "${CMKR_DIRECTORY}/build"
165+
--config "${CMKR_BUILD_TYPE}"
166+
--parallel
167+
)
168+
cmkr_exec("${CMAKE_COMMAND}"
169+
--install "${CMKR_DIRECTORY}/build"
170+
--config "${CMKR_BUILD_TYPE}"
171+
--prefix "${CMKR_DIRECTORY}"
172+
--component cmkr
173+
)
174+
if(NOT EXISTS ${CMKR_EXECUTABLE})
175+
message(FATAL_ERROR "[cmkr] Failed to bootstrap '${CMKR_EXECUTABLE}'")
176+
endif()
177+
cmkr_exec("${CMKR_EXECUTABLE}" version)
178+
message(STATUS "[cmkr] Bootstrapped ${CMKR_EXECUTABLE}")
179+
endif()
180+
execute_process(COMMAND "${CMKR_EXECUTABLE}" version
181+
RESULT_VARIABLE CMKR_EXEC_RESULT
182+
)
183+
if(NOT CMKR_EXEC_RESULT EQUAL 0)
184+
message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding")
185+
endif()
186+
187+
# Use cmkr.cmake as a script
188+
if(CMAKE_SCRIPT_MODE_FILE)
189+
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml")
190+
execute_process(COMMAND "${CMKR_EXECUTABLE}" init
191+
RESULT_VARIABLE CMKR_EXEC_RESULT
192+
)
193+
if(NOT CMKR_EXEC_RESULT EQUAL 0)
194+
message(FATAL_ERROR "[cmkr] Failed to bootstrap cmkr project. Please report an issue: https://github.com/build-cpp/cmkr/issues/new")
195+
else()
196+
message(STATUS "[cmkr] Modify cmake.toml and then configure using: cmake -B build")
197+
endif()
198+
else()
199+
execute_process(COMMAND "${CMKR_EXECUTABLE}" gen
200+
RESULT_VARIABLE CMKR_EXEC_RESULT
201+
)
202+
if(NOT CMKR_EXEC_RESULT EQUAL 0)
203+
message(FATAL_ERROR "[cmkr] Failed to generate project.")
204+
else()
205+
message(STATUS "[cmkr] Configure using: cmake -B build")
206+
endif()
207+
endif()
208+
endif()
209+
210+
# This is the macro that contains black magic
211+
macro(cmkr)
212+
# When this macro is called from the generated file, fake some internal CMake variables
213+
get_source_file_property(CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" CMKR_CURRENT_LIST_FILE)
214+
if(CMKR_CURRENT_LIST_FILE)
215+
set(CMAKE_CURRENT_LIST_FILE "${CMKR_CURRENT_LIST_FILE}")
216+
get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
217+
endif()
218+
219+
# File-based include guard (include_guard is not documented to work)
220+
get_source_file_property(CMKR_INCLUDE_GUARD "${CMAKE_CURRENT_LIST_FILE}" CMKR_INCLUDE_GUARD)
221+
if(NOT CMKR_INCLUDE_GUARD)
222+
set_source_files_properties("${CMAKE_CURRENT_LIST_FILE}" PROPERTIES CMKR_INCLUDE_GUARD TRUE)
223+
224+
file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_PRE)
225+
226+
# Generate CMakeLists.txt
227+
cmkr_exec("${CMKR_EXECUTABLE}" gen
228+
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
229+
)
230+
231+
file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_POST)
232+
233+
# Delete the temporary file if it was left for some reason
234+
set(CMKR_TEMP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CMakerLists.txt")
235+
if(EXISTS "${CMKR_TEMP_FILE}")
236+
file(REMOVE "${CMKR_TEMP_FILE}")
237+
endif()
238+
239+
if(NOT CMKR_LIST_FILE_SHA256_PRE STREQUAL CMKR_LIST_FILE_SHA256_POST)
240+
# Copy the now-generated CMakeLists.txt to CMakerLists.txt
241+
# This is done because you cannot include() a file you are currently in
242+
configure_file(CMakeLists.txt "${CMKR_TEMP_FILE}" COPYONLY)
243+
244+
# Add the macro required for the hack at the start of the cmkr macro
245+
set_source_files_properties("${CMKR_TEMP_FILE}" PROPERTIES
246+
CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}"
247+
)
248+
249+
# 'Execute' the newly-generated CMakeLists.txt
250+
include("${CMKR_TEMP_FILE}")
251+
252+
# Delete the generated file
253+
file(REMOVE "${CMKR_TEMP_FILE}")
254+
255+
# Do not execute the rest of the original CMakeLists.txt
256+
return()
257+
endif()
258+
# Resume executing the unmodified CMakeLists.txt
259+
endif()
260+
endmacro()

xmake.lua

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)