Logically I want to do something like this in my cmake build (given in pseudo C++)
exceptions_flag =
Compiler == Clang || Compiler == GCC ? "-fexceptions"
: Compiler == MSVC ? "/U_HAS_EXCEPTIONS;/D_HAS_EXCEPTIONS=1;/EHsc"
I'm not sure how to do this in one step with cmake generators the best I can think of is
set(EXCEPTIONS_FLAG
$<$<CXX_COMPILER_ID:MSVC>:"/U_HAS_EXCEPTIONS;/D_HAS_EXCEPTIONS=1;/EHsc">
if(NOT ${EXCEPTIONS_FLAG})
set(EXCEPTIONS_FLAG "-fexceptions")
endif()
Is there a better way to do this?
Related
For autotools there is a Macro called AC_COMPUTE_INT. It can be used to compute (detect) an integral compile time expression. How to do that in CMake?
A naive approach could be using try_run to output the number. However that breaks cross compilation and AC_COMPUTE_INT works with cross compilation by bisecting the number with compilation steps.
Edit:
The autotools AC_COMPUTE_INT works as follows:
It has a short-cut when not cross compiling and just runs a program to make things faster.
It repeatedly compiles a program containing (something similar to) char somearray[boolean_compile_time_expression ? 1 : -1]; to learn the value of boolean_compile_time_expression.
It first uses such an expression to check the sign of the integer expression being asked.
Then it looks for a bound of the integer expression by repeatedly checking whether it is smaller than 2 * lastbound + 1 (positive case).
Once it found an upper and lower bound, it does a binary search inside to get the actual value.
It usually takes less than 50 compile tests. (It's a bit worse than testing for each bit individually in the worst case.) For many (in particular small) values, it takes much less tests.
Since it doesn't use anything but the equivalent of try_compile (in the cross case), it is as portable as try_compile.
AC_CHECK_SIZEOF uses AC_COMPUTE_INT and thus inherits its portability properties.
After a few dumps of gcc intermediate compilation steps I've ended up with -fdump-tree-original. Which seems quite easy to parse and contains values of already evaluated expressions and sizeof.
Example C source:
#define FANCY_VALUE sizeof(int) * 10
int main(int argc, char **argv)
{
return FANCY_VALUE;
}
Result of gcc -fdump-tree-original example.c:
;; Function main (null)
;; enabled by -tree-original
{
return 40;
}
return 0;
Sooo... One of probably non-portable and gcc specific ways might look like this:
cmake_minimum_required(VERSION 3.5)
# AC_COMPUTE_INT function doing all the lifting
function(AC_COMPUTE_INT OUTPUT_VAR INPUT_EXP)
set(C_FILE ${CMAKE_BINARY_DIR}/ac_computer.c)
set(DUMP_FILE ${CMAKE_BINARY_DIR}/ac_computer.dump)
file(WRITE ${C_FILE}
"int main(int argc, char **argv) { return ${INPUT_EXP};}"
)
execute_process(
COMMAND ${CMAKE_C_COMPILER} -c -fdump-tree-original=${DUMP_FILE} ${C_FILE}
)
file(READ ${DUMP_FILE} AC_COMPUTER_DUMP)
string(REGEX MATCH "return [0-9]+" DUMP_MATCH ${AC_COMPUTER_DUMP})
string(REGEX REPLACE "return " "" DUMP_MATCH ${DUMP_MATCH})
set(${OUTPUT_VAR} "${DUMP_MATCH}" PARENT_SCOPE)
endfunction()
set(MY_FANCY_INPUT "sizeof(int) * 8 + 1")
AC_COMPUTE_INT(MY_FANCY_OUTPUT ${MY_FANCY_INPUT})
message(STATUS "Expression: ${MY_FANCY_INPUT}")
message(STATUS "Evaluates to: ${MY_FANCY_OUTPUT}"
Which brings us the following:
$ cmake ../
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Expression: sizeof(int) * 8 + 1
-- Evaluates to: 33
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/c_test/bin
EDIT:
as far as I get from autoconf source, it does series of compile cycles with possible size values (binary search between lo and hi bounds). Event thought, still not sure how exactly it connects to proper expression execution.
EDIT2:
relevant autoconf commit and source of _AC_COMPUTE_INT
OK, giving it another shot. Dumb bruteforce in the right direction of the value using _Static_assert() from C11. Bruteforce part to be updated to proper binary search.
cmake_minimum_required(VERSION 3.5)
set(CMAKE_C_STANDARD 11)
# we need this gimmic because math(EXPR ...) does not work well with negative numbers
function (INC OUTPUT_VAR NUMBER)
if (${NUMBER} LESS 0)
math(EXPR res_var "0 ${NUMBER} + 1")
else()
math(EXPR res_var "${NUMBER} + 1")
endif()
set(${OUTPUT_VAR} ${res_var} PARENT_SCOPE)
endfunction()
function (DEC OUTPUT_VAR NUMBER)
if (${NUMBER} LESS 0)
math(EXPR res_var "0 ${NUMBER} - 1")
else()
math(EXPR res_var "${NUMBER} - 1")
endif()
set(${OUTPUT_VAR} ${res_var} PARENT_SCOPE)
endfunction()
# passing expression through pipe to C compiler instead of file.
# can be done in more portable manner, of course
function(GCC_ASSERT OUTPUT_VAR EXPRESSION)
execute_process(
COMMAND bash -c "echo '${EXPRESSION}' | ${CMAKE_C_COMPILER} -o /dev/null -xc -c -"
RESULT_VARIABLE result_var
OUTPUT_QUIET ERROR_QUIET
)
if (${result_var} EQUAL 0)
set(${OUTPUT_VAR} true PARENT_SCOPE)
else()
set(${OUTPUT_VAR} false PARENT_SCOPE)
endif()
endfunction()
function(GCC_IF_LESS OUTPUT_VAR A B)
set(C_EXPRESSION "_Static_assert(((signed int)${A}) < ((signed int)${B}), \"\")\;")
GCC_ASSERT(TEST_CON_LESS ${C_EXPRESSION})
set(${OUTPUT_VAR} ${TEST_CON_LESS} PARENT_SCOPE)
endfunction()
function(AC_COMPUTE_INT OUTPUT_VAR EXPRESSION)
set(MID_POINT 1)
# if expression evaluates to something < MID_POINT, keep decreasing it
# if expression evaluates to something > MID_POINT, keep increasing it
# if it's neither, we have the right MID_POINT which is equal to
# evaluated expression
while(true)
GCC_IF_LESS(EXPRESSION_IS_LESS ${EXPRESSION} ${MID_POINT})
GCC_IF_LESS(EXPRESSION_IS_MORE ${MID_POINT} ${EXPRESSION})
if (${EXPRESSION_IS_LESS})
DEC(MID_POINT ${MID_POINT})
elseif(${EXPRESSION_IS_MORE})
INC(MID_POINT ${MID_POINT})
else()
set(${OUTPUT_VAR} ${MID_POINT} PARENT_SCOPE)
break()
endif()
endwhile()
endfunction()
set(MY_FANCY_INPUT "sizeof(int) * 8 - 40")
AC_COMPUTE_INT(MY_FANCY_OUTPUT ${MY_FANCY_INPUT})
message(STATUS "Expression: ${MY_FANCY_INPUT}")
message(STATUS "Evaluates to: ${MY_FANCY_OUTPUT}")
Example output:
-- Expression: sizeof(int) * 8 - 40
-- Evaluates to: -8
-- Configuring done
-- Generating done
I'm not aware if there is an existing module for this.
However, here is an approach, that you can try to implement yourself. You can use execute_process to run ${CMAKE_C_COMPILER} -E on a file containing something like
// all #include's you need
xxx(YOUR_DEFINE)xxx
This would produce a file with xxx(<some_int>)xxx line. Now use CMake's file(READ and string(REGEX to pull that out.
I'd like to detect the current project language, for example if I have something like this:
cmake_minimum_required (VERSION 3.0)
project (foo VERSION 1.0 LANGUAGES CXX)
I need something like this
if (project_lang EQUAL "CXX")
# do something for c++
endif ()
Thanks!
You can use global property ENABLED_LANGUAGES:
get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES)
message("languages: ${languages}")
for project(Foo), i.e. default values:
languages: C;CXX;RC
for project(Foo LANGUAGES CXX), i.e. C++ project:
languages: CXX;RC
for project(Foo LANGUAGES C), i.e. C project:
languages: C;RC
etc.
The best command to check that the exact language is enabled is if(... IN_LIST ...) (available since CMake 3.3):
if("CXX" IN_LIST languages)
message("C++ enabled")
endif()
There are plenty of examples of using cmake to set a preprocessor value. I'm having the reverse problem -- I want to find the value of __GLIBCXX__ and then perform other cmake commands conditionally based on the result.
Up until now, I had been using the GCC version as a surrogate for libstdc++ functionality, like this:
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6)
....
# other gcc versions
....
endif()
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# and so on
endif()
The problem I'm now having is the fallout from a known issue with libstdc++ and gcc-4.8 c++11 regex support, and the fact on many setups clang reuses the system libstdc++, therefore inheriting the same problem. Under these circumstances, there's no version test for clang that will help, since it's specifically related to libstdc++, and my surrogate method of using the compiler version no longer works.
In order to fallback on Boost.Regex or PCRE if either clang or gcc are using the libstdc++ distributed with gcc-4.8 or earlier, the best way I can think of is to check if __GLIBCXX__ <= 20140404, but I can't see how to get cmake to do it in a straight-forward way, since clang might not always be using libstdc++, e.g. most OS X systems.
CheckVariableExists doesn't seem to help, I suppose for at least two reasons; firstly, a preprocessor macro isn't a variable, and secondly, it doesn't give the value, only indicates its presence.
You could use CHECK_CXX_SOURCE_COMPILES to compile a specific test which fails when your condition is not met:
INCLUDE (CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES(
"
#include <cstdio>
#ifdef __GLIBCXX__
#if __GLIBCXX__ <= 20140404
#error test failed
#endif
#endif
int main() { return 0;}
" GLIBCXX_TEST)
IF(NOT GLIBCXX_TEST)
MESSAGE(STATUS "__GLIBCXX__ test failed")
ENDIF()
Based on m.s.'s idea and taking Marc Glisse's observation about __GLIBCXX__ not being a reliable way to test for this, I wrote a CMake module to test for broken implementations of regex support. In order for this test to pass, the compiler will need to be targetting C++11 or higher.
Gist is here: https://gist.github.com/anonymous/7520ce6f64c63e2f8e79
Sample use:
include(CheckForRegex)
check_cxx_native_regex_works(USE_NATIVE_REGEX)
add_definitions("-DUSE_NATIVE_REGEX=${USE_NATIVE_REGEX}")
if (NOT USE_NATIVE_REGEX)
find_package(Boost REQUIRED COMPONENTS regex)
endif()
Note: This is my first time using CMake. I don't know much about it, so I'm just posting a bunch of information to see if anyone can see my problem.
I would like the ability to automatically determine which c++11 flag is appropriate, given my compiler. There are many examples of this line. Here is my CMakeLists.txt following such an example:
cmake_minimum_required (VERSION 2.8)
#Add the c++11 flag, whatever it is
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG(-std=c++0x COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
project(AnalyzeGames)
set(AnalyzeGames_SRCS AnalyzeGames.cpp)
add_executable(AnalyzeGames ${AnalyzeGames_SRCS})
Here is my cmake output when trying to use this file: http://pastebin.com/3AUwqffD
Here is CMakeError.log: http://pastebin.com/EbNKvGt8
Here is CMakeOutput.log: http://pastebin.com/kVJ0enJC
echo $CC: /usr/bin/gcc
echo $CXX: /usr/bin/g++
I can compile a simple test executable with g++ using either flag manually.
cmake --version: cmake version 2.8.12.2
For some reason CMake is not recognizing that my compiler does support both of those flags.
The cmake output tells you that it does not recognize the '.cxx' extension because it doesn't know that your project is a C++ project. To fix this, you should enable C++ in the project command. Try to change the following line:
project(AnalyzeGames)
to:
project(AnalyzeGames CXX)
and then move it to the 2nd line of the CMakeLists.txt, right under cmake_minimum_required. The configuration should work as expected after this.
TLDR
Compiler checks are only performed in the variable passed is not previously defined, which includes in the cache from previous failed attempts. Use unset(my_var CACHE) to force checking to always occur, or just be aware of this behaviour and clear the cache manually when needed.
Detail
I too had this problem (with cmake 2.8.12.2) and I had to turn on trace output, and step through the code to get a similar toy build to work I had make sure the variables I used (COMPILER_SUPPORTS_CXX11_*) in these calls:
CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG(-std=c++0x COMPILER_SUPPORTS_CXX0X)
Were set such that they named themselves:
set(COMPILER_SUPPORTS_CXX11 "COMPILER_SUPPORTS_CXX11")
The other posters solution didn't work for me, it mainly just seemed to limit the detecting of compilers to just CXX and ignored the C compiler.
The issue appears to be with this line of code in the cmake module:
if("${VAR}" MATCHES "^${VAR}$")
Which in the trace output is:
/usr/share/cmake/Modules/CheckCXXSourceCompiles.cmake(30): if(COMPILER_SUPPORTS_CXX0X MATCHES ^COMPILER_SUPPORTS_CXX0X$ )
It looks as if the expression on the left of the MATCHES is replaced with the variables value, but the expression on the right is assumed to be plain text.
If the MATCH fails then the main part of the macro is skipped and according the to the log the check fails.
Looking at later versions of this macro online it looks as if this line has changed to only perform the compile check if the variable is undefined.
It as at this point that I realise that this is the intent / hack of the original code; if the X is undefined then "X" MATCHES "^X$" will be true, but then the compile check can be performed, fail for some other reason and then never be performed again.
So the solution is either force unset of variable in cache before calling the macro using:
unset(COMPILER_SUPPORTS_CXX0X CACHE)
Or clear the cache manually and be prepared for this behaviour.
I try do compile my opencl kernel to llvm IR.
With the following instruction
/home/mypass/llvm/Debug+Asserts/bin/clang -I/home/ian031545/libclc/generic/include -include clc/clc.h -Dcl_clang_storage_class_specifiers -target nvptx--nvidiacl -Xclang -mlink-bitcode-file -Xclang /ian031545/libclc/nvptx--nvidiacl/lib/builtins.bc -S -emit-llvm kernel.cl -o kernel.ll
The opencl kernel's structure look like this
__kernel(){
if() x[i]=a+b+1
else x[i]=a+b+2
}
And the llvm IR after using the instruction above look like this
entry: // it perform a+b here , we say c
then part: // it perform c+1
else part: // it perform c+2
Does anyone know why does clang do this kind of optimization here ? ( we say it frontend )
Or it may not be a kind of optimization ?
I don't know why clang do this here , for what purpose ?
Can i ask clang not to do this by adding flag to the instruction above ?
Thanks in advance
Try using -O0 flag with clang.