Eclipse indexer proper c++11 syntax highlighting when generating projects with cmake - c++

I know you can enable proper syntax highlighting with the GXX_EXPERIMENTAL hack described here:
Eclipse CDT indexer does not know C++11 containers
But i think, when generating projects with cmake, one should never need to touch the project settings at all.
So. Is there a simpler solution?

The answer is pretty simple.
The eclipse cdt generator ignores the definitions added with add_definitions(...) when parsing the symbols. Instead it uses the CMAKE_CXX_COMPILER_ARG1.
So all you have to do is: Add -DCMAKE_CXX_COMPILER_ARG1=-std=c++11 when invoking cmake
Generating project files from commandline:
cmake ../../src -G"Eclipse CDT4 - MinGW Makefiles" -DCMAKE_ECLIPSE_VERSION=4.2 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER_ARG1=-std=c++11
Generating projects from cmake gui:
- Select source and build directory.
- now BEFORE hitting configure or generate. Press "Add Entry" and add a new entry. Name:CMAKE_CXX_COMPILER_ARG1 Type:STRING Value:-std=c++11
- press Generate and create the Eclipse project
It is important to set the CMAKE_CXX_COMPILER_ARG1 upfront before hitting configure or generate the first time!
That´s it. The project will be generated with correct symbols. indexer, syntax highlighting and autocompletion should work as intended without changing any project settings by hand.

As already mentioned, the invocation of the project generators runs before the parsing of the CMakeLists.txt.
Thus, any definitions inside of CMakeLists.txt don't have any effect on the generated project files.
In case of eclipse-project generation, the capabilities of the compiler are requested inside CMakeExtraGeneratorDetermineCompilerMacrosAndIncludeDirs.cmake.
In line 23 the variable CMAKE_CXX_FLAGS is parsed which is evaluated in line 30.
Especially this CMAKE_CXX_FLAGS variable can only be set while invoking cmake from command line.
Recommodation of proper cmake invokation: cmake -G"Eclipse CDT4 - Unix Makefiles" -DCMAKE_CXX_FLAGS="-std=c++11" (or replace c++11 with eg. c++14 or any other standard you like)
Hint:
The result from evaluating line 30 can be seen from running the following command as an example: touch /tmp/dummy; /usr/bin/c++ -v -E -x c++ -std=c++11 -dD /tmp/dummy. It outputs all the defines from the compiler which are parsed into the eclipse-project:
...
#define __STDC__ 1
#define __cplusplus 201103L
...

In version 3.1 of cmake a new variable CMAKE_CXX_STANDARD was introduced that can activate C++11 support. Try something like this:
cmake ../../src -G "Eclipse CDT4 - Unix Makefiles" -DCMAKE_CXX_STANDARD=11
This seems to carry through to the generated Eclipse project. I tried it with verison 3.2.0-rc2 and Eclipse recognized C++11 features like std::shared_ptr<>.
Some documentation links:
CMAKE_CXX_STANDARD
Optional Compile Features (read towards the bottom of the section)

Related

CMake won't select the correct C++ compiler [duplicate]

