How to add a compiler option to every port being built? - vcpkg

Is there a way to add a compiler option to every vcpkg port being built?
In particular I need every port to be compiled with -fdata-section -ffunction-section -flto in my Linux vcpkg instance.

Kudos to "isanych" (see this):
You can use VCPKG_C_FLAGS* VCPKG_CXX_FLAGS* VCPKG_LINKER_FLAGS* variables in you custom triplet files. Here how I do lto on linux:
set(VCPKG_CXX_FLAGS_RELEASE -flto)
set(VCPKG_C_FLAGS_RELEASE -flto)
set(VCPKG_LINKER_FLAGS_RELEASE -flto)
and on windows:
set(VCPKG_CXX_FLAGS_RELEASE "/GL /Gw /GS-")
set(VCPKG_C_FLAGS_RELEASE "/GL /Gw /GS-")
set(VCPKG_LINKER_FLAGS_RELEASE "/OPT:ICF=3 /LTCG")
There is an issue #7159 with multiple flags in boost, with fix #7160.
Note: as of now VCPKG_LINKER_FLAGS_RELEASE isn't being used particularly wide amongst ports.

Related

per target cuda compiler options with cmake

So I have a bit of an issue with setting up pdbs in cuda when using cmake and visual studio (2013 in the case).
Basically I think I want to do something like :
-Xcompiler "/Fd whatever.pdb"
to each add_cuda_library, but I can only seem to set CUDA_NVCC_FLAGS, CUDA_NVCC_FLAGS_RELEASE, CUDA_NVCC_FLAGS_DEBUG etc globally.
Right now I use
SET(CUDA_NVCC_FLAGS_RELEASE ${CUDA_NVCC_FLAGS}; -Xcompiler "/Fd nvcc_all.pdb")
And this dumps all the symbols into one file.
Problem is sometimes the build breaks when there are concurrent writes to that pdb. I've tried adding /FS, but it doesn't help.
Is there a cmake incantation to allow me to add a per lib cuda pdbs ?
You can try to pass the flags like this:
CUDA_ADD_LIBRARY(foo
...
OPTIONS "/Fd foo.pdb"
)

multiple gcc versions in makefile

In my Makefile I have
CC=g++
When I do mgrep gcc, I have several versions listed like:
gnu/gcc/4.2.1
gnu/gcc/4.7.3
etc
I can do a module load to change my gcc version.
Now suppose I want to use multiple versions simultaneously in different makefiles, how do I do it?
The module system is basically just setting up a path to the requested module. If you want a particular compiler in a particular makefile, then you can do three things:
Expect the user of the makefile to load the correct version before calling Make. Possibly combined with some condition based on gcc -v|grep ${GCC_VERSION} to check that it's the right version.
Perform module load gnu/gcc/${GCC_VERSION} inside your makefile.
Use CC=/somewhere/path-to-gcc-version/bin/g++ instead of CC=g++.
Personally, I prefer 1 or 3. You can find out what the path is by doing module load ... and then which g++.
[By the way, I would use CXX=g++ and CC=gcc - assuming you are not compiling files called *.c as C++-code]

CMake coloring errors and warnings

