Sorry in advance because this is a little long, but I have been trying to get this to work for about a week now with no luck. I have come pretty far, but there are still a few problems preventing me from finishing this.
I use cygwin on windows purely to act as my dev environment. From cygwin, I primarily use mintty with tmux and vim. I tend to avoid using other utilities from cygwin due to them not working with a lot of native windows utilities. For example, I use a native windows build of cmake (3.18.1) and not the one that is distributed with cygwin.
I have recently begun a new project and one of the first things I want to tackle is getting through all the hard parts involved in setting up the build system. After a lot of trial and error, I can now build my project with cmake and ninja while using mingw as the compiler. This is great, but if I am going to make windows builds that I eventually intend on distributing, I think it’s important that I can do 32bit and 64bit builds with msvc, but being able to do this within my tmux mintty session seems nearly impossible.
My only solution to this has been using the Developer Command Prompt that comes with Visual Studio (2019 Community in my case). This prompt calls C:\"Program Files (x86)"\"Microsoft Visual Studio"\2019\Community\Common7\Tools\VsDevCmd.bat
on startup. From this command prompt, I can run the following and everything will build and link.
cmake -G "Ninja" ../../
ninja
If I instead run cmake -G "Ninja" ../../
from one my tmux panes, cmake doesn’t identify cl as the default compiler. It identifies the mingw compiler that I have already confirmed to work for building the project. I found out about cmake toolchain files and decided to create a simple one to specify cl as the compiler to be used. Here what msvc64.toolchain
looks like.
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR AMD64)
set(compiler "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.27.29110/bin/Hostx64/x64/cl.exe")
set(CMAKE_C_COMPILER ${compiler})
set(CMAKE_CXX_COMPILER ${compiler})
This allows cmake to select the correct compiler for building the project, but it fails when compiling the simple cmake test program due to missing library files that need to be linked to build the simple test. I have encountered this problem before when I had a serious urge to simply use cl from the mintty terminal. I ended up creating this file (it’s weird, I know). This allows me to run clc
to compile, and cll
to link from my terminal using the microsoft compiler. I decided to use a similar solution in my msvc64.toolchain
file and this is what it looks like now.
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR AMD64)
set(compiler "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.27.29110/bin/Hostx64/x64/cl.exe")
set(CMAKE_C_COMPILER ${compiler})
set(CMAKE_CXX_COMPILER ${compiler})
set(prgx86 "C:/Program Files (x86)")
set(winkit_include_root "${prgx86}/Windows Kits/10/Include/10.0.18326.0")
set(inc_a "/I\"${prgx86}/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.27.29110/include\"")
set(inc_b "/I\"${winkit_include_root}/um\"")
set(inc_c "/I\"${winkit_include_root}/ucrt\"")
set(inc_d "/I\"${winkit_include_root}/shared\"")
set(CMAKE_C_FLAGS "${inc_a} ${inc_b} ${inc_c} ${inc_d}")
set(CMAKE_CXX_FLAGS "${inc_a} ${inc_b} ${inc_c} ${inc_d}")
set(lib_a "/LIBPATH:${prgx86}/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.27.29110/lib/x64")
set(lib_b "/LIBPATH:${prgx86}/Windows Kits/10/Lib/10.0.18326/um/x64")
set(lib_c "/LIBPATH:${prgx86}/Windows Kits/10/Lib/10.0.18326/ucrt/x64")
set(CMAKE_EXE_LINKER_FLAGS "${lib_a} ${lib_b} ${lib_c}")
This definitely feels closer to something that is actually functional, but it is still not working. It’s actually a bit further away from functional. When I run cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="../msvc64.toolchain" ../../
, the simple test program actually fails to compile. When I looked inside CMakeError.log
, I found this monstrosity.
Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" failed.
Compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.27.29110/bin/Hostx64/x64/cl.exe
Build flags: /I/"C:/Program;Files;(x86)/Microsoft;Visual;Studio/2019/Community/VC/Tools/MSVC/14.27.29110/include";/I/"C:/Program;Files;(x86)/Windows;Kits/10/Include/10.0.18326.0/um";/I/"C:/Program;Files;(x86)/Windows;Kits/10/Include/10.0.18326.0/ucrt";/I/"C:/Program;Files;(x86)/Windows;Kits/10/Include/10.0.18326.0/shared"
Id flags:
The output was:
2
Microsoft (R) C/C++ Optimizing Compiler Version 19.27.29111 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
cl : Command line warning D9024 : unrecognized source file type 'Files', object file assumed
cl : Command line warning D9024 : unrecognized source file type '(x86)/Microsoft', object file assumed
cl : Command line warning D9024 : unrecognized source file type 'Visual', object file assumed
cl : Command line warning D9024 : unrecognized source file type 'Studio/2019/Community/VC/Tools/MSVC/14.27.29110/include"', object file assumed
cl : Command line warning D9024 : unrecognized source file type 'Files', object file assumed
cl : Command line warning D9024 : unrecognized source file type '(x86)/Windows', object file assumed
cl : Command line warning D9024 : unrecognized source file type 'Kits/10/Include/10.0.18326.0/um"', object file assumed
cl : Command line warning D9024 : unrecognized source file type 'Files', object file assumed
cl : Command line warning D9024 : unrecognized source file type '(x86)/Windows', object file assumed
cl : Command line warning D9024 : unrecognized source file type 'Kits/10/Include/10.0.18326.0/ucrt"', object file assumed
cl : Command line warning D9024 : unrecognized source file type 'Files', object file assumed
cl : Command line warning D9024 : unrecognized source file type '(x86)/Windows', object file assumed
cl : Command line warning D9024 : unrecognized source file type 'Kits/10/Include/10.0.18326.0/shared"', object file assumed
CMakeCXXCompilerId.cpp
Microsoft (R) Incremental Linker Version 14.27.29111.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:Files.exe
Files
(x86)/Microsoft
Visual
Studio/2019/Community/VC/Tools/MSVC/14.27.29110/include\
Files
(x86)/Windows
Kits/10/Include/10.0.18326.0/um\
Files
(x86)/Windows
Kits/10/Include/10.0.18326.0/ucrt\
Files
(x86)/Windows
Kits/10/Include/10.0.18326.0/shared\
CMakeCXXCompilerId.obj
LINK : fatal error LNK1181: cannot open input file 'Files.obj'
Detecting C compiler ABI info failed to compile with the following output:
Change Dir: C:/Users/underdisc/home/tech/varkor/build/msvc64/CMakeFiles/CMakeTmp
It seems pretty obvious that cmake is interpretting every space as a delimeter for different flags to give to the compiler when it should just be a single flag. I have tried escaping these spaces with backslashes and the results are the same. I have also tried this C:/Program\\ Files\\ (x86)...
because someone suggested it here. Is there a way to pass these flags to the compiler as intended?
This isn’t just about passing the compiler flags correctly though. I noticed that the CMakeCXXCompilerId.cpp
file doesn’t actually have a single include in it. If I get rid of set(CMAKE_CXX_FLAGS...)
and set(CMAKE_C_FLAGS...)
The compiling step then succeeds but then the link step still fails. Here is the most important part of CMakeError.log
after removing those sets.
Compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.27.29110/bin/Hostx64/x64/cl.exe
Build flags:
Id flags:
The output was:
2
Microsoft (R) C/C++ Optimizing Compiler Version 19.27.29111 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
CMakeCXXCompilerId.cpp
Microsoft (R) Incremental Linker Version 14.27.29111.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:CMakeCXXCompilerId.exe
CMakeCXXCompilerId.obj
LINK : fatal error LNK1104: cannot open file 'LIBCMT.lib'
This is odd to me because I know and verified exactly where that file is. It’s here C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.27.29110/lib/x64
and I have included that directory as a library path for link.exe
to search through. The only difference is that the name of the file is all lowercase. I know that this should work though. The bashrc file I linked earlier does work when compiling simple hello world programs, so something is going wrong when these additional arguments from CMAKE_EXE_LINKER_FLAGS
are passed to link.exe
, but I have no idea what. Does anyone see the problem here?
Furthermore, is there anything else I should be aware of as I continue attempting to get this working? I do feel like I am very close, but after hitting and jumping over so many blockades, I am not sure. The real goal here is to do the entire build process for my project from the mintty terminal I use and not the developer command prompt that ships with visual studio.
|Small Notes|
I am aware of the vcvars[32|64].bat
files. I have already attempted to use them in the past and again now, but it has never worked and I am pretty certain it is from a conflict with my cygwin setup. I don’t know specifically why though.
My next step is diving into the cmake source, but I figure somebody here already knows their way around it and could point me in the right direction if necessary.
Thanks in advance for any help and/or ideas