CMake & MinGW Compilation on Windows, without needing the -G "MinGW Makefiles" flag - c++

I want to build my C++ applications from the Windows PowerShell command line using CMake and MinGW.
When I do this in the "normal way," with these commands:
mkdir build
cd build
cmake ..
make
CMake chooses Visual Studio as the default compiler, and doesn't generate any Makefiles for me.
I want CMake to use MinGW as the default compiler, and generate Makefiles.
It works exactly the way that I want it to when I run these commands, adding the -G "MinGW Makefiles" flag:
mkdir build
cd build
cmake .. -G "MinGW Makefiles"
make
How can I make CMake behave this way all the time, without adding the -G "MinGW Makefiles" flag?
I've tried setting up a CMAKE_GENERATOR environment variable in Windows, and pointing it to "path\to\mingw\bin", "path\to\mingw\bin\mingw32-make.exe", as well as a string that reads "MinGW Makefile".
None of these worked for me after running refreshenv and then trying to run cmake .. again.
Does anybody know if this is the correct environment variable to use in order to specify CMake's default behavior? If it is, what value should I be using?

How can I make CMake behave this way all the time, without adding the -G "MinGW Makefiles" flag?
You can't, not in any version of CMake released to date. CMake chooses a generator before it starts evaluating any CMakeLists.txt files. By default, it chooses a generator based on runtime platform and available toolsets, and command-line options are the only way presently available to influence or override CMake's choice of generator.
In comments, #Tsyvarev pointed out an open CMake issue report asking for the very same feature you are asking for. The associated comment thread provides more detail, and the last comment was earlier this year. I would guess that eventually CMake will add support for specifying a generator via environment variable, but for now, your -G option is the only available alternative. You could consider scripting it if you want to save keystrokes and reduce the risk of typos.

I know this is late. but in case someone came here and find this answer useful
all you have to do is to create a function something like this:
function gcmake {cmake .. -G "MinGW Makefiles"}
then you can simply type
mkdir build
cd build
gcmake ..
make
tip: you can add this function to your profile so that it will be saved to any new session. you can follow this nice guide

cmake uses Visual Studio generator for MinGW on Windows by default (even without Visual Studio!), this is the real annoying issue (Cygwin is not affected).
We need to work around MinGW only. What will be the most reliable hook for MinGW? I think MSYSTEM is very popular environment variable that will always be defined for MinGW.
You can place PreLoad.cmake in the project root with the following content:
if (NOT "$ENV{MSYSTEM}" STREQUAL "" AND "$ENV{VisualStudioVersion}" STREQUAL "")
find_program (CMAKE_NINJA_BINARY NAMES "ninja")
if (CMAKE_NINJA_BINARY)
set (
CMAKE_GENERATOR "Ninja"
CACHE INTERNAL "Cmake generator"
)
return ()
endif ()
find_program (CMAKE_MAKE_BINARY NAMES "gmake" "make")
if (CMAKE_MAKE_BINARY)
set (
CMAKE_GENERATOR "Unix Makefiles"
CACHE INTERNAL "Cmake generator"
)
return ()
endif ()
endif ()
Unfortunately this solution is not universal:
MSYSTEM=MINGW64 cmake -G "Unix Makefiles" ..
CMake Error: Error: generator : Unix Makefiles
Does not match the generator used previously: Ninja
Either remove the CMakeCache.txt file and CMakeFiles directory or choose a different binary directory.
If you are setting CMAKE_GENERATOR inside PreLoad.cmake than you are loosing ability to use -G cmake option. If you don't need this option, than this solution will be just fine.
PS It is not possible to access -G option value inside PreLoad.cmake as CMAKE_GENERATOR or another option. So it is not possible to add guard case like NOT DEFINED CMAKE_GENERATOR to check whether generator has been provided explicitly using -G option.

Related

How to install a cpp library using cmake on Windows x64?

