EST. 2026 — Notes from real server work SYSADMIN · SECURITY · AI · DIRECTADMIN Issue 01
THE SYSADMIN ALMANAC
Home / Web / Build APM on Windows, Part 4: Compile MariaDB 11.8 LTS
Web — Build APM บน Windows

Build APM on Windows, Part 4: Compile MariaDB 11.8 LTS

by Ton-Or ·22 Oct 2026·14 min read
Build APM on Windows, Part 4: Compile MariaDB 11.8 LTS

This build takes about half an hour, but the script is very short. What you really need to understand is which options are disabled and why collation must be pinned before creating the first database.

I was rebuilding the entire APM stack after PHP released patches on October 21 (read about the vulnerabilities in php2shell: Update PHP Now), and now it is time for the database. In this part, I will compile MariaDB 11.8.9 from source to produce a stage\mariadb folder ready for installation in Part 7. I will cover enough detail for you to follow without guessing. Every step will specify which terminal to open, which folder to work in, what command to run, what you should see, and how to check that it passed.

If you are joining here, this series starts with the table of contents. Parts 1 through 3 covered preparing the tools, downloading the source, and building Apache. All folder names in this article assume you extracted the script package to C:\apm-build as described in Part 1.

What this part does and what you need first

The script for this part is scripts\40-mariadb.ps1. It performs three operations in sequence: cmake configure, cmake --build, and cmake --install. The output goes to C:\apm-build\stage\mariadb. It makes no system changes, installs nothing in Program Files, and requires no admin privileges.

What makes this part easier than Apache is that MariaDB does not depend on any libraries built by vcpkg in Part 2. It carries the libraries it needs in its own source tree (including the SSL library referred to as bundled). This script therefore needs just four things, and with all four available, it can run independently without waiting for any other steps.

30 minutesfirst build
0.3 minutesrerun
669 MBstage\mariadb
1.7 GBbuild\mariadb

The times and sizes above were measured on my machine (Windows 11 x64, i5-12500H 16 threads, RAM 32 GB). The 30 minutes is the first-run time recorded in the HOWTO. The 0.3 minutes is a rerun with the cache still present. The 669 MB is the size of stage\mariadb before Part 7 removes .pdb, lib, and include (after deployment, about 201 MB remains).

40-mariadb.ps1 runs in this orderversions.jsonversion 11.8.900-fetchmariadb-11.8.9configurecmake -S -Bbuildninja ~30 mininstallstage\mariadbMSVCcl.exe link.exewin_bisonbuilds parserStrawberryperl for buildDashed lines show tools used by configure and build (prepared in Parts 1-2)Every step appends to one log: build\logs\mariadb.logOnly [..] and [OK] appear on screen; all output is redirected to this file
The configure through install steps use MSVC, win_bison, and Strawberry Perl, downloaded into toolchain in Part 2

There are four prerequisites, and I will have you check each one in the next section.

  1. Visual Studio 2022 Build Tools with the MSVC v143 compiler (Part 1)
  2. CMake 3.24 or later and Ninja (Part 1)
  3. MariaDB source extracted to C:\apm-build\src\mariadb-11.8.9 (Part 2, through 00-fetch.ps1)
  4. Strawberry Perl and winflexbison in C:\apm-build\toolchain (also Part 2)

Check everything before starting

I have broken this down in detail because this is where most people run into trouble halfway through, only discovering a missing prerequisite after building for half an hour.

Step 1: Open PowerShell 7 as a normal user

Open Start, type pwsh, and select PowerShell 7. Do not right-click and choose Run as administrator, because the entire set of build scripts is designed to run as a normal user. Check that you are using PowerShell 7 with this command.

$PSVersionTable.PSVersion.ToString()

You should see version 7.5 or later (mine is 7.6.1). If you see 5.1, you have opened the old Windows PowerShell. Close it and open the correct one.

Step 2: Change to the script package folder

Set-Location C:\apm-build

There is no output; this command is silent on success. Check that you are in the right place with Get-Location, which must show C:\apm-build, and check that build.cmd appears when you run Get-ChildItem -Name.

Step 3: Check that the MariaDB source is present

Test-Path C:\apm-build\src\mariadb-11.8.9\CMakeLists.txt

The result must be True. If it is False, return to Part 2 and run pwsh -NoProfile -File scripts\00-fetch.ps1 -Only mariadb, which downloads only MariaDB.

