[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