How to specify new GCC path for CMake
Do not overwrite CMAKE_C_COMPILER
, but export CC
(and CXX
) before calling cmake:
export CC=/usr/local/bin/gcc
export CXX=/usr/local/bin/g++
cmake /path/to/your/project
make
The export only needs to be done once, the first time you configure the project, then those values will be read from the CMake cache.
UPDATE: longer explanation on why not overriding CMAKE_C(XX)_COMPILER
after Jake's comment
I recommend against overriding the CMAKE_C(XX)_COMPILER
value for two main reasons: because it won't play well with CMake's cache and because it breaks compiler checks and tooling detection.
When using the set
command, you have three options:
- without cache, to create a normal variable
- with cache, to create a cached variable
- force cache, to always force the cache value when configuring
Let's see what happens for the three possible calls to set
:
Without cache
set(CMAKE_C_COMPILER /usr/bin/clang)
set(CMAKE_CXX_COMPILER /usr/bin/clang++)
When doing this, you create a "normal" variable CMAKE_C(XX)_COMPILER
that hides the cache variable of the same name. That means your compiler is now hard-coded in your build script and you cannot give it a custom value. This will be a problem if you have multiple build environments with different compilers. You could just update your script each time you want to use a different compiler, but that removes the value of using CMake in the first place.
Ok, then, let's update the cache...
With cache
set(CMAKE_C_COMPILER /usr/bin/clang CACHE PATH "")
set(CMAKE_CXX_COMPILER /usr/bin/clang++ CACHE PATH "")
This version will just "not work". The CMAKE_C(XX)_COMPILER
variable is already in the cache, so it won't get updated unless you force it.
Ah... let's use the force, then...
Force cache
set(CMAKE_C_COMPILER /usr/bin/clang CACHE PATH "" FORCE)
set(CMAKE_CXX_COMPILER /usr/bin/clang++ CACHE PATH "" FORCE)
This is almost the same as the "normal" variable version, the only difference is your value will be set in the cache, so users can see it. But any change will be overwritten by the set
command.
Breaking compiler checks and tooling
Early in the configuration process, CMake performs checks on the compiler: Does it work? Is it able to produce executables? etc. It also uses the compiler to detect related tools, like ar
and ranlib
. When you override the compiler value in a script, it's "too late", all checks and detections are already done.
For instance, on my machine with gcc as default compiler, when using the set
command to /usr/bin/clang
, ar
is set to /usr/bin/gcc-ar-7
. When using an export before running CMake it is set to /usr/lib/llvm-3.8/bin/llvm-ar
.
How to get CMake to use the default compiler on system PATH?
As is already written in the answer to the other question, CMake prefers the generic compiler names cc
and c++
when searching for the C and C++ compilers. These probably refer to GNU version 4.1 compilers on your system.
Anyway, to force CMake to use the default compilers on the system path, add the following code to the beginning of your outermost CMakeLists.txt
.
find_program(CMAKE_C_COMPILER NAMES $ENV{CC} gcc PATHS ENV PATH NO_DEFAULT_PATH)
find_program(CMAKE_CXX_COMPILER NAMES $ENV{CXX} g++ PATHS ENV PATH NO_DEFAULT_PATH)
...
project (Foo C CXX)
The find_program
calls must occur before the call to project
or enable_language
.
How to Get CMake to Use Default Compiler on System PATH?
CMake honors the setting of the PATH
environment variable, but gives preference to the generic compiler names cc
and c++
. To determine which C compiler will be used by default under UNIX by CMake, run:
$ which cc
To determine the default C++ compiler, run:
$ which c++
If you generate a symbolic link c++
in /opt/gcc-4.8/bin
which points to /opt/gcc-4.8/bin/g++
, CMake should use GCC 4.8 by default.
How to find compiler path automatically in cmake?
Variables Intel_C_COMPILER
and Intel_CXX_COMPILER
have trailing newline. Way for removing that newline are described in that question and its answers: How to strip trailing whitespace in CMake variable?
E.g., you may run execute_process
with OUTPUT_STRIP_TRAILING_WHITESPACE option, so it will behave similar to the shell's backtick operator (`which icc`).
Detailed description
Most of shell utilities output single- (or even multi-) line information with trailing newline. And utility which
is not an exception. With trailing newline an output looks nice when one run these utilities in the terminal.
But when run such utility in the script and grab its output programmatically, one need to care about such newline.
Setting default compiler in 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.
How to specify a compiler in CMake?
To select a specific compiler, you have several solutions, as exaplained in CMake wiki:
Method 1: use environment variables
For C and C++, set the CC
and CXX
environment variables. This method is not guaranteed to work for all generators. (Specifically, if you are trying to set Xcode's GCC_VERSION
, this method confuses Xcode.)
For example:
CC=gcc-4.2 CXX=/usr/bin/g++-4.2 cmake -G "Your Generator" path/to/your/source
Method 2: use cmake -D
Set the appropriate CMAKE_FOO_COMPILER
variable(s) to a valid compiler name or full path on the command-line using cmake -D
.
For example:
cmake -G "Your Generator" -D CMAKE_C_COMPILER=gcc-4.2 -D CMAKE_CXX_COMPILER=g++-4.2 path/to/your/source
Method 3 (avoid): use set()
Set the appropriate CMAKE_FOO_COMPILER
variable(s) to a valid compiler name or full path in a list file using set()
. This must be done before any language is set (ie: before any project()
or enable_language()
command).
For example:
set(CMAKE_C_COMPILER "gcc-4.2")
set(CMAKE_CXX_COMPILER "/usr/bin/g++-4.2")
project("YourProjectName")
The wiki doesn't provide reason why 3rd method should be avoided...
CMake on Windows
Because CMake's error message is misleading here, I think it warrants a little more detailed answer.
In short, you ran into a chicken-and-egg kind of a problem.
CMake's compiler detection is mighty, but since - during the first try -
- you didn't give any explicit generator to use with
-G
- it couldn't find a Visual Studio installed
- it couldn't find any C/C++ compiler in your
PATH
environment - it couldn't find a
CC
environment variable defined with the full path to a compiler
It was defaulting to nmake
.
Now here comes the problem: it does remember your implicit generator/compiler choice in it's variable cache (see CMAKE_GENERATOR
in CMakeCache.txt
). What is a very useful feature, if you have multiple compilers installed.
But if you then declare the CC
environment variable - as the error message suggests - it's too late since your generator's choice was remembered in the first try.
I see two possible ways out of this:
- Overrule the generator choice by given the right one with
cmake.exe -G "MinGW Makefiles" ..
(as the answer linked by @Guillaume suggests) - Delete your project's binary output directory (including
CMakeCache.txt
) and docmake.exe ..
after you added your compiler'sbin
folder to yourPATH
environment.
References
- Running CMake on Windows
- What is the default generator for CMake in Windows?
- CMake error at CMakeLists.txt:30 (project): No CMAKE_C_COMPILER could be found
- CMake: how to specify the version of Visual C++ to work with?
Related Topics
How Is It Possible That Kill -9 for a Process on Linux Has No Effect
Linux/Bash, Using Ps -O to Get Process by Specific Name
What's the Difference of Redirect an Output Using ">", "&>", ">&" and "2&>"
Get First Line of a Shell Command's Output
How to Concatenate Two Strings to Build a Complete Path
Split Output of Command by Columns Using Bash
Mongodb Data Directory /Data/Db Not Found
Show Special Characters in Unix While Using 'Less' Command
How to Install SQL * Plus Client in Linux
How Can Objdump Emit Intel Syntax
Shell Script Current Directory
Using Sed to Split a String with a Delimiter
How to Break Up an Extremely Long String Literal in Bash
Abuse Curl to Communicate with Redis
How to Use 'Mv' Command to Move Files Except Those in a Specific Directory