Step 4: Check that Strawberry Perl is present

Test-Path C:\apm-build\toolchain\strawberry\perl\bin\perl.exe

The result must be True. The reason this specific Perl distribution is required is explained in the script walkthrough. If it is False, run fetch with -Only strawberry.

Step 5: Check that win_bison is present

Test-Path C:\apm-build\toolchain\winflexbison\win_bison.exe

The result must be True. If it is False, run fetch with -Only winflexbison.

Step 6: Check CMake and Ninja

cmake --version | Select-Object -First 1
ninja --version

On my machine, the expected output is:

cmake version 4.1.2
1.13.1

Your versions may be newer, as long as CMake is at least 3.24. If either command reports "not recognized", this terminal has not picked up the new PATH. Close it and reopen it as described in Part 1.

No need to open a Developer Prompt

The script calls Enter-VsEnv from lib.ps1 to load the MSVC environment (vcvars64.bat) automatically. This makes cl.exe available inside the script even in a regular pwsh session. If you already have a Developer Command Prompt open, that is fine too; the script checks and skips this step.

The complete script, section by section

This is the complete scripts\40-mariadb.ps1 from the downloaded package, with nothing removed.

# 40-mariadb.ps1 - build MariaDB server + client (CMake + Ninja, MSVC x64, bundled wolfSSL)
$ErrorActionPreference = 'Stop'
$Root = Split-Path $PSScriptRoot -Parent
. "$PSScriptRoot\lib.ps1"
$Ver = (Get-Content "$Root\versions.json" -Raw | ConvertFrom-Json).sources.mariadb.version
$Src = "$Root\src\mariadb-$Ver"
$Bld = "$Root\build\mariadb"
$Pfx = "$Root\stage\mariadb" -replace '\\','/'
$Log = "$Root\build\logs\mariadb.log"
New-Item -ItemType Directory -Force "$Root\build\logs" | Out-Null
Remove-Item $Log -ErrorAction SilentlyContinue
Enter-VsEnv
# Strawberry perl (native) for build-time scripts; never Git's cygwin perl
$env:Path = "$Root\toolchain\strawberry\perl\bin;$env:Path"

$opts = @(
  '-G','Ninja','-DCMAKE_BUILD_TYPE=RelWithDebInfo',"-DCMAKE_INSTALL_PREFIX=$Pfx",
  '-DWITH_SSL=bundled','-DWITH_UNIT_TESTS=OFF','-DINSTALL_MYSQLTESTDIR=',
  "-DBISON_EXECUTABLE=$Root\toolchain\winflexbison\win_bison.exe",
  # engines/plugins dev work never touches - skipping them saves most of the build time
  '-DPLUGIN_ROCKSDB=NO','-DPLUGIN_COLUMNSTORE=NO','-DPLUGIN_CONNECT=NO','-DPLUGIN_MROONGA=NO',
  '-DPLUGIN_SPIDER=NO','-DPLUGIN_OQGRAPH=NO','-DPLUGIN_SPHINX=NO','-DPLUGIN_DUCKDB=NO',
  '-DPLUGIN_S3=NO','-DPLUGIN_AWS_KEY_MANAGEMENT=NO','-DPLUGIN_HASHICORP_KEY_MANAGEMENT=NO',
  '-DPLUGIN_EXAMPLE=NO','-DPLUGIN_TEST_SQL_DISCOVERY=NO'
)
Invoke-Step 'mariadb configure' { cmake -S $Src -B $Bld @opts } $Log
Invoke-Step 'mariadb build'     { cmake --build $Bld } $Log
Invoke-Step 'mariadb install'   { cmake --install $Bld } $Log
& "$Pfx\bin\mariadbd.exe" --version

Section 1: Variables and paths (lines 2 through 10)

$Root is the parent folder of scripts, which is C:\apm-build, because $PSScriptRoot points to C:\apm-build\scripts and Split-Path -Parent moves up one level. The version number is not hardcoded in the script. It is read from sources.mariadb.version in versions.json (currently 11.8.9). This is the central idea behind the whole series: change the number in one file, and the scripts point to the new source automatically.

The resulting variables are $Src = C:\apm-build\src\mariadb-11.8.9 (source), $Bld = C:\apm-build\build\mariadb (intermediate build files), and $Pfx = C:/apm-build/stage/mariadb (installation destination). Notice that $Pfx has \ converted to /, because CMake treats backslashes as escape characters in paths. Passing C:\apm-build\... directly often produces incorrect results.

