PostBuild.ps1 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. # TeamAAS PostBuild: move all DLL/PDB/XML/Plugins/native libs/resource cultures from root to Runtime subdir.
  2. # Duplicate files are skipped (delete source if dest already exists) to keep rebuild idempotent.
  3. # Root keeps: EXE + .config + config-class folders (Config/Logs/Products/Recipe).
  4. # Runtime gets: all DLL/PDB/XML + Plugins/ + dll/ + satellite culture folders (zh-CN, en-US, ...).
  5. # Uses .NET File/Directory APIs directly to avoid PowerShell path-inference quirks.
  6. param(
  7. [Parameter(Mandatory=$true)]
  8. [string]$OutDir
  9. )
  10. $ErrorActionPreference = 'Stop'
  11. if (-not $OutDir.EndsWith('\')) { $OutDir = $OutDir + '\' }
  12. $root = $OutDir
  13. $runtime = Join-Path $root 'Runtime'
  14. # Config-class folders that must stay in root (whitelist). Runtime itself is also excluded.
  15. $configFolders = @('Config', 'Logs', 'Products', 'Recipe', 'Runtime','Calibration')
  16. if (-not [System.IO.Directory]::Exists($runtime)) {
  17. [System.IO.Directory]::CreateDirectory($runtime) | Out-Null
  18. }
  19. $pluginsDest = Join-Path $runtime 'Plugins'
  20. $dllDest = Join-Path $runtime 'dll\x64'
  21. if (-not [System.IO.Directory]::Exists($pluginsDest)) {
  22. [System.IO.Directory]::CreateDirectory($pluginsDest) | Out-Null
  23. }
  24. if (-not [System.IO.Directory]::Exists($dllDest)) {
  25. [System.IO.Directory]::CreateDirectory($dllDest) | Out-Null
  26. }
  27. function Move-FileNoConflict {
  28. # Move single file $Source -> $Target. If Target exists, **overwrite with new Source**
  29. # (critical: keep Target always up-to-date; the old "delete source" behavior left
  30. # stale Target DLLs after rebuild → MissingMethodException at runtime).
  31. param([string]$Source, [string]$Target)
  32. if (-not [System.IO.File]::Exists($Source)) { return }
  33. $targetParent = [System.IO.Path]::GetDirectoryName($Target)
  34. if (-not [System.IO.Directory]::Exists($targetParent)) {
  35. [System.IO.Directory]::CreateDirectory($targetParent) | Out-Null
  36. }
  37. try {
  38. # Copy with overwrite, then delete source. Works whether Target exists or not.
  39. [System.IO.File]::Copy($Source, $Target, $true)
  40. [System.IO.File]::Delete($Source)
  41. } catch {
  42. try {
  43. # If copy failed (e.g. file locked), try plain move as fallback.
  44. if (-not [System.IO.File]::Exists($Target)) {
  45. [System.IO.File]::Move($Source, $Target)
  46. } else {
  47. # Target exists and copy failed → leave Source in place (do not fail build).
  48. Write-Warning "[PostBuild] could not update $Target with $Source : $($_.Exception.Message)"
  49. }
  50. } catch {
  51. Write-Warning "[PostBuild] could not move $Source -> $Target : $($_.Exception.Message)"
  52. }
  53. }
  54. }
  55. function Move-DirectoryTree {
  56. # Move entire subdir tree from $SourceDir to $TargetDir (preserving relative structure).
  57. param([string]$SourceDir, [string]$TargetDir)
  58. if (-not [System.IO.Directory]::Exists($SourceDir)) { return }
  59. if (-not [System.IO.Directory]::Exists($TargetDir)) {
  60. [System.IO.Directory]::CreateDirectory($TargetDir) | Out-Null
  61. }
  62. $files = [System.IO.Directory]::EnumerateFiles($SourceDir, '*', [System.IO.SearchOption]::AllDirectories)
  63. foreach ($srcFile in $files) {
  64. $rel = $srcFile.Substring($SourceDir.Length + 1)
  65. $tgt = [System.IO.Path]::Combine($TargetDir, $rel)
  66. Move-FileNoConflict -Source $srcFile -Target $tgt
  67. }
  68. # Cleanup empty source dir
  69. try { [System.IO.Directory]::Delete($SourceDir, $true) } catch {}
  70. }
  71. $exts = @('.dll', '.pdb', '.xml')
  72. # 1) Root *.dll / *.pdb / *.xml -> Runtime root
  73. $rootFiles = [System.IO.Directory]::EnumerateFiles($root)
  74. foreach ($file in $rootFiles) {
  75. $ext = [System.IO.Path]::GetExtension($file)
  76. if ($exts -contains $ext) {
  77. $tgt = [System.IO.Path]::Combine($runtime, [System.IO.Path]::GetFileName($file))
  78. Move-FileNoConflict -Source $file -Target $tgt
  79. }
  80. }
  81. # 2) Plugins\* -> Runtime\Plugins (preserve tree)
  82. $pluginsSrc = Join-Path $root 'Plugins'
  83. if ([System.IO.Directory]::Exists($pluginsSrc)) {
  84. Move-DirectoryTree -SourceDir $pluginsSrc -TargetDir $pluginsDest
  85. }
  86. # 3) dll\* -> Runtime\dll (preserve tree)
  87. $dllSrc = Join-Path $root 'dll'
  88. if ([System.IO.Directory]::Exists($dllSrc)) {
  89. Move-DirectoryTree -SourceDir $dllSrc -TargetDir (Join-Path $runtime 'dll')
  90. }
  91. # 4) createdump.exe -> Runtime
  92. $createdump = Join-Path $root 'createdump.exe'
  93. if ([System.IO.File]::Exists($createdump)) {
  94. $tgt = Join-Path $runtime 'createdump.exe'
  95. Move-FileNoConflict -Source $createdump -Target $tgt
  96. }
  97. # 5) All other subfolders in root (not in config-class whitelist, not Runtime itself) -> Runtime\<folder>
  98. # Covers satellite culture folders (zh-CN, en-US, ...) and any future non-config folders.
  99. $subDirs = [System.IO.Directory]::GetDirectories($root)
  100. foreach ($d in $subDirs) {
  101. $name = [System.IO.Path]::GetFileName($d)
  102. if ($configFolders -notcontains $name) {
  103. Move-DirectoryTree -SourceDir $d -TargetDir (Join-Path $runtime $name)
  104. }
  105. }
  106. Write-Host "[PostBuild] OK: root keeps EXE + config folders, others in $runtime"