MSVC Linker option debug:fastlink causing program execution slowdown - visual-studio

When passing the linker switch debug:fastlink to Visual studio's linker (version 14.11.25547 - VS 2017 update 15.5) I always get a 5-7 second delay in my program execution when trying to run it inside VS debugger. I'm assuming the debug:fastlink option is the issue since when I remove it, everything works alright. Also, no change occurs if I try the option debug:full. It seems in order for VS debugger to hit my breakpoints the linker needs to be passed one of these options. Is anyone else having this issue? And is there any workout/solution for this? Just in case here is my build.bat file:
#echo off
set CompilerFlags= -DHANDMADE_SLOW_BUILD=1 -DHANDMADE_DEVELOPER_BUILD=1 -MT -Gm- -Z7 -nologo -Oi -Od -WX -W3 -GR -EHa-
set IncludePaths="w:\handmade\third party\sdl\include"
set LibraryPaths=/LIBPATH:"w:\handmade\third party\sdl\lib\x64"
set Libraries="SDL2.lib" "SDL2main.lib"
REM debug:fastlink/full options seem to slow the initial runtime of the app when trying to run in the debugger.
set LinkerFlags=-subsystem:CONSOLE -machine:x64 -incremental:no -nologo debug:fastlink -opt:ref
IF NOT EXIST build mkdir build
pushd build
REM 32-bit build
REM cl %CommonCompilerFlags% ..\handmade\code\win32_handmade.cpp /link -subsystem:windows,5.1 %CommonLinkerFlags%
REM 64-bit build
cl /c %CompilerFlags% -I %IncludePaths% w:\handmade\source\win32_handmade.cpp
link %LinkerFlags% -out:win32_handmade.exe ../build/win32_handmade.obj %Libraries% %LibraryPaths%
copy /y "w:\handmade\third party\sdl\lib\x64\SDL2.dll" "w:\handmade\build"
popd

Related

Visual Studio 2017 command line tools don't work when launched from batch file

I am experiencing a very strange behavior, old batch file works well under windows XP. Why doesn't it work when compiling a simple file like hello.c under (Vs2017 + Win10) by a batch file in cmd window?
When realizing that Win10 has new security policy,,I read some articles on Microsoft's website. They recommend using the developer command-line window for command-line compilation.
Indeed, manual operation works well. But when I logged on Win10 as a super administrator and tried to run everything via a batch file,
it didn't work, just finished the environment configuration.
When running the commands in the batch file manually, everything works as expected (executable file successfully generated).
What is wrong with that?
Here is the content of the batch file:
%comspec% /k "C:\Program Files(x86)\Microsoft Visual Studio\2017 \Community\VC\Auxiliary\Build\vcvars64.bat"
cd g:\testdir
g:
cl TestBatFileCompile.c
Preliminary Notes:
vcvars64.bat simply calls vcvarsall.bat and it passes the x64 argument to it, followed by its own (if any)
vcvarsall.bat mainly sets some env vars (set VSCMD_DEBUG=3 prior running it, for verbose output) required for the VStudio build tools to work. Check [MS.Docs]: Build C/C++ code on the command line for more details
I enhanced / simplified your example for more clarity:
script.bat:
#echo off
echo Running vcvars...
%comspec% /K "c:\Install\x86\Microsoft\Visual Studio Community\2017\VC\Auxiliary\Build\vcvarsall.bat" x64
echo Ran vcvars: %ERRORLEVEL%
echo Running cl...
cl /nologo dummy.c /link /NOLOGO
echo Ran cl: %ERRORLEVEL%
dummy.c:
int main() {
return 0;
}
Output:
e:\Work\Dev\StackOverflow\q053523085>dir /b
dummy.c
script.bat
e:\Work\Dev\StackOverflow\q053523085>script.bat
Running vcvars...
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.2
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'
e:\Work\Dev\StackOverflow\q053523085>rem HMMM, SOMETHING DOESN'T SEEM QUITE RIGHT. LET'S TRY EXITING CMD...
e:\Work\Dev\StackOverflow\q053523085>exit
Ran vcvars: 0
Running cl...
'cl' is not recognized as an internal or external command,
operable program or batch file.
Ran cl: 9009
What happened?
cmd /K ([MS.Docs]: Cmd) opened a new cmd instance, on top of the existing one (using the same window)
vcvarsall was called in this (2nd) instance, did its job and finished, and things seem to have been left in the air
But after typing exit, it turns out that cl did run, but in the 1st cmd instance (in the background, if you will), and since the variables were not previously set by vcvarsall, it failed
To make things work, invoke vcvarsall using [MS.Docs]: call:
call "c:\Install\x86\Microsoft\Visual Studio Community\2017\VC\Auxiliary\Build\vcvarsall.bat" x64
Output (in a new cmd window):
e:\Work\Dev\StackOverflow\q053523085>dir /b
dummy.c
script.bat
e:\Work\Dev\StackOverflow\q053523085>script.bat
Running vcvars...
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.2
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'
Ran vcvars: 0
Running cl...
dummy.c
Ran cl: 0
e:\Work\Dev\StackOverflow\q053523085>dir /b
dummy.c
dummy.exe
dummy.obj
script.bat

