187 lines
7.6 KiB
CMake
187 lines
7.6 KiB
CMake
# Recommendation: Place this file in source control.
|
|
# Auto-generated by `./dk dksdk.project.new` of dktool.
|
|
|
|
include(FetchContent)
|
|
|
|
function(parse_dktool_command_line)
|
|
# The first argument is <command>. All dots will be replaced with a
|
|
# triple underscore as a convenience and to be pretty for the user.
|
|
if(ARGC EQUAL 0)
|
|
message(FATAL_ERROR "Missing <command>. Usage: ./dk <command> [args]")
|
|
endif()
|
|
set(command ${ARGV0})
|
|
string(REPLACE "." "___" expected_function_name ${command})
|
|
message(VERBOSE "Searching for ${expected_function_name}")
|
|
|
|
# Set policies (we are in a new EVAL CODE context)
|
|
# Included scripts do automatic cmake_policy PUSH and POP
|
|
if(POLICY CMP0011)
|
|
cmake_policy(SET CMP0011 NEW)
|
|
endif()
|
|
|
|
# Parse the remainder of the arguments [args]
|
|
# * Use technique from [Professional CMake: A Practical Guide - Forwarding Command Arguments]
|
|
# to be able to forward arguments correctly to an inner function (the <command> function).
|
|
cmake_parse_arguments(PARSE_ARGV 1 FWD "" "" "")
|
|
set(quotedArgs "")
|
|
foreach(arg IN LISTS FWD_UNPARSED_ARGUMENTS)
|
|
string(APPEND quotedArgs " [===[${arg}]===]")
|
|
endforeach()
|
|
|
|
# Setup the binary directory
|
|
if(NOT DKTOOL_WORKDIR)
|
|
message(FATAL_ERROR "Illegal state. Expecting DKTOOL_WORKDIR")
|
|
endif()
|
|
set(CMAKE_BINARY_DIR ${DKTOOL_WORKDIR})
|
|
set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_BINARY_DIR})
|
|
|
|
# Search in all the user scripts
|
|
set(dot_function_names)
|
|
file(GLOB_RECURSE command_files
|
|
LIST_DIRECTORIES FALSE
|
|
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/scripts
|
|
cmake/scripts/*.cmake)
|
|
foreach(command_file IN LISTS command_files)
|
|
# Normalize and lowercase
|
|
cmake_path(NORMAL_PATH command_file)
|
|
string(TOLOWER "${command_file}" command_file)
|
|
cmake_path(REMOVE_EXTENSION command_file OUTPUT_VARIABLE command_file_no_ext)
|
|
|
|
# Convert to list
|
|
string(REPLACE "/" ";" command_stems_no_namespace ${command_file_no_ext})
|
|
|
|
# Make a pretty description only for validation
|
|
set(pretty_stems ${command_stems_no_namespace})
|
|
list(TRANSFORM pretty_stems PREPEND "'")
|
|
list(TRANSFORM pretty_stems APPEND "'")
|
|
string(JOIN ", " pretty_stems_str ${pretty_stems})
|
|
string(REGEX REPLACE ",([^,]*)" " and \\1" pretty_stems_str "${pretty_stems_str}")
|
|
|
|
# Validate that only alphanumeric with underscores (but not the reserved three underscores)
|
|
string(REGEX MATCH "[/a-z0-9_]*" only_alphanum_and_underscores "${command_file_no_ext}")
|
|
if(NOT only_alphanum_and_underscores STREQUAL "${command_file_no_ext}")
|
|
message(WARNING "Ignoring user script ${CMAKE_CURRENT_SOURCE_DIR}/${command_file}.
|
|
The stems of the user script (${pretty_stems_str}) must only contain letters, numbers and underscores.")
|
|
continue()
|
|
endif()
|
|
string(FIND "${command_file_no_ext}" "___" reserved_underscores)
|
|
if(reserved_underscores GREATER_EQUAL 0)
|
|
message(WARNING "Ignoring user script ${CMAKE_CURRENT_SOURCE_DIR}/${command_file}.
|
|
No stem of the user script (${pretty_stems_str}) can contain a triple underscore ('___').")
|
|
continue()
|
|
endif()
|
|
|
|
# Translate dev/xxx.cmake to the "user" namespaced function name
|
|
# `user__dev__xxx` and `user.dev.xxx`.
|
|
set(command_stems ${command_stems_no_namespace})
|
|
list(PREPEND command_stems "user")
|
|
string(JOIN "___" command_function_name ${command_stems})
|
|
string(JOIN "." dot_function_name ${command_stems})
|
|
list(APPEND dot_function_names ${dot_function_name})
|
|
|
|
# In a new scope (to avoid a global, leaky namespace) register the function.
|
|
message(VERBOSE "Shimming ${command_function_name}")
|
|
cmake_language(EVAL CODE "
|
|
function(${command_function_name})
|
|
include(\"${CMAKE_CURRENT_SOURCE_DIR}/cmake/scripts/${command_file}\")
|
|
if(COMMAND run)
|
|
run(${quotedArgs})
|
|
else()
|
|
message(FATAL_ERROR [[The user script ${CMAKE_CURRENT_SOURCE_DIR}/cmake/scripts/${command_file} was missing:
|
|
function(run)
|
|
# Your user code
|
|
endfunction()
|
|
]])
|
|
endif()
|
|
endfunction()
|
|
")
|
|
endforeach()
|
|
|
|
# Include all the system scripts.
|
|
# - Since the system scripts come after the user scripts, the user scripts
|
|
# don't override the system scripts unless the user scripts use deferred
|
|
# hooks or redefine CMake built-in functions. Regardless, the user
|
|
# scripts are namespaced with `user__` prefix
|
|
if(NOT IS_DIRECTORY cmake/scripts/dksdk)
|
|
# If this project (ex. dktool) has the system scripts, it must
|
|
# have all of them. Otherwise we download the system scripts.
|
|
FetchContent_Populate(dktool
|
|
QUIET
|
|
GIT_REPOSITORY https://gitlab.com/diskuv/dktool.git
|
|
GIT_TAG 1.0
|
|
)
|
|
file(GLOB_RECURSE system_command_files
|
|
LIST_DIRECTORIES FALSE
|
|
RELATIVE ${dktool_SOURCE_DIR}/cmake/scripts
|
|
${dktool_SOURCE_DIR}/cmake/scripts/dkml/*.cmake
|
|
${dktool_SOURCE_DIR}/cmake/scripts/dksdk/*.cmake)
|
|
foreach(command_file IN LISTS system_command_files)
|
|
# Normalize and lowercase
|
|
cmake_path(NORMAL_PATH command_file)
|
|
string(TOLOWER "${command_file}" command_file)
|
|
cmake_path(REMOVE_EXTENSION command_file OUTPUT_VARIABLE command_file_no_ext)
|
|
|
|
# Convert to list
|
|
string(REPLACE "/" ";" command_stems_no_namespace ${command_file_no_ext})
|
|
|
|
# Translate dksdk/xxx.cmake to the function name `dksdk__xxx` and `dksdk.xxx`
|
|
set(command_stems ${command_stems_no_namespace})
|
|
string(JOIN "___" command_function_name ${command_stems})
|
|
string(JOIN "." dot_function_name ${command_stems})
|
|
list(APPEND dot_function_names ${dot_function_name})
|
|
|
|
# In a new scope (to avoid a global, leaky namespace) register the function.
|
|
message(VERBOSE "Shimming ${command_function_name}")
|
|
cmake_language(EVAL CODE "
|
|
function(${command_function_name})
|
|
include(\"${dktool_SOURCE_DIR}/cmake/scripts/${command_file}\")
|
|
if(COMMAND run)
|
|
run(${quotedArgs})
|
|
else()
|
|
message(FATAL_ERROR [[The system script ${dktool_SOURCE_DIR}/cmake/scripts/${command_file} was missing:
|
|
function(run)
|
|
# The system code
|
|
endfunction()
|
|
]])
|
|
endif()
|
|
endfunction()
|
|
")
|
|
|
|
endforeach()
|
|
endif()
|
|
|
|
# Validate the <command> exists
|
|
if(NOT COMMAND ${expected_function_name})
|
|
set(pretty_function_names ${dot_function_names})
|
|
list(TRANSFORM pretty_function_names PREPEND " ")
|
|
list(TRANSFORM pretty_function_names APPEND "\n")
|
|
string(JOIN "" str_pretty_function_names ${pretty_function_names})
|
|
message(FATAL_ERROR "No command '${command}' exists. The following commands are available:
|
|
${str_pretty_function_names}")
|
|
message(FATAL_ERROR "No command '${command}' exists")
|
|
endif()
|
|
|
|
# Call the <command> function
|
|
cmake_language(EVAL CODE "${expected_function_name}()")
|
|
endfunction()
|
|
|
|
# DkML data home
|
|
if(WIN32)
|
|
set(DKML_DATA_HOME "$ENV{LOCALAPPDATA}/Programs/DiskuvOCaml")
|
|
elseif(DEFINED ENV{XDG_DATA_HOME})
|
|
set(DKML_DATA_HOME "$ENV{XDG_DATA_HOME}/diskuv-ocaml")
|
|
else()
|
|
set(DKML_DATA_HOME "$ENV{HOME}/.local/share/diskuv-ocaml")
|
|
endif()
|
|
|
|
# DkSDK data home
|
|
if(WIN32)
|
|
set(DKSDK_DATA_HOME "$ENV{LOCALAPPDATA}/Programs/DkSDK")
|
|
elseif(DEFINED ENV{XDG_DATA_HOME})
|
|
set(DKSDK_DATA_HOME "$ENV{XDG_DATA_HOME}/dksdk")
|
|
else()
|
|
set(DKSDK_DATA_HOME "$ENV{HOME}/.local/share/dksdk")
|
|
endif()
|
|
|
|
# Splat DKTOOL_CMDLINE
|
|
cmake_language(EVAL CODE "parse_dktool_command_line(${DKTOOL_CMDLINE})")
|