11$ErrorActionPreference  =  ' Stop' 
22
3- function  not-exist  { -not  (Test-Path  $args ) }
4- Set-Alias  ! exists not- exist - Option " Constant, AllScope" 
5- Set-Alias  exists Test-Path  - Option " Constant, AllScope" 
6- 
73function  exec  {
84    [CmdletBinding ()]
95    param ([Parameter (Position = 0 , Mandatory = 1 )][scriptblock ]$cmd )
@@ -17,52 +13,84 @@ function exec {
1713    }
1814}
1915
20- function  Init-VS  {
16+ function  Initialize-Python  {
17+     if  ($env: USE_CONDA  -eq  1 ) {
18+         $env: CONDA_ROOT  =  $pwd.Path   +  " \external\miniconda_$env: PYTHON_ARCH " 
19+         &  .\.github\scripts\install-miniconda.ps1 
20+         &  $env: CONDA_ROOT \shell\condabin\conda- hook.ps1
21+         exec { conda update -- yes - n base - c defaults conda }
22+     }
23+     #  Check Python version/arch
24+     exec { python - c " import platform; assert platform.python_version().startswith('$env: PYTHON_VERSION ')" 
25+     exec { python - c " import struct; assert struct.calcsize('P') * 8 == $env: PYTHON_ARCH " 
26+ }
27+ 
28+ function  Create-VEnv  {
29+     [CmdletBinding ()]
30+     param ([Parameter (Position = 0 , Mandatory = 1 )][string ]$name )
31+     if  ($env: USE_CONDA  -eq  1 ) {
32+         exec { conda create -- yes -- name $name  - c defaults -- strict- channel- priority python= $env: PYTHON_VERSION  -- force }
33+     } else  {
34+         exec { python - m venv env\$name  }
35+     }
36+ }
37+ 
38+ function  Enter-VEnv  {
39+     [CmdletBinding ()]
40+     param ([Parameter (Position = 0 , Mandatory = 1 )][string ]$name )
41+     if  ($env: USE_CONDA  -eq  1 ) {
42+         conda activate $name 
43+     } else  {
44+         &  .\env\$name \scripts\activate
45+     }
46+ }
47+ 
48+ function  Create-And-Enter-VEnv  {
49+     [CmdletBinding ()]
50+     param ([Parameter (Position = 0 , Mandatory = 1 )][string ]$name )
51+     Create- VEnv $name 
52+     Enter-VEnv  $name 
53+ }
54+ 
55+ function  Exit-VEnv  {
56+     if  ($env: USE_CONDA  -eq  1 ) {
57+         conda deactivate
58+     } else  {
59+         deactivate
60+     }
61+ }
62+ 
63+ function  Initialize-VS  {
2164    #  https://wiki.python.org/moin/WindowsCompilers
2265    #  setuptools automatically selects the right compiler for building
2366    #  the extension module. The following is mostly for building any
24-     #  dependencies like liblensfun .
67+     #  native  dependencies, here via CMake .
2568    #  https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line
2669    #  https://docs.microsoft.com/en-us/cpp/porting/binary-compat-2015-2017
2770
28-     $VS2017_ROOT  =  " C:\Program Files (x86)\Microsoft Visual Studio\2017" 
29-     $VS2019_ROOT  =  " C:\Program Files (x86)\Microsoft Visual Studio\2019" 
71+     $VS_ROOT  =  " C:\Program Files (x86)\Microsoft Visual Studio" 
72+     $VS_VERSIONS  =  @ (" 2017" ,  " 2019" 
73+     $VS_EDITIONS  =  @ (" Enterprise" ,  " Professional" ,  " Community" 
74+     $VS_INIT_CMD_SUFFIX  =  " Common7\Tools\vsdevcmd.bat" 
3075
3176    $VS_ARCH  =  if  ($env: PYTHON_ARCH  -eq  ' 32' ' x86' else  { ' x64' 
32- 
33-     $PYTHON_VERSION_TUPLE  =  $env: PYTHON_VERSION.split  (' .' 
34-     $PYTHON_VERSION_MAJOR  =  $PYTHON_VERSION_TUPLE [0 ]
35-     $PYTHON_VERSION_MINOR  =  $PYTHON_VERSION_TUPLE [1 ]
36- 
37-     if  ($PYTHON_VERSION_MAJOR  -eq  ' 3' 
38-         if  ($PYTHON_VERSION_MINOR  -le  ' 4' 
39-             throw  (" Python <= 3.4 unsupported: $env: PYTHON_VERSION " 
40-         }
41-         if  (exists $VS2017_ROOT ) {
42-             $VS_VERSION  =  " 2017" 
43-             if  (exists " $VS2017_ROOT \Enterprise" 
44-                 $VS_ROOT  =  " $VS2017_ROOT \Enterprise" 
45-             } else  {
46-                 $VS_ROOT  =  " $VS2017_ROOT \Community" 
77+     $VS_INIT_ARGS  =  " -arch=$VS_ARCH  -no_logo" 
78+ 
79+     $found  =  $false 
80+     :outer foreach  ($version  in  $VS_VERSIONS ) {
81+         foreach  ($edition  in  $VS_EDITIONS ) {
82+             $VS_INIT_CMD  =  " $VS_ROOT \$version \$edition \$VS_INIT_CMD_SUFFIX " 
83+             if  (Test-Path  $VS_INIT_CMD ) {
84+                 $found  =  $true 
85+                 break  outer
4786            }
48-             $VS_INIT_CMD  =  " $VS_ROOT \Common7\Tools\vsdevcmd.bat" 
49-             $VS_INIT_ARGS  =  " -arch=$VS_ARCH  -no_logo" 
50-         } elseif  (exists $VS2019_ROOT ) {
51-             $VS_VERSION  =  " 2019" 
52-             if  (exists " $VS2019_ROOT \Enterprise" 
53-                 $VS_ROOT  =  " $VS2019_ROOT \Enterprise" 
54-             } else  {
55-                 $VS_ROOT  =  " $VS2019_ROOT \Community" 
56-             }
57-             $VS_INIT_CMD  =  " $VS_ROOT \Common7\Tools\vsdevcmd.bat" 
58-             $VS_INIT_ARGS  =  " -arch=$VS_ARCH  -no_logo" 
59-         } else  {
60-             throw  (" No suitable Visual Studio installation found" 
6187        }
62-     } else  {
63-         throw  (" Unsupported Python version: $PYTHON_VERSION_MAJOR " 
6488    }
65-     Write-Host  " Configuring VS$VS_VERSION  for Python $env: PYTHON_VERSION  on a $env: PYTHON_ARCH  bit architecture" 
89+ 
90+     if  (! $found ) {
91+         throw  (" No suitable Visual Studio installation found" 
92+     }
93+ 
6694    Write-Host  " Executing: $VS_INIT_CMD  $VS_INIT_ARGS " 
6795
6896    #  https://github.com/Microsoft/vswhere/wiki/Start-Developer-Command-Prompt
@@ -85,66 +113,44 @@ if (!$env:NUMPY_VERSION) {
85113    throw  " NUMPY_VERSION env var missing" 
86114}
87115
88- Init- VS
116+ Initialize-VS 
117+ Initialize-Python 
89118
90119Get-ChildItem  env:
91120
92- $env: CONDA_ROOT  =  $pwd.Path   +  " \external\miniconda_$env: PYTHON_ARCH " 
93- &  .\.github\scripts\install-miniconda.ps1 
94- 
95- &  $env: CONDA_ROOT \shell\condabin\conda- hook.ps1
96- 
97- exec { conda update -- yes - n base - c defaults conda }
98121
99- exec { conda create -- yes -- name pyenv_build python= $env: PYTHON_VERSION  numpy= $env: NUMPY_VERSION  cython -- force }
100- exec { conda activate pyenv_build }
101- 
102- #  Check that we have the expected version and architecture for Python
103- exec { python -- version }
104- exec { python - c " import struct; assert struct.calcsize('P') * 8 == $env: PYTHON_ARCH " 
105- exec { python - c " import sys; print(sys.prefix)" 
106- 
107- #  output what's installed
108- exec { python - m pip freeze }
109- 
110- #  Build the compiled extension.
111- #  -u disables output buffering which caused intermixing of lines
112- #  when the external tools were started  
122+ #  Build the wheel.
123+ Create- And- Enter-VEnv  build
124+ exec { python - m pip install -- upgrade pip wheel setuptools }
125+ exec { python - m pip install -- only- binary :all: numpy== $env: NUMPY_VERSION  cython }
113126exec { python - u setup.py bdist_wheel }
127+ Exit-VEnv 
114128
115- #  Necessary to avoid bug when switching to test env.
116- exec { conda deactivate }
117- 
118- #  Import test on a minimal environment
119- #  (to catch DLL issues)
120- exec { conda create -- yes -- name pyenv_minimal python= $env: PYTHON_VERSION  -- force }
121- exec { conda activate pyenv_minimal }
122- 
123- #  Avoid using in-source package
124- New-Item  - Force - ItemType directory tmp_for_test |  out-null 
125- cd tmp_for_test
126- 
129+ #  Install and import in an empty environment.
130+ #  This is to catch DLL issues that may be hidden with dependencies.
131+ Create- And- Enter-VEnv  import-test 
127132python - m pip uninstall - y lensfunpy
128- ls ..\dist\* .whl |  %  { exec { python - m pip install $_  } }
129- exec { python - c " import lensfunpy" 
133+ ls dist\* .whl |  %  { exec { python - m pip install $_  } }
130134
131- #  Necessary to avoid bug when switching to test env.
132- exec { conda deactivate }
135+ #  Avoid using in-source package during tests
136+ mkdir -f  tmp_for_test |  out-null 
137+ pushd tmp_for_test
138+ exec { python - c " import lensfunpy" 
139+ popd
133140
134- #  Test
135- exec { conda create -- yes -- name pyenv_test python= $env: PYTHON_VERSION  numpy scipy -- force }
136- exec { conda activate pyenv_test }
141+ Exit-VEnv 
137142
138- #  Check that we have the expected version and architecture for Python
139- exec { python -- version }
140- exec { python - c " import struct; assert struct.calcsize('P') * 8 == $env: PYTHON_ARCH " 
141- exec { python - c " import sys; print(sys.prefix)" 
143+ #  Run test suite with all required and optional dependencies
144+ Create- And- Enter-VEnv  testsuite
145+ exec { python - m pip install -- only- binary :all: numpy scipy }
146+ python - m pip uninstall - y lensfunpy
147+ ls dist\* .whl |  %  { exec { python - m pip install $_  } }
148+ exec { python - m pip install - r dev- requirements.txt }
142149
143- #  output what's installed
144- exec { python - m pip freeze }
150+ #  Avoid using in-source package during tests
151+ mkdir -f  tmp_for_test |  out-null 
152+ pushd tmp_for_test
153+ exec { pytest -- verbosity= 3  - s ../ test }
154+ popd
145155
146- python - m pip uninstall - y lensfunpy
147- ls ..\dist\* .whl |  %  { exec { python - m pip install $_  } }
148- exec { python - m pip install - r ..\dev- requirements.txt }
149- exec { nosetests -- verbosity= 3  -- nocapture ../ test }
150- cd ..
156+ Exit-VEnv 
0 commit comments