Am Mittwoch, den 20.12.2006, 17:53 +0100 schrieb frederic heem:
> Hi,
> Is there a nice way to find out if a target is using -fPIC ?
> Indeed, this information is needed for generating compiled header. 
> At the moment, a kludge is to use the following code:
> 
>     #If the target is a shared library, add -fPIC to compile
>     GET_TARGET_PROPERTY(_targetType ${_targetName} TYPE)
>     IF(${_targetType} STREQUAL SHARED_LIBRARY)
>       SET(_compile_FLAGS "${_compile_FLAGS} -fPIC")
>     ENDIF(${_targetType} STREQUAL SHARED_LIBRARY)
> 
> This works but is not a proper solution, one shall not know in which 
> case -fPIC is used or not.
> Thanks,
> Frederic Heem

I ran into this problem and your solutions works like a charm. 

I also worked on msvc support(see attached file), but it only work if
CMAKE_BUILD_TYPE equals "Release", since /Fd wants to add debugging
informations and fails due to inconsitent pdb files. If someone know's
more about this issue, please give me a hint.

merry Christmas, Maik
# - Try to find precompiled headers support for GCC 3.4 and 4.x
# Once done this will define:
#
# Variable:
#   PCHSupport_FOUND
#
# Macro:
#   ADD_PRECOMPILED_HEADER

IF(CMAKE_COMPILER_IS_GNUCXX)

    EXEC_PROGRAM(
        ${CMAKE_CXX_COMPILER} 
        ARGS                    --version 
        OUTPUT_VARIABLE _compiler_output)
    STRING(REGEX REPLACE ".* ([0-9]\\.[0-9]\\.[0-9]) .*" "\\1" 
           gcc_compiler_version ${_compiler_output})
    #MESSAGE("GCC Version: ${gcc_compiler_version}")
    IF(gcc_compiler_version MATCHES "4\\.[0-9]\\.[0-9]")
        SET(PCHSupport_FOUND TRUE)
    ELSE(gcc_compiler_version MATCHES "4\\.[0-9]\\.[0-9]")
        IF(gcc_compiler_version MATCHES "3\\.4\\.[0-9]")
            SET(PCHSupport_FOUND TRUE)
        ENDIF(gcc_compiler_version MATCHES "3\\.4\\.[0-9]")
    ENDIF(gcc_compiler_version MATCHES "4\\.[0-9]\\.[0-9]")
    
        SET(_PCH_include_prefix "-I")
        
ELSE(CMAKE_COMPILER_IS_GNUCXX)
        
        SET(PCHSupport_FOUND TRUE) # for experimental msvc support
        SET(_PCH_include_prefix "/I")
        
ENDIF(CMAKE_COMPILER_IS_GNUCXX)



MACRO(_PCH_GET_COMPILE_FLAGS _out_compile_flags)


        STRING(TOUPPER "CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}" _flags_var_name)
    SET(_compile_FLAGS ${${_flags_var_name}} )


        IF(CMAKE_COMPILER_IS_GNUCXX)
        
        GET_TARGET_PROPERTY(_targetType ${_PCH_current_target} TYPE)
        IF(${_targetType} STREQUAL SHARED_LIBRARY)
                LIST(APPEND _compile_FLAGS "${_compile_FLAGS} -fPIC")
        ENDIF(${_targetType} STREQUAL SHARED_LIBRARY)
        
        ELSE(CMAKE_COMPILER_IS_GNUCXX)
                ## TODO ... ? or does it work out of the box 
        ENDIF(CMAKE_COMPILER_IS_GNUCXX)
        
        FOREACH(item ${_directory_flags})
                LIST(APPEND _compile_FLAGS "${_PCH_include_prefix}${item}")
    ENDFOREACH(item)

        GET_DIRECTORY_PROPERTY(_directory_flags DEFINITIONS)
    LIST(APPEND _compile_FLAGS ${_directory_flags})
        LIST(APPEND _compile_FLAGS ${CMAKE_CXX_FLAGS} )

    SEPARATE_ARGUMENTS(_compile_FLAGS)

ENDMACRO(_PCH_GET_COMPILE_FLAGS)



MACRO(_PCH_TEST_PATH _path )

        GET_DIRECTORY_PROPERTY(_directory_flags INCLUDE_DIRECTORIES)

        SET(_CMAKE_CURRENT_BINARY_DIR_included_before_path FALSE)
        FOREACH(item ${_directory_flags})
                IF(${item}  STREQUAL ${_path} AND NOT 
_CMAKE_CURRENT_BINARY_DIR_included_before_path )
                        MESSAGE(FATAL_ERROR 
                                "This is the ADD_PRECOMPILED_HEADER macro. "
                                "CMAKE_CURREN_BINARY_DIR has to mentioned at 
INCLUDE_DIRECTORIES's argument list before :${_path}:, where ${_name} is 
located"
                        )       
                ENDIF(${item}  STREQUAL ${_path} AND NOT 
_CMAKE_CURRENT_BINARY_DIR_included_before_path )
        
                IF(${item}  STREQUAL ${CMAKE_CURRENT_BINARY_DIR})
                        SET(_CMAKE_CURRENT_BINARY_DIR_included_before_path TRUE)
                ENDIF(${item}  STREQUAL ${CMAKE_CURRENT_BINARY_DIR})
    ENDFOREACH(item)
    