$Log is the single log file for this step. The script deletes it with Remove-Item before every run so that the log contains only the current run.

Section 2: Enter-VsEnv and the Perl PATH

Enter-VsEnv (in lib.ps1) runs vcvars64.bat in a cmd process, then imports all its environment variables into the running PowerShell session. This makes cl.exe, link.exe, and the entire Windows SDK available. It also removes paths containing xampp from this process's PATH to keep XAMPP binaries out of the build. If cl.exe still cannot be found after loading the environment, it throws [ERR] MSVC environment not loaded.

The next line puts toolchain\strawberry\perl\bin at the very front of PATH. Why must it be Strawberry Perl, and why must you avoid the Perl bundled with Git for Windows? Git's Perl is a cygwin version. It generates Unix-style paths (such as /c/...) that Windows tools cannot read. I encountered this while building OpenSSL in the same package (it failed for this reason). MariaDB also runs Perl scripts during its build, so the same rule applies: PATH must always find Strawberry first.

Section 3: Each CMake option

option Value What it does and why
-G Ninja Ninja Uses Ninja to drive the build instead of MSBuild. It is faster and automatically runs compilation in parallel according to the core count.
CMAKE_BUILD_TYPE RelWithDebInfo Optimizes like Release but keeps .pdb files, providing debugging information if mariadbd.exe crashes. Part 7 removes .pdb files during deployment.
CMAKE_INSTALL_PREFIX C:/apm-build/stage/mariadb The destination for cmake --install.
WITH_SSL bundled Uses wolfSSL bundled with the source, which is the standard MariaDB setting on Windows. It requires no external OpenSSL, and @@have_ssl returns YES.
WITH_UNIT_TESTS OFF Skips building unit tests. I am building MariaDB to use it, not developing it.
INSTALL_MYSQLTESTDIR (empty) An empty value means the mysql-test test suite folder is not installed into stage.
BISON_EXECUTABLE ...\win_bison.exe The SQL parser generator requires bison, which Windows does not include, so this points to winflexbison downloaded in Part 2.

The PLUGIN_*=NO block disables engines and plugins that the dev machine does not use. The script comment says this substantially reduces build time. I did not measure the actual time saved (I did not build with everything enabled for comparison), so I will not give a number.

Disabled plugin Brief description
ROCKSDB An LSM-tree storage engine.
COLUMNSTORE A column-oriented storage engine for analytics.
CONNECT An engine that reads external data as tables.
MROONGA A full-text search engine.
SPIDER An engine that distributes tables across multiple servers.
OQGRAPH An engine for graph data.
SPHINX A connector for Sphinx search.
DUCKDB A plugin related to DuckDB (named after the option in the 11.8 source).
S3 An engine that stores tables on S3.
AWS_KEY_MANAGEMENT, HASHICORP_KEY_MANAGEMENT Encryption key managers using AWS and HashiCorp.
EXAMPLE, TEST_SQL_DISCOVERY Examples and tests for MariaDB developers.

InnoDB, Aria, MyISAM, and the other main engines used by typical websites remain available. I inspected the actual output's lib\plugin folder and still found ha_archive.dll, ha_blackhole.dll, ha_federated.dll, and all the auth plugins. If you later need one of the disabled engines, you can change its =NO setting and rebuild (I have not tried enabling any of them, so I cannot guarantee that each one builds successfully on Windows).

Section 4: Invoke-Step wraps every command

The three lines starting with Invoke-Step work as follows. First, they print [..] step name, then run the command while appending all output to the log file (*>> $Log). When the command finishes, if its exit code is not 0, they print the last 30 lines of the log to the screen and throw [ERR] step name failed rc=... (log: ...). If it is 0, they print [OK] step name.

This is why your screen will remain completely still for half an hour between [..] mariadb build and [OK] mariadb build. It has not hung; everything is going into the log file. Here are some actual lines from that file (I changed the paths to C:\apm-build).

-- Running cmake version 4.1.2
-- MariaDB 11.8.9
-- Will download and bundle pcre2
-- Build files have been written to: C:/apm-build/build/mariadb
[1/95] Building C object libmariadb\libmariadb\CMakeFiles\mariadb_obj.dir\ma_errmsg.c.obj