I'm using CLion with MinGW-GCC on the Windows-x64 platform - This is the background of the problem.
I was trying to install gtest before. But a lot of confusion arose in the middle.
First time I ran those commands(in googletest-release-1.12.1\) according to the instructions of googletest-release-1.12.1\googletest\README.md:
mkdir build
cd build
cmake ..
But I got error messages like:
CMake Error at CMakeLists.txt:51 (project):
Failed to run MSBuild command:
C:/Windows/Microsoft.NET/Framework/v4.0.30319/MSBuild.exe
to get the value of VCTargetsPath:
Then I changed my last command to
cmake -G "MinGW Makefiles" ..
because I use make provided by MinGW. I don't know whether it's right but, it ran properly.
then I called
make
make install
make ran smoothly. But when I ran make install, I got these messages:
Install the project...
-- Install configuration: ""
-- Installing: C:/Program Files (x86)/googletest-distribution/include
CMake Error at googlemock/cmake_install.cmake:41 (file):
file INSTALL cannot make directory "C:/Program Files
(x86)/googletest-distribution/include": No such file or directory.
Call Stack (most recent call first):
cmake_install.cmake:42 (include)
make: *** [Makefile:109: install] Error 1
I have no idea at all this time. So I changed my way. According to this answer, I copied the whole library into my project and edited CMakeLists.txt like this:
cmake_minimum_required(VERSION 3.23)
project(gtest_study)
set(CMAKE_CXX_STANDARD 20)
add_subdirectory(googletest-release-1.12.1)
include_directories(googletest-release-1.12.1/googletest/include)
include_directories(googletest-release-1.12.1/googlemock/include)
add_executable(gtest_study main.cpp)
target_link_libraries(gtest_study gtest gtest_main)
target_link_libraries(gtest_study gmock gmock_main)
So my questions are:
Is there any difference between the two which build it using make and cmake metioned firstly, and just use commands like include_directories and target_link_libraries in CMakeLists.txt? (maybe like .h and .dll file? Or just completely the same? I don't know)
When I use make install to install a library on Windows, what should I do in particular? Specify some directory (I don't know which one) or what?
Although in my system environment I use MinGW-makefile, in CLion which the libraries are eventually used, I use ninja as the generator for CMake (it just comes with CLion, not installed for the system). Do I have to specify it and how? (-G "Ninja"doesn't work in my native env)
The difference between
cmake ..
and
cmake -G "MinGW Makefiles" ..
Is the choice of generator: The former uses the default generator, the latter uses the generator you specified. (cmake --help should put a * next to the default generator.)
Based on the error message I assume this is a visual studio generator and you may not be able to run that one properly from within a MinGW terminal.
In the latter case the default install directory seems to be based on the target OS (Windows) but does not seem to incorporate the fact that you're running from a MinGW terminal where the default install path (C:/Program Files (x86)/googletest-distribution) is not valid.
You could try to fix this by providing it during cmake configuration (passing -D 'CMAKE_INSTALL_PREFIX=/c/Program Files (x86)/googletest-distribution' before the source dir) or by providing the install directory during the installation.
The following process should allow you to install the lib. I'm using my preferred way of building here, i.e. not using build system dependent commands, but using cmake to run the build/install commands. I assume the working directory to be the root directory of the gtest sources:
cmake -G "MinGW Makefiles" -S . -B build
cmake --build build
cmake --install build --prefix '/c/Program Files (x86)/googletest-distribution'
The last command needs to be run with admin privileges, the first 2 I don't recommend running as admin. You could instead install to a directory where you do have the permissions to create directories even without admin privileges.
The difference between using the process described above and using add_subdirectory is that the former results in a installation on the system which can be used via find_package and the google test libs won't be rebuilt for every project where you do this.
...
project(gtest_study)
...
# you may need to pass the install location via -D CMAKE_PREFIX_PATH=<install_location> during configuration for this to work
find_package(GTest REQUIRED)
target_link_libraries(gtest_study PRIVATE GTest::gtest_main GTest::gmock)
The latter builds the google test project as part of your own project build and for every project where you use this approach a seperate version of the google test libs is built. Note: there should be no need to specify the include dirs yourself, since this kind of information is attached to the cmake target and gets applied to the linking target automatically:
#include_directories(googletest-release-1.12.1/googletest/include)
#include_directories(googletest-release-1.12.1/googlemock/include)
add_executable(gtest_study main.cpp)
target_link_libraries(gtest_study PRIVATE gtest_main gmock)
As for 3.: The CMake generator used for building GTest should be independent of the generator of the project using it. The thing that's important is that the compilers used by the build systems are compatible. I cannot go into detail about this, since I've never used CLion and therefore have too little knowlege about the compilers used by it. (Personally I'm working with Visual Studio on Windows.)

Setting Default Compiler in Visual Studio CMake

I am using Visual Studio Community 2019.
I always need to change the CMakeSettings.json for every new CMake Project I make.
SET( CMAKE_CXX_COMPILER "C:/MinGW/bin/g++" )
How can i set MinGW as my default compiler so that i do not have to worry about setting compiler every time I create a new CMake Project.
There are solution given on this link:
Setting default compiler in CMake
but I am unable to follow any of them because they are not very clear for me.
Like the accepted solution says:
Set CMAKE_GENERATOR environment variable to specify the default generator to be used on your system.
But I don't know how to set CMAKE_GENERATOR environment variable to specify the default generator to be used on my system.
I can do for my current project but i am unable to set the compiler at "C:/MinGW/bin/g++" as default for every new CMake Project.
I know people have given working solutions but even after hours, due to very general instructions, i am unable to follow. Please provide step by step instructions with where to look for the file which i need to change.
Perhaps, the easiest way to do this globally for all your new CMake projects is to set the CMAKE_GENERATOR environment variable on your system (available with CMake 3.15 or greater). Since it appears you are using Windows, here is how to set it on Windows 10:
Open the Windows Start Search (by pressing the Windows Key), type
"env", and choose "Edit the system environment variables".
Click "Environment Variables...".
Under "System variables", click the "New..." button to add a new environment variable.
For "Variable name:", use CMAKE_GENERATOR, and for "Variable value:" use "MinGW
Makefiles".
Click "OK", then "OK" again to save the new environment variable.
Now, CMake will use this environment variable to set MinGW Makesfiles as the default generator when new projects are invoked. You should also make sure the path to MinGW (C:/MinGW/bin/g++) is included in your Path environment variable.
If you are using an earlier version of CMake (< 3.15), you have to specify the generator manually when invoking CMake:
cmake -DCMAKE_GENERATOR="MinGW Makefiles" ..
or
cmake -G "MinGW Makefiles" ..
But I don't know how to set CMAKE_GENERATOR environment variable to specify the default generator to be used on my system.
That variable is taken from the environment, but can also be sent as a parameter to CMake commands:
cmake .. -DCMAKE_GENERATOR="Mingw Makefiles"
In the command line you can also set the desired compiler:
cmake .. -DCMAKE_GENERATOR="Mingw Makefiles" -DCMAKE_CXX_COMPILER="C:/MinGW/bin/g++"

Unable to generate makefile from CMake

I'm interested in CMake, so decided to learn about it. I followed the CMake Tutorial until the point where it states "That is all there is to it. At this point you should be able to build the tutorial", so I thought, let's try it!
Alas, it seems it wasn't all so simple. I initially attempted to run cmake -A "Unix Makefiles" after consulting cmake --help, but no luck there either. Rather, it gives me the following:
CMake Error at CMakeLists.txt:2 (project):
Generator
Unix Makefiles
does not support platform specification, but platform
Unix Makefiles
was specified.
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
I began searching around on the Internet and found this, but it gave me the exact same error. Other answers I found seemed to be Windows-related, but myself I'm on Fedora 29.
I want to generate a makefile using CMake, any suggestions? (I have gcc and g++ installed, by the way)
On Fedora, generating Unix Makefiles (e.g. Makefile, which GNU Make will be able to use) is probably the default. In general, don't specify a generator: then you'll get what makes the most sense on your installed OS. Some OS do pick a different default: FreeBSD uses Ninja, for instance.
When running CMake you may need to specify the source-directory. If CMake has been run before, successfully, you can leave off the directory. When there are no other options or arguments to CMake, you'll need to give the directory.
If you've copy-pasted the CMakeLists and C++ files from the tutorial page, this will create whatever build-system comes from the default generator:
cmake .
Do note that if you don't give CMake any arguments at all, then it gives you a usage string. That's why there's that . there, to build from the current directory. If you want to specify a particular generator,
cmake -G "Unix Makefiles" .
If you are building in a separate directory (generally a good idea)
cmake /path/to/the/sources
Your original error message, by the way, tells you that CMake is, by default, using the generator Unix Makefiles, which doesn't support setting a platform. The no-arguments-at-all behavior seems to have tripped you up afterwards.
After a discussion in the comments, I realised the issue was that I had done it wrong from the start. The solution ultimately was to remove all CMake-related files (except for CMakeLists.txt and do it all over again, this time running cmake .. on its own (without any arguments) from a subdirectory.

Debug vs Release in CMake

In a GCC compiled project,
How do I run CMake for each target type (debug/release)?
How do I specify debug and release C/C++ flags using CMake?
How do I express that the main executable will be compiled with g++ and one nested library with gcc?
With CMake, it's generally recommended to do an "out of source" build. Create your CMakeLists.txt in the root of your project. Then from the root of your project:
mkdir Release
cd Release
cmake -DCMAKE_BUILD_TYPE=Release ..
make
And for Debug (again from the root of your project):
mkdir Debug
cd Debug
cmake -DCMAKE_BUILD_TYPE=Debug ..
make
Release / Debug will add the appropriate flags for your compiler. There are also RelWithDebInfo and MinSizeRel build configurations.
You can modify/add to the flags by specifying a toolchain file in which you can add CMAKE_<LANG>_FLAGS_<CONFIG>_INIT variables, e.g.:
set(CMAKE_CXX_FLAGS_DEBUG_INIT "-Wall")
set(CMAKE_CXX_FLAGS_RELEASE_INIT "-Wall")
See CMAKE_BUILD_TYPE for more details.
As for your third question, I'm not sure what you are asking exactly. CMake should automatically detect and use the compiler appropriate for your different source files.
A lot of the answers here are out of date/bad. So I'm going to attempt to answer it better. Granted I'm answering this question in 2020, so it's expected things would change.
How do I run CMake for each target type (debug/release)?
First off Debug/Release are called configurations in cmake (nitpick).
If you are using a single configuration generator (Ninja/Unix-Makefiles) you must specify the CMAKE_BUILD_TYPE.
Like this:
# Configure the build
cmake -S . -B build/ -D CMAKE_BUILD_TYPE=Debug
# Actually build the binaries
cmake --build build/
# Configure a release build
cmake -S . -B build/ -D CMAKE_BUILD_TYPE=Release
# Build release binaries
cmake --build build/
For multi-configuration generators it's slightly different (Ninja Multi-Config, Visual Studio)
# Configure the build
cmake -S . -B build
# Build debug binaries
cmake --build build --config Debug
# Build release binaries
cmake --build build --config Release
If you are wondering why this is necessary it's because cmake isn't a build system. It's a meta-build system (IE a build system that build's build systems). This is basically the result of handling build systems that support multiple-configurations in 1 build. If you'd like a deeper understanding I'd suggest reading a bit about cmake in Craig Scott's book "Professional CMake: A Practical Guide
How do I specify debug and release C/C++ flags using CMake?
The modern practice is to use target's and properties.
Here is an example:
add_library(foobar)
# Add this compile definition for debug builds, this same logic works for
# target_compile_options, target_link_options, etc.
target_compile_definitions(foobar PRIVATE
$<$<CONFIG:Debug>:
FOOBAR_DEBUG=1
>
)
NOTE: How I'm using generator expressions to specify the configuration!
Using CMAKE_BUILD_TYPE will result in bad builds for any multi-configuration generator!
Further more sometimes you need to set things globally and not just for one target.
Use add_compile_definitions, add_compile_options, etc. Those functions support generator expressions. Don't use old style cmake unless you have to (that path is a land of nightmares)
How do I express that the main executable will be compiled with g++ and one nested library with gcc?
Your last question really doesn't make sense.
For debug/release flags, see the CMAKE_BUILD_TYPE variable (you pass it as cmake -DCMAKE_BUILD_TYPE=value). It takes values like Release, Debug, etc.
https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/Useful-Variables#compilers-and-tools
cmake uses the extension to choose the compiler, so just name your files .c.
You can override this with various settings:
For example:
set_source_files_properties(yourfile.c LANGUAGE CXX)
Would compile .c files with g++. The link above also shows how to select a specific compiler for C/C++.
Instead of manipulating the CMAKE_CXX_FLAGS strings directly (which could be done more nicely using string(APPEND CMAKE_CXX_FLAGS_DEBUG " -g3") btw), you can use add_compile_options:
add_compile_options(
"-Wall" "-Wpedantic" "-Wextra" "-fexceptions"
"$<$<CONFIG:DEBUG>:-O0;-g3;-ggdb>"
)
This would add the specified warnings to all build types, but only the given debugging flags to the DEBUG build. Note that compile options are stored as a CMake list, which is just a string separating its elements by semicolons ;.
// CMakeLists.txt : release
set(CMAKE_CONFIGURATION_TYPES "Release" CACHE STRING "" FORCE)
// CMakeLists.txt : debug
set(CMAKE_CONFIGURATION_TYPES "Debug" CACHE STRING "" FORCE)
If you want to build a different configuration without regenerating if using you can also run cmake --build {$PWD} --config <cfg> For multi-configuration tools, choose <cfg> ex. Debug, Release, MinSizeRel, RelWithDebInfo
https://cmake.org/cmake/help/v2.8.11/cmake.html#opt%3a--builddir

Setting default compiler in CMake

I'm using CMake version 2.8 on WinXP SP3. Whenever i run my CMakeLists script by default CMake use Visual Studio 10 compiler. I've tried to do:
SET( CMAKE_CXX_COMPILER "C:/MinGW/bin/g++" )
without success. How can i set MinGW as my default compiler so that i do not have to worry about setting compiler in the CMakeLists?
CMake 3.15 or later supports overriding the default generator by setting the environment variable CMAKE_GENERATOR.
E.g., using PowerShell, set the environment variable in the following way to make MinGW the default generator:
$Env:CMAKE_GENERATOR = 'MinGW Makefiles'
For older CMake versions (< 3.15), CMake uses the newest Visual Studio installation as default generator, unless the generator is explicitly specified upon invoking CMake. This behavior is hard coded and cannot be changed.
As a work-around you can use a batch wrapper script titled cmake.cmd with the following contents:
#cmake.exe -G "MinGW Makefiles" %*
The script should be placed in a directory on the system PATH and should take precedence over the CMake executable cmake.exe.
The script invokes cmake.exe with MinGW as a generator and forwards all other parameters to it.
You only have to set the toolchain/output format once, typically you'd do this upon running cmake for the first time:
cmake -G "MinGW Makefiles" .
Instead of the dot you can use your own parameters (if any) and/or the path to the source.
As an alternative, especially when you're new to CMake, use the GUI version under windows (run cmake-gui without parameters instead of cmake).
Once opened, set your paths and click on "Configure". If there's no compiler set, it will ask you to pick one (otherwise you have to clear the cache to make it reappear).
Updated configuration values will appear in red and it will also allow you to select files and paths using the common Windows dialog boxes.
Once configuration is complete and without errors you can hit "generate" to create your makefiles or project files. To update these later on, you can use cmake-gui again or just use the usual command line version cmake.
With CMake version 3.15 or later, you can set the CMAKE_GENERATOR environment variable to specify the default generator to be used on your system.