ENDMACRO(_PCH_TEST_PATH)



MACRO(_PCH_GET_COMPILE_COMMAND out_command _input _output)

        FILE(TO_NATIVE_PATH ${_input} _native_input)
        FILE(TO_NATIVE_PATH ${_output} _native_output)
        

        IF(CMAKE_COMPILER_IS_GNUCXX)
        
                SET(${out_command} 
                        ${CMAKE_CXX_COMPILER} ${_compile_FLAGS} -x c++-header 
-o ${_output} ${_input} 
                )
        
        ELSE(CMAKE_COMPILER_IS_GNUCXX)
                
                SET(_dummy_str "#include <${_input}>")
                FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/pch_dummy.cpp 
${_dummy_str})
        
                SET(${out_command} 
                        ${CMAKE_CXX_COMPILER} ${_compile_FLAGS} /c 
/Fp${_native_output} /Yc${_native_input} pch_dummy.cpp
                )       
                #/out:${_output}

        ENDIF(CMAKE_COMPILER_IS_GNUCXX)
        
ENDMACRO(_PCH_GET_COMPILE_COMMAND )



MACRO(_PCH_GET_TARGET_COMPILE_FLAGS _cflags  _header_name _pch_path  )

        FILE(TO_NATIVE_PATH ${_pch_path} _native_pch_path)
        message(${_native_pch_path})

        IF(CMAKE_COMPILER_IS_GNUCXX)
        
                set(${_cflags} "-include ${_header_name} -Winvalid-pch" )
        
        ELSE(CMAKE_COMPILER_IS_GNUCXX)

                set(${_cflags} "/Fp${_native_pch_path} /Yu${_header_name}" )    

        ENDIF(CMAKE_COMPILER_IS_GNUCXX) 

ENDMACRO(_PCH_GET_TARGET_COMPILE_FLAGS )



MACRO(ADD_PRECOMPILED_HEADER _targetName _input )

        SET(_PCH_current_target ${_targetName})

        IF(NOT CMAKE_BUILD_TYPE)
                MESSAGE(FATAL_ERROR 
                        "This is the ADD_PRECOMPILED_HEADER macro. " 
                        "You must set CMAKE_BUILD_TYPE!"
                )
        ENDIF(NOT CMAKE_BUILD_TYPE)

    GET_FILENAME_COMPONENT(_name ${_input} NAME)
        GET_FILENAME_COMPONENT(_path ${_input} PATH)
    SET(_outdir "${CMAKE_CURRENT_BINARY_DIR}/${_name}.gch")
        SET(_output "${_outdir}/${CMAKE_BUILD_TYPE}.c++")

    ADD_CUSTOM_COMMAND(
                OUTPUT ${_outdir}
                COMMAND mkdir ${_outdir} # TODO: {CMAKE_COMMAND} -E ... 
!doesn't work in win32
        )
    
    _PCH_TEST_PATH(_path)
    _PCH_GET_COMPILE_FLAGS(_compile_FLAGS)

    #MESSAGE("_compiler_FLAGS: ${_compiler_FLAGS}")
        message(${_compile_FLAGS} )
    #message("COMMAND ${CMAKE_CXX_COMPILER}     ${_compile_FLAGS} -x c++-header 
-o ${_output} ${_input}")
        
        ADD_CUSTOM_COMMAND(
                OUTPUT  ${CMAKE_CURRENT_BINARY_DIR}/${_name} 
                COMMAND ${CMAKE_COMMAND} -E copy  ${_input} 
${CMAKE_CURRENT_BINARY_DIR}/${_name} # ensure same directory! Required by gcc
        )

        #message("_command  ${_input} ${_output}")
        _PCH_GET_COMPILE_COMMAND(_command  ${_input} ${_output} )

        #message(${_input} )
        message("${_command}")

    ADD_CUSTOM_COMMAND(
        OUTPUT ${_output}       
                COMMAND ${_command}
        DEPENDS ${_input} ${_outdir} ${CMAKE_CURRENT_BINARY_DIR}/${_name}       
        )
        ADD_CUSTOM_TARGET(${_targetName}_gch 
                DEPENDS ${_output}      
        )
    ADD_DEPENDENCIES(${_targetName} ${_targetName}_gch )
   
   _PCH_GET_TARGET_COMPILE_FLAGS(_target_cflags ${_name} ${_output})
    
    #message("${_target_cflags}")
    
    SET_TARGET_PROPERTIES(${_targetName} 
                PROPERTIES      
                        COMPILE_FLAGS ${_target_cflags} 
    )
        
        
ENDMACRO(ADD_PRECOMPILED_HEADER)

_______________________________________________
CMake mailing list
CMake@cmake.org
http://www.cmake.org/mailman/listinfo/cmake

Reply via email to