CMakeLists.txt 11.3 KB
Newer Older
Ken Martin's avatar
Ken Martin committed
1
cmake_minimum_required (VERSION 2.6)
2
project(TryCompile)
3

4 5 6
macro(TEST_ASSERT value msg)
  if (NOT ${value})
    message (SEND_ERROR "Assertion failure:" ${msg} )
7 8
  endif ()
endmacro()
Alexander Neundorf's avatar
 
Alexander Neundorf committed
9

10 11 12
macro(TEST_FAIL value msg)
  if (${value})
    message (SEND_ERROR "Failing test succeeded:" ${msg} )
13 14
  endif ()
endmacro()
Alexander Neundorf's avatar
 
Alexander Neundorf committed
15

16 17 18
macro(TEST_EXPECT_EXACT command expected)
  if(NOT "x${result}" STREQUAL "x${expected}")
    message(SEND_ERROR "${CMAKE_CURRENT_LIST_LINE}: TEST \"${command}\" failed: \"${result}\" expected: \"${expected}\"")
19 20
  endif()
endmacro()
Alexander Neundorf's avatar
 
Alexander Neundorf committed
21

22 23 24
macro(TEST_EXPECT_CONTAINS command expected)
  if(NOT "${result}" MATCHES "${expected}")
    message(SEND_ERROR "${CMAKE_CURRENT_LIST_LINE}: TEST \"${command}\" failed: \"${result}\" expected: \"${expected}\"")
25 26
  endif()
endmacro()
Alexander Neundorf's avatar
 
Alexander Neundorf committed
27

Bill Hoffman's avatar
Bill Hoffman committed
28

29
# try to compile a file that should compile
Alexander Neundorf's avatar
 
Alexander Neundorf committed
30
# also check that COPY_FILE works
31
try_compile(SHOULD_PASS
32
    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
33
    ${TryCompile_SOURCE_DIR}/pass.c
Alexander Neundorf's avatar
 
Alexander Neundorf committed
34 35 36 37
    OUTPUT_VARIABLE TRY_OUT
    COPY_FILE ${TryCompile_BINARY_DIR}/CopyOfPass
    )

38 39
if(NOT SHOULD_PASS)
  message(SEND_ERROR "should pass failed ${TRY_OUT}")
40
endif()
41 42
if(NOT EXISTS "${TryCompile_BINARY_DIR}/CopyOfPass")
   message(SEND_ERROR "COPY_FILE to \"${TryCompile_BINARY_DIR}/CopyOfPass\" failed")
43
else()
44
   file(REMOVE "${TryCompile_BINARY_DIR}/CopyOfPass")
45
endif()
46

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
# try to compile a file that should compile
# also check that COPY_FILE_ERROR works
file(WRITE ${TryCompile_BINARY_DIR}/invalid "")
try_compile(SHOULD_PASS
    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
    ${TryCompile_SOURCE_DIR}/pass.c
    OUTPUT_VARIABLE TRY_OUT
    COPY_FILE ${TryCompile_BINARY_DIR}/invalid/path
    COPY_FILE_ERROR _captured
    )
if(NOT SHOULD_PASS)
  message(SEND_ERROR "should pass failed ${TRY_OUT}")
endif()
if(NOT _captured MATCHES "Cannot copy output executable.*/invalid/path")
  message(SEND_ERROR "COPY_FILE_ERROR did not capture expected message")
endif()

64
# try to compile a file that should not compile
65
try_compile(SHOULD_FAIL
66
    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
67
    ${TryCompile_SOURCE_DIR}/fail.c
68
    OUTPUT_VARIABLE TRY_OUT)
69 70
if(SHOULD_FAIL)
   message(SEND_ERROR "Should fail passed ${TRY_OUT}")
71
endif()
72 73

# try to compile a file that should compile
74
try_compile(SHOULD_PASS
75
    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
76
    ${TryCompile_SOURCE_DIR}/pass.c
77
    OUTPUT_VARIABLE TRY_OUT)
78 79
if(NOT SHOULD_PASS)
  message(SEND_ERROR "should pass failed ${TRY_OUT}")
80
endif()
81 82

# try to compile a file that should not compile
83
try_compile(SHOULD_FAIL
84
    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
85
    ${TryCompile_SOURCE_DIR}/fail.c
86
    OUTPUT_VARIABLE TRY_OUT)
87 88
if(SHOULD_FAIL)
   message(SEND_ERROR "Should fail passed ${TRY_OUT}")
89
endif()
90

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
# try to compile two files that should compile
try_compile(SHOULD_PASS
    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
    SOURCES ${TryCompile_SOURCE_DIR}/pass2a.c ${TryCompile_SOURCE_DIR}/pass2b.cxx
    OUTPUT_VARIABLE TRY_OUT)
