chore: baseline usable version

This commit is contained in:
dela
2026-06-10 11:17:51 +08:00
commit a2f82a86b6
932 changed files with 172551 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
# MIT License
# Copyright (c) 2023 SineStriker
# Description:
# Command that executes `configure_file`.
# Usage:
# cmake
# -D input=<file>
# -D output=<file>
# -D force=TRUE/FALSE
# [-D args=<args...>]
# -P configure_file.cmake
if(force AND EXISTS ${_output})
file(REMOVE ${_output})
endif()
configure_file(${input} ${output} ${args})

View File

@@ -0,0 +1,64 @@
# MIT License
# Copyright (c) 2023 SineStriker
# Description:
# Copy file or directory to destination if different.
# Mainly use `file(INSTALL)` to implement.
# Usage:
# cmake
# -D src=<files/dirs...>
# -D dest=<dir>
# [-D dest_base=<dir>]
# [-D args=<args...>]
# -P copy.cmake
# Check required arguments
if(NOT src)
message(FATAL_ERROR "src not defined.")
endif()
if(NOT dest)
message(FATAL_ERROR "dest not defined.")
endif()
# Calculate destination
if(dest_base)
set(_dest_base ${dest_base})
else()
set(_dest_base ${CMAKE_BINARY_DIR})
endif()
get_filename_component(_dest ${dest} ABSOLUTE BASE_DIR ${_dest_base})
# Copy
foreach(_file IN LISTS src)
# Avoid using `get_filename_component` to keep the trailing slash
set(_path ${_file})
if(NOT IS_ABSOLUTE ${_path})
set(_path "${CMAKE_BINARY_DIR}/${_path}")
endif()
if(IS_DIRECTORY ${_path})
file(INSTALL DESTINATION ${_dest}
TYPE DIRECTORY
FILES ${_path}
${args}
)
else()
set(_paths)
if(${_path} MATCHES "\\*\\*")
file(GLOB_RECURSE _paths ${_path})
else()
file(GLOB _paths ${_path})
endif()
file(INSTALL DESTINATION ${_dest}
TYPE FILE
FILES ${_paths}
${args}
)
endif()
endforeach()

View File