There are two things to explain in this block. First, Will download and bundle pcre2 means the configure step needs an internet connection, because MariaDB downloads its own PCRE2 (separate from the vcpkg PCRE2 in Part 2). If your machine cannot access the internet at this point, configure will fail. Second, the log shown here is from a rerun with the cache present, which is why the [1/95] count is small. I did not keep the log from the first build from scratch. I expect the total count for that first run to be much larger, but I want to stress that this is an estimate, not a measured number.

The log also contains lines such as Could NOT find CURL, Could NOT find LZ4, Could NOT find LZO, and so on during configure. These are optional client libraries, not requirements, and these messages are not errors. My configure step finished normally with Configuring done and Generating done.

Section 5: The script's final line

& "$Pfx\bin\mariadbd.exe" --version prints the version of the binary just installed, providing the first confirmation that the file was actually produced. On my machine, it printed this line (I changed my local path to C:\apm-build).

C:\apm-build\stage\mariadb\bin\mariadbd.exe  Ver 11.8.9-MariaDB for Win64 on AMD64 (Source distribution)

The words (Source distribution) here are evidence that this was built from source rather than downloaded as a prebuilt binary from mariadb.org.

Run it, step by step

Step 1: Run the script

In the same terminal window (PowerShell 7 as a normal user, still in C:\apm-build), run:

pwsh -NoProfile -File scripts\40-mariadb.ps1

If you are already using build.cmd and it failed at this step, use build.cmd -From mariadb. This runs this step, followed by imagemagick and php in the order defined by build-all.ps1.

You should immediately see one line:

[..] mariadb configure

Step 2: Open a second terminal to watch the log (optional, but recommended)

Open another PowerShell 7 window (as a normal user) and run the following. This command works once the log file exists, which should happen within a few seconds of Step 1.

Get-Content C:\apm-build\build\logs\mariadb.log -Tail 5 -Wait

You should see the last 5 lines of the log, followed by new lines as they appear. Stop watching with Ctrl+C. Stopping here does not affect the build in the first window.

Step 3: Wait for configure to finish

This does not take long (the cached run I measured took 1.8 seconds for configure; the first run takes longer because it must download PCRE2 and generate Ninja files). You should see:

[OK] mariadb configure
[..] mariadb build

If you see [ERR] mariadb configure failed, read the 30 lines printed afterward by the script, then go to "If this step fails".

Step 4: Wait about 30 minutes for the build

During this time, the CPU will be busy on every core, the fans will be loud, and the first terminal window will be still. This is normal. Use the log window you opened to watch progress. Counts at the start of lines, such as [1234/2000], show Ninja's completed/total steps. Do not close the first window or let the machine sleep (on a laptop, temporarily set Power & sleep to Never before starting).

If you accidentally close it or lose power halfway through, that is fine. Repeat Step 2, and Ninja will resume from the files already completed (my rerun took 0.3 minutes). However, the log will be deleted and started over because of the Remove-Item $Log line.

Step 5: Wait for install to finish

When everything passes, you should see:

[OK] mariadb build
[..] mariadb install
[OK] mariadb install
C:\apm-build\stage\mariadb\bin\mariadbd.exe  Ver 11.8.9-MariaDB for Win64 on AMD64 (Source distribution)

Step 6: Check the output files

Get-ChildItem C:\apm-build\stage\mariadb\bin\mariadb*.exe -Name

You should see at least these five files (the order may differ slightly).

mariadb-admin.exe
mariadb-dump.exe
mariadb-install-db.exe
mariadb.exe
mariadbd.exe

My bin folder contains 71 files in total. If your count is close to this, you can be reasonably confident.

Test on port 3399, then shut down cleanly

I do not consider this passed just because the files exist. I need to see the server respond to a real query first. This test creates a temporary datadir separate from the real one, uses port 3399 (avoiding any other MySQL/MariaDB instance that may be running on 3306), and deletes it afterward. Run it in the same terminal window, still as a normal user.

Test in 5 steps, then remove everything with nothing left behindinstall-dbcreate datadirmariadbdport 3399mariadbselect version()shutdownstop cleanlyRemove-Itemdelete datadirExpected select resultversion() @@character_set_server @@have_ssl11.8.9-MariaDB utf8mb4 YESPort 3399 avoids other MySQL or MariaDB instances that may be running on port 3306
If shutdown does not happen, the process stays running and locks files in the datadir, causing deletion to fail