Is there a way how to produce a colorful output from gcc which is called from Makefile generated by cmake? It would make debugging application a lot easier.
Do you want colourful output from cmake binary? For that I don't know any solution.
CMake can generate Makefiles that provide verbose (and colourful) information about the build process. This can be enabled in the following way:
SET(CMAKE_COLOR_MAKEFILE ON)
# And optionally
SET(CMAKE_VERBOSE_MAKEFILE ON)
If you want to have the gcc output colourised, then have a look at colorgcc perl script. Having it installed try something like this:
CC=/usr/bin/colorgcc cmake .....
Or use the newer solution proposed in another answer by gfour - the gccfilter
Other tools are not necessary now. GCC and Clang produce color output but hide it when they detect they're being used in a pipeline like CMake Makefiles use. They have flags to force color though.
CMakeLists.txt:
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
add_compile_options(-fdiagnostics-color=always)
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_compile_options(-fcolor-diagnostics)
endif()
If you do pipe the output of make sometimes, you can put this behind a flag.
Color output preview:
Reference:
https://medium.com/#alasher/colored-c-compiler-output-with-ninja-clang-gcc-10bfe7f2b949
Download gccfilter (needs perl, libregexp and libgetopt-argvfile), then run:
gccfilter -c cmake ...
This will colorize the messages from the build process (which I assume are gcc mesages).
Try colout, it is designed to seamlessly color the output of any command, and comes with a g++ AND a cmake theme, which you can use together:
make something 2>&1 | colout -t cmake | colout -t g++
Besides improving the cmake colorscheme, it even applies syntax coloring on the code printed out by g++.
Since CMake v3.24, there is the CMAKE_COLOR_DIAGNOSTICS variable. Follow that link for the most up-to-date version of the docs. Here is a quote from the 3.24.2 docs:
Enable color diagnostics throughout.
This variable uses three states: ON, OFF and not defined.
When not defined:
Makefile Generators initialize the CMAKE_COLOR_MAKEFILE variable to ON. It controls color buildsystem messages.
GNU/Clang compilers are not invoked with any color diagnostics flag.
When ON:
Makefile Generators produce color buildsystem messages by default. CMAKE_COLOR_MAKEFILE is not initialized, but may be explicitly set to OFF to disable color buildsystem messages.
GNU/Clang compilers are invoked with a flag enabling color diagnostics (-fcolor-diagnostics).
When OFF:
Makefile Generators do not produce color buildsystem messages by default. CMAKE_COLOR_MAKEFILE is not initialized, but may be explicitly set to ON to enable color buildsystem messages.
GNU/Clang compilers are invoked with a flag disabling color diagnostics (-fno-color-diagnostics).
If the CMAKE_COLOR_DIAGNOSTICS environment variable is set, its value is used. Otherwise, CMAKE_COLOR_DIAGNOSTICS is not defined by default.
Based on this discussion I've created an alias in ~/.bashrc for make:
alias make="make VERBOSE=1 2>&1 | sed -e 's%^.*: error: .*$%\x1b[37;41m&\x1b[m%' -e 's%^.*: warning: .*$%\x1b[30;43m&\x1b[m%'"
it's not really nice solution, but it does the job.

The proper way of forcing a 32-bit compile using CMake

