build(msys2): add local Windows build support
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -8,4 +8,8 @@ scripts/yaml-cpp
|
||||
.DS_Store
|
||||
src/.DS_Store
|
||||
|
||||
build
|
||||
build
|
||||
bridge/libmihomo.a
|
||||
bridge/libmihomo.so
|
||||
bridge/libmihomo.dll
|
||||
bridge/libmihomo.dll.a
|
||||
|
||||
@@ -1460,7 +1460,11 @@ public:
|
||||
if(!rt)
|
||||
throw std::runtime_error{"qjs: Cannot create runtime"};
|
||||
|
||||
#ifdef _WIN32
|
||||
JS_SetHostPromiseRejectionTracker(rt, promise_unhandled_rejection_tracker, NULL);
|
||||
#else
|
||||
JS_SetHostUnhandledPromiseRejectionTracker(rt, promise_unhandled_rejection_tracker, NULL);
|
||||
#endif // _WIN32
|
||||
JS_SetModuleLoaderFunc(rt, nullptr, module_loader, nullptr);
|
||||
}
|
||||
|
||||
|
||||
94
scripts/build-local-msys2.ps1
Normal file
94
scripts/build-local-msys2.ps1
Normal file
@@ -0,0 +1,94 @@
|
||||
param(
|
||||
[ValidateRange(1, 32)]
|
||||
[int]$Jobs = 8,
|
||||
|
||||
[ValidateSet("Debug", "Release", "RelWithDebInfo")]
|
||||
[string]$BuildType = "RelWithDebInfo",
|
||||
|
||||
[switch]$RebuildBridge,
|
||||
[switch]$RebuildLibCron
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
|
||||
$bash = "C:\msys64\usr\bin\bash.exe"
|
||||
|
||||
if (-not (Test-Path $bash)) {
|
||||
throw "MSYS2 was not found at C:\msys64. Install MSYS2 first."
|
||||
}
|
||||
|
||||
$env:SCX_ROOT_WIN = $repoRoot
|
||||
$env:SCX_JOBS = [string]$Jobs
|
||||
$env:SCX_BUILD_TYPE = $BuildType
|
||||
$env:SCX_REBUILD_BRIDGE = if ($RebuildBridge) { "1" } else { "0" }
|
||||
$env:SCX_REBUILD_LIBCRON = if ($RebuildLibCron) { "1" } else { "0" }
|
||||
|
||||
$script = @'
|
||||
set -euo pipefail
|
||||
|
||||
export MSYSTEM=UCRT64
|
||||
export PATH="/c/Program Files/Go/bin:/ucrt64/bin:/usr/bin:$PATH"
|
||||
|
||||
root="$(cygpath -u "$SCX_ROOT_WIN")"
|
||||
cd "$root"
|
||||
|
||||
for tool in gcc g++ cmake ninja pkg-config git go; do
|
||||
command -v "$tool" >/dev/null || {
|
||||
echo "Missing required tool: $tool" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
pkg-config --exists libcurl yaml-cpp libpcre2-8 || {
|
||||
echo "Missing one or more pkg-config dependencies: libcurl yaml-cpp libpcre2-8" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ ! -f /ucrt64/include/quickjs/quickjs.h ] || [ ! -f /ucrt64/lib/quickjs/libquickjs.a ]; then
|
||||
echo "Missing QuickJS. Install mingw-w64-ucrt-x86_64-quickjs in MSYS2." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$SCX_REBUILD_LIBCRON" = "1" ] || [ ! -f /ucrt64/lib/liblibcron.a ]; then
|
||||
work=/tmp/subconverter-build-deps
|
||||
mkdir -p "$work"
|
||||
cd "$work"
|
||||
if [ ! -d libcron/.git ]; then
|
||||
git clone --depth=1 https://github.com/PerMalmberg/libcron
|
||||
fi
|
||||
cd libcron
|
||||
git submodule update --init
|
||||
cmake -S . -B build-ucrt -G Ninja -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build-ucrt --target libcron -j "$SCX_JOBS"
|
||||
mkdir -p /ucrt64/lib /ucrt64/include/libcron /ucrt64/include/date
|
||||
cp -f libcron/out/Release/liblibcron.a /ucrt64/lib/
|
||||
cp -f libcron/include/libcron/* /ucrt64/include/libcron/
|
||||
cp -f libcron/externals/date/include/date/* /ucrt64/include/date/
|
||||
cd "$root"
|
||||
fi
|
||||
|
||||
if [ "$SCX_REBUILD_BRIDGE" = "1" ] || [ ! -f bridge/libmihomo.a ]; then
|
||||
cd "$root/bridge"
|
||||
go mod download
|
||||
CC=gcc CXX=g++ CGO_ENABLED=1 go build -buildmode=c-archive -o libmihomo.a .
|
||||
unix2dos libmihomo.h >/dev/null 2>&1 || true
|
||||
cd "$root"
|
||||
fi
|
||||
|
||||
cmake -S . -B build/ucrt64 -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE="$SCX_BUILD_TYPE" \
|
||||
-DCMAKE_PREFIX_PATH=/ucrt64 \
|
||||
-DCMAKE_C_COMPILER=gcc \
|
||||
-DCMAKE_CXX_COMPILER=g++ \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
cmake --build build/ucrt64 -j "$SCX_JOBS"
|
||||
|
||||
echo
|
||||
echo "Built: $root/build/ucrt64/subconverter.exe"
|
||||
echo "Run: ./scripts/run-local-msys2.ps1"
|
||||
'@
|
||||
|
||||
& $bash -lc $script
|
||||
exit $LASTEXITCODE
|
||||
37
scripts/run-local-msys2.ps1
Normal file
37
scripts/run-local-msys2.ps1
Normal file
@@ -0,0 +1,37 @@
|
||||
param(
|
||||
[string]$Config = "base/pref.example.toml"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
|
||||
$bash = "C:\msys64\usr\bin\bash.exe"
|
||||
$exe = Join-Path $repoRoot "build\ucrt64\subconverter.exe"
|
||||
$configPath = Resolve-Path (Join-Path $repoRoot $Config)
|
||||
|
||||
if (-not (Test-Path $bash)) {
|
||||
throw "MSYS2 was not found at C:\msys64."
|
||||
}
|
||||
|
||||
if (-not (Test-Path $exe)) {
|
||||
throw "subconverter.exe was not found. Run scripts\build-local-msys2.ps1 first."
|
||||
}
|
||||
|
||||
$env:SCX_ROOT_WIN = $repoRoot
|
||||
$env:SCX_CONFIG_WIN = $configPath.Path
|
||||
|
||||
$script = @'
|
||||
set -euo pipefail
|
||||
|
||||
export MSYSTEM=UCRT64
|
||||
export PATH="/ucrt64/bin:/usr/bin:$PATH"
|
||||
|
||||
root="$(cygpath -u "$SCX_ROOT_WIN")"
|
||||
config="$(cygpath -w "$SCX_CONFIG_WIN")"
|
||||
|
||||
cd "$root"
|
||||
exec ./build/ucrt64/subconverter.exe -f "$config"
|
||||
'@
|
||||
|
||||
& $bash -lc $script
|
||||
exit $LASTEXITCODE
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "utils/rapidjson_extra.h"
|
||||
#include "utils/regexp.h"
|
||||
#include "utils/stl_extra.h"
|
||||
#include "utils/time_compat.h"
|
||||
#include "utils/urlencode.h"
|
||||
#include "utils/yamlcpp_extra.h"
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "utils/logger.h"
|
||||
#include "utils/network.h"
|
||||
#include "utils/regexp.h"
|
||||
#include "utils/time_compat.h"
|
||||
#include "utils/urlencode.h"
|
||||
#include "utils/yamlcpp_extra.h"
|
||||
#include "templates.h"
|
||||
@@ -312,12 +313,13 @@ int render_template(const std::string &content, const template_args &vars,
|
||||
#endif // NO_WEBGET
|
||||
//env.add_callback("parseHostname", 1, parseHostname);
|
||||
|
||||
env.set_include_callback([&](const std::string &name, const std::string &template_name)
|
||||
env.set_include_callback([&](const std::filesystem::path &path, const std::string &template_name)
|
||||
{
|
||||
const std::string include_path = path.string();
|
||||
std::string absolute_path;
|
||||
try
|
||||
{
|
||||
absolute_path = std::filesystem::canonical(template_name).string();
|
||||
absolute_path = std::filesystem::canonical(path).string();
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
@@ -326,7 +328,7 @@ int render_template(const std::string &content, const template_args &vars,
|
||||
if(!absolute_scope.empty() &&
|
||||
!path_is_inside_scope(absolute_path, absolute_scope))
|
||||
throw inja::FileError("access denied when trying to include '" + template_name + "': out of scope");
|
||||
return env.parse(fileGet(template_name, true));
|
||||
return env.parse(fileGet(include_path, true));
|
||||
});
|
||||
env.set_search_included_templates_in_files(false);
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "server/webserver.h"
|
||||
#include "settings.h"
|
||||
#include "upload.h"
|
||||
#include "utils/time_compat.h"
|
||||
|
||||
// Multiple CDN fallback URLs for default external config
|
||||
// Will be tried in order if user-provided config fails to load
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "utils/rapidjson_extra.h"
|
||||
#include "utils/regexp.h"
|
||||
#include "utils/string.h"
|
||||
#include "utils/time_compat.h"
|
||||
|
||||
unsigned long long streamToInt(const std::string &stream)
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "defer.h"
|
||||
#include "lock.h"
|
||||
#include "logger.h"
|
||||
#include "time_compat.h"
|
||||
|
||||
std::string getTime(int type)
|
||||
{
|
||||
|
||||
14
src/utils/time_compat.h
Normal file
14
src/utils/time_compat.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef TIME_COMPAT_H_INCLUDED
|
||||
#define TIME_COMPAT_H_INCLUDED
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#ifdef _WIN32
|
||||
inline tm *localtime_r(const time_t *timep, tm *result) {
|
||||
if (timep == nullptr || result == nullptr)
|
||||
return nullptr;
|
||||
return localtime_s(result, timep) == 0 ? result : nullptr;
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
#endif // TIME_COMPAT_H_INCLUDED
|
||||
Reference in New Issue
Block a user