Step 1: Set the two path variables

$M = "C:\apm-build\stage\mariadb\bin"; $D = "C:\apm-build\build\test-mariadb-data"

There is no output. These variables exist only in this terminal window. If you close it along the way, you must set them again.

Step 2: Create the test datadir

& "$M\mariadb-install-db.exe" --datadir=$D --port=3399

This command initializes an empty database (creating the mysql system database and so on). It takes a few seconds. I did not keep its output, so I am not showing it here. To check it, look for a config file created in that folder.

Step 3: Check that the datadir was created

Test-Path "$D\my.ini"

The result must be True, because mariadb-install-db writes my.ini into the datadir, and the next step uses that file to start the server.

Step 4: Start the server in the background

$p = Start-Process "$M\mariadbd.exe" -ArgumentList "--defaults-file=$D\my.ini","--console" -PassThru -WindowStyle Hidden

There is no output and no new window because it is explicitly hidden. -PassThru stores the process in $p for checking later. --console sends the log to the process's console (which is hidden).

Step 5: Wait for the server to start

Start-Sleep 6

Six seconds was enough on my machine. If yours is slower and the next step reports that it cannot connect, wait another ten seconds and repeat the next step.

Step 6: Query the version and SSL status

& "$M\mariadb.exe" -uroot --port=3399 --protocol=tcp -e "select version(), @@character_set_server, @@have_ssl"

You should see:

version()       @@character_set_server  @@have_ssl
11.8.9-MariaDB  utf8mb4                 YES

This line confirms three things at once: the version is correct, the default character set is utf8mb4, and SSL was compiled in (WITH_SSL=bundled worked). The root user has no password in this test database, which is the default behavior of mariadb-install-db.

Step 7: Shut down the server with its own command

& "$M\mariadb-admin.exe" -uroot --port=3399 --protocol=tcp shutdown

There is no output on success. I do not use Stop-Process on MariaDB because killing the process outright prevents InnoDB from flushing its data properly. shutdown lets it close down in the proper sequence.

Step 8: Confirm that the process has exited

$p.HasExited

The result must be True. If it is False, wait a few seconds and run it again. If it still does not stop, see "If this step fails".

Step 9: Delete the test datadir

Remove-Item $D -Recurse -Force

There is no output. Check that it is gone with Test-Path $D, which must return False.

This test does not yet use APM's my.ini

The test database above uses the defaults from mariadb-install-db, so its collation has not been pinned yet. The pinned @@collation_server result is in the next section, measured on a machine already deployed according to Part 7.

my.ini and why collation must be pinned

In Part 7, deploy.cmd substitutes the placeholders in the script package's templates\my.ini and places it at C:\APM\mariadb\my.ini. Then mariadb-install-db copies it into the datadir. The file the server actually reads at runtime is C:\APM\data\mysql\my.ini. I am showing it now because it determines something that is difficult to reverse later.

Changing the datadir my.ini through deploy

Because the server uses the copy in the datadir, editing only C:\APM\mariadb\my.ini or the template has no effect (for example, change the database port and the server still listens on the old one). Kits from before the afternoon of 22 Oct had this bug. deploy.cmd -ResetConfig now also copies mariadb\my.ini over data\mysql\my.ini; details are in Part 7. Another bug in the old deploy: the mariadb\lib\plugin folder went missing (so plugins such as ha_archive and auth_ed25519 were absent) because the copy command dropped every folder named lib. It is fixed in the new kit.

it determines something that is difficult to reverse later.
# APM my.ini - MariaDB 11.8 (dev box). Placeholders are filled in by scripts\90-deploy.ps1.
# mariadb-install-db copies this into <datadir>\my.ini, which is the file the server runs with.

[client-server]
port = {{DB_PORT}}

[client]
default-character-set = utf8mb4

[mariadbd]
basedir = "{{APM_ROOT}}/mariadb"
datadir = "{{APM_ROOT}}/data/mysql"
bind-address = 127.0.0.1
port = {{DB_PORT}}
# Keep new tables importable into a MariaDB 10.6 production server: 11.x would default to utf8mb4_uca1400_ai_ci,
# which 10.6 does not know -> dumps from APM would fail there.
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
character_set_collations = utf8mb4=utf8mb4_unicode_ci

