[Cmake] FILE WRITE and TRY_COMPILE

Amitha Perera perera at cs.rpi.edu
Thu, 6 May 2004 15:47:37 -0400


On Thu 06 May 2004, Andy Cedilnik wrote:
> Could you write example for where it fails?

See below.

On Thu 06 May 2004, William A. Hoffman wrote:
> To clarify further, the problem that FILE_WRITE is talking about
> only happens when you do something like this:
> 
> FILE_WRITE(foo.cmake)
> INCLUDE(foo.cmake)

That's what I thought. However, the error made me think I'd misunderstood.

> TRY_COMPILE creates a completely separate cmake environment.   I suppose
> if you put the FILE_WRITE into a CMakeList file in a trycompile directory
> you would get the error and would have a problem.  Is that the case
> in VXL?

I don't think so. The revelant macro is below. As far as I can tell,
the cause is what is now the CONFIGURE_FILE line, just before the
TRY_COMPILE. (The contents of the cxx.in file is below the macro
code.) Previously, the CONFIGURE_FILE line used to be a FILE WRITE:


        FILE(WRITE ${CHECK_PROTOTYPE_EXISTS_FILE}
          "#include <${FILE}>\n"
          ${CHECK_PROTOTYPE_EXISTS_EXTERNC_BEGIN}
          "typedef union { int member; } dummyStruct;\n"
          "dummyStruct ${FUNC}( dummyStruct );\n"
          ${CHECK_PROTOTYPE_EXISTS_EXTERNC_END}
          "int main(){return 0;}\n" )


This caused an error: 

   CMake Error: File c:/software/tmp/CheckPrototypeExists.cxx is
   written by WRITE_FILE (or FILE WRITE) command and should not be used
   as input to CMake. Please use CONFIGURE_FILE to be safe. Refer to the
   note next to FILE WRITE command.


Amitha.


-------- CheckPrototypeExistsCXX.cmake ------------------------------------

#
# This checks if a prototype for FUNC (with C linkage) has been
# declared in any one of the header files listed in INCLUDE. It uses
# the C++ compiler.
#
# (The check is actually whether declaring a prototype will cause a
# conflict and thus an error. The results may differ depending on the
# compiler. For example, gcc under Cygwin will issue a warning but g++
# will issue an error. In the DCMTK, the prototypes are used in a C++
# context, so we use the C++ compiler to check.
#
MACRO(CHECK_PROTOTYPE_EXISTS_CXX FUNC INCLUDE VARIABLE)
  IF("${VARIABLE}" MATCHES "^${VARIABLE}$")
    SET( CHECK_PROTOTYPE_EXISTS_CXX_FILE_IN "${VXL_CMAKE_DIR}/CheckPrototypeExists.cxx.in" )
    SET( CHECK_PROTOTYPE_EXISTS_CXX_FILE "${CMAKE_BINARY_DIR}/CMakeTmp/CheckPrototypeExists.cxx" )
    SET( CHECK_PROTOTYPE_EXISTS_CXX_EXTERNC_BEGIN "extern \"C\" {\n" )
    SET( CHECK_PROTOTYPE_EXISTS_CXX_EXTERNC_END "}\n" )

    SET(MACRO_CHECK_PROTOTYPE_EXISTS_CXX_FLAGS ${CMAKE_REQUIRED_FLAGS})
    MESSAGE(STATUS "Looking for prototype for ${FUNC} in ${INCLUDE}")

    SET( ${VARIABLE} 0 )
    FOREACH(FILE ${INCLUDE})

      # First check if the header exists. Cache the result in a variable named after
      # the header, so that we don't re-do the effort
      STRING( REGEX REPLACE "\\.|/" "_" CLEAN_FILE ${FILE} )
      SET( CHECK_PROTOTYPE_EXISTS_CXX_INCLUDE "CHECK_PROTOTYPE_EXISTS_CXX_INCLUDE_${CLEAN_FILE}" )
      CHECK_INCLUDE_FILE( ${FILE} ${CHECK_PROTOTYPE_EXISTS_CXX_INCLUDE} )
      IF( CHECK_PROTOTYPE_EXISTS_CXX_INCLUDE )

        FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeOutput.log "Trying struct with ${FILE}\n" )
        CONFIGURE_FILE( ${CHECK_PROTOTYPE_EXISTS_CXX_FILE_IN}
                        ${CHECK_PROTOTYPE_EXISTS_CXX_FILE} IMMEDIATE )

        TRY_COMPILE( CHECK_PROTOTYPE_EXISTS_CXX_RESULT
          ${CMAKE_BINARY_DIR}
          ${CHECK_PROTOTYPE_EXISTS_CXX_FILE}
          CMAKE_FLAGS 
          -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_PROTOTYPE_EXISTS_CXX_FLAGS}
          OUTPUT_VARIABLE OUTPUT)
        IF( CHECK_PROTOTYPE_EXISTS_CXX_RESULT ) 
          FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeOutput.log 
            "Determining if prototype ${FUNC} exists in ${FILE} "
            "failed with the following output:\n"
            "${OUTPUT}\n\n")
        ELSE( CHECK_PROTOTYPE_EXISTS_CXX_RESULT ) 
          FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeOutput.log 
            "Determining if prototype ${FUNC} exists in ${FILE} "
            "passed with the following output:\n"
            "${OUTPUT}\n\n")
          MESSAGE(STATUS "    Found in ${FILE}")
          SET( ${VARIABLE} 1 )
        ENDIF( CHECK_PROTOTYPE_EXISTS_CXX_RESULT )

      ENDIF( CHECK_PROTOTYPE_EXISTS_CXX_INCLUDE )
    ENDFOREACH(FILE)

    IF( ${VARIABLE} )
      MESSAGE(STATUS "Looking for prototype of ${FUNC} - found")
      SET(${VARIABLE} 1 CACHE INTERNAL "Have prototype ${VARIABLE}")
    ELSE(${VARIABLE})
      MESSAGE(STATUS "Looking for prototype of ${FUNC} - not found")
      SET(${VARIABLE} "" CACHE INTERNAL "Have prototype ${VARIABLE}")
    ENDIF(${VARIABLE})
  ENDIF("${VARIABLE}" MATCHES "^${VARIABLE}$")
ENDMACRO(CHECK_PROTOTYPE_EXISTS_CXX)




------- CheckPrototypeExists.cxx.in ---------------------------------------


${CHECK_PROTOTYPE_EXISTS_CXX_EXTERNC_BEGIN}

typedef union { int member; } dummyStruct;

dummyStruct ${FUNC}( dummyStruct );

${CHECK_PROTOTYPE_EXISTS_CXX_EXTERNC_END}

int main() {
  return 0;
}

---------------------------------------------------------------------------