[CMake] Help using CMake & Expat in Windows

John Drescher drescherjm at gmail.com
Fri Jul 30 19:15:45 EDT 2010


> 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


More information about the CMake mailing list