diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e9ceef4 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,106 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +env: + XLINGS_VERSION: v0.4.0 + +jobs: + build-linux: + runs-on: ubuntu-24.04 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install system deps + run: | + sudo apt-get update -qq + sudo apt-get install -y curl git build-essential + + - name: Install Xlings + env: + XLINGS_NON_INTERACTIVE: 1 + run: | + VERSION_NUM="${XLINGS_VERSION#v}" + TARBALL="xlings-${VERSION_NUM}-linux-x86_64.tar.gz" + curl -fSL -o "$RUNNER_TEMP/$TARBALL" "https://github.com/d2learn/xlings/releases/download/${XLINGS_VERSION}/${TARBALL}" + tar -xzf "$RUNNER_TEMP/$TARBALL" -C "$RUNNER_TEMP" + EXTRACT_DIR=$(find "$RUNNER_TEMP" -maxdepth 1 -type d -name "xlings-*" | head -1) + chmod +x "$EXTRACT_DIR/bin/xlings" + "$EXTRACT_DIR/bin/xlings" self install + echo "PATH=$HOME/.xlings/subos/current/bin:$PATH" >> "$GITHUB_ENV" + + - name: Install Project Dependencies via Xlings + run: | + #xlings install + cd .. + xlings install xmake@3.0.7 gcc@15 openssl@3.1.5 -y + + + - name: Build with xmake + run: | + xmake f -m release -vv -y + xmake -j$(nproc) + + - name: Verify d2x --version + run: ./build/linux/x86_64/release/d2x --version + + build-macos: + runs-on: [macos-latest] + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Xlings + env: + XLINGS_NON_INTERACTIVE: 1 + run: | + VERSION_NUM="${XLINGS_VERSION#v}" + TARBALL="xlings-${VERSION_NUM}-macosx-arm64.tar.gz" + curl -fSL -o "$RUNNER_TEMP/$TARBALL" "https://github.com/d2learn/xlings/releases/download/${XLINGS_VERSION}/${TARBALL}" + tar -xzf "$RUNNER_TEMP/$TARBALL" -C "$RUNNER_TEMP" + EXTRACT_DIR=$(find "$RUNNER_TEMP" -maxdepth 1 -type d -name "xlings-*" | head -1) + xattr -dr com.apple.quarantine "$EXTRACT_DIR" 2>/dev/null || true + chmod +x "$EXTRACT_DIR/bin/xlings" + "$EXTRACT_DIR/bin/xlings" self install + echo "PATH=$HOME/.xlings/subos/current/bin:$PATH" >> "$GITHUB_ENV" + + - name: Install Project Dependencies via Xlings + run: | + cd .. + xlings install xmake@3.0.7 llvm@20 -y + clang --version + + + - name: Build with xmake + run: | + export LLVM_PREFIX=$HOME/.xlings/data/xpkgs/xim-x-llvm/20.1.7 + ls -al $LLVM_PREFIX + xmake f -m release --toolchain=llvm --sdk=$LLVM_PREFIX -vv -y + xmake -j$(nproc) + + - name: Verify d2x --version + run: ./build/macosx/arm64/release/d2x --version + + build-windows: + runs-on: windows-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup xmake + uses: xmake-io/github-action-setup-xmake@v1 + with: + xmake-version: latest + + - name: Build with xmake + run: | + xmake f -m release -y + xmake -j$env:NUMBER_OF_PROCESSORS + + - name: Verify d2x --version + run: build\windows\x64\release\d2x.exe --version \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b273e24..d7c9d45 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,34 +8,41 @@ on: required: true type: string +env: + XLINGS_VERSION: v0.4.0 + jobs: build-linux: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout code uses: actions/checkout@v4 - - name: Setup xmake - uses: xmake-io/github-action-setup-xmake@v1 - with: - xmake-version: latest - - - name: Install dependencies + - name: Install system deps run: | - sudo apt-get update - sudo apt-get install -y build-essential + sudo apt-get update -qq + sudo apt-get install -y curl git build-essential - name: Install Xlings - run: curl -fsSL https://d2learn.org/xlings-install.sh | bash - - - name: install gcc 15.1 with Xlings + env: + XLINGS_NON_INTERACTIVE: 1 + run: | + VERSION_NUM="${XLINGS_VERSION#v}" + TARBALL="xlings-${VERSION_NUM}-linux-x86_64.tar.gz" + curl -fSL -o "$RUNNER_TEMP/$TARBALL" "https://github.com/d2learn/xlings/releases/download/${XLINGS_VERSION}/${TARBALL}" + tar -xzf "$RUNNER_TEMP/$TARBALL" -C "$RUNNER_TEMP" + EXTRACT_DIR=$(find "$RUNNER_TEMP" -maxdepth 1 -type d -name "xlings-*" | head -1) + chmod +x "$EXTRACT_DIR/bin/xlings" + "$EXTRACT_DIR/bin/xlings" self install + echo "PATH=$HOME/.xlings/subos/current/bin:$PATH" >> "$GITHUB_ENV" + + - name: Install Project Dependencies via Xlings run: | - export PATH=/home/xlings/.xlings_data/bin:$PATH - xlings install gcc@15.1 -y + cd .. + xlings install xmake@3.0.7 gcc@15 openssl@3.1.5 -y - name: Build with xmake run: | - export PATH=/home/xlings/.xlings_data/bin:$PATH xmake f -m release -y xmake -j$(nproc) @@ -52,19 +59,36 @@ jobs: path: d2x-${{ inputs.version }}-linux-x86_64.tar.gz build-macos: - runs-on: macos-14 + runs-on: [macos-latest] steps: - name: Checkout code uses: actions/checkout@v4 - - name: Install system deps - run: brew install xmake llvm@20 + - name: Install Xlings + env: + XLINGS_NON_INTERACTIVE: 1 + run: | + VERSION_NUM="${XLINGS_VERSION#v}" + TARBALL="xlings-${VERSION_NUM}-macosx-arm64.tar.gz" + curl -fSL -o "$RUNNER_TEMP/$TARBALL" "https://github.com/d2learn/xlings/releases/download/${XLINGS_VERSION}/${TARBALL}" + tar -xzf "$RUNNER_TEMP/$TARBALL" -C "$RUNNER_TEMP" + EXTRACT_DIR=$(find "$RUNNER_TEMP" -maxdepth 1 -type d -name "xlings-*" | head -1) + xattr -dr com.apple.quarantine "$EXTRACT_DIR" 2>/dev/null || true + chmod +x "$EXTRACT_DIR/bin/xlings" + "$EXTRACT_DIR/bin/xlings" self install + echo "PATH=$HOME/.xlings/subos/current/bin:$PATH" >> "$GITHUB_ENV" + + - name: Install Project Dependencies via Xlings + run: | + cd .. + xlings install xmake@3.0.7 llvm@20 -y + clang --version - - name: Build with xmake (LLVM 20 toolchain) + - name: Build with xmake run: | - export PATH=/opt/homebrew/opt/llvm@20/bin:$PATH - xmake f -p macosx -m release --toolchain=llvm --sdk=/opt/homebrew/opt/llvm@20 -y - xmake -j$(sysctl -n hw.ncpu) + export LLVM_PREFIX=$HOME/.xlings/data/xpkgs/xim-x-llvm/20.1.7 + xmake f -m release --toolchain=llvm --sdk=$LLVM_PREFIX -vv -y + xmake -j$(nproc) - name: Verify no LLVM runtime dependency run: | diff --git a/.xlings.json b/.xlings.json new file mode 100644 index 0000000..3fb332f --- /dev/null +++ b/.xlings.json @@ -0,0 +1,8 @@ +{ + "workspace": { + "xmake": "3.0.7", + "gcc": { "linux": "15.1.0" }, + "openssl": { "linux": "3.1.5" }, + "llvm": { "macos": "20" } + } +} \ No newline at end of file diff --git a/README.md b/README.md index fd4990c..13c57d4 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ | --- | ```cpp -d2x version: 0.1.1 +d2x version: 0.1.4 Usage: $ d2x [command] [target] [options] diff --git a/config.xlings b/config.xlings deleted file mode 100644 index ea3a52e..0000000 --- a/config.xlings +++ /dev/null @@ -1,8 +0,0 @@ --- https://github.com/d2learn/xlings - -xname = "d2x" - -xim = { - xmake = "3.0.4", - cpp = "", -} \ No newline at end of file diff --git a/src/config.cppm b/src/config.cppm index f7d3d49..472c75d 100644 --- a/src/config.cppm +++ b/src/config.cppm @@ -17,7 +17,7 @@ export struct EnvVars; export class Config; struct Info { - static constexpr std::string_view VERSION = "0.1.3"; + static constexpr std::string_view VERSION = "0.1.4"; static constexpr std::string_view REPO = "https://github.com/d2learn/d2x"; }; diff --git a/src/platform.cppm b/src/platform.cppm index b9ca897..79c37aa 100644 --- a/src/platform.cppm +++ b/src/platform.cppm @@ -11,7 +11,7 @@ namespace platform { static std::string gRundir = std::filesystem::current_path().string(); - export using platform_impl::XLINGS_BIN; + export using platform_impl::get_xlings_bin; export using platform_impl::XLINGS_INSTALL_CMD; export using platform_impl::clear_console; @@ -65,7 +65,7 @@ namespace platform { int status = platform::exec(std::string(XLINGS_INSTALL_CMD)); if (status == 0) { std::println("xlings 安装成功!"); - std::string xlings_path { std::filesystem::path(XLINGS_BIN).parent_path().string() }; + std::string xlings_path { std::filesystem::path(get_xlings_bin()).parent_path().string() }; char* path_env = std::getenv("PATH"); if (path_env) { std::string new_path = std::string(path_env) + ";" + xlings_path; diff --git a/src/platform/linux.cppm b/src/platform/linux.cppm index 8783617..867d185 100644 --- a/src/platform/linux.cppm +++ b/src/platform/linux.cppm @@ -12,7 +12,6 @@ import std; namespace d2x { namespace platform_impl { - export constexpr std::string_view XLINGS_BIN = "/home/xlings/.xlings_data/bin/xlings"; export constexpr std::string_view XLINGS_INSTALL_CMD = "curl -fsSL https://d2learn.org/xlings-install.sh | bash"; export std::pair run_command_capture(const std::string& cmd) { @@ -41,6 +40,10 @@ namespace platform_impl { return "."; } + export inline std::string get_xlings_bin() { + return get_home_dir() + "/.xlings/subos/current/bin/xlings"; + } + export void set_env_variable(const std::string& key, const std::string& value) { ::setenv(key.c_str(), value.c_str(), 1); } diff --git a/src/platform/macos.cppm b/src/platform/macos.cppm index 568072b..dad3508 100644 --- a/src/platform/macos.cppm +++ b/src/platform/macos.cppm @@ -12,7 +12,6 @@ import std; namespace d2x { namespace platform_impl { - export constexpr std::string_view XLINGS_BIN = "/Users/xlings/.xlings_data/bin/xlings"; export constexpr std::string_view XLINGS_INSTALL_CMD = "curl -fsSL https://d2learn.org/xlings-install.sh | bash"; export std::pair run_command_capture(const std::string& cmd) { @@ -42,6 +41,10 @@ namespace platform_impl { return "."; } + export inline std::string get_xlings_bin() { + return get_home_dir() + "/.xlings/subos/current/bin/xlings"; + } + export void set_env_variable(const std::string& key, const std::string& value) { ::setenv(key.c_str(), value.c_str(), 1); } diff --git a/src/platform/windows.cppm b/src/platform/windows.cppm index 77fde6b..9ad2402 100644 --- a/src/platform/windows.cppm +++ b/src/platform/windows.cppm @@ -12,7 +12,6 @@ import std; namespace d2x { namespace platform_impl { - export constexpr std::string_view XLINGS_BIN = "C:\\Users\\Public\\xlings\\.xlings_data\\bin\\xlings"; export constexpr std::string_view XLINGS_INSTALL_CMD = "powershell -Command \"irm https://d2learn.org/xlings-install.ps1.txt | iex\""; export std::pair run_command_capture(const std::string& cmd) { @@ -40,6 +39,10 @@ namespace platform_impl { return "."; } + export inline std::string get_xlings_bin() { + return get_home_dir() + "\\.xlings\\subos\\current\\bin\\xlings"; + } + export void set_env_variable(const std::string& key, const std::string& value) { _putenv_s(key.c_str(), value.c_str()); } diff --git a/src/xlings.cppm b/src/xlings.cppm index 07c18bb..e482eb3 100644 --- a/src/xlings.cppm +++ b/src/xlings.cppm @@ -10,17 +10,15 @@ namespace xlings { [[nodiscard]] bool has_xlings() { - // check by XLINGS_BIN - if (std::filesystem::exists(platform::XLINGS_BIN)) { + // check by xlings binary path + if (std::filesystem::exists(platform::get_xlings_bin())) { return true; } - auto [status, output] = d2x::platform::run_command_capture("xlings"); + auto [status, output] = d2x::platform::run_command_capture("xlings --version"); auto clean_output = d2x::utils::strip_ansi(output); - return status == 0 && ( - clean_output.find("xlings version") != std::string::npos || - clean_output.find("xlings 版本") != std::string::npos - ); + // match xlings x.x.x format to check if xlings is installed + return status == 0 && std::regex_match(clean_output, std::regex("xlings (\\d+\\.\\d+\\.\\d+)")); } export bool ensure_xlings_installed() { diff --git a/xmake.lua b/xmake.lua index d8fde2f..e91ce3b 100644 --- a/xmake.lua +++ b/xmake.lua @@ -5,7 +5,7 @@ set_languages("c++23") add_repositories("mcpplibs-index https://github.com/mcpplibs/mcpplibs-index.git") add_requires("llmapi 0.0.2") -add_requires("cmdline 0.0.1") +add_requires("cmdline 0.0.2") add_requires("ftxui 6.1.9") target("d2x") @@ -19,11 +19,16 @@ target("d2x") -- platform specific settings if is_plat("macosx") then - - local llvm_prefix = os.getenv("LLVM_PREFIX") or "/opt/homebrew/opt/llvm@20" - add_linkdirs(llvm_prefix .. "/lib/c++") - add_ldflags("-Wl,-rpath," .. llvm_prefix .. "/lib/c++", {force = true}) + set_toolchains("llvm") + local llvm_prefix = os.getenv("LLVM_PREFIX") + if llvm_prefix then -- if LLVM_PREFIX is set, we assume it's a recent version of LLVM that provides its own libc++ with C++23 support + -- 静态链接 LLVM 自带的 libc++,避免依赖系统 libc++.dylib 中缺失的 C++23 符号 + -- (std::println 等 C++23 特性需要 macOS 15+ 的 libc++,静态链接后可在 macOS 11+ 运行) + add_ldflags("-nostdlib++", {force = true}) + add_ldflags(llvm_prefix .. "/lib/libc++.a", {force = true}) + add_ldflags(llvm_prefix .. "/lib/libc++abi.a", {force = true}) + end elseif is_plat("linux") then - add_ldflags("-static-libstdc++", "-static-libgcc", {force = true}) + add_ldflags("-static", {force = true}) end