【问题标题】:Linking problem when trying to cross-compile a qt application using cmake尝试使用 cmake 交叉编译 qt 应用程序时出现链接问题
【发布时间】:2011-10-15 23:33:24
【问题描述】:

我目前正在将我的 Qt 应用程序的构建系统从 qmake 切换到 cmake。在尝试使用 MinGW(静态 Qt 构建)为 Windows 进行交叉编译时,我遇到了一个我无法解释的奇怪问题:

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++ 调用 with -lQtGui -lQtCore flags:

/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 脚本仍然会设置它们。但这似乎还不够。我绝对不明白为什么如果自动设置标志一次或手动添加标志三次会有所不同。这和flag的顺序有关系吗?

你有什么想法吗?任何帮助表示赞赏。


更新:

没关系...

我刚刚更改了库的顺序

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:我会发布这个作为答案,但由于缺乏声誉,我还不允许这样做。

【问题讨论】:

标签: c++ qt cmake mingw cross-compiling


【解决方案1】:

许多架构在链接时会通过库列表进行单次传递。即,如果您有一个未定义的符号,则链接列表中稍后的库必须定义它。链接器不会通过库列表“向后”搜索来解析符号。

在这种情况下,QtGui 依赖于 QtCore。因此,QtCore 在链接列表中必须出现在 QtGui 之后。

解决此问题的最简单方法是使用 ${QT_LIBRARIES} cmake 变量,该变量在您执行 FIND_PACKAGE(Qt4...) 时神奇地定义。它以正确的链接顺序包含所有相关的 Qt 库。

FindQt4 CMake documentation

【讨论】:

    猜你喜欢
    • 2020-02-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-25
    • 1970-01-01
    • 2016-07-07
    • 1970-01-01
    • 2021-09-07
    • 1970-01-01
    相关资源
    最近更新 更多