Batch file to conditionally execute ifortvars.bat

I am using a make.bat file to compile my Fortran code. To compile using the ifort command, I first need to initialize the compiler by executing ifortvarsbat intel64 command where I had to setup the path variable.
This works fine, however, the path keeps increasing in size and says command too long after 3-4 runs. Now, I open a command prompt, run the make.bat file once and then comment the ifort setup section so my successive run of the make.bat do not set the path multiple times.
I was hoping I could write an IF ELSE command to check whether ifort command executes or not and only set the path and call ifortvars if its not already set. This would save me commenting and uncommenting the make.bat file every time I open a new command prompt.
Unfortunately, I don't know much about batch script writing. Can someone help me with this.
#echo on
#echo ==============================================
#echo Setting Intel Fortran Compiler, please wait ...
#echo ==============================================
::set MY_PATH=C:\Program Files (x86)\Intel\Composer XE 2013\bin
::call "%MY_PATH%"\ifortvars.bat intel64
::call "%MY_PATH%"\ifortvars.bat ia32
#echo ==============================================
#echo Compiling program:
#echo ==============================================
:: -O3 option is used to optimize the code
ifort -O3 "Main.F90"
Instead of checking the path variable, directly check if the compiler is available
where ifort >nul 2>&1 || call "%MY_PATH%\ifortvars.bat" intel64
where command will search for the indicated program inside the path and if found it echoes to console its path. If it does not find the program it echoes an error and sets errorlevel variable.
In the code all the output from where is hidden redirecting the stdout and stderr streams to nul device (>nul 2>&1) and conditional execution is used. The || operator means "execute the following command if the previous one failed"
So, if ifort can not be found then call the configuration batch.
A faster solution could be to directly check a "flag" variable that you define the first time the environment is configured.
if not defined FCompilerSetup (
call "%MY_PATH%\ifortvars.bat" intel64
set "FCompilerSetup=1"
)
note: From my point of view, the recomendation from miltonb and i_am_jorf is the correct way to handle the problem. setlocal / endlocal will remove the problem with the path and is cleaner and easier. But the batch file to set the environment will be called each time you compile your program and the changes removed on end. If any of the changes made to the environment is needed after compilation, it will not be available.
Using setlocal will not change your path beyond the scope of the batch file, so that when it runs again it will modify the path again.
Before running: PATH=C:\Mypath;
setlocal
::set MY_PATH=C:\Program Files (x86)\Intel\Composer XE 2013\bin
....other lines....
endlocal
After running: PATH=C:\Mypath;

How do I use this command in a pre build event in Visual Studio

I will be concise.
The command FOR /F %i IN (C:\Version.txt) DO #set Version=%i works perfectly fine in cmd.exe to read the text of the file into a variable. but whenever I put that line into a prebuild event in Visual Studio it says Exited with code 255.
On http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx I found that 0xFF / 255 means: The extended attributes are inconsistent..
How do I use that command in a pre build event?
Many thanks.
The correct syntax is
FOR /F %%i IN (C:\Version.txt) DO #set Version=%%i
However this will not work as you epxect: VS spawns a cmd.exe process to execute build events, meaning that if you set a variable it is local to that cmd.exe only, hence the rest of your build will not have access to Version.
Luckily there are much better alternatives than batch files: if you're using VS2010 or higher, the project files are msbuild files, so to get all possible versioning things working you just create a common msbuild script to do whatever you need to do with the version (eg create a .res file if it's for C++, or modify the AssemblyInfo.cs for C#) and include it in all your projects.

D9024 make unrecognized source file type

If I run this cmd on cmd line using MS cl:
cl -c /W3 /Od ioapi.c
the object file, ioapi.obj is created as expected.
If however I create a makefile with this entry:
ioapi.obj: ioapi.c
cl -c /W3 /Od ioapi.c
There is a tab before cl above
and run make ioapi.obj then I get this error:
make ioapi.obj
cl -c /W3 /Od ioapi.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
cl : Command line warning D9024 : unrecognized source file type 'C:/MinGW/msys/1.0/W3', object file assumed
cl : Command line warning D9027 : source file 'C:/MinGW/msys/1.0/W3' ignored
cl : Command line warning D9024 : unrecognized source file type 'C:/MinGW/msys/1.0/Od', object file assumed
cl : Command line warning D9027 : source file 'C:/MinGW/msys/1.0/Od' ignored
ioapi.c
cl : Command line warning D9024 : unrecognized source file type 'C:/MinGW/msys/1.0/W3', object file assumed
cl is the MS VS 2008 compiler.
I have installed minGW, version is from 6 months ago.
If I run make -n ioapi.c I get this reported as expected:
cl -c /W3 /Od ioapi.c
I am running cl.exe from the Visual Studio 2008 command prompt (where the VS2008 env variables are pre-setup).
Why am I getting this strange error and how to fix it?
I did wonder if it was a problem with the MS environment. But even if I run the vcvars32.bat file to setup the MS environment before running make it makes no difference.
I noticed that if I use this:
ioapi.obj: ioapi.c
cl -c ioapi.c
Then the error goes away. But I do need to pass in compiler switches.
The problem was make's handling of the /W3 /Od switches. It seems make thinks /W3 is the start of a file due to the / symbol. So to prevent this I changed the switches to use - instead of /. eg -W3 -Od which is acceptable to the MS complier/linker.
So the change in the makefile which was required is:
ioapi.obj: ioapi.c
cl -c -W3 -Od ioapi.c