Sorry that there are many similar questions, but I do find that Googling for CMake queries always yields similar-but-not-the-same scenarios, conflicting CMake commands and so on!
I need to force my project to build 32-bit binaries because I have to link with a library which is only available as 32-bit. I diagnosed this based on error messages such as:
/usr/bin/ld: i386 architecture of input file `*external-32bit-lib*' is incompatible with i386:x86-64 output
From what I gather, I should therefore use:
set (CMAKE_CXX_FLAGS "-m32")
This does change things - I now get several errors like:
/usr/bin/ld: i386 architecture of input file `*project-output-lib*' is incompatible with i386:x86-64 output
AND still get the same errors for the external library too. I think this is because the -m32 made gcc generate 32-bit binaries, but ld is still trying for 64-bit output? Further Googling for this problem didn't give any success, so if anyone could verify that I am right and give the correct way of doing this, I would be very grateful!
Many thanks!
If you want to compile and link for 32 bit using cmake use this for creating libraries and binaries:
Creating libraries:
add_library(mylib SHARED my_source.c)
set_target_properties(mylib PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
creating executables:
add_executable(mybin sources.c)
set_target_properties(mybin PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
Even if this seems like extra works, I believe a proper solution is to use toolchain file in this case. Something like:
# the name of the target operating system
set(CMAKE_SYSTEM_NAME Linux)
# which compilers to use for C and C++
set(CMAKE_C_COMPILER gcc)
set(CMAKE_C_FLAGS -m32)
set(CMAKE_CXX_COMPILER g++)
set(CMAKE_CXX_FLAGS -m32)
# here is the target environment located
set(CMAKE_FIND_ROOT_PATH /usr/i486-linux-gnu )
# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Then usage is simply:
$ cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake /path/to/source
The important part here is that one is now able to specify a root dir path (CMAKE_FIND_ROOT_PATH) which should be used to search for third party lib. Indeed your compiler may not be smart enough to know where to search for an x86 Qt library on an x86_64 system.
Having a toolchain file allows one to specify a different one on a par compiler basis, and you should be able to tweak the option when compiling in 32bits from a windows environement.
Nowadays this is extra works since compiling 32bits from an x86_64 Linux OS is pretty much trivial, but this solution will work for other more exotic setup.
For more information on toolchain file, one can check for example:
https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/cross_compiling/Mingw
CMAKE_CXX_FLAGS only affects the C++ compiler. You probably also have to set the flag for the C compiler:
set (CMAKE_C_FLAGS "-m32")
It sounds like you did not pass m32 to LFLAGS too, or there are old obj files skulking about. Be sure to clean first.
This question is similar to yours: cmake, gcc, cuda and -m32
Use TRY_RUN command by the following source.
size.cpp:
#include <cstdlib>
int main( int argc, char** argv )
{
size_t size = sizeof(void*);
if ( size == 4 )
return 0;
return 1;
}
CMakeLists.txt:
TRY_RUN(RUN_RESULT_VAR COMPILE_RESULT_VAR ${your_temp_dir} size.cpp RUN_OUTPUT_VARIABLE IS_64_SYSTEM)
IF(IS_64_SYSTEM)
MESSAGE(FATAL_ERROR "64 compiling not allowed!")
ENDIF(IS_64_SYSTEM)
It will work on all standard compiler.
I used malat's approach and made a Toolchain file.
I have a Toolchain file that works on some Linux dists, perhaps it will give you inspiration. It may work for you as is, or you may need other ugly hacks to get other cmake scripts you rely on to work or w/e:
https://github.com/visualboyadvance-m/visualboyadvance-m/blob/master/cmake/Toolchain-cross-m32.cmake

How to Use CCache with CMake?

I would like to do the following: If CCache is present in PATH, use "ccache g++" for compilation, else use g++. I tried writing a small my-cmake script containing
CC="ccache gcc" CXX="ccache g++" cmake $*
but it does not seem to work (running make still does not use ccache; I checked this using CMAKE_VERBOSE_MAKEFILE on).
Update:
As per this link I tried changing my script to
cmake -D CMAKE_CXX_COMPILER="ccache" -D CMAKE_CXX_COMPILER_ARG1="g++" -D CMAKE_C_COMPILER="ccache" -D CMAKE_C_COMPILER_ARG1="gcc" $*
but cmake bails out complaining that a test failed on using the compiler ccache (which can be expected).
As of CMAKE 3.4 you can do:
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
It is now possible to specify ccache as a launcher for compile commands and link commands (since cmake 2.8.0). That works for Makefile and Ninja generator. To do this, just set the following properties :
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) # Less useful to do it for linking, see edit2
endif(CCACHE_FOUND)
It is also possible to set these properties only for specific directories or targets.
For Ninja, this is possible since version 3.4.
For XCode, Craig Scott gives a workaround in his answer.
Edit : Thanks to uprego and Lekensteyn's comment, I edited the answer to check if ccache is available before using it as launcher and for which generators is it possible to use a compile launcher.
Edit2: #Emilio Cobos recommended to avoid doing that for the linking part as ccache doesn't improve linking speed and can mess with other types of cache like sccache
I personally have /usr/lib/ccache in my $PATH. This directory contains loads of symlinks for every possible name the compiler could be called from (like gcc and gcc-4.3), all pointing to ccache.
And I didn't even create the symlinks. That directory comes pre-filled when I install ccache on Debian.
From CMake 3.1, it is possible to use ccache with the Xcode generator and Ninja is supported from CMake 3.4 onwards. Ninja will honour RULE_LAUNCH_COMPILE just like the Unix Makefiles generator (so #Babcool's answer gets you there for Ninja too), but getting ccache working for the Xcode generator takes a little more work. The following article explains the method in detail, focussing on a general implementation which works for all three CMake generators and making no assumptions about setting up ccache symlinks or the underlying compiler used (it still lets CMake decide the compiler):
https://crascit.com/2016/04/09/using-ccache-with-cmake/
The general gist of the article is as follows. The start of your CMakeLists.txt file should be set up something like this:
cmake_minimum_required(VERSION 2.8)
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
# Support Unix Makefiles and Ninja
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
endif()
project(SomeProject)
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
if(RULE_LAUNCH_COMPILE AND CMAKE_GENERATOR STREQUAL "Xcode")
# Set up wrapper scripts
configure_file(launch-c.in launch-c)
configure_file(launch-cxx.in launch-cxx)
execute_process(COMMAND chmod a+rx
"${CMAKE_BINARY_DIR}/launch-c"
"${CMAKE_BINARY_DIR}/launch-cxx")
# Set Xcode project attributes to route compilation through our scripts
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx")
endif()
The two script template files launch-c.in and launch-cxx.in look like this (they should be in the same directory as the CMakeLists.txt file):
launch-c.in:
#!/bin/sh
export CCACHE_CPP2=true
exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_C_COMPILER}" "$#"
launch-cxx.in:
#!/bin/sh
export CCACHE_CPP2=true
exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_CXX_COMPILER}" "$#"
The above uses RULE_LAUNCH_COMPILE alone for Unix Makefiles and Ninja, but for the Xcode generator it relies on help from CMake's CMAKE_XCODE_ATTRIBUTE_... variables support. The setting of the CC and CXX user-defined Xcode attributes to control the compiler command and LD and LDPLUSPLUS for the linker command is not, as far as I can tell, a documented feature of Xcode projects, but it does seem to work. If anyone can confirm it is officially supported by Apple, I'll update the linked article and this answer accordingly.
I didn't like to set a symlink from g++ to ccache. And CXX="ccache g++" didn't work for me as some cmake test case wanted to have just the compiler program without attributes.
So I used a small bash script instead:
#!/bin/bash
ccache g++ "$#"
and saved it as an executable in /usr/bin/ccache-g++.
Then C configured cmake to use /usr/bin/ccache-g++ as C++ compiler.
This way it passes the cmake test cases and I feel more comfortable than having symlinks that I might forget about in 2 or 3 weeks and then maybe wonder if something doesn't work...
I verified the following works (source: this link):
CC="gcc" CXX="g++" cmake -D CMAKE_CXX_COMPILER="ccache" -D CMAKE_CXX_COMPILER_ARG1="g++" -D CMAKE_C_COMPILER="ccache" -D CMAKE_C_COMPILER_ARG1="gcc" $*
Update: I later realized that even this does not work. Strangely it works every alternate time (the other times cmake complains).
Let me add one important item that was not mentioned here before.
While bootstrapping a minimalistic build system from the ubuntu:18.04 docker image, I've found that order of installation makes a difference.
In my case ccache worked fine when calling gcc, but failed to catch invocations of the same compiler by the other names: cc and c++.
To fully install ccache, you need to make sure all compilers are installed first, or add a call to update-ccache symlinks to be safe.
sudo /usr/sbin/update-ccache-symlinks
export PATH="/usr/lib/ccache/:$PATH"```
... and then (due to updated symlinks) also calls to cc and c++ get caught!
In my opinion the best way is to symlink gcc,g++ to ccache, but if you would like to use within cmake, try this:
export CC="ccache gcc" CXX="ccache g++" cmake ...
Here are 2 methods I think are clean/robust, and also don't pollute your CMake code.
1.) Set environment variables
This method is nice since you don't have to individually set it up for each CMake project. The con is you may not want ccache for each CMake project.
# Requires CMake 3.17 (https://cmake.org/cmake/help/latest/envvar/CMAKE_LANG_COMPILER_LAUNCHER.html)
export CMAKE_CXX_COMPILER_LAUNCHER=/usr/bin/ccache
export CMAKE_C_COMPILER_LAUNCHER=/usr/bin/ccache
2.) Pass in cache variables during project configuration
Con a bit annoying to do for each project. This can be negated by your IDE though.
# Requires CMake 3.4
$ cmake ... -D CMAKE_CXX_COMPILER_LAUNCHER=/usr/bin/ccache \
-D CMAKE_C_COMPILER_LAUNCHER=/usr/bin/ccache
NOTE: It isn't really necessary to specify the full path.
If ccache is in your path you can just specify ccache instead.
export CMAKE_CXX_COMPILER_LAUNCHER=ccache
export CMAKE_C_COMPILER_LAUNCHER=ccache
It is extending #Nicolas answer.
Add following line to your cmake file:
list(PREPEND CMAKE_PROGRAM_PATH /usr/lib/ccache)
Or add it as argument to cmake configuration step:
cmake -DCMAKE_PROGRAM_PATH=/usr/lib/ccache