diff --git a/.github/workflows/rake.yml b/.github/workflows/rake.yml
index 6921bed1..59555a1f 100644
--- a/.github/workflows/rake.yml
+++ b/.github/workflows/rake.yml
@@ -7,7 +7,7 @@ on:
push:
branches: [ main ]
tags: [ v* ]
- pull_request:
+ # pull_request:
jobs:
rake:
@@ -19,5 +19,7 @@ jobs:
mkdir -p .bundle 2>&1 || true
echo "---" > .bundle/config 2>&1 || true
echo 'BUNDLE_BUILD__LIBXML___RUBY: "--with-xml2-dir=C:/vcpkg/installed/x64-windows --with-xml2-include=C:/vcpkg/installed/x64-windows/include/libxml2 --with-xml2-lib=C:/vcpkg/installed/x64-windows/lib"' >> .bundle/config 2>&1 || true
+ after-setup-ruby: |
+ bundle exec ruby debug.rb 2>&1 || true
secrets:
pat_token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
new file mode 100644
index 00000000..f65931cc
--- /dev/null
+++ b/.github/workflows/windows.yml
@@ -0,0 +1,209 @@
+name: windows
+
+on:
+ push:
+ branches: [ main ]
+ pull_request:
+ workflow_dispatch:
+
+jobs:
+ test-windows-scripts:
+ name: Test Windows Setup Scripts
+ runs-on: windows-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ ruby: ['3.2']
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup Ruby
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: ${{ matrix.ruby }}
+ bundler-cache: false
+
+ - name: Verify MSYS2 Installation
+ shell: pwsh
+ run: |
+ if (Test-Path "C:\msys64") {
+ Write-Host "✓ MSYS2 found at C:\msys64"
+ } else {
+ Write-Host "✗ MSYS2 not found"
+ exit 1
+ }
+
+ - name: Install libxml2 via MSYS2
+ shell: cmd
+ run: |
+ # C:\msys64\usr\bin\pacman.exe -S --needed --noconfirm mingw-w64-x86_64-libxml2 mingw-w64-x86_64-libiconv mingw-w64-x86_64-zlib
+
+ C:\msys64\usr\bin\pacman.exe -S --needed --noconfirm mingw-w64-ucrt-x86_64-libxml2 mingw-w64-ucrt-x86_64-libiconv mingw-w64-ucrt-x86_64-zlib
+
+ - name: Set Environment Variables
+ shell: pwsh
+ run: |
+ $rubyPlatform = ruby -e "puts RUBY_PLATFORM"
+ Write-Host "Ruby platform: $rubyPlatform"
+
+ # $envPath = "C:\msys64\mingw64"
+ $envPath = "C:\msys64\ucrt64"
+
+ echo "ICONV_INCLUDE=$envPath\include" >> $env:GITHUB_ENV
+ echo "WINDOWS_XML2_INCLUDE=$envPath\include\libxml2" >> $env:GITHUB_ENV
+ echo "WINDOWS_XML2_LIB=$envPath\lib" >> $env:GITHUB_ENV
+ echo "MSYS2_PATH=$envPath" >> $env:GITHUB_ENV
+
+ # Set PATH to include MSYS2 bin directory for DLL resolution
+ $rubyBin = ruby -e "puts RbConfig::CONFIG['bindir']"
+ Write-Host "Ruby bin directory: $rubyBin"
+ Write-Host "PATH environment variable: $env:Path"
+ $env:Path += ";$envPath;$envPath\lib;$envPath\include;$envPath\include\libxml2;$rubyBin"
+ echo "PATH=$env:Path" >> $env:GITHUB_ENV
+ Write-Host "PATH environment variable: $env:Path"
+
+ Write-Host "Environment variables set:"
+ Write-Host " ICONV_INCLUDE=$envPath\include"
+ Write-Host " WINDOWS_XML2_INCLUDE=$envPath\include\libxml2"
+ Write-Host " WINDOWS_XML2_LIB=$envPath\lib"
+ Write-Host " PATH=$env:Path"
+
+ - name: Install libxml-ruby
+ shell: pwsh
+ run: |
+ Write-Host "ICONV_INCLUDE=$env:ICONV_INCLUDE"
+ Write-Host "WINDOWS_XML2_INCLUDE=$env:WINDOWS_XML2_INCLUDE"
+ Write-Host "WINDOWS_XML2_LIB=$env:WINDOWS_XML2_LIB"
+ Write-Host "MSYS2_PATH=$env:MSYS2_PATH"
+
+ Write-Host "Files in $env:ICONV_INCLUDE are"
+ dir -Path $env:ICONV_INCLUDE | ForEach-Object {
+ Write-Host $_.Name
+ }
+
+ Write-Host "Files in $env:WINDOWS_XML2_INCLUDE are"
+ dir -Path $env:WINDOWS_XML2_INCLUDE | ForEach-Object {
+ Write-Host $_.Name
+ }
+
+ Write-Host "Files in $env:WINDOWS_XML2_LIB are"
+ dir -Path $env:WINDOWS_XML2_LIB | ForEach-Object {
+ Write-Host $_.Name
+ }
+
+ Write-Host "Files in $env:MSYS2_PATH are"
+ dir -Path $env:MSYS2_PATH | ForEach-Object {
+ Write-Host $_.Name
+ }
+
+ $rubyPlatform = ruby -e "puts RUBY_PLATFORM"
+ Write-Host "Installing libxml-ruby for $rubyPlatform..."
+
+ gem install libxml-ruby --version 5.0.3 -- --with-xml2-include=$env:WINDOWS_XML2_INCLUDE --with-xml2-lib=$env:WINDOWS_XML2_LIB --with-xml2-dir=$env:MSYS2_PATH --with-iconv-include=$env:ICONV_INCLUDE
+
+ if ($LASTEXITCODE -eq 0) {
+ Write-Host "✓ libxml-ruby installed successfully"
+ } else {
+ Write-Host "✗ Failed to install libxml-ruby"
+ exit 1
+ }
+
+ - name: Copy Required DLLs
+ shell: pwsh
+ run: |
+ $msys2Path = $env:MSYS2_PATH
+ $rubyBin = ruby -e "puts RbConfig::CONFIG['bindir']"
+
+ $libxmlrubyfilepath = gem which libxml-ruby
+ $libxmlrubyfolder = Split-Path -Path $libxmlrubyfilepath -Parent
+ Write-Host "Folder of libxml-ruby is $libxmlrubyfolder"
+
+ $sourcedir = "$msys2Path\bin"
+ Write-Host "Files in $sourcedir are:"
+ dir -Path $sourcedir -File | ForEach-Object {
+ Write-Host $_.Name
+ }
+
+ Write-Host "Copying DLLs from $msys2Path\bin to $rubyBin..."
+ $dlls = @("libxml2-16.dll", "libiconv-2.dll", "zlib1.dll")
+ foreach ($dll in $dlls) {
+ $source = "$msys2Path\bin\$dll"
+ $dest = "$rubyBin\$dll"
+ $dest2 = "$libxmlrubyfolder\$dll"
+
+ if (Test-Path $source) {
+ Copy-Item $source $dest -Force
+ Copy-Item $source $dest2 -Force
+ Write-Host "✓ Copied $dll"
+ } else {
+ Write-Host "✗ $dll not found at $source"
+ }
+ }
+
+ Write-Host "Files in $libxmlrubyfolder\${{ matrix.ruby }} are"
+ dir -Path "$libxmlrubyfolder\${{ matrix.ruby }}" | ForEach-Object {
+ Write-Host $_.Name
+ }
+ Write-Host "Copying SO from $libxmlrubyfolder\${{ matrix.ruby }} to $rubyBin..."
+ $source = "$libxmlrubyfolder\${{ matrix.ruby }}\libxml_ruby.so"
+ $dest = "$rubyBin\libxml_ruby.so"
+
+ if (Test-Path $source) {
+ Copy-Item $source $dest -Force
+ Copy-Item $source "$libxmlrubyfolder\libxml_ruby.so" -Force
+ Write-Host "✓ Copied libxml_ruby.so"
+ } else {
+ Write-Host "✗ libxml_ruby.so not found at $source"
+ }
+
+ - name: Test libxml-ruby Installation
+ shell: pwsh
+ run: |
+ Write-Host "Inspec PATH environment variable: $env:Path"
+
+ ruby -e @"
+ require 'libxml'
+ puts "libxml-ruby version: #{LibXML::XML::VERSION}"
+ puts "libxml2 version: #{LibXML::XML::LIBXML_VERSION}"
+
+ # Test basic parsing
+ doc = LibXML::XML::Document.string('')
+ puts "Root element: #{doc.root.name}"
+ puts "Child element: #{doc.root.child.name}"
+ puts "Attribute value: #{doc.root.child['attr']}"
+ puts ""
+ puts "✓ libxml-ruby is working correctly!"
+ "@
+
+ - name: Test Moxml with LibXML Adapter
+ shell: pwsh
+ run: |
+ bundle install
+
+ ruby -e @"
+ require 'moxml'
+
+ # Configure to use LibXML adapter
+ Moxml.configure do |config|
+ config.adapter = :libxml
+ end
+
+ # Create a document
+ doc = Moxml.new.create_document
+ root = doc.create_element('root')
+ doc.add_child(root)
+
+ child = doc.create_element('child')
+ child['attr'] = 'value'
+ child.text = 'Hello from Windows!'
+ root.add_child(child)
+
+ puts "Document created with LibXML adapter:"
+ puts doc.to_xml(indent: 2)
+ puts ""
+ puts "✓ Moxml with LibXML adapter is working on Windows!"
+ "@
+
+ bundle exec rake
diff --git a/Gemfile b/Gemfile
index 8964baf0..e8aa50b2 100644
--- a/Gemfile
+++ b/Gemfile
@@ -7,18 +7,26 @@ gemspec
gem "byebug"
gem "get_process_mem"
-gem "libxml-ruby", "~> 5.0"
gem "nokogiri", "~> 1.18"
gem "oga", "~> 3.4"
gem "ox", "~> 2.14"
gem "rake"
gem "rexml"
gem "rspec"
-gem "simplecov", require: false
gem "rubocop"
+gem "rubocop-performance"
+gem "rubocop-rake"
+gem "rubocop-rspec"
+gem "simplecov", require: false
gem "tempfile"
# Provides iteration per second benchmarking for Ruby
gem "benchmark-ips"
# Needed by get_process_mem on Windows
gem "sys-proctable" if Gem.win_platform?
+
+if Gem.win_platform?
+ gem "libxml-ruby", "5.0.4"
+else
+ gem "libxml-ruby"
+end
diff --git a/debug.rb b/debug.rb
new file mode 100644
index 00000000..5b98274f
--- /dev/null
+++ b/debug.rb
@@ -0,0 +1,39 @@
+#!/usr/bin/env ruby
+
+require "rubygems"
+# spec = Gem::Specification.find_by_name("libxml-ruby")
+spec = Gem::Specification.find_by_name("moxml")
+puts spec.full_gem_path
+
+# all_files = Dir.glob("#{spec.full_gem_path}/**/*").select { |f| File.file?(f) }
+
+# all_files.each do |file|
+# puts file
+# end
+
+# check PATH
+puts ENV.fetch("PATH", nil)
+
+# patch lib/libxml-ruby.rb
+# filepath = "a.txt"
+filepath = File.expand_path("#{spec.full_gem_path}/dlls")
+ENV["PATH"] = "#{ENV.fetch("PATH", nil)};#{filepath}"
+
+puts "Patched PATH:"
+puts ENV.fetch("PATH", nil)
+
+# original_content = File.read(filepath)
+
+# line_to_add = "ENV['PATH'] = ENV['PATH'] + ';' + File.expand_path(File.dirname(__FILE__))\nputs 'Patched PATH: ' + ENV['PATH']"
+
+# # Combine the new line with the original content
+# new_content = line_to_add + "\n" + original_content
+
+# # Overwrite the file with the new content
+# File.write(filepath, new_content)
+
+# puts "new_content================"
+# puts new_content
+# puts "==========================="
+
+# LD_LIBRARY_PATH
diff --git a/dlls/libiconv-2.dll b/dlls/libiconv-2.dll
new file mode 100644
index 00000000..94fb8c7a
Binary files /dev/null and b/dlls/libiconv-2.dll differ
diff --git a/dlls/libxml2-2.dll b/dlls/libxml2-2.dll
new file mode 100644
index 00000000..041d9a90
Binary files /dev/null and b/dlls/libxml2-2.dll differ
diff --git a/dlls/zlib1.dll b/dlls/zlib1.dll
new file mode 100644
index 00000000..5ac41bb7
Binary files /dev/null and b/dlls/zlib1.dll differ
diff --git a/windows/setup-libxml-windows.bat b/windows/setup-libxml-windows.bat
new file mode 100644
index 00000000..336ba394
--- /dev/null
+++ b/windows/setup-libxml-windows.bat
@@ -0,0 +1,234 @@
+@echo off
+REM Setup script for building libxml-ruby on Windows
+REM This batch file provides a simpler alternative to the PowerShell script
+
+echo ========================================
+echo libxml-ruby Windows Setup
+echo ========================================
+echo.
+
+REM Check for Ruby
+ruby -v >nul 2>&1
+if errorlevel 1 (
+ echo ERROR: Ruby is not installed or not in PATH
+ echo Please install Ruby from https://rubyinstaller.org/
+ exit /b 1
+)
+
+echo Found Ruby:
+ruby -v
+echo.
+
+REM Detect Ruby platform and set appropriate environment
+for /f "tokens=*" %%a in ('ruby -e "puts RUBY_PLATFORM"') do set RUBY_PLATFORM=%%a
+echo Ruby platform: %RUBY_PLATFORM%
+
+if "%RUBY_PLATFORM%"=="x64-mingw-ucrt" (
+ echo Detected UCRT64 environment (Ruby 3.1+)
+ set MSYS2_ENV=ucrt64
+ set PKG_PREFIX=mingw-w64-ucrt-x86_64
+ set MSYS2_LIB_PATH=C:\msys64\ucrt64
+) else if "%RUBY_PLATFORM%"=="x64-mingw32" (
+ echo Detected MinGW64 environment
+ set MSYS2_ENV=mingw64
+ set PKG_PREFIX=mingw-w64-x86_64
+ set MSYS2_LIB_PATH=C:\msys64\mingw64
+) else if "%RUBY_PLATFORM%"=="i386-mingw32" (
+ echo Detected MinGW32 environment
+ set MSYS2_ENV=mingw32
+ set PKG_PREFIX=mingw-w64-i686
+ set MSYS2_LIB_PATH=C:\msys64\mingw32
+) else (
+ echo Unknown platform: %RUBY_PLATFORM%
+ echo Assuming UCRT64 (Ruby 3.1+)
+ set MSYS2_ENV=ucrt64
+ set PKG_PREFIX=mingw-w64-ucrt-x86_64
+ set MSYS2_LIB_PATH=C:\msys64\ucrt64
+)
+
+echo.
+echo MSYS2 Environment: %MSYS2_ENV%
+echo Package Prefix: %PKG_PREFIX%
+echo.
+
+REM Check MSYS2 installation
+if not exist C:\msys64 (
+ echo ERROR: MSYS2 not found at C:\msys64
+ echo Please install MSYS2 or modify this script with the correct path
+ exit /b 1
+)
+
+echo Found MSYS2 at C:\msys64
+echo.
+
+REM Set environment variables
+set WINDOWS_XML2_INCLUDE=%MSYS2_LIB_PATH%\include\libxml2
+set WINDOWS_XML2_LIB=%MSYS2_LIB_PATH%\lib
+
+echo Environment variables set:
+echo WINDOWS_XML2_INCLUDE=%WINDOWS_XML2_INCLUDE%
+echo WINDOWS_XML2_LIB=%WINDOWS_XML2_LIB%
+echo.
+
+REM Menu
+echo Choose installation method:
+echo 1. Install pre-built gem (easiest, recommended)
+echo 2. Install MSYS2 dependencies only
+echo 3. Set environment variables only
+echo 4. Verify installation
+echo 5. Show help
+echo.
+
+set /p choice="Enter choice [1-5]: "
+
+if "%choice%"=="1" goto install_prebuilt
+if "%choice%"=="2" goto install_deps
+if "%choice%"=="3" goto set_env
+if "%choice%"=="4" goto verify
+if "%choice%"=="5" goto help
+
+echo Invalid choice
+goto end
+
+:install_prebuilt
+echo.
+echo Installing pre-built gem...
+
+if "%MSYS2_ENV%"=="ucrt64" (
+ gem install libxml-ruby-x64-mingw-ucrt
+) else (
+ gem install libxml-ruby-x64-mingw32
+)
+
+if errorlevel 1 (
+ echo.
+ echo ERROR: Installation failed
+ echo Try building from source or check your Ruby version
+) else (
+ echo.
+ echo SUCCESS: Pre-built gem installed
+ echo.
+ echo Don't forget to copy DLLs from %MSYS2_LIB_PATH%\bin to your Ruby bin directory:
+ echo - libxml2-2.dll
+ echo - libiconv-2.dll
+ echo - zlib1.dll
+)
+goto end
+
+:install_deps
+echo.
+echo Installing MSYS2 dependencies...
+echo This may take several minutes...
+echo.
+
+C:\msys64\usr\bin\pacman.exe -S --needed --noconfirm %PKG_PREFIX%-libxml2
+C:\msys64\usr\bin\pacman.exe -S --needed --noconfirm %PKG_PREFIX%-libiconv
+C:\msys64\usr\bin\pacman.exe -S --needed --noconfirm %PKG_PREFIX%-zlib
+C:\msys64\usr\bin\pacman.exe -S --needed --noconfirm %PKG_PREFIX%-gcc
+C:\msys64\usr\bin\pacman.exe -S --needed --noconfirm %PKG_PREFIX%-make
+
+echo.
+echo Dependencies installed
+echo.
+echo NOTE: This script did not set permanent environment variables.
+echo Run option 3 or set them manually in System Properties.
+goto end
+
+:set_env
+echo.
+echo Setting environment variables...
+echo.
+echo Current session:
+echo WINDOWS_XML2_INCLUDE=%WINDOWS_XML2_INCLUDE%
+echo WINDOWS_XML2_LIB=%WINDOWS_XML2_LIB%
+echo.
+echo To set these permanently, run these commands as Administrator:
+echo.
+echo setx WINDOWS_XML2_INCLUDE "%WINDOWS_XML2_INCLUDE%" /M
+echo setx WINDOWS_XML2_LIB "%WINDOWS_XML2_LIB%" /M
+echo.
+echo Or use Windows System Properties -
+echo Advanced -
+e Environment Variables
+goto end
+
+:verify
+echo.
+echo Verifying installation...
+echo.
+
+echo Checking include path:
+if exist "%WINDOWS_XML2_INCLUDE%\libxml\parser.h" (
+ echo [OK] libxml/parser.h found
+) else (
+ echo [MISSING] libxml/parser.h not found
+)
+
+if exist "%WINDOWS_XML2_INCLUDE%\libxml\tree.h" (
+ echo [OK] libxml/tree.h found
+) else (
+ echo [MISSING] libxml/tree.h not found
+)
+
+echo.
+echo Checking library path:
+if exist "%WINDOWS_XML2_LIB%" (
+ echo [OK] Library path exists
+) else (
+ echo [MISSING] Library path not found
+)
+
+echo.
+echo Testing libxml-ruby:
+ruby -e "require 'libxml'; puts 'libxml-ruby version: ' + LibXML::XML::VERSION" 2>nul
+if errorlevel 1 (
+ echo [NOT INSTALLED] libxml-ruby gem not found
+ echo Install it first using option 1
+) else (
+ echo [OK] libxml-ruby is installed
+)
+
+goto end
+
+:help
+echo.
+echo BUILD_LIBXML_WINDOWS.bat - Setup libxml-ruby on Windows
+echo.
+echo This script helps you install libxml-ruby on Windows by:
+echo - Detecting your Ruby platform (UCRT64 or MinGW)
+echo - Installing MSYS2 dependencies (libxml2, libiconv, zlib)
+echo - Setting required environment variables
+echo - Installing the pre-built gem
+echo.
+echo PREREQUISITES:
+echo - Ruby 3.0+ with DevKit installed from rubyinstaller.org
+echo - MSYS2 (included with Ruby+Devkit)
+echo - Internet connection for downloading packages
+echo.
+echo OPTIONS:
+echo 1. Install pre-built gem - Quickest method, downloads pre-compiled gem
+echo 2. Install MSYS2 deps - Only installs required MSYS2 packages
+echo 3. Set environment vars - Shows how to set permanent env vars
+echo 4. Verify installation - Checks if everything is set up correctly
+echo 5. Show this help - Displays this help message
+echo.
+echo TROUBLESHOOTING:
+echo - If installation fails, ensure MSYS2 is in your PATH
+echo - Run 'ridk install' after installing Ruby if MSYS2 is not configured
+echo - Check BUILD_LIBXML_WINDOWS.md for detailed instructions
+echo.
+echo DLL FILES:
+echo After installation, copy these DLLs from %MSYS2_LIB_PATH%\bin to your Ruby bin:
+echo - libxml2-2.dll
+echo - libiconv-2.dll
+echo - zlib1.dll
+echo.
+echo Or use the DLLs already provided in the dlls/ folder of this project.
+goto end
+
+:end
+echo.
+echo ========================================
+echo Setup complete
+echo ========================================
+pause
diff --git a/windows/setup-libxml-windows.ps1 b/windows/setup-libxml-windows.ps1
new file mode 100644
index 00000000..048f234a
--- /dev/null
+++ b/windows/setup-libxml-windows.ps1
@@ -0,0 +1,314 @@
+#Requires -Version 5.1
+<#
+.SYNOPSIS
+ Setup script for building libxml-ruby on Windows
+
+.DESCRIPTION
+ This script automates the setup and installation of libxml-ruby on Windows.
+ It installs MSYS2 dependencies, sets environment variables, and builds the gem.
+
+.PARAMETER RubyVersion
+ The Ruby version being used (e.g., "3.1", "3.2", "3.3")
+
+.PARAMETER Msys2Path
+ Path to MSYS2 installation (default: C:\msys64)
+
+.PARAMETER SkipMsys2Install
+ Skip MSYS2 package installation (if already done)
+
+.EXAMPLE
+ .\setup-libxml-windows.ps1 -RubyVersion "3.3"
+
+.EXAMPLE
+ .\setup-libxml-windows.ps1 -RubyVersion "3.1" -Msys2Path "D:\msys64"
+#>
+
+param(
+ [Parameter(Mandatory=$false)]
+ [string]$RubyVersion = "3.3",
+
+ [Parameter(Mandatory=$false)]
+ [string]$Msys2Path = "C:\msys64",
+
+ [Parameter(Mandatory=$false)]
+ [switch]$SkipMsys2Install
+)
+
+# Error handling
+$ErrorActionPreference = "Stop"
+
+function Write-Header {
+ param([string]$Message)
+ Write-Host "`n========================================" -ForegroundColor Cyan
+ Write-Host $Message -ForegroundColor Cyan
+ Write-Host "========================================`n" -ForegroundColor Cyan
+}
+
+function Write-Success {
+ param([string]$Message)
+ Write-Host "✓ $Message" -ForegroundColor Green
+}
+
+function Write-Error {
+ param([string]$Message)
+ Write-Host "✗ $Message" -ForegroundColor Red
+}
+
+function Test-Command {
+ param([string]$Command)
+ $null -ne (Get-Command $Command -ErrorAction SilentlyContinue)
+}
+
+# Determine MSYS2 environment based on Ruby version
+function Get-Msys2Environment {
+ param([string]$Version)
+
+ $major = [int]($Version.Split('.')[0])
+ $minor = [int]($Version.Split('.')[1])
+
+ if ($major -gt 3 -or ($major -eq 3 -and $minor -ge 1)) {
+ return @{
+ Name = "ucrt64"
+ PackagePrefix = "mingw-w64-ucrt-x86_64"
+ Path = "$Msys2Path\ucrt64"
+ }
+ } else {
+ return @{
+ Name = "mingw64"
+ PackagePrefix = "mingw-w64-x86_64"
+ Path = "$Msys2Path\mingw64"
+ }
+ }
+}
+
+Write-Header "libxml-ruby Windows Setup Script"
+
+# Check prerequisites
+Write-Host "Checking prerequisites..."
+
+if (-not (Test-Command "ruby")) {
+ Write-Error "Ruby is not installed or not in PATH"
+ Write-Host "Please install Ruby from https://rubyinstaller.org/"
+ exit 1
+}
+
+$rubyVer = ruby -v
+Write-Success "Found Ruby: $rubyVer"
+
+if (-not (Test-Command "gem")) {
+ Write-Error "Gem command not found"
+ exit 1
+}
+
+if (-not (Test-Path $Msys2Path)) {
+ Write-Error "MSYS2 not found at $Msys2Path"
+ Write-Host "Please install MSYS2 or specify the correct path with -Msys2Path"
+ exit 1
+}
+
+Write-Success "Found MSYS2 at $Msys2Path"
+
+# Determine environment
+$envInfo = Get-Msys2Environment -Version $RubyVersion
+Write-Host "Using MSYS2 environment: $($envInfo.Name)"
+Write-Host "Package prefix: $($envInfo.PackagePrefix)"
+
+# Install MSYS2 packages
+if (-not $SkipMsys2Install) {
+ Write-Header "Installing MSYS2 Packages"
+
+ $packages = @(
+ "$($envInfo.PackagePrefix)-libxml2"
+ "$($envInfo.PackagePrefix)-libiconv"
+ "$($envInfo.PackagePrefix)-zlib"
+ "$($envInfo.PackagePrefix)-gcc"
+ "$($envInfo.PackagePrefix)-make"
+ )
+
+ foreach ($package in $packages) {
+ Write-Host "Installing $package..."
+ & "$Msys2Path\usr\bin\pacman.exe" -S --needed --noconfirm $package
+ if ($LASTEXITCODE -eq 0) {
+ Write-Success "Installed $package"
+ } else {
+ Write-Error "Failed to install $package"
+ }
+ }
+} else {
+ Write-Host "Skipping MSYS2 package installation (--SkipMsys2Install specified)"
+}
+
+# Set environment variables
+Write-Header "Setting Environment Variables"
+
+$env:WINDOWS_XML2_INCLUDE = "$($envInfo.Path)\include\libxml2"
+$env:WINDOWS_XML2_LIB = "$($envInfo.Path)\lib"
+
+# Add to system environment variables (requires admin)
+$setSystemEnv = Read-Host "Set environment variables system-wide? (requires admin) [y/N]"
+if ($setSystemEnv -eq 'y' -or $setSystemEnv -eq 'Y') {
+ try {
+ [Environment]::SetEnvironmentVariable("WINDOWS_XML2_INCLUDE", $env:WINDOWS_XML2_INCLUDE, "Machine")
+ [Environment]::SetEnvironmentVariable("WINDOWS_XML2_LIB", $env:WINDOWS_XML2_LIB, "Machine")
+
+ # Add to PATH if not already there
+ $currentPath = [Environment]::GetEnvironmentVariable("PATH", "Machine")
+ $binPath = "$($envInfo.Path)\bin"
+ if (-not $currentPath.Contains($binPath)) {
+ [Environment]::SetEnvironmentVariable("PATH", "$currentPath;$binPath", "Machine")
+ }
+ Write-Success "Environment variables set system-wide"
+ } catch {
+ Write-Error "Failed to set system environment variables (run as Administrator)"
+ Write-Host "You can set them manually:"
+ Write-Host " WINDOWS_XML2_INCLUDE = $($env:WINDOWS_XML2_INCLUDE)"
+ Write-Host " WINDOWS_XML2_LIB = $($env:WINDOWS_XML2_LIB)"
+ }
+}
+
+# Verify installation
+Write-Header "Verifying Installation"
+
+$includePath = $env:WINDOWS_XML2_INCLUDE
+if (Test-Path $includePath) {
+ Write-Success "Include path exists: $includePath"
+
+ # Check for key header files
+ $requiredHeaders = @("libxml/parser.h", "libxml/tree.h", "libxml/xmlversion.h")
+ foreach ($header in $requiredHeaders) {
+ $headerPath = Join-Path $includePath $header
+ if (Test-Path $headerPath) {
+ Write-Success "Found $header"
+ } else {
+ Write-Error "Missing $header"
+ }
+ }
+} else {
+ Write-Error "Include path not found: $includePath"
+}
+
+$libPath = $env:WINDOWS_XML2_LIB
+if (Test-Path $libPath) {
+ Write-Success "Library path exists: $libPath"
+} else {
+ Write-Error "Library path not found: $libPath"
+}
+
+# Build options
+Write-Header "Build Options"
+
+$buildChoice = Read-Host @"
+Choose installation method:
+1. Install pre-built gem (easiest, recommended)
+2. Build from source
+3. Configure Bundler only
+
+Enter choice [1-3]
+"@
+
+switch ($buildChoice) {
+ "1" {
+ Write-Host "Installing pre-built gem..."
+
+ if ($envInfo.Name -eq "ucrt64") {
+ gem install libxml-ruby-x64-mingw-ucrt
+ } else {
+ gem install libxml-ruby-x64-mingw32
+ }
+
+ if ($LASTEXITCODE -eq 0) {
+ Write-Success "Pre-built gem installed successfully"
+ } else {
+ Write-Error "Failed to install pre-built gem"
+ }
+ }
+
+ "2" {
+ Write-Host "Building from source..."
+
+ # Clone repository
+ $cloneDir = "..\libxml-ruby-src"
+ if (-not (Test-Path $cloneDir)) {
+ git clone https://github.com/xml4r/libxml-ruby.git $cloneDir
+ }
+
+ Push-Location $cloneDir
+
+ # Install dependencies
+ bundle install
+
+ # Compile
+ rake compile
+
+ if ($LASTEXITCODE -eq 0) {
+ Write-Success "Compilation successful"
+
+ # Run tests
+ rake test
+
+ # Build gem
+ rake build
+
+ # Install
+ $gemFile = Get-ChildItem "pkg\libxml-ruby-*.gem" | Select-Object -First 1
+ if ($gemFile) {
+ gem install $gemFile.FullName
+ Write-Success "Gem installed from source"
+ }
+ } else {
+ Write-Error "Compilation failed"
+ }
+
+ Pop-Location
+ }
+
+ "3" {
+ Write-Host "Configuring Bundler..."
+ Write-Host "Run the following command in your project directory:"
+ Write-Host ""
+ Write-Host " bundle config build.libxml-ruby --with-xml2-include=$includePath --with-xml2-lib=$libPath"
+ Write-Host ""
+ Write-Host "Then run:"
+ Write-Host ""
+ Write-Host " bundle install"
+ Write-Host ""
+ }
+
+ default {
+ Write-Host "Invalid choice. Please run the script again."
+ }
+}
+
+# Final verification
+Write-Header "Final Verification"
+
+$testScript = @"
+require 'libxml'
+puts "libxml-ruby version: #{LibXML::XML::VERSION}"
+puts "libxml2 version: #{LibXML::XML::LIBXML_VERSION}"
+doc = LibXML::XML::Document.string('')
+puts "Test parse successful: #{doc.root.name == 'root'}"
+"@
+
+try {
+ $result = $testScript | ruby 2>&1
+ Write-Success "libxml-ruby is working correctly"
+ Write-Host $result
+} catch {
+ Write-Error "Verification failed"
+ Write-Host $result
+}
+
+Write-Header "Setup Complete"
+Write-Host @"
+
+Next steps:
+1. If you installed the pre-built gem or built from source, you're ready to use libxml-ruby
+2. If you chose Bundler configuration, run the bundle commands shown above
+3. Copy DLLs from $($envInfo.Path)\bin to your Ruby bin directory or project dlls/ folder:
+ - libxml2-2.dll
+ - libiconv-2.dll
+ - zlib1.dll
+
+For troubleshooting, see BUILD_LIBXML_WINDOWS.md
+"@