sql_mode = STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
lower_case_table_names = 2
max_allowed_packet = 256M
max_connections = 200
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_file_per_table = 1
log-error = "{{APM_ROOT}}/logs/mariadb/mariadb.err"
slow_query_log = 1
slow_query_log_file = "{{APM_ROOT}}/logs/mariadb/slow.log"
long_query_time = 2

{{DB_PORT}} and {{APM_ROOT}} are still placeholders. Part 7 replaces them with port 3307 and C:/APM. You do not need to edit them yourself.

The three lines that explain why this file exists

The production server I need to move data between and APM runs MariaDB 10.6. MariaDB 11.8 defaults to utf8mb4_uca1400_ai_ci for utf8mb4 collation, which 10.6 does not recognize. As a result, if APM starts with no changes, every newly created table will use that collation, and dumps from APM cannot be imported into production (the file comments explain this reason too). I therefore pin three settings.

Not pinned

11.8 defaults

New tables get utf8mb4_uca1400_ai_ci. The dump specifies this collation in CREATE TABLE statements. Production 10.6 does not recognize it, so the dump file must be edited every time.

Pinned in my.ini

utf8mb4_unicode_ci

Every new table uses a collation that 10.6 recognizes. Dumps can move back and forth without file edits, and character sorting behaves the same as on the real server.

Why my.ini must pin collationWithout pinningMariaDB 11.8default uca1400_ai_cidump filetable collation setproduction 10.6unknown collationPinned in my.iniMariaDB 11.8unicode_ci all tablesdump filespecifies unicode_ciproduction 10.6imports normallyThree my.ini lines produce the lower result; explained in the collation section below
Pinning it once at the source is better than editing dumps every time a database moves to production
  • character-set-server = utf8mb4 sets the server's default character set.
  • collation-server = utf8mb4_unicode_ci sets the server's default collation.
  • character_set_collations = utf8mb4=utf8mb4_unicode_ci forces the utf8mb4 character set to always pair with utf8mb4_unicode_ci, even when someone writes CHARSET utf8mb4 without specifying a collation. This variable has been available since the 11.x series, and this line prevents the new 11.8 default from slipping in through the back door.

I consider pinning it at the source much cheaper than fixing it later, because collation is written into every table during CREATE TABLE. If you forget and create ten databases, you must use ALTER TABLE to change them back one table at a time. By comparison, adding these three lines before creating the first database takes less than a minute.

Check the result after deployment

This step is only possible after Part 7 (C:\APM does not exist yet). I am including the measured result now so you can see what to expect when the file is actually in use. Start the server with Start-Process C:\APM\mariadb\bin\mariadbd.exe -ArgumentList '--defaults-file=C:\APM\data\mysql\my.ini', then query:

C:\APM\mariadb\bin\mariadb.exe -uroot --port=3307 --protocol=tcp -e "select version(), @@collation_server, @@have_ssl, @@bind_address"
version()            @@collation_server    @@have_ssl   @@bind_address
11.8.9-MariaDB-log   utf8mb4_unicode_ci    YES          127.0.0.1

Shut it down with C:\APM\mariadb\bin\mariadb-admin.exe -uroot --port=3307 --protocol=tcp shutdown. Notice two things: @@collation_server is utf8mb4_unicode_ci as pinned, and @@bind_address is 127.0.0.1, meaning MariaDB listens only locally and does not accept connections from other machines on the network.

Other settings in the file worth knowing

Setting Meaning
bind-address = 127.0.0.1 Listens only on loopback, suitable for a dev machine.
sql_mode = STRICT_TRANS_TABLES,... Rejects invalid values instead of silently truncating them, closer to the real server's behavior.
lower_case_table_names = 2 On Windows, stores table names as typed but compares them without case sensitivity.
max_allowed_packet = 256M Allows large queries/rows (such as importing dumps containing blobs).
max_connections = 200 The maximum number of simultaneous connections.
innodb_buffer_pool_size = 1G InnoDB cache memory, sized for a dev machine. Reduce it if you have less than 8 GB of RAM.
innodb_log_file_size = 256M Redo log size.
slow_query_log = 1, long_query_time = 2 Logs queries taking longer than 2 seconds to logs\mariadb\slow.log.

If this step fails

I encountered no build errors during the measured run of this step. The list below therefore contains two kinds of entries: symptoms actually recorded in the HOWTO, and causes inferred from the script, which I identify in the source column as things I did not encounter myself.

