-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDirectory.Build.targets
More file actions
218 lines (200 loc) · 13.6 KB
/
Copy pathDirectory.Build.targets
File metadata and controls
218 lines (200 loc) · 13.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
<?xml version="1.0" encoding="utf-8"?>
<Project>
<!--
Auto-provision the in-repo vcpkg tool (./vcpkg submodule, see Directory.Build.props)
on a fresh checkout, so that `git clone` + build just works with no documented
manual steps. Without this, the first build fails in the vcpkg integration with
"vcpkg.exe is not recognized ... exited with code 9009" because the submodule has
not been checked out / bootstrapped yet.
The hook runs only when vcpkg.exe is missing (so it costs nothing on normal
incremental builds) and just before the vcpkg manifest-install target consumes it.
tools\ensure-vcpkg.ps1 does the submodule checkout + bootstrap and serializes
itself across parallel MSBuild nodes with a named mutex.
-->
<!--
Seed rtc\dll\src\buildstamp.h when it is absent, so a fresh clone builds with a
bare `msbuild all22.sln` or an F5 in Visual Studio. gen\General.cpp includes it,
it is gitignored, and GeoDmsVersion.cmd (i.e. Build.bat and the three flavor
scripts) is otherwise the only thing that writes it.
The version numbers deliberately need NO such hook: they live in the tracked
rtc\dll\src\RtcVersionNumbers.h, which the compiler reads directly.
Only when missing. Writing it on every build would make the header newer than
the outputs, forcing a needless Rtc recompile+relink each time and emitting
.pdb files that no longer match installed binaries, the very thing the
GEODMS_VERSION_HEADER_DONE guard in GeoDmsVersion.cmd exists to avoid.
-->
<Target Name="DmsEnsureBuildStamp"
BeforeTargets="ClCompile"
Condition="!Exists('$(MSBuildThisFileDirectory)rtc\dll\src\buildstamp.h')">
<PropertyGroup>
<_DmsStampDate>$([System.DateTime]::Now.ToString('yyyy-MM-dd'))</_DmsStampDate>
<_DmsStampTime>$([System.DateTime]::Now.ToString('HH:mm:ss'))</_DmsStampTime>
</PropertyGroup>
<Message Importance="high" Text="Seeding rtc\dll\src\buildstamp.h (absent in this checkout)..." />
<WriteLinesToFile File="$(MSBuildThisFileDirectory)rtc\dll\src\buildstamp.h"
Lines="#define DMS_BUILD_DATE "$(_DmsStampDate)";#define DMS_BUILD_TIME "$(_DmsStampTime)""
Overwrite="true" />
</Target>
<Target Name="EnsureVcpkgBootstrapped"
BeforeTargets="VcpkgInstallManifestDependencies"
Condition="!Exists('$(VcpkgRoot)\vcpkg.exe')">
<Message Importance="high"
Text="Bootstrapping in-repo vcpkg ($(VcpkgRoot)) — one-time setup for this checkout..." />
<Exec Command="powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "$(MSBuildThisFileDirectory)tools\ensure-vcpkg.ps1""
WorkingDirectory="$(MSBuildThisFileDirectory)" />
</Target>
<Target Name="DmsRequireGlobioEnvironment"
BeforeTargets="VcpkgInstallManifestDependencies;ClCompile"
Condition="'$(GeoDmsGlobio)' == 'true'">
<Error Condition="'$(GeoDmsGlobioRoot)' == ''"
Text="GLOBIO_ENV_ROOT is not set. Point it at the conda environment locked by vcpkg-globio\environment.yml." />
<Error Condition="!Exists('$(GeoDmsGlobioRoot)\python.exe') or !Exists('$(GeoDmsGlobioRoot)\Library\bin\gdal301.dll')"
Text="GLOBIO_ENV_ROOT does not contain the required CPython 3.9/GDAL 3.1.4 environment: $(GeoDmsGlobioRoot)" />
</Target>
<Target Name="DmsValidateGlobioEnvironment"
BeforeTargets="VcpkgInstallManifestDependencies;ClCompile"
DependsOnTargets="DmsRequireGlobioEnvironment"
Condition="'$(GeoDmsGlobio)' == 'true' and '$(MSBuildProjectName)' == 'DmRtc'">
<Exec Command="powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "$(MSBuildThisFileDirectory)tools\verify-globio-environment.ps1" -GlobioRoot "$(GeoDmsGlobioRoot)""
WorkingDirectory="$(MSBuildThisFileDirectory)" />
</Target>
<!--
Counterpart to the vcpkg.props import in Directory.Build.props: pull in the submodule's
vcpkg.targets late (manifest install + include/lib injection + applocal DLL copy). It
must come after the per-project property sheet DmsDef.props (which sets
VcpkgEnableManifest / VcpkgTriplet / VcpkgInstalledDir); Directory.Build.targets is
imported at the very end of evaluation, so that ordering holds. The
EnsureVcpkgBootstrapped target above hooks BeforeTargets="VcpkgInstallManifestDependencies",
which this import defines.
-->
<Import Project="$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.targets"
Condition="Exists('$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.targets')" />
<!--
Widen the manifest-install gate to the inputs that actually determine the vcpkg ABI.
vcpkg.targets runs VcpkgInstallManifestDependencies as an incremental MSBuild target with
Inputs = vcpkg.json (+ vcpkg-configuration.json) and Outputs = the .msbuildstamp file, so
MSBuild SKIPS it entirely whenever the stamp is newer. vcpkg is then never invoked and the
installed tree is never re-checked against the current configuration. Anything that changes
a port's ABI hash WITHOUT touching vcpkg.json is therefore invisible to the .m flavor: the
triplet file, the MSVC pin in Directory.Build.props, or a vcpkg submodule bump.
That is not hypothetical. The 2026-06-03 baseline bump moved vcpkg's pinned cmake
3.31.10 -> 4.3.2; cmake's version is an ABI input for every vcpkg-cmake port, so the whole
vc_archives cache went stale. .m never noticed (stamp still newer than vcpkg.json, dated
2026-07-11), and the cost landed on .c (whose CMake toolchain installs on every configure
and has no such gate) as a 47-minute rebuild of 144 already-installed ports.
Listing those files as additional Inputs costs nothing while they are older than the stamp,
and forces exactly one re-check when one of them changes. vcpkg's own ABI comparison then
decides whether anything actually needs rebuilding, which is the correct authority.
-->
<ItemGroup Condition="'$(VcpkgEnabled)' == 'true' and '$(VcpkgEnableManifest)' == 'true' and '$(VcpkgManifestInstall)' == 'true'">
<_ZVcpkgInstallManifestDependenciesInputs Include="$(VcpkgManifestRoot)vcpkg.json"
Condition="Exists('$(VcpkgManifestRoot)vcpkg.json')" />
<_ZVcpkgInstallManifestDependenciesInputs Include="$(VcpkgManifestRoot)vcpkg-configuration.json"
Condition="Exists('$(VcpkgManifestRoot)vcpkg-configuration.json')" />
<!-- the triplet: carries VCPKG_PLATFORM_TOOLSET / arch and feeds triplet_abi -->
<_ZVcpkgInstallManifestDependenciesInputs Include="$(MSBuildThisFileDirectory)vcpkg-triplets\$(VcpkgTriplet).cmake"
Condition="Exists('$(MSBuildThisFileDirectory)vcpkg-triplets\$(VcpkgTriplet).cmake')" />
<!-- the MSVC pin (VCToolsVersion) and the vcpkg root/host-triplet selection -->
<_ZVcpkgInstallManifestDependenciesInputs Include="$(MSBuildThisFileDirectory)Directory.Build.props" />
<_ZVcpkgInstallManifestDependenciesInputs Include="$(MSBuildThisFileDirectory)DmsDef.props"
Condition="Exists('$(MSBuildThisFileDirectory)DmsDef.props')" />
<!-- vcpkg's own pinned tool versions (cmake, powershell, ...), i.e. the submodule pointer -->
<_ZVcpkgInstallManifestDependenciesInputs Include="$(VcpkgRoot)\scripts\vcpkg-tools.json"
Condition="Exists('$(VcpkgRoot)\scripts\vcpkg-tools.json')" />
</ItemGroup>
<!--
Repo-owned, self-healing deployment of the vcpkg runtime DLLs next to the exes.
The vcpkg baseline (2026.05.25) carries upstream #50521, which gates its applocal
copy (AppLocalFromInstalled) on '$(LinkSkippedExecution)' != 'true' — i.e. it only
deploys when the linker actually re-links. On a no-relink incremental build (a bare
`msbuild all22.sln`, or F5 after Ctrl+Alt+B) the copy is skipped, and MSBuild's
IncrementalClean then reaps the previously-deployed DLLs as orphan outputs. The
upstream AppLocalFromInstalledPreserve target only re-registers EXISTING files to
protect them from clean; it cannot restore ones already deleted, so once bin\<cfg>\x64
is stripped, no incremental build (msbuild OR VS) brings them back without a full relink.
This target sidesteps both problems: it runs AfterTargets="Build" for every exe project
(which all share one $(OutDir)), unconditionally — not gated on relink — and copies with
SkipUnchangedFiles, so a normal build copies nothing but a stripped output dir is
refilled. Glob-based (bin\*.dll), so GDAL/boost/etc. version bumps are picked up with no
edits. Config-aware: Debug deps live in a separate debug\bin subdir with different names
(gdald.dll, proj_9_d.dll, ...). CopiedFiles feed @(FileWrites) so the next build's
IncrementalClean treats them as claimed, not orphans.
MSBuild-only (the .m flavor). The CMake flavors deploy via vcpkg's own CMake applocal
(Windows) or $ORIGIN rpath + setup bundling (Linux) and don't hit IncrementalClean
reaping, so they need no equivalent here.
-->
<!--
Close the IncrementalClean orphan-reaping hole in the vcpkg applocal integration
(the recurring NSIS "tinyxml2.dll -> no files found" failure, reproduced+binlogged
2026-07-11). The two vcpkg.targets applocal targets register the copied runtime
DLLs in FileWrites ASYMMETRICALLY: on a link-skipped build,
AppLocalFromInstalledPreserve adds them (so they get recorded in that build's
FileListAbsolute.txt), but on a relinking build AppLocalFromInstalled does NOT
(ReferenceCopyLocalPaths only). So any relink build that follows a link-skipped
build finds the DLLs claimed in the prior file list but absent from current
FileWrites, and IncrementalClean deletes the whole gdal/geos/proj/... set from
bin\<cfg>\x64 as orphan outputs - in EVERY project with a vcpkg.applocal.log
(StgDll, Geo, GeoDmsGuiQt, DmsPython, ...). The per-exe DmsDeployVcpkgDeps
refill below cannot save the day: the last poisoned project (DmsPython) builds
after the last exe deploy and strips bin again.
Fix: register the applocal log into FileWrites on EVERY build - relinked or
skipped - so consecutive file lists always agree and IncrementalClean never sees
the DLLs as orphans. When dependencies genuinely change, the next relink rewrites
vcpkg.applocal.log and truly obsolete DLLs are cleaned exactly once - correct.
Hooked BeforeTargets=_CleanGetCurrentAndPriorFileWrites: in time for both the
orphan computation and _CleanRecordFileWrites. Defined after the vcpkg.targets
import above, so on link-skipped builds it runs alongside the upstream preserve
target (duplicate FileWrites entries are deduplicated by MSBuild).
-->
<Target Name="DmsRegisterAppLocalFileWrites"
AfterTargets="CopyFilesToOutputDirectory"
BeforeTargets="_CleanGetCurrentAndPriorFileWrites"
Condition="'@(Link)' != '' and Exists('$(IntDir)vcpkg.applocal.log')">
<ReadLinesFromFile File="$(IntDir)vcpkg.applocal.log">
<Output TaskParameter="Lines" ItemName="_DmsAppLocalDLLs" />
</ReadLinesFromFile>
<ItemGroup>
<FileWrites Include="@(_DmsAppLocalDLLs -> '$(OutDir)%(Filename)%(Extension)')" />
</ItemGroup>
</Target>
<Target Name="DmsDeployVcpkgDeps"
AfterTargets="Build"
Condition="'$(ConfigurationType)' == 'Application' and '$(VcpkgInstalledDir)' != '' and '$(VcpkgTriplet)' != ''">
<PropertyGroup>
<_DmsVcpkgBin>$(VcpkgInstalledDir)$(VcpkgTriplet)\bin</_DmsVcpkgBin>
<_DmsVcpkgBin Condition="'$(Configuration)' == 'Debug' and '$(GeoDmsGlobio)' != 'true'">$(VcpkgInstalledDir)$(VcpkgTriplet)\debug\bin</_DmsVcpkgBin>
</PropertyGroup>
<ItemGroup>
<!-- python3 is a vcpkg build/host dependency, not a GeoDMS application
dependency. The bindings use the separately configured CPython ABI
matrix and Python itself supplies the matching runtime when importing
a .pyd. Copying vcpkg's minor here created the python313/python312
mismatch from issue #1105. -->
<_DmsVcpkgDll Include="$(_DmsVcpkgBin)\*.dll"
Exclude="$(_DmsVcpkgBin)\python*.dll" />
</ItemGroup>
<Copy SourceFiles="@(_DmsVcpkgDll)"
DestinationFolder="$(OutDir)"
SkipUnchangedFiles="true"
Retries="3"
Condition="'@(_DmsVcpkgDll)' != ''">
<Output TaskParameter="CopiedFiles" ItemName="FileWrites" />
</Copy>
</Target>
<!-- Deploy only the transitive conda DLLs actually imported by the G build.
The script deliberately prefers the locked GLOBIO copies for shared names
(geos_c.dll, tiff.dll, sqlite3.dll, ...) but retains the current v145 CRT. -->
<Target Name="DmsDeployGlobioDeps"
AfterTargets="Build"
Condition="'$(GeoDmsGlobio)' == 'true' and '$(ConfigurationType)' == 'Application' and Exists('$(OutDir)')">
<Exec Command="powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "$(MSBuildThisFileDirectory)tools\deploy-globio-runtime.ps1" -OutputDir "$(OutDir.TrimEnd('\'))" -GlobioRoot "$(GeoDmsGlobioRoot)" -CopiedFilesLog "$(IntDir)globio.applocal.log""
WorkingDirectory="$(MSBuildThisFileDirectory)" />
<ReadLinesFromFile File="$(IntDir)globio.applocal.log"
Condition="Exists('$(IntDir)globio.applocal.log')">
<Output TaskParameter="Lines" ItemName="_DmsGlobioAppLocalDLLs" />
</ReadLinesFromFile>
<ItemGroup>
<FileWrites Include="@(_DmsGlobioAppLocalDLLs)" />
</ItemGroup>
</Target>
</Project>