if(NOT SHOULD_PASS)
  message(SEND_ERROR "should pass failed ${TRY_OUT}")
endif()

# try to compile two files that should not compile
try_compile(SHOULD_FAIL
    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
    SOURCES ${TryCompile_SOURCE_DIR}/fail2a.c ${TryCompile_SOURCE_DIR}/fail2b.c
    OUTPUT_VARIABLE TRY_OUT)
if(SHOULD_FAIL)
   message(SEND_ERROR "Should fail passed ${TRY_OUT}")
endif()

109 110
# try to compile a file that should compile
set(_c_flags "${CMAKE_C_FLAGS}")
Brad King's avatar
Brad King committed
111
if(WATCOM)
Daniel Pfeifer's avatar
Daniel Pfeifer committed
112
  string(APPEND CMAKE_C_FLAGS " -dTESTDEF")
113
else()
Daniel Pfeifer's avatar
Daniel Pfeifer committed
114
  string(APPEND CMAKE_C_FLAGS " \"-DTESTDEF\"")
115 116 117 118 119 120 121 122 123 124
endif()
try_compile(SHOULD_PASS
    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
    ${TryCompile_SOURCE_DIR}/testdef.c
    OUTPUT_VARIABLE TRY_OUT)
if(NOT SHOULD_PASS)
  message(SEND_ERROR "should pass failed ${TRY_OUT}")
endif()
set(CMAKE_C_FLAGS "${_c_flags}")

125 126 127
if(NOT SHOULD_FAIL)
  if(SHOULD_PASS)
    message("All Tests passed, ignore all previous output.")
128
  else()
129
    message("Test failed")
130 131
  endif()
else()
132
  message("Test failed")
133
endif()
134
try_compile(CMAKE_ANSI_FOR_SCOPE
135
  ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
136
    ${CMAKE_ROOT}/Modules/TestForAnsiForScope.cxx OUTPUT_VARIABLE OUT)
137 138
if (CMAKE_ANSI_FOR_SCOPE)
   message("Compiler supports ansi for")
139
else()
140
   message("Compiler does not support ansi for scope")
141
endif()
142

143
try_compile(CMAKE_ANSI_FOR_SCOPE
144
  ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
145
    ${CMAKE_ROOT}/Modules/TestForAnsiForScope.cxx OUTPUT_VARIABLE OUT)
146 147
if (CMAKE_ANSI_FOR_SCOPE)
   message("Compiler supports ansi for")
148
else()
149
   message("Compiler does not support ansi for scope")
150
endif()
151 152 153 154 155

message("use the module now")
include(${CMAKE_ROOT}/Modules/TestForANSIForScope.cmake)
if (CMAKE_ANSI_FOR_SCOPE)
   message("Compiler supports ansi for")
156
else()
157
   message("Compiler does not support ansi for scope")
158
endif()
159 160 161

message("Testing try_compile project mode")
try_compile(TEST_INNER
Brad King's avatar
Brad King committed
162 163
  ${TryCompile_BINARY_DIR}/CMakeFiles/Inner
  ${TryCompile_SOURCE_DIR}/Inner
164 165 166
  TryCompileInner innerexe
  OUTPUT_VARIABLE output)
TEST_ASSERT(TEST_INNER "try_compile project mode failed:\n${output}")
Brad King's avatar
Brad King committed
167

168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
try_compile(COMPILE_DEFINITIONS_LIST_EXPANDED
    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
    ${TryCompile_SOURCE_DIR}/check_a_b.c
    OUTPUT_VARIABLE output
    COMPILE_DEFINITIONS "-DDEF_A;-DDEF_B"
    )
if(COMPILE_DEFINITIONS_LIST_EXPANDED)
  message(STATUS "COMPILE_DEFINITIONS list expanded correctly")
else()
  string(REPLACE "\n" "\n  " output "  ${output}")
  message(SEND_ERROR "COMPILE_DEFINITIONS list did not expand correctly\n${output}")
endif()

try_compile(SHOULD_FAIL_DUE_TO_BAD_SOURCE
    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
    ${TryCompile_SOURCE_DIR}/pass.c
    OUTPUT_VARIABLE output
    COMPILE_DEFINITIONS "bad#source.c"
    )
if(SHOULD_FAIL_DUE_TO_BAD_SOURCE AND NOT CMAKE_GENERATOR MATCHES "Watcom WMake|NMake Makefiles")
  string(REPLACE "\n" "\n  " output "  ${output}")
  message(SEND_ERROR "try_compile with bad#source.c did not fail:\n${output}")
