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:
char somearray[boolean_compile_time_expression ? 1 : -1];
to learn the value of boolean_compile_time_expression
.2 * lastbound + 1
(positive case).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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With