@@ -0,0 +1,245 @@
#!/bin/bash
# MIT License
# Copyright (c) 2023 SineStriker
# Description: This script calls `qmcorecmd` to deploy dependencies on Mac/Linux.
# Show usage
usage() {
echo "Usage: $(basename $0) -i <dir> -m <path>"
echo " --plugindir <plugin_dir> --libdir <lib_dir> --qmldir <qml_dir>"
echo " [--qmake <qmake_path>] [--extra <extra_path>]..."
echo " [--qml <qml_module>]... [--plugin <plugin>]... [--copy <src> <dest>]..."
echo " [-f] [-s] [-V] [-h]"
echo " -i <input_dir> Directory containing binaries and libraries"
echo " -m <corecmd_path> Path to corecmd"
echo " --plugindir <plugin_dir> Output directory for plugins"
echo " --libdir <lib_dir> Output directory for libraries"
echo " --qmldir <qml_dir> Output directory for QML files"
echo " --qmake <qmake_path> Path to qmake (optional)"
echo " --extra <extra_path> Extra plugin searching path (repeatable)"
echo " --qml <qml_module> Relative path to QML directory (repeatable)"
echo " --plugin <plugin> Specify a Qt plugin to deploy (repeatable)"
echo " --copy <src> <dest> Specify additional binary file to copy and its destination directory (repeatable)"
echo " --linkdirs-file Add library searching paths from a list file"
echo " -L Add a library searching path"
echo " -f Force overwrite existing files"
echo " -s Ignore C/C++ runtime and system libraries"
echo " -V Show verbose output"
echo " -h Show this help message"
}
# Initialize arguments
EXTRA_PLUGIN_PATHS=()
QML_REL_PATHS=()
ARGS=()
VERBOSE=""
PLUGINS=()
FILES=""
# Parse command line
while (( "$#" )); do
case "$1" in
-i) INPUT_DIR="$2"; shift 2;;
-m) CORECMD_PATH="$2"; shift 2;;
-L) ARGS+=("-L \"$2\""); shift 2;;
--linkdirs-file) ARGS+=("--linkdirs-file \"$2\""); shift 2;;
--plugindir) PLUGIN_DIR="$2"; shift 2;;
--libdir) LIB_DIR="$2"; shift 2;;
--qmldir) QML_DIR="$2"; shift 2;;
--qmake) QMAKE_PATH="$2"; shift 2;;
--extra) EXTRA_PLUGIN_PATHS+=("$2"); shift 2;;
--plugin) PLUGINS+=("$2"); shift 2;;
--qml) QML_REL_PATHS+=("$2"); shift 2;;
--copy) ARGS+=("-c \"$2\" \"$3\""); shift 3;;
-f|-s) ARGS+=("$1"); shift;;
-V) VERBOSE="-V"; shift;;
-h) usage; exit 0;;
*) echo "Error: Unsupported argument $1"; usage; exit 1;;
esac
done
# Check required arguments
for arg in INPUT_DIR PLUGIN_DIR LIB_DIR QML_DIR CORECMD_PATH; do
if [[ -z ${!arg} ]]; then
echo "Error: Missing required argument '$arg'"
usage
exit 1
fi
done
# Get Qt plugin and QML paths
PLUGIN_PATHS=()
QML_PATH=""
if [[ -n "$QMAKE_PATH" ]]; then
QMAKE_PLUGIN_PATH=$($QMAKE_PATH -query QT_INSTALL_PLUGINS)
PLUGIN_PATHS+=("$QMAKE_PLUGIN_PATH")
QML_PATH=$($QMAKE_PATH -query QT_INSTALL_QML)
fi
# Add extra plugin searching paths
PLUGIN_PATHS+=("${EXTRA_PLUGIN_PATHS[@]}")
# Ensure that the QML search path is not empty
# when the QML related path is specified (qmake needs to be specified)
if [[ ${#QML_REL_PATHS[@]} -gt 0 && -z "$QML_PATH" ]]; then
echo "Error: qmake path must be specified when QML paths are provided"
usage
exit 1
fi
# Search input directory
search_input_dir() {
local path="$1"
for item in "$path"/*; do
if [ -d "$item" ]; then
# Check if the directory is mac .framework
if [[ "OSTYPE" == "darwin"* ]] && [[ "$item" == *.framework ]]; then
FILES="$FILES \"$item\""
else
search_input_dir "$item"
fi
elif [ -f "$item" ]; then
if [[ "$OSTYPE" == "msys"* ]] || [[ "$OSTYPE" == "win32" ]] || [[ "$OSTYPE" == "cygwin"* ]]; then
# On Windows, search for.exe and.dll files
FILES="$FILES \"$item\""
else
# On Unix, traverse all files, using the file command to
# check for executable binary files
file_type=$(file -b "$item")
if [[ ($file_type == "ELF"* || $file_type == "Mach-O"*) && -x "$item" ]]; then
FILES="$FILES \"$item\""
fi
fi
fi
done
}
search_input_dir "$INPUT_DIR"
# Find the full path to the Qt plugin
for plugin_path in "${PLUGINS[@]}"; do
# Check format
if [[ $plugin_path == */* ]]; then
IFS='/' read -r -a plugin_parts <<< "$plugin_path"
# Extracts the category and name
category=${plugin_parts[0]}
name=${plugin_parts[1]}
# Calculate destination directory
dest_dir="${PLUGIN_DIR}/${category}"
# Initialize an array to store found plugins
found_plugins=""
# Traverse the path and find the specific plug-in files
for search_path in "${PLUGIN_PATHS[@]}"; do
while IFS= read -r plugin; do
# Get name
plugin_name=$(basename "$plugin")
# Check if the plugin was already found to avoid duplicates
if [[ ! $found_plugins =~ $plugin_name ]]; then
found_plugins+="$plugin_name "
ARGS+=("-c \"$plugin\" \"$dest_dir\"")
fi
done < <(find "${search_path}/${category}" -name "lib${name}.*" ! -name "*debug*" ! -type d -print)
done
if [ ${#found_plugins[@]} -eq 0 ]; then
echo "Error: Plugin '${plugin_path}' not found in any search paths."
exit 1
fi
else
echo "Error: Invalid plugin format '${plugin_path}'. Expected format: <category>/<name>"
exit 1
fi
done
# Process QML item
handle_qml_file() {
local file="$1"
local rel_path="${file#$QML_PATH/}"
local target="$QML_DIR/$rel_path"
local target_dir="$(dirname "$target")"
# Directory: must be mac framework
if [ -d "$file" ]; then
ARGS+=("-c \"$file\" \"$target_dir\"")
return
fi
# Ignore specific files
if [[ "$OSTYPE" == "msys"* ]] || [[ "$OSTYPE" == "win32" ]] || [[ "$OSTYPE" == "cygwin"* ]]; then
if [[ "$file" == *.pdb ]] || [[ "$file" == *d.dll ]]; then
return
fi
else
if [[ "$file" == *_debug.dylib ]] || [[ "$file" == *.so.debug ]]; then
return
fi
fi
# Determine whether it is an executable binary file and handle it accordingly
if [[ "$OSTYPE" == "msys"* ]] || [[ "$OSTYPE" == "win32" ]] || [[ "$OSTYPE" == "cygwin"* ]]; then
if [[ "$file" == *.dll || "$file" == *.exe ]]; then
ARGS+=("-c \"$file\" \"$target_dir\"")
else
mkdir -p "$target_dir"
cp "$file" "$target"
fi
else
file_type=$(file -b "$file")
if [[ ($file_type == "ELF"* || $file_type == "Mach-O"*) && -x "$file" ]]; then
ARGS+=("-c \"$file\" \"$target_dir\"")
else
mkdir -p "$target_dir"
cp "$file" "$target"
fi
fi
}
# Search QML directory
search_qml_dir() {
local path="$1"
for item in "$path"/*; do
if [ -d "$item" ]; then
# Check if the path is mac .framework
if [[ "OSTYPE" == "darwin"* ]] && [[ "$item" == *.framework ]]; then
handle_qml_file "$item"
else
search_qml_dir "$item"
fi
elif [ -f "$item" ]; then
handle_qml_file "$item"
fi
done
}
# Process QML directories
for qml_rel_path in "${QML_REL_PATHS[@]}"; do
full_path="$QML_PATH/$qml_rel_path"
if [[ -d "$full_path" ]]; then
# Directory
search_qml_dir "$full_path"
elif [[ -f "$full_path" ]]; then
# File
handle_qml_file "$full_path" "$QML_DIR"
fi
done
# Build and execute the deploy command
DEPLOY_CMD="$CORECMD_PATH deploy $FILES ${ARGS[@]} -o \"$LIB_DIR\" $VERBOSE"
if [[ "$VERBOSE" == "-V" ]]; then
echo "Executing: $DEPLOY_CMD"
fi
eval $DEPLOY_CMD
# Check the deployment result
if [ $? -ne 0 ]; then
exit 1
fi

View File

@@ -0,0 +1,294 @@
:: MIT License
:: Copyright (c) 2023 SineStriker
:: Description: This script calls `qmcorecmd` to deploy dependencies on Windows.
@echo off
setlocal enabledelayedexpansion
:: Initialize arguments
set "INPUT_DIR="
set "PLUGIN_DIR="
set "LIB_DIR="
set "QML_DIR="
set "QMAKE_PATH="
set "CORECMD_PATH="
set "VERBOSE="
set "FILES="
set "EXTRA_PLUGIN_PATHS="
set "PLUGINS=" & set /a "PLUGIN_COUNT=0"
set "QML_REL_PATHS="
set "ARGS=" & set /a "ARG_COUNT=0"
:: Parse command line
:parse_args
if "%~1"=="" goto :end_parse_args
if "%1"=="-i" set "INPUT_DIR=%~2" & shift & shift & goto :parse_args
if "%1"=="-m" set "CORECMD_PATH=%~2" & shift & shift & goto :parse_args
if "%1"=="--plugindir" set "PLUGIN_DIR=%~2" & shift & shift & goto :parse_args
if "%1"=="--libdir" set "LIB_DIR=%~2" & shift & shift & goto :parse_args
if "%1"=="--qmldir" set "QML_DIR=%~2" & shift & shift & goto :parse_args
if "%1"=="--qmake" set "QMAKE_PATH=%~2" & shift & shift & goto :parse_args
if "%1"=="--extra" set "EXTRA_PLUGIN_PATHS=!EXTRA_PLUGIN_PATHS! %~2" & shift & shift & goto :parse_args
if "%1"=="--plugin" set /a "PLUGIN_COUNT+=1" & set "PLUGINS[!PLUGIN_COUNT!]=%~2" & shift & shift & goto :parse_args
if "%1"=="--qml" set "QML_REL_PATHS=!QML_REL_PATHS! %~2" & shift & shift & goto :parse_args
if "%1"=="--copy" call :push_args -c %~2 %~3 & shift & shift & shift & goto :parse_args
if "%1"=="-f" call :push_args -f & shift & goto :parse_args
if "%1"=="-s" call :push_args -s & shift & goto :parse_args
if "%1"=="-V" set "VERBOSE=-V" & shift & goto :parse_args
if "%1"=="-h" call :usage & exit /b
if "%1"=="--linkdirs-file" call :push_args --linkdirs-file %~2 & shift & shift & goto :parse_args
if "%1"=="-L" call :push_args -L %~2 & shift & shift & goto :parse_args
shift
goto :parse_args
:end_parse_args
:: Check required arguments
if not defined INPUT_DIR echo Error: Missing required argument 'INPUT_DIR' & call :usage & exit /b
if not defined PLUGIN_DIR echo Error: Missing required argument 'PLUGIN_DIR' & call :usage & exit /b
if not defined LIB_DIR echo Error: Missing required argument 'LIB_DIR' & call :usage & exit /b
if not defined QML_DIR echo Error: Missing required argument 'QML_DIR' & call :usage & exit /b
if not defined CORECMD_PATH echo Error: Missing required argument 'CORECMD_PATH' & call :usage & exit /b
:: Normalize
set "INPUT_DIR=!INPUT_DIR:/=\!"
set "PLUGIN_DIR=!PLUGIN_DIR:/=\!"
set "LIB_DIR=!LIB_DIR:/=\!"
set "QML_DIR=!QML_DIR:/=\!"
set "CORECMD_PATH=!CORECMD_PATH:/=\!"
:: Get Qt plugin and QML paths
set "PLUGIN_PATHS="
set "QML_PATH="
if defined QMAKE_PATH (
for /f "tokens=*" %%a in ('!QMAKE_PATH! -query QT_INSTALL_PLUGINS') do set "QMAKE_PLUGIN_PATH=%%a"
set "PLUGIN_PATHS=!QMAKE_PLUGIN_PATH!"
for /f "tokens=*" %%a in ('!QMAKE_PATH! -query QT_INSTALL_QML') do set "QML_PATH=%%a"
set "QML_PATH=!QML_PATH:/=\!"
:: Add Qt bin directory
for /f "tokens=*" %%a in ('!QMAKE_PATH! -query QT_INSTALL_BINS') do set "QT_BIN_PATH=%%a"
call :push_args -L !QT_BIN_PATH!
)
:: Add extra plugin searching paths
set "PLUGIN_PATHS=!PLUGIN_PATHS! !EXTRA_PLUGIN_PATHS!"
:: Ensure that the QML search path is not empty
:: when the QML related path is specified (qmake needs to be specified)
if not "%QML_REL_PATHS%"=="" (
if "%QML_PATH%"=="" (
echo Error: qmake path must be specified when QML paths are provided
exit /b
)
)
:: The type of file to be searched depends on the operating system
:: On Windows, search for.exe and.dll files
for /r "%INPUT_DIR%" %%f in (*.exe *.dll) do (
set "FILES=!FILES! %%f"
)
:: Find the full path to the Qt plugin
for /L %%i in (1,1,%PLUGIN_COUNT%) do (
set "plugin_path=!PLUGINS[%%i]!"
:: Check format
echo !plugin_path! | findstr /R "[^/]*\/[^/]*" >nul
if errorlevel 1 (
echo Error: Invalid plugin format '!plugin_path!'. Expected format: ^<category^>/^<name^>
exit /b
)
:: Extracts the category and name
for /f "tokens=1,2 delims=/" %%a in ("!plugin_path!") do (
set "category=%%a"
set "name=%%b"
:: Calculate destination directory
set "DESTINATION_DIR=!PLUGIN_DIR!\!category!"
set "DESTINATION_DIR=!DESTINATION_DIR:/=\!"
:: Traverse the path and find the specific plug-in file
set "FOUND_PLUGINS="
call :search_plugin
if not defined FOUND_PLUGINS (
echo Error: Plugin '!plugin_path!' not found in any search paths.
exit /b
)
)
)
:: Process QML directories
for %%q in (%QML_REL_PATHS%) do (
call :search_qml_dir "%%q"
)
:: Build and execute the deploy
set "ARGS_FILE=windeps_args.txt"
if exist "%ARGS_FILE%" del %ARGS_FILE%
for %%a in (!FILES!) do (
echo %%a >> %ARGS_FILE%
)
for /L %%i in (1,1,%ARG_COUNT%) do (
echo !ARGS[%%i]! >> %ARGS_FILE%
)
echo -o >> %ARGS_FILE%
echo !LIB_DIR! >> %ARGS_FILE%
echo !VERBOSE! >> %ARGS_FILE%
set "DEPLOY_CMD=!CORECMD_PATH! deploy @!ARGS_FILE!"
call !DEPLOY_CMD!
:: Check the deployment result
if %errorlevel% neq 0 exit /b
del %ARGS_FILE%
exit /b
:: ----------------------------------------------------------------------------------
:: Add args
:push_args
for %%x in (%*) do set /a "ARG_COUNT+=1" & set "ARGS[!ARG_COUNT!]=%%x"
exit /b
:: ----------------------------------------------------------------------------------
:: ----------------------------------------------------------------------------------
:: Search plugins
:search_plugin
for %%d in (!PLUGIN_PATHS!) do (
for %%f in ("%%d\!category!\!name!.dll") do (
if exist "%%f" (
call :check_debug "%%f"
if "!ok!"=="0" (
call :add_plugin "%%f"
)
)
)
)
exit /b
:: ----------------------------------------------------------------------------------
:: ----------------------------------------------------------------------------------
:: Add plugin if not already found
:add_plugin
set "plugin=%~1"
set "plugin_name=%~nx1"
for %%i in (!FOUND_PLUGINS!) do (
if "%%i"=="!plugin_name!" (
exit /b
)
)
set "FOUND_PLUGINS=!FOUND_PLUGINS! !plugin_name!"
call :push_args -c !plugin! !DESTINATION_DIR!
exit /b
:: ----------------------------------------------------------------------------------
:: ----------------------------------------------------------------------------------
:: Search QML directory
:search_qml_dir
set "full_path=%QML_PATH%\%~1"
if exist "%full_path%\" (
:: Directory
for /r "%full_path%" %%f in (*) do (
call :handle_qml_file "%%f"
)
) else if exist "%full_path%" (
:: File
call :handle_qml_file "%full_path%"
)
exit /b
:: ----------------------------------------------------------------------------------
:: ----------------------------------------------------------------------------------
:: Check debug version of a dll
:check_debug
set "ok=1"
set "file_path=%~1"
if "!file_path:~-4!"==".pdb" exit /b
if "!file_path:~-10!"==".dll.debug" exit /b
if "!file_path:~-5!" == "d.dll" (
set "prefix=!file_path:~0,-5!"
if exist "!prefix!.dll" (
exit /b
)
)
set "ok=0"
exit /b
:: ----------------------------------------------------------------------------------
:: ----------------------------------------------------------------------------------
:: Copy or add to a deployment command
:handle_qml_file
set "file=%~1"
set "file=!file:/=\!"
:: Ignore specific files (example)
call :check_debug "%file%"
if "!ok!"=="1" (
exit /b
)
:: Computes target file and folder in a very stupid way
set "rel_path=!file:%QML_PATH%\=!"
set "target=%QML_DIR%\%rel_path%"
for %%I in ("!file!") do (
set "file_dir=%%~dpI"
)
set "rel_dir_path=!file_dir:%QML_PATH%\=!"
set "target_dir=%QML_DIR%\%rel_dir_path%"
:: Determine whether it is an executable binary file and handle it accordingly
if "%file:~-4%"==".dll" (
call :push_args -c !file! !target_dir!
) else if "%file:~-4%"==".exe" (
call :push_args -c !file! !target_dir!
) else (
if not exist "%target%" (
mkdir "%target_dir%" >nul 2>&1
)
copy /Y "%file%" "%target%" >nul 2>&1
)
exit /b
:: ----------------------------------------------------------------------------------
:: ----------------------------------------------------------------------------------
:: Show usage
:usage
echo Usage: %~n0 -i ^<dir^> -m ^<path^>
echo --plugindir ^<plugin_dir^> --libdir ^<lib_dir^> --qmldir ^<qml_dir^>
echo [--qmake ^<qmake_path^>] [--extra ^<extra_path^>]...
echo [--qml ^<qml_module^>]... [--plugin ^<plugin^>]... [--copy ^<src^> ^<dest^>]...
echo [--linkdirs-file ^<file^>]... [-L ^<path^>]...
echo [-f] [-s] [-V] [-h]
exit /b
:: ----------------------------------------------------------------------------------

View File

@@ -0,0 +1,23 @@
if(NOT DEFINED input)
message(FATAL_ERROR "input not defined")
endif()
if(NOT DEFINED output)
message(FATAL_ERROR "output not defined")
endif()
if(NOT DEFINED name)
message(FATAL_ERROR "name not defined")
endif()
get_filename_component(_output_dir ${output} DIRECTORY)
if(NOT EXISTS ${_output_dir})
file(MAKE_DIRECTORY ${_output_dir})
endif()
file(READ ${input} _file_content HEX)
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1, " _hex_content ${_file_content})
file(WRITE ${output}
"unsigned char ${name}[] = {${_hex_content}};\n"
"unsigned int ${name}_len = sizeof(${name});\n"
)