This question already has answers here:
Correctly set Visual Studio linker flag /SUBSYSTEM in CMAKE
(2 answers)
Closed 29 days ago.
I want to set /SUBSYSTEM:WINDOWS option to a executable,but there is a default option /subsystem:console in there,I try to override it, but it didn't work.
Here is the log
cmd.exe /C "cd .&& F:\environment_application\CLion-2021.3.4.win\bin\cmake\win\bin\cmake.exe -E vs_link_exe --intdir=chapter5\CMakeFiles\meminfo.dir --rc="F:\Windows Kits\10\bin\10.0.22000.0\x64\rc.exe" --mt="F:\Windows Kits\10\bin\10.0.22000.0\x64\mt.exe" --manifests -- F:\environment_application\visual_studio\2022\Community\VC\Tools\MSVC\14.34.31933\bin\Hostx64\x64\link.exe /nologo chapter5\CMakeFiles\meminfo.dir\memInfo.cpp.obj /out:chapter5\meminfo.exe /implib:chapter5\meminfo.lib /pdb:chapter5\meminfo.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console /subsystem:WINDOWS kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
LINK Pass 1: command "F:\environment_application\visual_studio\2022\Community\VC\Tools\MSVC\14.34.31933\bin\Hostx64\x64\link.exe /nologo chapter5\CMakeFiles\meminfo.dir\memInfo.cpp.obj /out:chapter5\meminfo.exe /implib:chapter5\meminfo.lib /pdb:chapter5\meminfo.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console /subsystem:WINDOWS /SUBSYSTEM:WINDOWS kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:chapter5\CMakeFiles\meminfo.dir/intermediate.manifest chapter5\CMakeFiles\meminfo.dir/manifest.res" failed (exit code 1120) with the following output:
libcmtd.lib(exe_winmain.obj): error LNK2019: unresolved external symbol WinMain referenced in function "int __cdecl invoke_main(void)" (?invoke_main##YAHXZ)
notice the link options is
/version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console /subsystem:WINDOWS
The cmake code i used is here:
add_executable(meminfo memInfo.cpp memInfo.h)
target_compile_options(meminfo PUBLIC /MTd)
target_link_options(meminfo PUBLIC /SUBSYSTEM:WINDOWS)
set_target_properties(meminfo PROPERTIES
LINK_FLAGS
/subsystem:WINDOWS
)
Set the WIN32_EXECUTABLE to True.
set_target_properties(meminfo PROPERTIES WIN32_EXECUTABLE True)
You could also use the add_executable command to do this:
add_executable(meminfo WIN32 memInfo.cpp memInfo.h)
Related
I have a CMake file which I'm using to build some CUDA on Windows (NVCC/MSVC). I'm trying to set the MSVC warning level to /W4, using:
add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:--compiler-options=/W4>")
Building with CMake 3.9, I get this warning:
(CudaBuildCore target) ->
cl : Command line warning D9025: overriding '/W4' with '/W3'
In CMake 3.15, the policy was changed to not automatically set /W3 in the CUDA flags, but with that version I get:
(CudaBuildCore target) ->
cl : Command line warning D9025: overriding '/W4' with '/W1'
If I do the build step with --verbose I see the following with 3.9:
"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin\nvcc.exe" -gencode=arch=compute_30,code=\"compute_30,compute_30\" --use-local-env -ccbin "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64" -x cu -IC:\Users\eddi\Documents\temp\thur\sw\include -IC:\Users\eddi\Documents\temp\thur\sw\shared\common\include -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\include" --keep-dir x64\Debug -maxrregcount=0 --machine 64 --compile -cudart static --compiler-options=/W4 --compiler-options= -Xcompiler="/EHsc -Zi -Ob0" -g -D_WINDOWS -D"FISH_BUILD_TYPE=\"DEBUG\"" -D"CMAKE_INTDIR=\"Debug\"" -D"CMAKE_INTDIR=\"Debug\"" -D_MBCS -Xcompiler "/EHsc /W3 /nologo /Od /Fdfish.dir\Debug\fish.pdb /FS /Zi /RTC1 /MDd /GR" -o fish.dir\Debug\fish_cuda.obj "C:\Users\eddi\Documents\temp\thur\sw\fish_cuda.cpp"
and with 3.15:
"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin\nvcc.exe" -gencode=arch=compute_30,code=\"compute_30,compute_30\" --use-local-env -ccbin "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64" -x cu -IC:\Users\eddi\Documents\temp\thur\sw\include -IC:\Users\eddi\Documents\temp\thur\sw\shared\common\include -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\include" --keep-dir x64\Debug -maxrregcount=0 --machine 64 --compile -cudart static --compiler-options=/W4 --compiler-options= -Xcompiler="/EHsc -Zi -Ob0" -g -D_WINDOWS -D"FISH_BUILD_TYPE=\"DEBUG\"" -D"CMAKE_INTDIR=\"Debug\"" -D"CMAKE_INTDIR=\"Debug\"" -D_MBCS -Xcompiler "/EHsc /W1 /nologo /Od /Fdfish.dir\Debug\fish.pdb /FS /Zi /RTC1 /MDd /GR" -o fish.dir\Debug\fish_cuda.obj "C:\Users\eddi\Documents\temp\thur\sw\fish_cuda.cpp"
Spoiler: these are identical, except for the -Xcompiler "/EHsc /W3 /nologo /Od /Fdfish.dir\Debug\fish.pdb /FS /Zi /RTC1 /MDd /GR" portion.
Try as I might, I cannot find where this set of flags is being introduced (by CMake et al.), and hence can't start working out how to change the behaviour.
EDIT1: Adding color to the story...
I grep'd my CMake install for /nologo and found several .cmake files with lines like:
35: set(CMAKE_CL_NOLOGO "/nologo")
I changed them all to variations of
35: set(CMAKE_CL_NOLOGO "/nologo_EDD")
But none of them turn up in the confusing set of options. So either I've missed something or they're being introduced from something outside CMake?
EDIT2:
#squareskittles said:
you can remove the default flag from the CMAKE_CXX_FLAGS_INIT variable
Fair enough, I can see the logic to that: it's simple and it directly addresses my immediate issue. But it seems a bit blunt and doesn't address where the flags are coming from in the first place.
Anyway, objections aside, I added this ugly morsel to my script:
message( "--------------------------- ${CMAKE_CXX_FLAGS_INIT}")
string (REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT}")
message( "--------------------------- ${CMAKE_CXX_FLAGS_INIT}")
With CMake 3.9, I see:
--------------------------- /DWIN32 /D_WINDOWS /W3 /GR /EHsc
--------------------------- /DWIN32 /D_WINDOWS /GR /EHsc
as hoped. But with 3.15, I see:
--------------------------- /DWIN32 /D_WINDOWS /GR /EHsc
--------------------------- /DWIN32 /D_WINDOWS /GR /EHsc
ie, the /W3 flag isn't there in the first place (let alone a /W1 flag) due to the policy change. But even worse, the primary issue still persists in both cases:
nvcc.exe ... --compiler-options=/W4 -Xcompiler="/EHsc -Zi -Ob0" ... -Xcompiler "/EHsc /W3 /nologo /Od /Fdfish.dir\Debug\fish.pdb /FS /Zi /RTC1 /MDd /GR" ...
EDIT3: Some progress!
With this simple change:
#add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:--compiler-options=/W4>")
add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/W4>")
there are no more complaints! The confusing flags persist, but now read:
-Xcompiler "/EHsc /W4 /nologo /Od /Ffish.dir\Debug\fish.pdb
/FS /Zi /RTC1 /MDd /GR"
ie. CMake has spotted the /W4 and overridden its default.
But despite scouring the CMake source, I've still yet to determine where all this is done.
EDIT4: MSVC has a hand in all this.
The 'mystery' options are generated somewhat automatically by MSVC from the .vcxproj file. If I use the -Xcompile=/W4 approach, the project XML contains:
<CudaCompile>
...
<AdditionalOptions>%(AdditionalOptions) -Xcompiler="/EHsc -Zi -Ob1"</AdditionalOptions>
...
<Warning>W4</Warning>
</CudaCompile>
But with the original, --compiler-options=/W4 I get:
<CudaCompile>
<AdditionalOptions>%(AdditionalOptions) --compiler-options=/W4 -Xcompiler="/EHsc -Zi -Ob1"</AdditionalOptions>
...
</CudaCompile>
And this all sort of makes sense; with no Warning level specified, MSVC must default to W1, hence the complaint.
Also, there was a clue-with-hindsight: the build step had:
-Xcompiler="/EHsc -Zi -Ob0"
-Xcompiler "/EHsc /W1 /nologo /Od ..."
Note one has an equals and one does not implying they come from different places.
I think my investigation has gone far enough for now.
A TL;DR summary of my own shaggy-dog-tale of a question:
I had:
add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:--compiler-options=/W4>")
but found:
add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/W4>")
to be more appropriate.
Basically, the CMake/NVCC/MSVC pipeline understood that the -Xcompiler option overrode the default, but didn't realise that --compiler-options was an equivalent statement, resulting in a command line with ambiguous directives.
I had a similar issue (but with another flag) and used CMake's regular expressions to fix that. The code is like this.
foreach(flag_var
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
STRING (REGEX REPLACE "/W3" "/W4" ${flag_var} "${${flag_var}}")
endforeach(flag_var)
I'm trying to build a python c extension on windows with msvc (using distutils) which links in some other static libraries.
Basically I have test1.lib, test2.lib and test3.obj and want to build test4.dll which has test1.lib, test2.lib and test3.obj linked in.
I've inspected the generated dll with depends.exe and it is expecting a test1.dll and test2.dll.
Any ideas on how to tell msvc to properly link the files?
Here is the actual build command:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO /LIBPATH:C:\app\backend\opc_ua\ua_sd
k\lib /LIBPATH:C:\app\backend\opc_ua\ua_sdk\third-party\win64\vs2015\libxml2\out32dll /LIBPATH:C:\app\backend\opc_ua\ua_sdk\third-party\win64\vs2015\openssl\out32dll /LIBPATH:C:\Pyth
on-3.7.2-amd64\libs /LIBPATH:C:\Python-3.7.2-amd64\PCbuild\amd64 "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\LIB\amd64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\
lib\10.0.10240.0\ucrt\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\8.1\lib\winv6.3\um\x64" ws2_32.lib advapi32.lib uamodule.lib coremodule.lib uapkicpp.lib uabasecpp.lib xmlparsercpp.l
ib uastack.lib libxml2.lib libssl.lib libcrypto.lib mpr.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib /EXPORT:PyInit_opcua
build\temp.win-amd64-3.7\Release\uniauto_cpp\opcuamodule.obj build\temp.win-amd64-3.7\Release\uniauto_cpp\NodeManager.obj build\temp.win-amd64-3.7\Release\uniauto_cpp\opcserver.obj
build\temp.win-amd64-3.7\Release\uniauto_cpp\uamodeler_output\instancefactory_.obj build\temp.win-amd64-3.7\Release\uniauto_cpp\uamodeler_output\nodemanager.obj build\
temp.win-amd64-3.7\Release\uniauto_cpp\uamodeler_output\nodemanagerbase.obj /OUT:build\lib.win-amd64-3.7\opcua.cp37-win_amd64.pyd /IMPLIB:build\temp.win-amd64-3.7\Release\uni
auto_cpp\opcua.cp37-win_amd64.lib
And depends.exe says the output file depends on uastack.dll, libxml2.dll, libcrypto.dll when they are clearly listed in their .lib format.
I am compiling a class library in MSVS2008 that depends on a couple of reference libraries. If I look at the library's PropertiesPage.Linker.CommandLine, it correctly reflects the libraries I need:
/OUT:"C:\svn\Project\trunk\Service\Make\Debug\ABC_Access.dll" /INCREMENTAL /NOLOGO /DLL /MANIFEST /MANIFESTFILE:"Debug\ABC_Access.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /ASSEMBLYDEBUG /PDB:"C:\svn\Project\trunk\Service\Make\Debug\ABC_Access.pdb" /DYNAMICBASE /FIXED:No /NXCOMPAT /MACHINE:X86 /ERRORREPORT:PROMPT C:\svn\Project\trunk\Service\lib\Debug\MainLine_ABC.lib C:\svn\MainLine\Peripherals\nabc\lib\i86Win32VS2008\nabc1d.lib C:\svn\MainLine\Peripherals\nabc\lib\i86Win32VS2008\nabc2d.lib C:\svn\MainLine\Peripherals\nabc\lib\i86Win32VS2008\nabc3d.lib
However, the BuildLog shows the following and tells me one of the namespaces can't be found. Why are my library references (specifically, nabc1d.lib, nabc2d.lib, and nabc3d.lib) not fed to the compiler and linker?
Creating temporary file "c:\svn\Project\trunk\Service\Make\ABC_Access\ABC_Access\Debug\RSP00000858761372.rsp" with contents
[
/Od /I "C:\svn\Mainline\Peripherals\nabc\include" /I "C:\svn\Mainline\Peripherals\nabc" /I "C:\svn\Mainline\Mainline_ABC\trunk\ABC" /D "WIN32" /D "_DEBUG" /D "RTI_WIN32" /D "_UNICODE" /D "UNICODE" /D "_WINDLL" /FD /EHa /MDd /Fo"Debug\\" /Fd"Debug\vc90.pdb" /W3 /c /Zi /clr /TP /FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll" /FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll" /FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.XML.dll"
..\..\..\Service\Service\DataAccess\ABC\BasicTypes.cpp
..\..\..\Service\Service\DataAccess\ABC\BasicTypesSupport.cpp
..\..\..\Service\Service\DataAccess\ABC\BasicTypesPlugin.cpp
..\..\..\Service\Service\DataAccess\ABC\ServiceSupport.cpp
..\..\..\Service\Service\DataAccess\ABC\ServicePlugin.cpp
..\..\..\Service\Service\DataAccess\ABC\Service.cpp
]
Creating command line "cl.exe #c:\svn\Project\trunk\Service\Make\ABC_Access\ABC_Access\Debug\RSP00000858761372.rsp /nologo /errorReport:prompt"
Nevermind, I see that I'm comparing my linker inputs to the log's reflection of compiler commands here...
The following code comes from an answer to question 398069. It works very well for me under Linux and also under Windows in optim mode. Unfortunately, my app crashes under Windows and I have to debug it...
template <class T>
T *set_the_global(T *candidate)
{
std::map<std::string,void*>::iterator r = MainFactoriesMap::mainFactoriesMap().find(std::string(typeid(*candidate).name()));
...
}
In debug mode (Windows, with qtcreator, cmake 2.8.2, Visual C++ 10, Qt and boost are available as debug and not debug), the call to typeid, which occurs before entering main, crashes, throwing an exception it seems. I forced the use of /GR option. It makes no difference...
I put below the calls to compiler and linker in debug and output modes. Note that I tried to compile everything under Visual Studio but it fails (but this will be another question).
Optim build: it works
c:\PROGRA~2\MICROS~2.0\VC\bin\amd64\cl.exe /Zc:wchar_t- /EHsc /GR /MD /O2 /Ob2 /D NDEBUG -IE:\Projets\Amose\Sources\lima_common\src -IC:\Qt\v4.8.2\include -IC:\Qt\v4.8.2\include\QtXml -IC:\Qt\v4.8.2\include\QtCore -IC:\PROGRA~1\boost\BOOST_~1\include -Ic:\amose\include -D DEBUG_CD -D WIN32 -D QT_NO_KEYWORDS -Dlima_common_factory_EXPORTS -DQT_DLL -DQT_XML_LIB -DQT_CORE_LIB -DBOOST_ALL_DYN_LINK -DLIMA_FACTORY_EXPORTING -DQT_NO_DEBUG /TP /FoCMakeFiles\lima-common-factory.dir\AmosePluginsManager.cpp.obj /FdC:\amose-vcbuild\lima-common\src\common\AbstractFactoryPattern\lima-common-factory.pdb -c E:\Projets\Amose\Sources\lima_common\src\common\AbstractFactoryPattern\AmosePluginsManager.cpp
...
"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -E vs_link_dll c:\PROGRA~2\MICROS~2.0\VC\bin\amd64\link.exe #CMakeFiles\lima-common-factory.dir\objects1.rsp /out:lima-common-factory.dll /implib:lima-common-factory.lib /pdb:C:\amose-vcbuild\lima-common\src\common\AbstractFactoryPattern\lima-common-factory.pdb /dll /version:0.0 /STACK:10000000 /machine:x64 /INCREMENTAL:NO -LIBPATH:C:\PROGRA~1\boost\BOOST_~1\lib -LIBPATH:c:\amose\lib ..\QsLog\lima-common-qslog.lib ..\misc\lima-common-misc.lib ..\Data\lima-common-data.lib ..\QsLog\lima-common-qslog.lib C:\Qt\v4.8.2\lib\QtXml4.lib C:\Qt\v4.8.2\lib\QtCore4.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib
Debug build: it fails
c:\PROGRA~2\MICROS~2.0\VC\bin\amd64\cl.exe /Zc:wchar_t- /EHsc /GR /D_DEBUG /MDd /Zi /Ob0 /Od /RTC1 -IE:\Projets\Amose\Sources\lima_common\src -IC:\Qt\v4.8.2\include -IC:\Qt\v4.8.2\include\QtXml -IC:\Qt\v4.8.2\include\QtCore -IC:\PROGRA~1\boost\BOOST_~1\include -Ic:\amose-debug\include -D DEBUG_CD -D WIN32 -D QT_NO_KEYWORDS -Dlima_common_factory_EXPORTS -DQT_DLL -DQT_XML_LIB -DQT_CORE_LIB -DBOOST_ALL_DYN_LINK -DLIMA_FACTORY_EXPORTING -DQT_DEBUG /TP /FoCMakeFiles\lima-common-factory.dir\AmosePluginsManager.cpp.obj /FdC:\amose-vcbuild\lima-common-debug\src\common\AbstractFactoryPattern\lima-common-factoryd.pdb -c E:\Projets\Amose\Sources\lima_common\src\common\AbstractFactoryPattern\AmosePluginsManager.cpp
...
"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -E vs_link_dll c:\PROGRA~2\MICROS~2.0\VC\bin\amd64\link.exe #CMakeFiles\lima-common-factory.dir\objects1.rsp /out:lima-common-factoryd.dll /implib:lima-common-factoryd.lib /pdb:C:\amose-vcbuild\lima-common-debug\src\common\AbstractFactoryPattern\lima-common-factoryd.pdb /dll /version:0.0 /STACK:10000000 /machine:x64 /debug /INCREMENTAL -LIBPATH:C:\PROGRA~1\boost\BOOST_~1\lib -LIBPATH:c:\amose-debug\lib ..\QsLog\lima-common-qslogd.lib ..\misc\lima-common-miscd.lib ..\Data\lima-common-datad.lib ..\QsLog\lima-common-qslogd.lib C:\Qt\v4.8.2\lib\QtXmld4.lib C:\Qt\v4.8.2\lib\QtCored4.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib
Showing the debuging session using qtcreator:
When I compile my Visual c++ 2008 express program from inside the IDE and redistribute it on another computer, It starts up fine without any dll dependencies that I haven't accounted for. When I compile the same program from the visual c++ 2008 command line under the start menu and redistribute it to the other computer, it looks for msvcr90.dll at start-up.
Here is how it is compiled from the command line
cl /Fomain.obj /c main.cpp /nologo -O2 -DNDEBUG /MD /ID:(list of include directories)
link /nologo /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup /OUT:Build\myprogram.ex
e /LIBPATH:D:\libs (list of libraries)
and here is how the IDE builds it based on the relevant parts of the build log.
/O2 /Oi /GL /I clude" /I (list of includes) /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FD /EHsc /MD /Gy /Yu"stdafx.h" /Fp"Release\myprogram" /Fo"Release\\" /Fd"Release\vc90.pdb" /W3 /c /Zi /TP /wd4250 /vd2
Creating command line "cl.exe #d:\myprogram\Release\RSP00000118003188.rsp /nologo /errorReport:prompt"
/OUT:"D:\myprgram\Release\myprgram.exe" /INCREMENTAL:NO /LIBPATH:"d:\gtkmm\lib" /MANIFEST /MANIFESTFILE:"Release\myprogam.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"d:\myprogram\Release\myprogram.pdb" /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /LTCG /ENTRY:"mainCRTStartup" /DYNAMICBASE /NXCOMPAT /MACHINE:X86 (list of libraries)
Creating command line "link.exe #d:\myprogram\Release\RSP00000218003188.rsp /NOLOGO /ERRORREPORT:PROMPT"
/outputresource:"..\Release\myprogram.exe;#1" /manifest
.\Release\myprogram.exe.intermediate.manifest
Creating command line "mt.exe #d:\myprogram\Release\RSP00000318003188.rsp /nologo"
I would like to be able to compile it from the command line and not have it look for such a late version of the runtime dll, like the version compiled from the IDE seems not to do. Both versions pass /MD to the compiler, so i am not sure what to do.
I know it is not exactly what you are looking for but you can invoke the ide build form the command line and it should give you the same output:
devenv solution.sln /build Release
This will build the Release configuration for solution.sln. (devenv /? on the command line for more info).