[CMake] Help using CMake & Expat in Windows

Michael Jackson mike.jackson at bluequartz.net
Sat Jul 31 09:44:22 EDT 2010


On Fri, Jul 30, 2010 at 7:15 PM, John Drescher <drescherjm at gmail.com> wrote:
>> I have created a very simple CMake file (I am a newbie) that works
>> wonderfully in Linux, but am having problems in Windows.  The CMakeLists.txt
>> is below
>>
>> #I think 2.6 is required for some of things I do below, but I am not sure
>> CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
>>
>> # This is the CMake file for my application.  This
>> # will be my first CMake file of decent size, so please excuse
>> # any particularly bad syntax :)
>> PROJECT(MyApp)
>> FIND_PACKAGE(wxWidgets REQUIRED)
>> FIND_PACKAGE(OpenCV REQUIRED)
>> FIND_PACKAGE(EXPAT REQUIRED)
>> INCLUDE (${wxWidgets_USE_FILE} ${OpenCV_USE_FILE} ${EXPAT_INCLUDE_DIRS})
>>
>> SET(Headers myApp.h myAppGUI.h myAppGUImpl.h Coordinates/Coordinates.h)
>> SET(Src myApp.cpp myAppGUI.cpp myAppGUImpl.cpp Coordinates/Coordinates.cpp)
>> ADD_EXECUTABLE(myApp ${Headers} ${Src})
>> TARGET_LINK_LIBRARIES(myApp ${wxWidgets_LIBRARIES} ${OpenCV_LIBS}
>> ${EXPAT_LIBRARIES})
>>
>> #End of code
>>
>> Everything works great in Linux, but when I try to use this in Windows, I
>> have series of problems, all inter-related.
>>
>> Problem #1.  While wxWidgets and OpenCV work seamlessly, Cmake can't find
>> the expat libraries.  (They are installed.  I installed the expat libraries
>> using the basic windows download and install package).
>
> CMake rarely finds libraries on windows. The main reason is there is
> no OS standard path for libraries or header files. For me its even
> less likely to find stuff since I build on X: and not the same drive
> as the OS. To fix this normally you run cmake-gui and it tells me it
> can not find a package set the projectname_dir variable. After setting
> this variable in cmake-gui all is well.
>
>>
>> Problem #2.  While I can overcome problem #1 by hardcoding in where the
>> expat include directory and library files are (setting the values in the
>> CMake GUI), when I then open up the resulting solution in Visual Studio 2008
>> Express and compile my code, the compiler gives the error "can't find
>> expat.h"
>>
>
> That is normally the correct solution.
>
>>
>> Problem #3.  I can fix that problem as well by directly modifying the
>> solution properties, but then when I run the project, it dies because it
>> can't find libexpat.dll.
>>
> In your CMakeLists.txt have it copy the libexpat.dll to your debug,
> release .. folder. Do that as a custom build step or an install step.
>
> Here are two ways I do this for Qt libraries (modify this for libexpat):
>
> The first uses an install.
>
> IF (WIN32)
> IF (GET_RUNTIME)
> INSTALL(FILES
>                "${QT_BINARY_DIR}/QtCored${QT_VERSION_MAJOR}.dll"
>                "${QT_BINARY_DIR}/QtXmld${QT_VERSION_MAJOR}.dll"
>                "${QT_BINARY_DIR}/QtTestd${QT_VERSION_MAJOR}.dll"
>                "${QT_BINARY_DIR}/QtGuid${QT_VERSION_MAJOR}.dll"
>                "${QT_BINARY_DIR}/QtNetworkd${QT_VERSION_MAJOR}.dll"
>                "${QT_BINARY_DIR}/QtScriptd${QT_VERSION_MAJOR}.dll"
>                DESTINATION ${EXECUTABLE_OUTPUT_PATH}/Debug
> )
> INSTALL(FILES
>                "${QT_BINARY_DIR}/QtCore${QT_VERSION_MAJOR}.dll"
>                "${QT_BINARY_DIR}/QtXml${QT_VERSION_MAJOR}.dll"
>                "${QT_BINARY_DIR}/QtTest${QT_VERSION_MAJOR}.dll"
>                "${QT_BINARY_DIR}/QtGui${QT_VERSION_MAJOR}.dll"
>                "${QT_BINARY_DIR}/QtNetwork${QT_VERSION_MAJOR}.dll"
>                "${QT_BINARY_DIR}/QtScript${QT_VERSION_MAJOR}.dll"
>                DESTINATION ${EXECUTABLE_OUTPUT_PATH}/RelWithDebInfo
> )
> ENDIF(GET_RUNTIME)
> ENDIF(WIN32)
>
> The second uses a custom build step:
>
> # Copy the needed Qt libraries into the Build directory. Also add installation
> # and CPack code to support installer generation.
> # this is a complete hack for Visual Studio to copy the Qt libraries.
> if ( NOT Q_WS_MAC)
>   if (DEFINED QT_QMAKE_EXECUTABLE)
>       SET (QTLIBLIST QtCore QtGui)
>
>       IF (MSVC)
>           set(TYPE "d")
>           FOREACH(qtlib ${QTLIBLIST})
>             IF (WIN32)
>               GET_FILENAME_COMPONENT(QT_DLL_PATH_tmp
> ${QT_QMAKE_EXECUTABLE} PATH)
>               file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/Debug)
>               file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/Release)
>               file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/MinSizeRel)
>               file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/RelWithDebInfo)
>               INSTALL(FILES ${QT_DLL_PATH_tmp}/${qtlib}${type}d4.dll
>                   DESTINATION ./
>                   CONFIGURATIONS Debug
>                   COMPONENT Applications)
>               INSTALL(FILES ${QT_DLL_PATH_tmp}/${qtlib}4.dll
>                   DESTINATION ./
>                   CONFIGURATIONS Release
>                   COMPONENT Applications)
>               add_custom_target(ZZ_${qtlib}-Debug-Copy ALL
>                           COMMAND ${CMAKE_COMMAND} -E
>                                                        copy_if_different ${QT_DLL_PATH_tmp}/${qtlib}${TYPE}4.dll
>                           ${PROJECT_BINARY_DIR}/Debug/
>                           COMMENT "Copying ${qtlib}${TYPE}4.dll to
> ${PROJECT_BINARY_DIR}/Debug/")
>               add_custom_target(ZZ_${qtlib}-Release-Copy ALL
>                           COMMAND ${CMAKE_COMMAND} -E
>                                                   copy_if_different ${QT_DLL_PATH_tmp}/${qtlib}4.dll
>                           ${PROJECT_BINARY_DIR}/Release/
>                           COMMENT "Copying ${qtlib}4.dll to
> ${PROJECT_BINARY_DIR}/Release/")
>             ENDIF (WIN32)
>           ENDFOREACH(qtlib)
>
>       endif(MSVC)
>   endif(DEFINED QT_QMAKE_EXECUTABLE)
> endif(NOT Q_WS_MAC)
>
>
>>
>> So, in summary, I think cmake is completely ignoring libexpat, even when I
>> explicitly tell it (in the gui) where the include and library files are.
>>
>> Any ideas?
>>
> Follow the advice by Stefan. I too believe that is the reason why the
> include did not work.
>
> John

Here is a slightly improved version of the above:


# --------------------------------------------------------------------
# Copy the needed Qt libraries into the Build directory. Also add installation
# and CPack code to support installer generation.
# --------------------------------------------------------------------
if ( NOT Q_WS_MAC AND MSVC AND DEFINED QT_QMAKE_EXECUTABLE)

    SET (QTLIBLIST QtCore QtGui)
    SET (QTPLUGINLIST qgif qjpeg qtiff)
    set (BUILD_TYPES "Debug;Release")

    foreach (btype ${BUILD_TYPES})
        string(TOUPPER ${btype} BTYPE)
        file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${btype})
        foreach(qtlib ${QTLIBLIST})

            string(TOUPPER ${qtlib} QTLIB)
           # message(STATUS "QT_${QTLIB}_LIBRARY_${BTYPE}:
${QT_${QTLIB}_LIBRARY_${BTYPE}}")
            GET_FILENAME_COMPONENT(DLL_NAME
${QT_${QTLIB}_LIBRARY_${BTYPE}} NAME_WE)
           # message(STATUS "DLL_NAME: ${DLL_NAME}")
            GET_FILENAME_COMPONENT(QT_BIN_PATH ${QT_QMAKE_EXECUTABLE} PATH)
           # message(STATUS "QT_BIN_PATH: ${QT_BIN_PATH}")

            INSTALL(FILES ${QT_BIN_PATH}/${DLL_NAME}.dll
                DESTINATION ./
                CONFIGURATIONS ${btype}
                COMPONENT Applications)

            add_custom_target(Z_${qtlib}-${BTYPE}-Copy ALL
                        COMMAND ${CMAKE_COMMAND} -E copy_if_different
${QT_BIN_PATH}/${DLL_NAME}.dll
                        ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${btype}/
                        COMMENT "Copying
${QT_BIN_PATH}/${DLL_NAME}.dll to
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${btype}/")

        endforeach()

    # For this project we also need to copy the imageformat Qt plugins
which should have already been defined
    # in the cmake variables QTPLUGINS_DEBUG, QTPLUGINS_RELEASE and QTPLUGINS
        file(MAKE_DIRECTORY
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${btype}/plugins/imageformats)
        foreach(plugin ${QTPLUGINLIST})
            string(TOUPPER ${plugin} PLUGIN)
           # message(STATUS "QT_${QTLIB}_LIBRARY_${BTYPE}:
${QT_${QTLIB}_LIBRARY_${BTYPE}}")
            GET_FILENAME_COMPONENT(DLL_NAME
${QT_${PLUGIN}_PLUGIN_${BTYPE}} NAME_WE)
           # message(STATUS "DLL_NAME: ${DLL_NAME}")
           # GET_FILENAME_COMPONENT(QT_BIN_PATH ${QT_QMAKE_EXECUTABLE} PATH)
           # message(STATUS "QT_BIN_PATH: ${QT_BIN_PATH}")

            INSTALL(FILES ${QT_PLUGINS_DIR}/imageformats/${DLL_NAME}.dll
                DESTINATION ./plugins/imageformats
                CONFIGURATIONS ${btype}
                COMPONENT Applications)

            add_custom_target(Z_${plugin}-${BTYPE}-Copy ALL
                        COMMAND ${CMAKE_COMMAND} -E copy_if_different
${QT_PLUGINS_DIR}/imageformats/${DLL_NAME}.dll

${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${btype}/plugins/imageformats/
                        COMMENT "Copying
${QT_PLUGINS_DIR}/imageformats/${DLL_NAME}.dll to
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${btype}/plugins/imageformats")

        endforeach(plugin ${QTPLUGINS_${BTYPE}})
		
		#write a qt.conf file into the application directory and install it
		file(WRITE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${btype}/qt.conf "")
		INSTALL(FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${btype}/qt.conf
				DESTINATION .
				CONFIGURATIONS ${btype}
				COMPONENT Applications )
		
    endforeach()
endif()

Mike Jackson


More information about the CMake mailing list