Symptom Cause Fix Source
The build or OpenSSL fails with strange Unix-style paths Git's Perl (cygwin) appears before Strawberry in PATH Use only the Perl in toolchain\strawberry. The script already puts it first. If you run cmake manually, you must set PATH yourself too. Actually encountered (while building OpenSSL)
[ERR] Visual Studio 2022 with C++ x64 tools not found (see https://linuxthai.org/article/apm-build-windows-1-prepare-tools) lib.ps1 asked vswhere for a Visual Studio 2022 with the C++ x64 component and found none (any edition at any install path is found, as long as it has that component) Run the check in Step 1.5 of Part 3, or open the Visual Studio Installer and tick the C++ workload as in Part 1. You do not need to edit the script Read from lib.ps1
[ERR] MSVC environment not loaded Visual Studio was found, but cl.exe is still missing after vcvars64.bat runs Press Repair in the Visual Studio Installer and run again Read from lib.ps1
configure fails immediately because bison cannot be found toolchain\winflexbison\win_bison.exe is missing Run pwsh -NoProfile -File scripts\00-fetch.ps1 -Only winflexbison, then try again Read from the script
configure fails while downloading PCRE2 No internet access during configure Connect to the internet and rerun Read from the log (Will download and bundle pcre2)
The build stops halfway through (power loss, closed window) The process was killed Rerun the script; Ninja resumes where it left off Actually measured (rerun took 0.3 minutes)
The build takes more than 2 times as long as stated Defender is scanning tens of thousands of .obj files Add an exclusion as described in Part 1 HOWTO
Test step: mariadbd does not start, or the query cannot connect Port 3399 is in use, or the wait was too short Check with Get-NetTCPConnection -LocalPort 3399, then change the port in both the creation and connection steps, or wait longer Inferred from the test procedure; I did not encounter it myself
Remove-Item cannot delete the datadir mariadbd is still running and locking files Check $p.HasExited. If it is still False, use Stop-Process -Id $p.Id as a last resort, then delete again Inferred from the test procedure; I did not encounter it myself

If you see Unknown collation: 'utf8mb4_uca1400_ai_ci' while importing a dump into an older MariaDB version, that is the collation issue covered in the previous section (I did not reproduce this error; this message is written from knowledge of MariaDB's behavior, not taken from my log).

Do not expose the database port to the network

The test database's root user has no password, and APM's my.ini binds to 127.0.0.1 for this reason. If you change bind-address to allow other machines to connect, always set a root password and restrict users first. This is a tool for a dev machine.

Checklist before moving to Part 5

Complete every item before continuing. If any item fails, go back and finish it first.

  1. The script ends with [OK] mariadb install and a Ver 11.8.9-MariaDB line
  2. C:\apm-build\stage\mariadb\bin\mariadbd.exe exists, with mariadb.exe, mariadb-admin.exe, and mariadb-install-db.exe beside it
  3. The test on port 3399 returns 11.8.9-MariaDB utf8mb4 YES
  4. $p.HasExited returns True, and C:\apm-build\build\test-mariadb-data has been deleted
  5. You understand why templates\my.ini pins collation to utf8mb4_unicode_ci (Part 7 deploys this file automatically)
Don't want to build it yourself

If you just want to use APM without compiling anything, the finished build is at github.com/ChonLaWan/APM-Server. Download APM-1.0.0-win64.zip (about 140 MB) from Releases, compare its sha256 with the attached .sha256 file, unzip it anywhere and run manager\APMManager.exe. The Manager picks free ports, writes the config, issues the certificate and creates the database for you. Its Check for updates button downloads a new release, verifies the sha256 and swaps the binaries without touching your config, databases or sites.

Build APM on Windows series

Table of contents · Previous: Part 3: Compile Apache · Next: Part 5: Compile ImageMagick

The next part covers one of the most time-consuming pieces of the series: ImageMagick, along with around 40 delegate libraries that must all be built from source so PHP's imagick extension has what it needs in Part 6. As for further MariaDB configuration (such as setting the root password and creating an application user), I have not covered it in this series yet. I will come back and add it later.

Want us to set this up?

Get help with server setup, configuration, migration, or troubleshooting. Save time for the work that matters.

Get a quote

Hit something like this? Stuck somewhere?

Come trade notes on the LinuxThai board

→ Continue on the board

Comments 0

No comments yet — be the first