I would like to use the IAR compiler. I noticed CMake has already have a bunch of files about this compiler:
https://github.com/jevinskie/cmake/blob/master/Modules/Compiler/IAR.cmake
From what I read the common solution is to specify manually ALL the toolchain in my CMakeLists.txt:
set(CMAKE_C_COMPILER iccarm)
set(CMAKE_CPP_COMPILER iccarm)
How CMake can link these definitions with `Modules/Compiler/IAR.cmake"?
I thought I would just have to do
include("Modules/Compiler/IAR.cmake")
What is the correct way to specify my IAR compiler?
When I do
cmake .
It still tries to use gcc instead of my IAR compiler. Why?
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...
I see more and more people who set CMAKE_C_COMPILER and other compiler-related variables in the CMakeLists.txt after the project call and wonder why this approach breaks sometimes.
What happens actually
When CMake executes the project() call, it looks for a default compiler executable and determines the way for use it: default compiler flags, default linker flags, compile features, etc.
And CMake stores path to that default compiler executable in the CMAKE_C_COMPILER variable.
When one sets CMAKE_C_COMPILER variable after the project() call, this only changes the compiler executable: default flags, features all remains set for the default compiler.
AS RESULT: When the project is built, a build system calls the project-specified compiler executable but with parameters suitable for the default compiler.
As one could guess, this approach would work only when one replaces a default compiler with a highly compatible one. E.g. replacement of gcc with clang could work sometimes.
This approach will never work for replacement of cl compiler (used in Visual Studio) with gcc one. Nor this will work when replacing a native compiler with a cross-compiler.
What to do
Never set a compiler in CMakeLists.txt.
If you want, e.g., to use clang instead of defaulted gcc, then either:
Pass -DCMAKE_C_COMPILER=<compiler> to cmake when configure the project. That way CMake will use this compiler instead of default one and on the project() call it will adjust all flags for the specified compiler.
Set CC environment variable (CXX for C++ compiler). CMake checks this variable when selects a default compiler.
(Only in rare cases) Set CMAKE_C_COMPILER variable before the project() call. This approach is similar to the first one, but makes the project less flexible.
If the ways above do not work
If on setting CMAKE_C_COMPILER in the command line CMake errors that a compiler cannot "compile a simple project", then something wrong in your environment.. or you specify a compiler incompatible for chosen generator or platform.
Examples:
Visual Studio generators work with cl compiler but cannot work with gcc.
A MinGW compiler usually requires MinGW Makefiles generator.
Incompatible generator cannot be fixed in CMakeLists.txt. One need to pass the proper -G option to the cmake executable (or select the proper generator in CMake GUI).
Cross-compiling
Cross-compiling usually requires setting CMAKE_SYSTEM_NAME variable, and this setting should normally be done in the toolchain file. That toolchain file is also responsible for set a compiler.
Setting CMAKE_SYSTEM_NAME in the CMakeLists.txt is almost always an error.
You need to create a toolchain file, and use the CmakeForceCompiler module.
Here is an example toolchain file for bare-metal ARM development with IAR:
include(CMakeForceCompiler)
set(CMAKE_SYSTEM_NAME Generic) # Or name of your OS if you have one
set(CMAKE_SYSTEM_PROCESSOR arm) # Or whatever
set(CMAKE_CROSSCOMPILING 1)
set(CMAKE_C_COMPILER iccarm) # Change the arm suffix if appropriate
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # Required to make the previous line work for a target that requires a custom linker file
The last line is necessary because CMake will try to compile a test program with the compiler to make sure it works and to get some version information from preprocessor defines. Without this line, CMake will use add_executable() for the test program, and you will get the error "The C compiler "XXX" is not able to compile a simple test program." This is because the test program fails to link, as it doesn't have your custom linker file (I'm assuming bare-metal development since this is what IAR is usually used for). This line tells CMake to use add_library() instead, which makes the test succeed without the linker file. Source of this workaround: this CMake mailing list post.
Then, assuming that your toolchain file is named iar-toolchain.cmake, invoke CMake like this:
cmake -DCMAKE_TOOLCHAIN_FILE=iar-toolchain.cmake .
You can call cmake like this:
cmake -DCMAKE_C_COMPILER=iccarm ...
or
cmake -DCMAKE_CXX_COMPILER=...
If you don't want to use your PC's standard compiler, you have to give CMake the path to the compiler. You do this via environment variables, a toolchain file or direct definitions in the CMake command line (see e.g. CMake Error at CMakeLists.txt:30 (project): No CMAKE_C_COMPILER could be found).
Putting the compiler's name/path into your CMakeLists.txt would stop your project from being cross-platform.
CMake does check for the compiler ids by compiling special C/C++ files. So no need to manually include from Module/Compiler or Module/Platform.
This will be automatically done by CMake based on its compiler and platform checks.
References
CMake: In which Order are Files parsed (Cache, Toolchain, …)?
CMake GitLab Commit: Add support files for C, C++ and ASM for the IAR toolchain.
IAR Systems recently published a basic CMake tutorial with examples under their GitHub profile.
I like the the idea of a generic toolchain file which works seamlessly for both Windows and Linux compilers using find_program().
The following snippet will be used for when using C and can be used similarly for CXX:
# IAR C Compiler
find_program(CMAKE_C_COMPILER
NAMES icc${CMAKE_SYSTEM_PROCESSOR}
PATHS ${TOOLKIT}
"$ENV{ProgramFiles}/IAR Systems/*"
"$ENV{ProgramFiles\(x86\)}/IAR Systems/*"
/opt/iarsystems/bx${CMAKE_SYSTEM_PROCESSOR}
PATH_SUFFIXES bin ${CMAKE_SYSTEM_PROCESSOR}/bin
REQUIRED )
For ASM, I initially got puzzled with the NAMES but then I realized that the toolchain file was made that way for working with old Assemblers shipped with XLINK:
find_program(CMAKE_ASM_COMPILER
NAMES iasm${CMAKE_SYSTEM_PROCESSOR} a${CMAKE_SYSTEM_PROCESSOR}
PATHS ${TOOLKIT}
"$ENV{PROGRAMFILES}/IAR Systems/*"
"$ENV{ProgramFiles\(x86\)}/IAR Systems/*"
/opt/iarsystems/bx${CMAKE_SYSTEM_PROCESSOR}
PATH_SUFFIXES bin ${CMAKE_SYSTEM_PROCESSOR}/bin
REQUIRED )
Also, take a look at the full toolchain file. It will work automatically for "Arm" when the tools are installed on their default locations, otherwise it is just about updating the TOOLKIT variable and the compilers for all the supported languages should adjust automatically.
If your wanting to specify a compiler in cmake then just do ...
cmake_minimum_required(VERSION 3.22)
set(CMAKE_C_COMPILER "clang")
set(CMAKE_CXX_COMPILER "clang++")
Options 1 is only used if you want to specify what compiler you want to use as default for everything that you might compile on your computer. And I don't even think it would work on windows.
Option 2 would be used if you only want to use a different temporarily.
Option 3 is used if that's the compiler that should be used for that particular project. Also option 3 would be the most cross compatible.

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

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.

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.

How can I build curlpp on Windows for gcc?

I've downloaded the package from here: https://github.com/jpbarrette/curlpp
When I drag CMakelists.txt onto cmake.exe it does build something that looks like a Microsoft Visual Studio project. I want to build static library that I could use in Codeblocks with GCC instead. I've not idea how to do it, I don't know where the options are or how to set appropriate flags.
I've also followed this post: https://stackoverflow.com/a/27609214/7310666c which is about cURL - it build correctly, but when I linked it to my project it gave me undefined reference error.
Could anyone give me a hand here? My desktop is already littered by all the files I downloaded while trying.
As mentionned here:
CMake [..] is responsible for writing the input files for a native
build system.
The modules responsible of creating files for a specific build system are called "Generators". For a full list of those generators, please have a look at this.
In your case, by default it selects Visual Studio, even though "Code Blocks" should be available.
So, here's an example of how you could obtain the required files:
cd /path/to/curlpp/
mkdir build
cd build
cmake -G "CodeBlocks - NMake Makefiles" ..

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.