Recommended ways to use CMake with icc via configuration options? - build

I would like to use the Intel compiler icc (or icpc) with a CMake-based project (on Linux for what it's worth). I can of course export the CXX variable when calling cmake, e.g. like
CXX=icpc cmake ../
and this works fine. I would however like to make this choice available via a custom option. For this I parse custom option, e.g.
cmake -DMY_COMPILER_OPTION=Intel ..
as
IF (MY_COMPILER_OPTION STREQUAL "Intel")
MESSAGE(STATUS "** Compiling with Intel settings **")
SET(CMAKE_CXX_COMPILER "icpc")
SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -w")
SET(CMAKE_CXX_FLAGS_DEBUG "-g")
ENDIF ()
and set CMAKE_CXX_COMPILER together with some compiler flags. This also works, however there is an important "but".
I would also like to use the option -ipo (interprocedural optimization) for my code when compiling with icc plus I need to compile a static library within the build process. For this to work, I need to use Intel's xiar (and also xilink I guess).
cmake actually offers a special property for this
set_property(TARGET mytarget PROPERTY INTERPROCEDURAL_OPTIMIZATION 1)
however this only seems to works properly when the compiler has been set via the environment variable (then xiar is used). When setting the compiler via CMAKE_CXX_COMPILERthis property is ignored.
Is there another way to do this?. Some recommended way? Or at least a work-around?

The recommended way is to run cmake with the appropriate CMAKE_<LANG>_COMPILER defined.
Linux users
cmake -DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc -DCMAKE_Fortran_COMPILER=ifort ..
Windows users
From an Intel Compiler console:
cmake -G "NMake Makefiles" -DCMAKE_C_COMPILER=icl -DCMAKE_CXX_COMPILER=icl -DCMAKE_Fortran_COMPILER=ifort ..

Ok, since there have been no answers here, I've also turned to the CMake mailing list list for help on this issue. The consent of the experts there seems to be that the way I was trying to do this is a rather bad idea. The reason is that the parsing of my custom flags happens to late in the initialization process. One should therefore rely on setting the compiler via environment variables and let CMake do its magic during the initial configuration run. I will modify my approach..

Basically, avoid trying to change the compiler. See the FAQ: How do I use a different compiler?. CMake Toolchain files provide a way to support some complex cases, like an exotic HPC compiler.

Related

CMake Treat Warnings as Errors

How can I configure CMake to treat compiler warnings as errors during the build?
I am aware of the possibility to manually configure command line options for the compiler like -Werror through commands like target_compile_options, but I would prefer a portable solution that does not require fiddling with tool-dependent options.
This can be configured in CMake version 3.24 and higher via the COMPILE_WARNING_AS_ERROR target property.
For example, to enable warnings as errors for the my_app target you could write:
set_property(TARGET my_app PROPERTY COMPILE_WARNING_AS_ERROR ON)
You can also set a global default for all targets in your project via the CMAKE_COMPILE_WARNING_AS_ERROR variable:
set(CMAKE_COMPILE_WARNING_AS_ERROR ON)
add_executable(my_app1 [...])
add_executable(my_app2 [...])
add_executable(my_app3 [...])
If a user finds it annoying that this is set in the CMakeLists.txt file, they can still override it using the --compile-no-warning-as-error configure option.
Treating warnings as errors is a good practice for CI systems with a fixed and predictable toolchain, but it is inappropriate to force on all users. Many are likely using a different toolchain with different sets of warnings and sensitivities for those warnings. Enabling -Werror by default causes broken builds for your consumers and is a bad practice.
Notably, this exact issue was the source of one major debacle in the last year in the Linux kernel: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b339ec9c229aaf399296a120d7be0e34fbc355ca
It is also prohibited by the Gentoo packaging archives (important because it is a source-based distribution): https://devmanual.gentoo.org/ebuild-writing/common-mistakes/index.html
Do a bit more searching and you will hear the shouting from the mountaintops that warnings as errors is good for developers, but not for consumers.
The best way to do this, then, is to set the new (as of CMake 3.24) variable CMAKE_COMPILE_WARNING_AS_ERROR set to ON only when you know it is safe to do so. That is to say, it should not be on by default (but if you insist, then there must be a way to disable it).
There are many good ways to set this up:
You could add it to the cacheVariables section of a preset
You could set it to ON in a toolchain file
You can simply pass it at the command line when you want to toggle it on or off.
Speaking as someone who regularly uses top-of-tree compiler builds, where warnings break frequently, hard-coded warnings-as-errors is a blight. It forces me and countless other package maintainers, devops teams, and so on, to patch your build.

Cannot set g++ compiler for CMake

I want to use g++ compiler in my CPP project. So I setup Cmake file like this:
set(CMAKE_CXX_COMPILER "/usr/local/bin/g++")
project(GatewayTest LANGUAGES C CXX)
...
But when error still be shown with Clang. I ran on MacOS Sierra.
The error is:
clang: error: linker command failed with exit code 1 (use -v to see invocation).
Am i wrong with this setting?
Don't try to set the compiler from inside the CMakeLists.txt.
The idea behind this flag is that you give the user the opportunity to specify which compiler to use. This makes sense, as the user will know which machine they are going to build on, so they should know where to find the compiler. It does not make sense to make this information part of the build script, as the build script is, in principle, supposed to be portable to any machine and compiler.
If your project requires a specific compiler to be built correctly, you can inspect the variables like CMAKE_CXX_COMPILER and raise a diagnostic if they do not contain what you expect, but you should never write to those variables.
If you do want to scriptify compiler detection, you can either wrap the call to CMake in a shell script that sets the variables used for compiler detection or use a toolchain file for configuring CMake.
set(CMAKE_C_COMPILER "clang")
set(CMAKE_CXX_COMPILER "clang++")
project(GatewayTest LANGUAGES C CXX)
...

Creating CMakeLists for a project that depends on LLVM

I've decided to try LLVM and the CMake build system for my language project, but I'm not sure how to generate a proper cross-platform CMakeLists for it. Running "llvm-config --libs" returns about a hundred libraries (I'm still not sure which of them I actually need) and "--cxxflags" gives me g++-specific flags (I wouldn't know how they translate to other compilers).
Is there a way to get output for different compilers from llvm-config? (Perhaps it depends on how llvm is compiled?)
If so, could I run llvm-config from CMakeLists and use its output instead of hard-coding it?
Otherwise, what are some maintainable alternatives?
llvm-config --cxxflags will use the compiler you build LLVM with in the first place. So if you plan on using that and build LLVM itself with a different compiler than g++ (default), then you need to build LLVM itself with a different compiler - or not use llvm-config in the first place.
I went the former route, so I create a build.sh, which contains this:
CC=clang CXX=clang++ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=1 -DLLVM_T
ARGETS_TO_BUILD=X86 ../llvm
make
I then have a makefile that uses llvm-config to define flags and such (I don't use CMake, but the concept should be possible to move to CMake quite easily). See: https://github.com/Leporacanthicus/lacsap/blob/master/Makefile

Enabling RTTI for clang tool?

I'm experimenting with clang's libTooling to build a basic source-to-source transformation tool.
I want to use boost::regex and boost::filesystem, but linking against them requires exceptions and RTTI be enabled. According to the clang mailing list , it should be possible to enable RTTI without breaking anything.
That said, I can't find a setting or variable to instruct the build system to enable RTTI. (i'm using cmake). I can add the -frtti and -fexceptions flags to the compiler commands, but the clang build system is adding its own -fno-rtti, -fno-exceptions flags which seem to have higher priority.
The relevant variables are called LLVM_ENABLE_RTTI and LLVM_ENABLE_EH.
They can can be set either by using a cmake gui like ccmake or cmake-gui, or by passing them directly to the cmake invocation.

Using CMake with multiple compilers for the same language

It seems like CMake is fairly entrenched in its view that there should be one, and only one, CMAKE_CXX_COMPILER for all C++ source files. I can't find a way to override this on a per-target basis. This makes a mix of host-and-cross compiling in a single CMakeLists.txt very difficult with the built-in CMake facilities.
So, my question is: what's the best way to use multiple compilers for the same language (i.e. C++)?
It's impossible to do this with CMake.
CMake only keeps one set of compiler properties which is shared by all targets in a CMakeLists.txt file. If you want to use two compilers, you need to run CMake twice. This is even true for e.g. building 32bit and 64bit binaries from the same compiler toolchain.
The quick-and-dirty way around this is using custom commands. But then you end up with what are basically glorified shell-scripts, which is probably not what you want.
The clean solution is: Don't put them in the same CMakeLists.txt! You can't link between different architectures anyway, so there is no need for them to be in the same file. You may reduce redundancies by refactoring common parts of the CMake scripts into separate files and include() them.
The main disadvantage here is that you lose the ability to build with a single command, but you can solve that by writing a wrapper in your favorite scripting language that takes care of calling the different CMake-makefiles.
You might want to look at ExternalProject:
http://www.kitware.com/media/html/BuildingExternalProjectsWithCMake2.8.html
Not impossible as the top answer suggests. I have the same problem as OP. I have some sources for cross compiling for a raspberry pi pico, and then some unit tests that I am running on my host system.
To make this work, I'm using the very shameful "set" to override the compiler in the CMakeLists.txt for my test folder. Works great.
if(DEFINED ENV{HOST_CXX_COMPILER})
set(CMAKE_CXX_COMPILER $ENV{HOST_CXX_COMPILER})
else()
set(CMAKE_CXX_COMPILER "g++")
endif()
set(CMAKE_CXX_FLAGS "")
The cmake devs/community seems very against using set to change the compiler since for some reason. They assume that you need to use one compiler for the entire project which is an incorrect assumption for embedded systems projects.
My solution above works, and fits the philosophy I think. Users can still change their chosen compiler via environment variables, if it's not set then I do assume g++. set only changes variables for the current scope, so this doesn't affect the rest of the project.
To extend #Bill Hoffman's answer:
Build your project as a super-build, by using some kind of template like the one here https://github.com/Sarcasm/cmake-superbuild
which will configure both the dependencies and your project as an ExternalProject (standalone cmake configure/build/install environment).