1<!-- 2 Licensed to the Apache Software Foundation (ASF) under one 3 or more contributor license agreements. See the NOTICE file 4 distributed with this work for additional information 5 regarding copyright ownership. The ASF licenses this file 6 to you under the Apache License, Version 2.0 (the 7 "License"); you may not use this file except in compliance 8 with the License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, 13 software distributed under the License is distributed on an 14 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 KIND, either express or implied. See the License for the 16 specific language governing permissions and limitations 17 under the License. 18--> 19 20# `win10-msvc-trunk` — building trunk on Windows again 21 22**Status: the build is green, end to end.** On VS2019 14.29.30133 with Windows 23SDK 10.0.19041.0, `configure`, `bootstrap` and `build.pl` all run to 24completion into a `wntmsci14.pro` output tree, and `instsetoo_native` produces 25 26 openoffice450.msi 27 openoffice450sdk.msi 28 29Every bundled third-party library builds — including, for the first time on 30Windows, **Python**, which trunk has never built here at all. 31 32Two things that headline does not say, and both matter more than it does. 33 34**Nothing has been run.** The MSI exists; nobody has installed it or started 35the office. The single piece of runtime evidence points the wrong way: 36`testtools/source/bridgetest` fails with `getCaughtException() failed!`, which 37is UNO exception propagation through the x86 C++ bridge. See 38[The open defect](#the-open-defect). 39 40**Some of the green is subtraction.** The CLI/.NET binding is switched off 41entirely, and Python is built without `_ssl`, `_ctypes`, `_bz2`, `_lzma` and 42`_sqlite3`. Both are deliberate and both are described below, but a build that 43is green with those absent is a narrower claim than one that is green with 44them present. 45 46That is a different claim from the one this file made when it was written, and 47the difference was expensive: **forty defects so far, every one of them found 48by building and none of them by reading.** 49[What building found](#what-building-found) groups the forty by cause; 50[Verification](#verification) says what is now measured and what is still only 51argued. 52 53## Why trunk does not build on Windows 54 55Not one regression — a scissors motion between two changes that were each 56reasonable alone. 57 58* `main/configure.ac` errors out on any compiler that is not VS2008: 59 `Compiler too old. Use Microsoft C/C++ .NET 2008.` 60* Trunk's bundled dependencies moved past what VS2008 can compile. Boost is 61 **1.84** (`main/boost/makefile.mk`), which requires C++11; VC9 has no C++11 62 mode at all. Bundled Python is **3.11.15** (`main/python/pyversion.mk`), 63 which requires VS2017 or newer to build on Windows. 64 65So the configured compiler cannot build the configured dependencies, and there 66is no combination of the two that works. Every other platform moved: Linux and 67FreeBSD were raised to `gnu++11` in `7ce5b5df31`, macOS was already at C++11. 68Windows is the one that was left pinned. 69 70The fix is to let Windows use a modern MSVC, which is what this branch does. 71 72## Where the work came from 73 74The source half is **cherry-picked from `win10-64-minimal`**, a branch that 75already did this against a Bazel build of the same tree and reached a product 76that compiles and runs. That is the branch's value here: the conformance 77failures a modern MSVC finds in this source have already been found, once, by 78building — rather than being guessed at from a survey. 79 80Every source commit carries its `(cherry picked from commit ...)` line. 81 82### What was taken, and what was dropped from each 83 84Four of the picked commits were mixed — Bazel `BUILD.bazel`/`.bzl` changes 85alongside source changes — and only the source half applies here. Their 86messages still describe the whole commit as it was on the other branch, so the 87reconciliation is here rather than rewritten into history: 88 89| commit | taken here | dropped | 90| --- | --- | --- | 91| `97bc46e96b` (M3) | `cppuhelper/factory.cxx` C2694 fix, `uwinapi/sntprintf.c` guard, the stlport shim split | 7 `BUILD.bazel` files, the toolchain config, `win10-minimal/README.md` | 92| `82bbd76e57` (M4) | `comphelper` C2694 + `<iterator>`, `tools/dirent.cxx` `<time.h>`, the stlport `_MSC_VER >= 1900` arms | 88 `BUILD.bazel` files — the Bazel-side `snprintf` sweep, which has no dmake equivalent | 93| `e5b57b0a09` | `bridges/.../except.cxx` `<typeinfo>`, `stoc/javavm.cxx` `_tzname` | the bzlmod overlays for libxml2, rasqal and redland — replaced here by `b0fbb14822`, see below | 94| `d01dcefb61` | 5,069 of 5,070 files | `bridges/test/cppuno_roundtrip_test.cxx`, which exists only on the Bazel branch | 95 96Three commits from that branch were **not** picked at all: 97 98* the Python 2.7.18 fixes (`b6f8696d08`, `8ee3bd8d0f`) — trunk is on Python 99 3.11, so they are moot; 100* the NSS `<stdint.h>` overlay (`c06bca0c46`) — that shim was the Bazel 101 overlay's own invention. Trunk's `main/nss/nss_win.patch` already guards its 102 `<stdint.h>` substitute on `_MSC_VER < 1600` and takes the real header on 103 anything newer; 104* the Bazel-only commits (toolchain discovery, platform registration, the gtest 105 tuple define), which have no counterpart in a dmake tree. 106 107The toolchain half is new. `win10-64-minimal` expressed it as a third Bazel 108`cc_toolchain`; trunk needs it in `configure.ac`, `set_soenv.in` and 109`solenv/`, which share no code with that. 110 111## What is in the branch 112 113### The source conformance set (from `win10-64-minimal`) 114 115Roughly 64 files, all of it legal C++03 and inert on VC9. Five families: 116 117* **C2694 — a destructor's exception specification.** Under C++03 a 118 destructor with nothing written carries no specification, so nothing could 119 conflict. From C++11 on the compiler supplies one, and at any class 120 inheriting from both a pre-UNO hierarchy and a UNO one, three promises meet 121 and only one was written by a person. None of these destructors throws; it 122 is a paperwork conflict, and the fix changes no generated code. Fixed at the 123 base classes — `SfxBroadcaster`, `SfxListener`, `OWeakObject` and friends — 124 so one edit covers every derived class, and with a forward declaration 125 rather than a UNO include, so no coupling changes. 126* **C3848 — a comparator must be callable on a `const` comparator.** 127 `std::set`'s const members hold the comparator by const reference. A 128 standard requirement, not a modern-MSVC opinion; VC9's `<xtree>` reached it 129 through a non-const path and never checked. Eight sites in `sd`, `sdext` 130 and `sw`. 131* **C2280 — an output iterator must be CopyAssignable.** `chart2`'s 132 `DialogModel.cxx` defines two custom output iterators holding their 133 destination by reference, which deletes the implicit copy assignment. This 134 is the one item that is a latent defect rather than paperwork: the type was 135 never a conforming output iterator. Both now hold a pointer. 136* **Named includes.** `<time.h>` in `tools/dirent.cxx`, `<iterator>` in 137 `comphelper`, `xmloff` and `xmlhelp` — headers the code already depends on 138 and used to get transitively from VC9's `<algorithm>`. Only the ones a build 139 actually named were added; a sweep found ~25 candidates and most still 140 compile, so adding those would be churn in a diff meant to stay 141 backportable. 142* **The `snprintf` guards**, in `sal/inc/systools/win32/snprintf.h` and in 143 `uwinapi/sntprintf.c` — the declarations *and* the implementations, which 144 are two sites of one root cause. 145 146### The exception-specification removal 147 148`d01dcefb61`, 5,069 files. Dynamic exception specifications with a type list 149are gone from the tree, together with the two generators that emitted them 150(`cppumaker`'s `dumpExceptionSpecification`, and the skeletonmaker in 151`unodevtools`). The empty specification — `throw()`, `SAL_THROW( () )`, 152`SAL_THROW_EXTERN_C()` — is untouched: MSVC implements that one as 153`__declspec(nothrow)` and it is worth keeping. 154 155This is **not** required to compile: at `/std:c++14` the typed specifications 156are still legal. It is here because it is what the source branch actually 157ships, and because it makes the whole C2694 family evaporate rather than 158needing per-site annotation. 159 160`main/solenv/bin/throwspec.py` is the tool that did it, carried along so the 161next sweep does not have to re-derive the four rules that separate a 162specification from a `throw` statement. Run against this branch it reports no 163remaining typed specification, 7,202 empty ones (the follow-up task), 16 real 164throw statements, and the eight sites it rejects by design. 165 166### The toolchain 167 168`COMEX` gains the value **14**: the UCRT generation, VS2015 (`cl 19.00`) and 169everything since. One value rather than one per Visual Studio release, because 170nothing in this tree distinguishes VS2017 from VS2022 — what they share, and 171what VC9 does not, is the CRT and the SDK layout. `COMEX` already selects the 172platform makefile, the `CVER` define and the output tree, so 14 carries all 173three (`CVER=M1900`, output tree `wntmsci14` / `wntmscx14`). 174 175Four shape differences, each handled where it belongs: 176 177| | VC9 | VS2015+ | 178| --- | --- | --- | 179| `cl.exe` | `VC/bin`, cross tools at `bin/amd64` | `bin/Host<host>/<target>` | 180| mspdb | elsewhere — `Common7/IDE`, or the SDK's bin | next to `cl.exe`, so the hunt is skipped | 181| headers | one `Include/`, one `Lib/` | four include trees (`ucrt`, `um`, `shared`, `winrt`), two lib trees, both under a version | 182| ATL/MFC | in the Platform SDK | in the toolset, with a per-architecture lib directory | 183 184SDK version selection is "newest complete", compared component by component as 185integers — a string compare sorts `10.0.9xxxx` above `10.0.19041`, and 186completeness matters because `bin/` routinely holds more versions than 187`Include/` and `Lib/` do, so choosing on `bin/` alone can pick a version with 188no headers at all. Either half can be pinned: 189`--with-windows-sdk-home`, `--with-windows-sdk-version`. 190 191Which layout is in play is detected from the directory, and then cross-checked 192against what `cl.exe` reports: a `bin/Host*` tree whose compiler says VC9, or a 193VC9 tree whose compiler says 19.x, is an error rather than a guess. 194 195`solenv/inc/wntmsc14.mk` is the entire compiler delta, included at the end of 196`wntmsci11.mk` (x86) and `wntmscx.mk` (x64). It has no conditional inside it, 197because the file *is* the condition — which is what makes a VC9 build 198byte-identical. `solenv/gbuild/platform/windows.mk` carries the same block for 199the gbuild half; the two must agree, since a module built by one links against 200libraries built by the other. 201 202The one non-obvious flag choice is **`/std:c++14`, not 17**. Three things 203depend on the dialect and all three say 14: `std::tr1`, which the MSVC library 204still ships but only while `_HAS_CXX17` is 0 and which `boost/tr1` and the 205stlport shims name directly; the empty exception specification, deprecated in 206C++17 and removed in C++20, of which thousands remain; and 207`<hash_map>`/`<hash_set>`, which become a hard `#error` under C++17. There is 208no falling back further — a modern `cl` rejects `/std:c++03` outright (D9002), 209so C++14 is the floor whether or not it is chosen. 210 211### The STL shims 212 213`main/stlport/systemstl/` holds nine headers that pull STL types into `std`. 214Six of them **shadow** a standard header, and a shadowing header can only reach 215what it shadows through a path that resolves against the compiler's own include 216directory. VC9's spelling is `<../../VC/include/list>`; a modern toolset has no 217such directory, so each of the six gained a `_MSC_VER >= 1900` arm spelling it 218`<../include/list>`. 219 220**Branch order is what makes that work, and it was wrong in three of them.** 221`map`, `set` and `numeric` tested `__cplusplus` before `_MSC_VER` — and with 222`/Zc:__cplusplus` that arm is now true, and it does `#include_next`, a GCC 223extension MSVC does not have. The modern arm is now first in all six. 224 225This deliberately diverges from `win10-64-minimal`, which moved four of them 226into a `vc9/` subdirectory kept off the modern include path. Trunk's 227`stlport/makefile.mk` carries its install rule as its first and only target, 228which is also the module's default goal, so splitting that rule in two is not a 229safe edit here. 230 231The three that shadow nothing (`hash_map`, `hash_set`, `slist`) are untouched: 232they forward to `<unordered_map>` and friends with a plain `#include`. 233 234### Third-party 235 236`redland` and `rasqal` ship hand-written win32 config headers full of shims for 237what old MSVC lacked. Three of those stopped being redundant and became 238harmful once the UCRT started **declaring** the real function, because a macro 239rewrites that declaration as it is being parsed. `round` is the instructive 240one: it is declared in `corecrt_math.h`, so `#define round(x) floor(x+0.5)` 241makes the header stop parsing with C2059/C2143, some distance from anything 242that mentions `round`. 243 244Delivered as new `*.patch.ucrt` files listed after the existing 245`*.patch.win32`, so the base patches stay reviewable against upstream. 246 247`libxml2` needed nothing — 2.9.10 already guards its own `snprintf` shim on 248`_MSC_VER < 1900`. `nss` needed nothing either. 249 250## The old Platform SDK does not go away entirely 251 252`--with-frame-home` must keep pointing at the **Platform SDK v7.0**, whatever 253compiler is in use. It is checked by looking for `lib/mscoree.lib` 254([`configure.ac:2651`](../main/configure.ac)), and the Windows 10 SDK has no 255`mscoree.lib` anywhere in its `Lib/` tree — verified, not assumed. That library 256is the .NET Framework import library the CLI/managed parts link against, and it 257never moved into the new SDK. 258 259The other two flags a build script typically derives from the same variable do 260move: 261 262| flag | on a modern toolset | 263| --- | --- | 264| `--with-frame-home` | **keep** on Platform SDK v7.0 — `lib/mscoree.lib` | 265| `--with-psdk-home` | drop; the Windows 10 SDK is found automatically, and pointing this at v7.0 now warns | 266| `--with-midl-path` | drop, so the Windows 10 SDK's `midl.exe` is used — it has to match the headers it is generating against | 267 268`$FRAME_HOME/lib` is the whole v7.0 library directory, so it does put a full set 269of old import libraries on `LIB`. That is safe by ordering rather than by luck: 270`set_soenv.in` places the SDK's `ucrt` and `um` directories **before** it, so the 271Windows 10 copies of `kernel32.lib` and friends win, and v7.0 supplies only what 272the earlier directories do not have — which is `mscoree.lib`. 273 274## Known gap: the staged CRT is still VC90 275 276`bootstrap` calls `oowintool --msvc-copy-dlls`, which finds a compiler through 277the pre-Windows-8 registry keys it knows about, and on a machine that still has 278VS2008 installed that is VS2008. So `main/external/msvcp90/` receives 279`msvcr90.dll`, `msvcp90.dll`, `msvcm90.dll` and `Microsoft.VC90.CRT.manifest`, 280`main/external/prj/d.lst` delivers them, and the installer ships them -- 281while everything else is now built against the UCRT. 282 283This does **not** stop a build: the files exist, they are copied, nothing 284references them at link time. What it produces is an installation carrying 285three dead VC90 DLLs and missing the runtime it actually needs 286(`vcruntime140.dll`, `msvcp140.dll`, and the UCRT). On a developer machine 287that runs anyway, because installing Visual Studio installs the redistributable 288system-wide; on a clean machine it would not. 289 290The modern equivalent is `VC/Redist/MSVC/<toolset>/<arch>/Microsoft.VC142.CRT`, 291and note it is *not* a like-for-like swap: the UCRT is an operating-system 292component on Windows 10 rather than an application-private SxS assembly, so the 293manifest half of the old arrangement has no counterpart rather than a renamed 294one. 295 296`win10-64-minimal` drew its scope line in exactly the same place -- "this 297branch targets compiling; the CRT/SxS story is the phase after" -- so this is 298inherited, not newly introduced. It is recorded here because it is invisible 299until someone installs the result on a machine without Visual Studio. 300 301Related, same cause, harmless: `bootstrap` prints 302`Can't find MS Visual Studio / VC++ at ./oowintool line 228`. That is 303`find_msvs()`, which looks for the Visual Studio IDE through the same old 304registry keys; VS2019 BuildTools registers none of them. Nothing downstream 305needs the answer once `--with-cl-home` is given. 306 307## What building found 308 309Forty defects, grouped by cause rather than by module and running roughly in 310the order a build meets them. The grouping is the useful part: each family has 311more members further up the tree, and knowing the family is how the next one 312gets recognised in one reading instead of three. 313 314**The toolchain has to be located before it can be wrong** (4). 315`--with-cl-home` and friends were being overridden by the branch's own guesses 316rather than winning over them; `ml.exe` moved into a per-host subdirectory 317(`bin/Hostx64/x86`) that no longer matches the flat VC9 layout; and the Windows 31810 SDK search found Platform SDK v7.0 first and accepted it. The SDK search is 319now one rule over an ordered candidate list. 320 321**The UCRT stopped declaring things** (2). `PATH_MAX` in `soltools/cpp`, 322`__iob_func` in ICU's `icuio`. Both had been supplied by the old CRT without 323being anyone's deliberate dependency. 324 325**A shim that became harmful** (1 more, 5 total on this branch). `libxmlsec` 326joined `sal`, `uwinapi`, `redland` and `rasqal` in `#define`-ing away a name 327the UCRT now declares for real. The guard is always `_MSC_VER < 1900`. 328 329**Tools and flags that no longer exist** (4). `/OPT:NOWIN98`; `vcbuild.exe`, 330which is why CoinMP went 1.7.6 → 1.8.4; `lib.exe -EXTRACT:/`, which is below 331because of *how* it fails; and `/clr:oldSyntax`, which is its own entry. 332 333**The build host is not the target** (1). NSPR took its architecture from 334`uname`, which on a 64-bit Cygwin building a 32-bit product is wrong. 335 336**Bundled third-party builds more than we need** (2). ICU's test programs and 337`icuio` both fail and neither is used. 338 339**Patch mechanics, not code** (4). A gtest patch reconstructed by un-applying 340it mentally was wrong by one blank line and its hunk rejected silently; the 341bundled tr1 tuple was forced tree-wide instead of where it is needed; git was 342normalising CRLF inside `*.patch` files, now held by `.gitattributes`; and 343CoinMP 1.8.4 ships an upstream packaging bug naming `.vcxproj` files under a 344`v9` directory. 345 346**The CRT split in three** (5). `-NODEFAULTLIB` means every part must be 347named, and there turned out to be **three different ways to end up with one 348third of it**: `sal`'s `kill` chooses the static CRT through `DYNAMIC_CRT` 349and got a mismatched pair; `embedserv`'s in-process server *replaces* `LIBCMT` 350outright, so an append made earlier is lost; and `regpatchactivex` and 351`desktop`'s win32 setup never touch `LIBCMT` at all, appending `libcmt.lib` to 352their own `SHL1STDLIBS`. Each needed a different fix. Plus the gbuild side and 353the CoinMP link inputs. 354 355**Modern SDKs moved things, or dropped them** (3). The 64-bit shell extension 356computes its own library paths and both layouts had moved — the SDK gained a 357version level and split into `um/` and `ucrt/`, the toolset renamed `amd64/` 358to `x64/`. `mapix.h` is not in the Windows 10 SDK **at all**: extended MAPI 359went to Outlook, and only simple MAPI stayed. Python 3 split its public 360headers into `Include/` and `Include/cpython/`, and the delivery list only 361knew about the first. 362 363**An x64 source branch leaves x86 twins untouched** (1). The `<typeinfo.h>` 364fix was cherry-picked onto `msvc_win64_x86-64/except.cxx` and its message says 365"the file is the MSVC x64 bridge which no other platform compiles" — true 366where it came from. This build compiles `msvc_win32_intel`, which holds a 367second copy of the same line. Expect more of these. 368 369**Includes VC9 supplied by accident** (2 sweeps, 42 files). `std::back_inserter` 370and the iterator types live in `<iterator>`, which VC9's containers dragged in 371and a modern MSVC's do not. Recorded as two entries because the first sweep 372was wrong twice — see the note on sweeps below. 373 374**Deferred work coming due** (2). Two things trunk had explicitly parked until 375a modern compiler existed, which is what this branch is. The CLI binding is 376Managed Extensions for C++ and needs `/clr:oldSyntax`, removed after VS2015 — 377switched off here, and a C++/CLI port is its own piece of work. Python had its 378entire Windows half commented out with a note saying so; it now builds through 379PCbuild and MSBuild. 380 381**Building Python turned out to be four defects, not one** (4). `find_python.bat` 382probes only `py -3.10` and `py -3.9` and otherwise **downloads** a Python 383through nuget, which offline cannot do — `HOST_PYTHON` is the documented way 384past that. It must be a *native* Python: a cygwin one passes a version check 385and still reads the native paths PCbuild hands it as relative, prepending its 386own working directory. `IncludeExternals=false` looks like the way to stay 387offline and also silently removes zlib from `pythoncore`, which then does not 388compile. And `pcbuild.sln` carries dependencies that are editorial rather than 389structural — `python.vcxproj` declares one on `_ctypes` so the IDE yields a 390usable interpreter — so the projects are built individually instead. 391 392**An awk with a space in its path** (1). `configure.ac` spells `$AWK` 393unquoted in some forty places. On a Cygwin carrying `gawk-<version>.exe` but 394no plain `gawk`, the only `gawk` on `PATH` is Git for Windows' copy under 395`C:\Program Files`, and the build dies hundreds of lines away with 396`/cygdrive/c/Program: No such file`. Fixed by taking the 8.3 form, because the 397Cygwin-side fix does not survive a Cygwin update. 398 399**Symbols a modern compiler adds** (1). `__xmm@<hex>` vector constants appear 400in archive symbol tables exactly as `__real@<hex>` always has. They are merged 401COMDATs, not exports, and a `.def` naming one fails to link. 402 403### The most expensive shape: succeeding while doing nothing 404 405Three of the forty did not fail. They reported success, wrote a plausible 406output file, and left the damage to surface somewhere else entirely: 407 408* **`makedepend`** rejects `-std:c++14` — `-s` is one of its own options — and 409 exits before scanning a single `#include`. It still creates the `.d` file, 410 and that file still holds its target line, so make is satisfied. Every gbuild 411 C++ object in the build had an **empty dependency list**. A clean build is 412 unaffected, which is why it survived a full run; an incremental one silently 413 stops rebuilding on header changes. 414* **`lib.exe -EXTRACT:/`** cannot extract an archive's linker member any more. 415 It says so, writes nothing, and **exits 0**. The build fails later, in 416 `ldump`, naming the `.def` rather than the step that broke. 417* **An external module's `so_built_*` flag** is not invalidated by editing its 418 `BUILD_ACTION`. The first Python build after rewriting the whole Windows 419 half did nothing at all and reported success. 420 421The common thread is that none of them is visible from a green build. They are 422found by reading the noise in a log that already succeeded, which is a habit 423worth keeping for the rest of the port. 424 425### A note on sweeps 426 427The `<iterator>` sweep was wrong twice, and both times it looked complete. 428First it matched the factory functions (`std::back_inserter`) and not the 429types they return, so it missed a file whose only use is 430`typedef back_insert_iterator<contents_t> inserter_t`. Widened to bare names 431for files saying `using namespace std`, it missed the same file again, because 432that line reads `using namespace ::std;` and the pattern did not allow the 433leading `::`. 434 435A criterion narrower than the defect finds a tidy subset and reads like 436completeness. Both misses were found by the build rather than by re-reading 437the pattern. 438 439## The open defect 440 441 getCaughtException() failed! 442 dmake: Error code 1, while making 'runtest' 443 444`testtools/source/bridgetest` is the only thing on this branch that has 445actually been *run*, and it fails. It exercises UNO exception propagation 446across the C++ bridge, which is `cppu::getCaughtException()` reaching into 447MSVC's own exception machinery to recover the thrown object. 448 449The implementation is 450`bridges/source/cpp_uno/msvc_win32_intel/except.cxx`, and it decodes MSVC's 451`ThrowInfo` / `CatchableTypeArray` structures using layout assumptions that 452were true for VC9. `win10-64-minimal` rewrote the **x64** copy of that file 453against the modern layout — it carries its own SEH decoding and a long comment 454diagramming `EXCEPTION_RECORD` — and the x86 copy never received the same 455treatment, because that branch never compiled it. 456 457So this is the same family as the `<typeinfo.h>` miss, and a far deeper 458instance of it. It is not a build fix and has not been attempted here. 459 460It is worth being clear about the consequence: exception propagation is not a 461corner of this product. Until this works, a build that produces an installer 462should not be read as a product that runs. 463 464## Verification 465 466Honest accounting, because the gap still matters more than the list of changes. 467 468**Now measured, by building:** 469 470* `configure` runs and completes, and `configure.ac` therefore expands — 471 `autoconf` was not available when this file was first written, so the whole 472 file had never been through `m4`. 473* `bootstrap` runs, `set_soenv.in` produces a `winenv.set.sh` the build sources 474 without complaint, and `COMEX=14` selects a `wntmsci14.pro` output tree. 475* Every bundled third-party library builds and delivers, Python included. 476* Every module builds and delivers, and `instsetoo_native` assembles both 477 installers. 478* The awk fix is measured, not argued: `configure` now completes with Git for 479 Windows on `PATH`, and logs 480 `.../Program Files/Git/usr/bin/gawk has a space in it, using 481 /cygdrive/c/PROGRA~1/Git/usr/bin/gawk.exe instead`. Both checks that used to 482 die there — the environment sanity check and the GNU make version check — 483 pass. 484* `-Zm500` and `-safeseh` are still accepted; `-NODEFAULTLIB` plus the named 485 CRT libraries is the complete set in both the static and the dynamic model. 486* The `<../include/NAME>` retarget works. Four of the six shadowing headers — 487 `list`, `map`, `set`, `vector` — have now been compiled through on this 488 compiler, which the C4464 warnings in the log record by name. `map` and `set` 489 are also two of the three whose branch order was wrong, so that fix is 490 measured rather than argued. 491 492**Still only argued:** 493 494* **The product has never been started.** Building is not running, and the one 495 runtime test that exists fails. See [The open defect](#the-open-defect). 496* **The CLI/.NET binding is absent**, not fixed. Six places had to be taught 497 that — three `util/makefile.pmk` files, the SDK's file list, the SDK's 498 checker, bridgetest's IDL, and the installer via `SCPDEFS`. 499* **Python is missing five extension modules**, because their sources are 500 downloaded by `get_externals.bat` and an offline build cannot run it. 501* The **VC9 regression claim** is by construction, not by measurement: every 502 toolchain edit adds a branch in front of existing code rather than rewriting 503 it, and every source edit is legal C++03. Nothing on this branch has been 504 compiled with VC9. That is a strong argument and not a green build. 505* `functional` and `numeric`, the other two shadowing headers, have not been 506 reached yet. 507* Manifest handling (`mt.exe`, `_VC_MANIFEST_*`) — nothing built so far 508 exercises it. 509* Nothing has been **run**. The build produces libraries; whether the product 510 starts is a question this branch has not asked. See also 511 [Known gap: the staged CRT is still VC90](#known-gap-the-staged-crt-is-still-vc90), 512 which is a runtime problem by construction. 513 514The rate is the useful number here. On `win10-64-minimal` the last mile was six 515defects in four families; this branch took forty in a dozen to reach a green 516build, and a green build is not the finish line — it is the point at which the 517runtime questions start. 518