xref: /trunk/win10-msvc/README.md (revision 91144cd0085a7583d2099b982122deb2184ab956)
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* **C2694a 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/` treeverified, 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 havewhich 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.61.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 movedthe 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