elseif(NOT output MATCHES [[(bad#source\.c|bad\\)]])
  string(REPLACE "\n" "\n  " output "  ${output}")
  message(SEND_ERROR "try_compile with bad#source.c failed without mentioning bad source:\n${output}")
else()
  message(STATUS "try_compile with bad#source.c correctly failed")
endif()

197
add_executable(TryCompile pass.c)
Alexander Neundorf's avatar
 
Alexander Neundorf committed
198 199 200 201 202 203

######################################

# now two tests for TRY_RUN

# try to run a file that should compile and run without error
Alexander Neundorf's avatar
 
Alexander Neundorf committed
204 205
# also check that OUTPUT_VARIABLE contains both the compile output
# and the run output
206
try_run(SHOULD_RUN SHOULD_COMPILE
207
    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
Alexander Neundorf's avatar
 
Alexander Neundorf committed
208 209
    ${TryCompile_SOURCE_DIR}/exit_success.c
    OUTPUT_VARIABLE TRY_OUT)
210 211
if(NOT SHOULD_COMPILE)
  message(SEND_ERROR "exit_success failed compiling: ${TRY_OUT}")
212
endif()
213 214
if(NOT "${SHOULD_RUN}" STREQUAL "0")
  message(SEND_ERROR "exit_success failed running with exit code ${SHOULD_RUN}")
215
endif()
Alexander Neundorf's avatar
 
Alexander Neundorf committed
216
# check the compile output for the filename
217 218
if(NOT "${TRY_OUT}" MATCHES "exit_success")
  message(SEND_ERROR " TRY_OUT didn't contain \"exit_success\": \"${TRY_OUT}\"")
219
endif()
Alexander Neundorf's avatar
 
Alexander Neundorf committed
220
# check the run output
221 222
if(NOT "${TRY_OUT}" MATCHES "hello world")
  message(SEND_ERROR " TRY_OUT didn't contain \"hello world\": \"${TRY_OUT}\"")
223
endif()
Alexander Neundorf's avatar
 
Alexander Neundorf committed
224

225
try_run(ARG_TEST_RUN ARG_TEST_COMPILE
226
    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
227 228 229
    ${TryCompile_SOURCE_DIR}/expect_arg.c
    OUTPUT_VARIABLE TRY_OUT
    ARGS arg1 arg2)
230 231
if(NOT ARG_TEST_COMPILE)
  message(SEND_ERROR "expect_arg failed compiling: ${TRY_OUT}")
232
endif()
233 234
if(NOT "${ARG_TEST_RUN}" STREQUAL "0")
  message(SEND_ERROR "expect_arg failed running with exit code ${ARG_TEST_RUN} ${TRY_OUT}")
235
endif()
Alexander Neundorf's avatar
 
Alexander Neundorf committed
236 237

# try to run a file that should compile and run, but return an error
238
try_run(SHOULD_EXIT_WITH_ERROR SHOULD_COMPILE
239
    ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp
Alexander Neundorf's avatar
 
Alexander Neundorf committed
240
    ${TryCompile_SOURCE_DIR}/exit_with_error.c
Alexander Neundorf's avatar
 
Alexander Neundorf committed
241 242 243
    COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT
    RUN_OUTPUT_VARIABLE RUN_OUTPUT)

244 245
if(NOT SHOULD_COMPILE)
  message(STATUS " exit_with_error failed compiling: ${COMPILE_OUTPUT}")
246
endif()
247 248
if("${SHOULD_EXIT_WITH_ERROR}" STREQUAL "0")
  message(SEND_ERROR " exit_with_error passed with exit code ${SHOULD_EXIT_WITH_ERROR}")
249
endif()
Alexander Neundorf's avatar
 
Alexander Neundorf committed
250

Alexander Neundorf's avatar
 
Alexander Neundorf committed
251
# check the compile output, it should contain the filename
252 253
if(NOT "${COMPILE_OUTPUT}" MATCHES "exit_with_error")
  message(SEND_ERROR " COMPILE_OUT didn't contain \"exit_with_error\": \"${COMPILE_OUTPUT}\"")
254
endif()
Alexander Neundorf's avatar
 
Alexander Neundorf committed
255
#... but not the run time output
256 257
if("${COMPILE_OUTPUT}" MATCHES "hello world")
  message(SEND_ERROR " COMPILE_OUT contains the run output: \"${COMPILE_OUTPUT}\"")
258
endif()
Alexander Neundorf's avatar
 
Alexander Neundorf committed
259
# check the run output, it should stdout
260 261
if(NOT "${RUN_OUTPUT}" MATCHES "hello world")
  message(SEND_ERROR " RUN_OUTPUT didn't contain \"hello world\": \"${RUN_OUTPUT}\"")
262
endif()
Alexander Neundorf's avatar
 
Alexander Neundorf committed
263 264 265 266 267 268

#######################################################################
#
# also test that the CHECK_C_SOURCE_COMPILES, CHECK_CXX_SOURCE_COMPILES
# CHECK_C_SOURCE_RUNS and CHECK_CXX_SOURCE_RUNS macros work

269 270 271 272
include(CheckCSourceCompiles)
include(CheckCXXSourceCompiles)
include(CheckCSourceRuns)
include(CheckCXXSourceRuns)
Alexander Neundorf's avatar
 
Alexander Neundorf committed
273

Luz Paz's avatar
Luz Paz committed
274
CHECK_C_SOURCE_COMPILES("I don't build" C_BUILD_SHOULD_FAIL)
Alexander Neundorf's avatar
 
Alexander Neundorf committed
275 276 277 278 279 280 281 282 283
CHECK_C_SOURCE_COMPILES("int main() {return 0;}" C_BUILD_SHOULD_WORK)
CHECK_C_SOURCE_RUNS("int main() {return 1;}" C_RUN_SHOULD_FAIL)
CHECK_C_SOURCE_RUNS("int main() {return 0;}" C_RUN_SHOULD_WORK)

TEST_FAIL(C_BUILD_SHOULD_FAIL "CHECK_C_SOURCE_COMPILES() succeeded, but should have failed")
TEST_ASSERT(C_BUILD_SHOULD_WORK "CHECK_C_SOURCE_COMPILES() failed")
TEST_FAIL(C_RUN_SHOULD_FAIL "CHECK_C_SOURCE_RUNS() succeeded, but should have failed")
TEST_ASSERT(C_RUN_SHOULD_WORK "CHECK_C_SOURCE_RUNS() failed")

Luz Paz's avatar
Luz Paz committed
284
CHECK_CXX_SOURCE_COMPILES("I don't build" CXX_BUILD_SHOULD_FAIL)
Alexander Neundorf's avatar
 
Alexander Neundorf committed
285 286 287 288 289 290 291 292 293
CHECK_CXX_SOURCE_COMPILES("int main() {return 0;}" CXX_BUILD_SHOULD_WORK)
CHECK_CXX_SOURCE_RUNS("int main() {return 2;}" CXX_RUN_SHOULD_FAIL)
CHECK_CXX_SOURCE_RUNS("int main() {return 0;}" CXX_RUN_SHOULD_WORK)

TEST_FAIL(CXX_BUILD_SHOULD_FAIL "CHECK_CXX_SOURCE_COMPILES() succeeded, but should have failed")
TEST_ASSERT(CXX_BUILD_SHOULD_WORK "CHECK_CXX_SOURCE_COMPILES() failed")
TEST_FAIL(CXX_RUN_SHOULD_FAIL "CHECK_CXX_SOURCE_RUNS() succeeded, but should have failed")
TEST_ASSERT(CXX_RUN_SHOULD_WORK "CHECK_CXX_SOURCE_RUNS() failed")

294
foreach(lang C CXX)
295
  if(NOT CMAKE_${lang}_COMPILER_ID STREQUAL "PathScale")
296 297 298
    set(${lang}_DD --)
  endif()
endforeach()
299

300 301
unset(C_BOGUS_FLAG CACHE)
include(CheckCCompilerFlag)
302
CHECK_C_COMPILER_FLAG(${C_DD}-_this_is_not_a_flag_ C_BOGUS_FLAG)
303 304
TEST_FAIL(C_BOGUS_FLAG "CHECK_C_COMPILER_FLAG() succeeded, but should have failed")

305 306
unset(CXX_BOGUS_FLAG CACHE)
include(CheckCXXCompilerFlag)
307
CHECK_CXX_COMPILER_FLAG(${CXX_DD}-_this_is_not_a_flag_ CXX_BOGUS_FLAG)
308
TEST_FAIL(CXX_BOGUS_FLAG "CHECK_CXX_COMPILER_FLAG() succeeded, but should have failed")
309

310
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
311
  unset(C_STRICT_PROTOTYPES CACHE)
312 313
  CHECK_C_COMPILER_FLAG("-Werror;-Wstrict-prototypes" C_STRICT_PROTOTYPES)
  TEST_ASSERT(C_STRICT_PROTOTYPES "CHECK_C_COMPILER_FLAG failed -Werror -Wstrict-prototypes")
314
endif()
315 316 317 318 319 320 321 322 323 324 325 326 327

#######################################################################
#
# also test that the check_prototype_definition macro works

include(CheckPrototypeDefinition)

check_prototype_definition(remove
  "int remove(const char *pathname)"
  "0"
  "stdio.h"
  TEST_REMOVE_PROTO)
test_assert(TEST_REMOVE_PROTO "check_prototype_definition for remove() failed")