What are the Command Line options for the VB6 IDE (Compiler)

I'm doing batch compiling and need to specify the output directory.
/run
/runexit - Compile and then run it. Exit VB IDE when project returns to design mode.
/make or /m projectname - compiles an makes exe using the existing settings in proj file
/out filename
/outdir path Specifies a directory path to place all output files in when using /make
/d
/cmd
/mdi or /sdi
... and a couple of others.
Run vb6.exe /? for more information.
A bit of Google work suggests that such a list of options can be obtained by going to the directory containing vb6.exe in Command Prompt and running
vb6.exe /?
VB6
Information directly from running VB6.exe /?:
Command Line Options
VB6[.EXE] [[{/run | /r}] | [/runexit] | [{/make | /m}] projectname] [/out filename]
[/outdir path] [/d const=value{[:constN=valueN]}]
[/mdi | /sdi] [{/cmd argument | /c argument}]
/run or /r projectname Tells Visual Basic to compile projectname
and run it, using the arguments stored in the Command Line Arguments
field of the Make tab of the Project Properties dialog box.
/runexit projectname Tells Visual Basic to compile projectname and
run it. Visual Basic will exit when the project returns to design
mode.
/make or /m projectname Tells Visual Basic to compile projectname
and make an executable file from it, using the existing settings
stored in the project file.
/out filename Specifies a file to receive errors when you build
using /m or /runexit. If you do not use /out, command line build
errors are displayed in a message box.
/outdir path Specifies a directory path to place all output files in
when using /make.
/d or /D const=value... Tells Visual Basic which values to use for
conditional compilation constants when making an .EXE or ActiveX
component with the /make switch. Separate multiple constants with
colons.
/cmd or /c argument Puts argument in the Command Line Arguments
field in the Make tab of the Project Properties dialog box. When used,
this must be the last switch on the command line.
/mdi or /sdi Changes the Visual Basic environment to either Single
Document Interface (SDI) or Multiple Document Interface (MDI) mode.
Visual Basic remains in this mode until you change it.
You may use a group name in place of projectname in any of the above
switches.
Sourced from here is some additional information which pertains to older versions of VB as well. That external page may eventually disappear.
VB Command Line Summary
All Versions
vb*[.exe] [[{/run | /r} projectname] {/make | /m } projectname]
{/cmd argument | /c argument}]
projectname The name of your project (.vbp) file.
/run or /r Tells Visual Basic to compile and run projectname using
the arguments stored in the Command Line Arguments field of the Make
tab of the Project Properties dialog box. You can run more than one
project using this command. Replace projectname with
projectgroupname.
/make or /m Tells Visual Basic to compile projectname and make
an executable (.exe) file, using the existing settings of the Path,
EXEName, and Title properties of the APP object. You can compile and
make an executable (.exe) file from more than one project using this
command. Replace of the projectname with projectgroupname.
/cmd or /c Puts argument in the Command Line Arguments field in
the Make tab of the Project Properties dialog box. When used, this
must be the last switch on the command line.
Versions 4 + Only
vb*[.exe] {/d compileconst} [{/makedll | /l} projectname]
/makedll or /l Tells Visual Basic to compile projectname and make
an in-process ActiveX server (.dll) file from it.
/d or /D Tells Visual Basic which values to use for conditional
compilation constants when making an .EXE with the /make switch or an
ActiveX DLL with the /makedll switch.
compileconst The names and values of conditional compilation
constants used in the project file.
Version 5+ Only
vb*[.exe] [{/runexit} projectname][{/m} or {/runexit} projectname /out filename}][{/m}][/sdi] or [/mdi]
/runexit Tells Visual Basic to run projectname. If for any reason
the file is changed in the process of running, all changes are ignored
and no dialog appears on exit to design mode.
filename The name of the file to receive errors when you build an
executable using the /m or /runexit option.
/out Allows you to specify a file to receive errors when you build
using the /m or /runexit option. The first error encountered is
placed in this file with other status information. If you do not use
the /out option, command line build errors are displayed in a message
box. This option is useful if you are building multiple projects.
/? Lists the available Command Line arguments.
/sdi Changes the Visual Basic environment to SDI (Single Document
Interface) mode. Visual Basic remains in SDI mode until you change it.
You can change to MDI mode by using the /mdi argument or by clearing
the SDI Development Environment option in the Advanced tab of the
Options dialog box.
/mdi Opens Visual Basic in MDI (Multiple Document Interface) mode.
Visual Basic remains in MDI mode until you change it. You can change
to SDI mode by using the /sdi argument or by selecting the SDI
Development Environment option in the Advanced tab of the Options
dialog box. MDI mode is the default.
/make /outdir path
Here is the output of vb6.exe /?

Resources