Проблема с линковкой при попытке кросс-компиляции приложения qt с помощью cmake - PullRequest
3 голосов
/ 29 июля 2011

В настоящее время я переключаю систему сборки моего приложения Qt с qmake на cmake.При попытке кросс-компиляции для Windows с MinGW (статическая сборка Qt) я наткнулся на странную проблему, которую я не могу объяснить:

CMakeLists.txt:

project(noble)

cmake_minimum_required(VERSION 2.8.5)

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")

find_package(Boost COMPONENTS program_options thread REQUIRED)
find_package(Qt4 REQUIRED QtCore QtGui)
find_package(BLAS REQUIRED)
find_package(LAPACK REQUIRED)
find_package(Armadillo)
find_package(Qwt6 REQUIRED)

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR})

include(${QT_USE_FILE})

set(LIBRARIES
    ${Qwt6_Qt4_LIBRARY}
    ${QT_QTCORE_LIBRARY}
    ${QT_QTGUI_LIBRARY}
    ${Boost_LIBRARIES}
    ${BLAS_LIBRARIES}
    ${LAPACK_LIBRARIES}
    )

set(DEFINITIONS
    ${QT_DEFINITIONS}
    ${BLAS_LINKER_FLAGS}
    ${LAPACK_LINKER_FLAGS}
    -DBOOST_THREAD_USE_LIB
    )

add_subdirectory(src)
add_subdirectory(plugins)

src / CMakeLists.txt:

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(noble_SOURCES
    #file names...
    )

set(noble_HEADERS
    #file names...
    )

set(noble_FORMS
    #file names...
    )

QT4_WRAP_UI(noble_FORMS_HEADERS ${noble_FORMS})
QT4_WRAP_CPP(noble_HEADERS_MOC ${noble_HEADERS})

include_directories(
    ${Boost_INCLUDE_DIRS}
    ${ARMADILLO_INCLUDE_DIRS}
    ${Qwt6_INCLUDE_DIR}
    )

add_definitions(${DEFINITIONS})

add_executable(noble
    ${noble_SOURCES}
    ${noble_HEADERS_MOC}
    ${noble_FORMS_HEADERS}
    )

target_link_libraries(noble 
    ${LIBRARIES}
    -lQtGui -lQtCore
    -ljpeg -lpng -ltiff -lmng -lz -limm32 -llcms -lwinmm
    -fopenmp
    )

Я сейчас пытаюсь избавиться от установленных вручную флагов компилятора прямо в конце.Если я опускаю -lQtGui -lQtCore, я получаю целую кучу неопределенных ссылок, таких как

/home/mjung/Programme/mingw-cross-env-2.21/usr/lib/gcc/i686-pc-mingw32/4.6.0/../../../../i686-pc-mingw32/lib/libQtGui.a(qapplication.o):qapplication.cpp:(.text+0x2340): undefined reference to `QBasicTimer::stop()'

Если я сохраняю эти флаги, программа прекрасно компилируется.

Теперь странным является следующее:

вызов cmake g ++ с -lQtGui -lQtCore флагами:

/home/mjung/Programme/mingw-cross-env-2.21/usr/bin/i686-pc-mingw32-g++
-Wl,--whole-archive
CMakeFiles/noble.dir/objects.a
-Wl,--no-whole-archive
-o ../noble.exe
-Wl,--out-implib,../libnoble.dll.a
-Wl,--major-image-version,0,--minor-image-version,0
/home/mjung/Programme/windows_builds/usr/lib/libqwt.a
-Wl,-Bstatic
-lQtCore -lQtGui
-lboost_program_options-mt
-lboost_thread-mt
-Wl,-Bdynamic
/home/mjung/Programme/windows_builds/usr/lib/libblas.a
/home/mjung/Programme/windows_builds/usr/lib/liblapack.a
/home/mjung/Programme/windows_builds/usr/lib/libblas.a
-lQtGui -lQtCore
-ljpeg -lpng -ltiff -lmng -lz -limm32 -llcms -lwinmm
-fopenmp
/home/mjung/Programme/windows_builds/usr/lib/liblapack.a
-lQtGui -lQtCore
-ljpeg -lpng -ltiff -lmng -lz -limm32 -llcms -lwinmm
-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32

вызов cmake g ++ без -lQtGui -lQtCore флаги:

/home/mjung/Programme/mingw-cross-env-2.21/usr/bin/i686-pc-mingw32-g++
-Wl,--whole-archive
CMakeFiles/noble.dir/objects.a
-Wl,--no-whole-archive
-o ../noble.exe
-Wl,--out-implib,../libnoble.dll.a
-Wl,--major-image-version,0,--minor-image-version,0
/home/mjung/Programme/windows_builds/usr/lib/libqwt.a
-Wl,-Bstatic
-lQtCore -lQtGui
-lboost_program_options-mt
-lboost_thread-mt
-Wl,-Bdynamic
/home/mjung/Programme/windows_builds/usr/lib/libblas.a
/home/mjung/Programme/windows_builds/usr/lib/liblapack.a
/home/mjung/Programme/windows_builds/usr/lib/libblas.a

-ljpeg -lpng -ltiff -lmng -lz -limm32 -llcms -lwinmm
-fopenmp
/home/mjung/Programme/windows_builds/usr/lib/liblapack.a

-ljpeg -lpng -ltiff -lmng -lz -limm32 -llcms -lwinmm
-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32

Даже если я не устанавливаю флаги компилятора вручную, сценарий FindQt4.cmake все равно устанавливает их.Но этого, кажется, недостаточно.Я абсолютно не понимаю, почему имеет значение, если флаги устанавливаются один раз автоматически или три раза, если я добавляю их вручную.Это как-то связано с порядком флагов?

У вас есть идеи?Любая помощь приветствуется.


ОБНОВЛЕНИЕ:

Nevermind ...

Я просто изменил порядок библиотек с

set(LIBRARIES
    ${Qwt6_Qt4_LIBRARY}
    ${QT_QTCORE_LIBRARY}
    ${QT_QTGUI_LIBRARY}
    ${Boost_LIBRARIES}
    ${BLAS_LIBRARIES}
    ${LAPACK_LIBRARIES}
    )

до

set(LIBRARIES
    ${Qwt6_Qt4_LIBRARY}
    ${QT_QTGUI_LIBRARY}
    ${QT_QTCORE_LIBRARY}
    ${Boost_LIBRARIES}
    ${BLAS_LIBRARIES}
    ${LAPACK_LIBRARIES}
    )

Я не совсем понимаю, почему так должно быть, но теперь это работает ...

PS: Я бы написал этов качестве ответа, но мне пока не разрешено делать это из-за отсутствия репутации.

1 Ответ

3 голосов
/ 30 июля 2011

Многие архитектуры делают один проход по списку библиотек при компоновке.т.е. если у вас есть неопределенный символ, библиотека, которая находится позже в списке ссылок, должна определить его.Компоновщик не будет искать «назад» в списке библиотек для разрешения символа.

В этом случае QtGui зависит от QtCore.Поэтому QtCore должен появляться после QtGui в списке ссылок.

Самый простой способ обойти это - использовать переменную cmake $ {QT_LIBRARIES}, которая магически определяется при выполнении FIND_PACKAGE (Qt4 ...).Он содержит все соответствующие библиотеки Qt в правильном порядке для ссылки.

FindQt4 CMake документация

...