1 | @setlocal EnableDelayedExpansion EnableExtensions |
2 | |
3 | IF NOT DEFINED VERBOSE_MAKE @echo off |
4 | |
5 | REM Option flags |
6 | set /a shift_counter=0 |
7 | set /a flag_local=0 |
8 | |
9 | REM Option variables |
10 | set compiler= |
11 | set subcmd= |
12 | set target=build |
13 | |
14 | REM TCC variables |
15 | set "tcc_url=https://github.com/vlang/tccbin" |
16 | set "tcc_dir=thirdparty\tcc" |
17 | set "tcc_exe=thirdparty\tcc\tcc.exe" |
18 | if "%PROCESSOR_ARCHITECTURE%" == "x86" ( set "tcc_branch=thirdparty-windows-i386" ) else ( set "tcc_branch=thirdparty-windows-amd64" ) |
19 | if "%~1" == "-tcc32" set "tcc_branch=thirdparty-windows-i386" |
20 | |
21 | REM VC settings |
22 | set "vc_url=https://github.com/vlang/vc" |
23 | set "vc_dir=%~dp0vc" |
24 | |
25 | REM Let a particular environment specify their own TCC and VC repos (to help mirrors) |
26 | if /I not ["%TCC_GIT%"] == [""] set "tcc_url=%TCC_GIT%" |
27 | if /I not ["%TCC_BRANCH%"] == [""] set "tcc_branch=%TCC_BRANCH%" |
28 | |
29 | if /I not ["%VC_GIT%"] == [""] set "vc_url=%VC_GIT%" |
30 | |
31 | pushd %~dp0 |
32 | |
33 | :verifyopt |
34 | REM Read stdin EOF |
35 | if ["%~1"] == [""] goto :init |
36 | |
37 | REM Target options |
38 | if !shift_counter! LSS 1 ( |
39 | if "%~1" == "help" ( |
40 | if not ["%~2"] == [""] set "subcmd=%~2"& shift& set /a shift_counter+=1 |
41 | ) |
42 | for %%z in (build clean cleanall help) do ( |
43 | if "%~1" == "%%z" set target=%1& shift& set /a shift_counter+=1& goto :verifyopt |
44 | ) |
45 | ) |
46 | |
47 | REM Compiler option |
48 | for %%g in (-gcc -msvc -tcc -tcc32 -clang) do ( |
49 | if "%~1" == "%%g" set compiler=%~1& set compiler=!compiler:~1!& shift& set /a shift_counter+=1& goto :verifyopt |
50 | ) |
51 | |
52 | REM Standard options |
53 | if "%~1" == "--local" ( |
54 | if !flag_local! NEQ 0 ( |
55 | echo The flag %~1 has already been specified. 1>&2 |
56 | exit /b 2 |
57 | ) |
58 | set /a flag_local=1 |
59 | set /a shift_counter+=1 |
60 | shift |
61 | goto :verifyopt |
62 | ) |
63 | |
64 | echo Undefined option: %~1 |
65 | exit /b 2 |
66 | |
67 | :init |
68 | goto :!target! |
69 | |
70 | :cleanall |
71 | call :clean |
72 | if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL% |
73 | echo. |
74 | echo Cleanup vc |
75 | echo ^> Purge TCC binaries |
76 | rmdir /s /q "%tcc_dir%" |
77 | echo ^> Purge vc repository |
78 | rmdir /s /q "%vc_dir%" |
79 | exit /b 0 |
80 | |
81 | :clean |
82 | echo Cleanup build artifacts |
83 | echo ^> Purge debug symbols |
84 | del *.pdb *.lib *.bak *.out *.ilk *.exp *.obj *.o *.a *.so |
85 | |
86 | echo ^> Delete old V executable |
87 | del v_old.exe v*.exe |
88 | exit /b 0 |
89 | |
90 | :help |
91 | if [!subcmd!] == [] ( |
92 | call :usage |
93 | ) else ( |
94 | call :help_!subcmd! |
95 | ) |
96 | if %ERRORLEVEL% NEQ 0 echo Invalid subcommand: !subcmd! |
97 | exit /b %ERRORLEVEL% |
98 | |
99 | :build |
100 | if !flag_local! NEQ 1 ( |
101 | call :download_tcc |
102 | if %ERRORLEVEL% NEQ 0 goto :error |
103 | pushd "%vc_dir%" && ( |
104 | echo Updating vc... |
105 | echo ^> Sync with remote !vc_url! |
106 | cd "%vc_dir%" |
107 | git pull --quiet |
108 | cd .. |
109 | popd |
110 | ) || call :cloning_vc |
111 | echo. |
112 | ) |
113 | |
114 | echo Building V... |
115 | if not [!compiler!] == [] goto :!compiler!_strap |
116 | |
117 | |
118 | REM By default, use tcc, since we have it prebuilt: |
119 | :tcc_strap |
120 | :tcc32_strap |
121 | echo ^> Attempting to build v_win.c with "!tcc_exe!" |
122 | "!tcc_exe!" -Bthirdparty/tcc -bt10 -g -w -o v.exe vc\v_win.c -ladvapi32 |
123 | if %ERRORLEVEL% NEQ 0 goto :compile_error |
124 | echo ^> Compiling .\v.exe with itself |
125 | v.exe -keepc -g -showcc -cc "!tcc_exe!" -cflags -Bthirdparty/tcc -o v2.exe cmd/v |
126 | if %ERRORLEVEL% NEQ 0 goto :clang_strap |
127 | del v.exe |
128 | move v2.exe v.exe |
129 | goto :success |
130 | |
131 | :clang_strap |
132 | where /q clang |
133 | if %ERRORLEVEL% NEQ 0 ( |
134 | echo ^> Clang not found |
135 | if not [!compiler!] == [] goto :error |
136 | goto :gcc_strap |
137 | ) |
138 | |
139 | echo ^> Attempting to build v_win.c with Clang |
140 | clang -std=c99 -municode -g -w -o v.exe .\vc\v_win.c -ladvapi32 |
141 | if %ERRORLEVEL% NEQ 0 ( |
142 | echo In most cases, compile errors happen because the version of Clang installed is too old |
143 | clang --version |
144 | goto :compile_error |
145 | ) |
146 | |
147 | echo ^> Compiling .\v.exe with itself |
148 | v.exe -keepc -g -showcc -cc clang -o v2.exe cmd/v |
149 | if %ERRORLEVEL% NEQ 0 goto :compile_error |
150 | del v.exe |
151 | move v2.exe v.exe |
152 | goto :success |
153 | |
154 | :gcc_strap |
155 | where /q gcc |
156 | if %ERRORLEVEL% NEQ 0 ( |
157 | echo ^> GCC not found |
158 | if not [!compiler!] == [] goto :error |
159 | goto :msvc_strap |
160 | ) |
161 | |
162 | echo ^> Attempting to build v_win.c with GCC |
163 | gcc -std=c99 -municode -g -w -o v.exe .\vc\v_win.c -ladvapi32 |
164 | if %ERRORLEVEL% NEQ 0 ( |
165 | echo In most cases, compile errors happen because the version of GCC installed is too old |
166 | gcc --version |
167 | goto :compile_error |
168 | ) |
169 | |
170 | echo ^> Compiling .\v.exe with itself |
171 | v.exe -keepc -g -showcc -cc gcc -o v2.exe cmd/v |
172 | if %ERRORLEVEL% NEQ 0 goto :compile_error |
173 | del v.exe |
174 | move v2.exe v.exe |
175 | goto :success |
176 | |
177 | :msvc_strap |
178 | set VsWhereDir=%ProgramFiles(x86)% |
179 | set HostArch=x64 |
180 | if "%PROCESSOR_ARCHITECTURE%" == "x86" ( |
181 | echo Using x86 Build Tools... |
182 | set VsWhereDir=%ProgramFiles% |
183 | set HostArch=x86 |
184 | ) |
185 | |
186 | if not exist "%VsWhereDir%\Microsoft Visual Studio\Installer\vswhere.exe" ( |
187 | echo ^> MSVC not found |
188 | if not [!compiler!] == [] goto :error |
189 | goto :compile_error |
190 | ) |
191 | |
192 | for /f "usebackq tokens=*" %%i in (`"%VsWhereDir%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do ( |
193 | set InstallDir=%%i |
194 | ) |
195 | |
196 | if exist "%InstallDir%\Common7\Tools\vsdevcmd.bat" ( |
197 | call "%InstallDir%\Common7\Tools\vsdevcmd.bat" -arch=%HostArch% -host_arch=%HostArch% -no_logo |
198 | ) else if exist "%VsWhereDir%\Microsoft Visual Studio 14.0\Common7\Tools\vsdevcmd.bat" ( |
199 | call "%VsWhereDir%\Microsoft Visual Studio 14.0\Common7\Tools\vsdevcmd.bat" -arch=%HostArch% -host_arch=%HostArch% -no_logo |
200 | ) |
201 | |
202 | set ObjFile=.v.c.obj |
203 | |
204 | echo ^> Attempting to build v_win.c with MSVC |
205 | cl.exe /volatile:ms /Fo%ObjFile% /O2 /MD /D_VBOOTSTRAP vc\v_win.c user32.lib kernel32.lib advapi32.lib shell32.lib /link /nologo /out:v.exe /incremental:no |
206 | if %ERRORLEVEL% NEQ 0 ( |
207 | echo In some cases, compile errors happen because of the MSVC compiler version |
208 | cl.exe |
209 | goto :compile_error |
210 | ) |
211 | |
212 | echo ^> Compiling .\v.exe with itself |
213 | v.exe -keepc -g -showcc -cc msvc -o v2.exe cmd/v |
214 | del %ObjFile% |
215 | if %ERRORLEVEL% NEQ 0 goto :compile_error |
216 | del v.exe |
217 | move v2.exe v.exe |
218 | goto :success |
219 | |
220 | :download_tcc |
221 | pushd %tcc_dir% && ( |
222 | echo Updating TCC |
223 | echo ^> Syncing TCC from !tcc_url! |
224 | git pull --quiet |
225 | popd |
226 | ) || call :bootstrap_tcc |
227 | |
228 | if [!tcc_exe!] == [] echo ^> TCC not found, even after cloning& goto :error |
229 | echo. |
230 | exit /b 0 |
231 | |
232 | :compile_error |
233 | echo. |
234 | echo Backend compiler error |
235 | goto :error |
236 | |
237 | :error |
238 | echo. |
239 | echo Exiting from error |
240 | echo ERROR: please follow the instructions in https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Windows |
241 | exit /b 1 |
242 | |
243 | :success |
244 | .\v.exe run cmd\tools\detect_tcc.v |
245 | echo ^> V built successfully! |
246 | echo ^> To add V to your PATH, run `.\v.exe symlink`. |
247 | |
248 | :version |
249 | echo. |
250 | echo | set /p="V version: " |
251 | .\v.exe version |
252 | goto :eof |
253 | |
254 | :usage |
255 | echo Usage: |
256 | echo make.bat [target] [compiler] [options] |
257 | echo. |
258 | echo Compiler: |
259 | echo -msvc ^| -gcc ^| -tcc ^| -tcc32 ^| -clang Set C compiler |
260 | echo. |
261 | echo Target: |
262 | echo build[default] Compiles V using the given C compiler |
263 | echo clean Clean build artifacts and debugging symbols |
264 | echo cleanall Cleanup entire ALL build artifacts and vc repository |
265 | echo help Display usage help for the given target |
266 | echo. |
267 | echo Examples: |
268 | echo make.bat -msvc |
269 | echo make.bat -gcc --local |
270 | echo make.bat build -tcc --local |
271 | echo make.bat -tcc32 |
272 | echo make.bat help clean |
273 | echo. |
274 | echo Use "make help <target>" for more information about a target, for instance: "make help clean" |
275 | echo. |
276 | echo Note: Any undefined/unsupported options will be ignored |
277 | exit /b 0 |
278 | |
279 | :help_help |
280 | echo Usage: |
281 | echo make.bat help [target] |
282 | echo. |
283 | echo Target: |
284 | echo build ^| clean ^| cleanall ^| help Query given target |
285 | exit /b 0 |
286 | |
287 | :help_clean |
288 | echo Usage: |
289 | echo make.bat clean |
290 | echo. |
291 | exit /b 0 |
292 | |
293 | :help_cleanall |
294 | echo Usage: |
295 | echo make.bat cleanall |
296 | echo. |
297 | exit /b 0 |
298 | |
299 | :help_build |
300 | echo Usage: |
301 | echo make.bat build [compiler] [options] |
302 | echo. |
303 | echo Compiler: |
304 | echo -msvc ^| -gcc ^| -tcc ^| -tcc32 ^| -clang Set C compiler |
305 | echo. |
306 | echo Options: |
307 | echo --local Use the local vc repository without |
308 | echo syncing with remote |
309 | exit /b 0 |
310 | |
311 | :bootstrap_tcc |
312 | echo Bootstraping TCC... |
313 | echo ^> TCC not found |
314 | if "!tcc_branch!" == "thirdparty-windows-i386" ( echo ^> Downloading TCC32 from !tcc_url! , branch !tcc_branch! ) else ( echo ^> Downloading TCC64 from !tcc_url! , branch !tcc_branch! ) |
315 | git clone --depth 1 --quiet --single-branch --branch !tcc_branch! !tcc_url! "%tcc_dir%" |
316 | git -C "%tcc_dir%" log -n3 |
317 | exit /b 0 |
318 | |
319 | :cloning_vc |
320 | echo Cloning vc... |
321 | echo ^> Cloning from remote !vc_url! |
322 | git clone --depth 1 --quiet "%vc_url%" |
323 | exit /b 0 |
324 | |
325 | :eof |
326 | popd |
327 | endlocal |
328 | exit /b 0 |