如何正确使用CMake获取Qt?

huangapple go评论83阅读模式
英文:

How to properly fetch Qt using CMake?

问题

我遇到了以下问题:我正在尝试使用 `CMake` 函数 `FetchContent_Declare` 获取 `Qt` C++ 库,特别是版本 6.4.2。我正在按照[此][1]网站上的指南进行操作,该指南解释了如何从源代码构建 Qt,如果手动执行且不使用 `CMake`,则可以正常工作;但是如果我想将它与 `FetchContent_Declare` 结合使用,事情就会变得更加困难,因为在编译之前,如链接中所示,我需要运行初始化命令:

perl init-repository


以及配置命令(在构建之前):

mkdir qt6-build
cd qt6-build
../qt6/configure


我该如何将这两个步骤整合到 CMake 的 fetch content 部分呢?

我的当前 `CMake` 脚本是:

include( FetchContent )

FetchContent_Declare(
Qt6
GIT_REPOSITORY "https://github.com/qt/qt5"
GIT_TAG v6.4.2
CONFIGURE_COMMAND "perl init-repository && ./configure"
)

FetchContent_MakeAvailable( Qt6 )


但是似乎不起作用:

CMake Error at /usr/share/cmake-3.22/Modules/FetchContent.cmake:1087 (message):
Build step for qt6 failed: 2
Call Stack (most recent call first):
/usr/share/cmake-3.22/Modules/FetchContent.cmake:1216:EVAL:2 (__FetchContent_directPopulate)
/usr/share/cmake-3.22/Modules/FetchContent.cmake:1216 (cmake_language)
/usr/share/cmake-3.22/Modules/FetchContent.cmake:1259 (FetchContent_Populate)
deps/qt6/CMakeLists.txt:19 (FetchContent_MakeAvailable)


如果可能的话,我还需要一种在通过 `FetchContent_Declare` 配置和安装库时不要求 GitHub 用户名和密码的方法。

  [1]: https://wiki.qt.io/Building_Qt_6_from_Git#:~:text=perl%20init%2Drepository-,Configuring%20and%20Building,Where%20dot%20after%20%22%2D%2Dbuild%22%20means%20current%20folder.,-On%20Windows%3A
英文:

I am facing the following problem: I am trying to use the CMake function FetchContent_Declare to fetch Qt C++ library and in particular the version 6.4.2. I am following the guide from this site in which is explained how to build Qt from source and it works well if performed "by hand" without CMake; but if I want to incorporate it with FetchContent_Declare things became harder since before compiling, as you can see from the link, I need to run the initialization command:

perl init-repository

and the configuration one (before building):

mkdir qt6-build
cd qt6-build
../qt6/configure

How can I incorporate these two steps into the fetch content part of CMake?

My current CMake script is:

include( FetchContent )

FetchContent_Declare(
  Qt6
  GIT_REPOSITORY "https://github.com/qt/qt5"
  GIT_TAG v6.4.2
  CONFIGURE_COMMAND "perl init-repository && ./configure"
)

FetchContent_MakeAvailable( Qt6 ) 

but it seems not correctly working:

CMake Error at /usr/share/cmake-3.22/Modules/FetchContent.cmake:1087 (message):
  Build step for qt6 failed: 2
Call Stack (most recent call first):
  /usr/share/cmake-3.22/Modules/FetchContent.cmake:1216:EVAL:2 (__FetchContent_directPopulate)
  /usr/share/cmake-3.22/Modules/FetchContent.cmake:1216 (cmake_language)
  /usr/share/cmake-3.22/Modules/FetchContent.cmake:1259 (FetchContent_Populate)
  deps/qt6/CMakeLists.txt:19 (FetchContent_MakeAvailable)

I need also a way, if possible, to not ask GitHube username and password when configuring and installing the library through FetchContent_Declare.

答案1

得分: 1

我终于找到了一个解决方案!这个 `CMakeLists.txt` 完美地满足了这个目的:

项目设置

cmake_minimum_required(VERSION 3.15)

project(key-manager-dependencies-qt6
VERSION 1.0
DESCRIPTION "key-manager Qt6 依赖项的构建系统。"
LANGUAGES CXX
)

如果在源目录(或任何包含 CMakeLists.txt 文件的目录)中构建,则出现错误

file(TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/CMakeLists.txt" LOC_PATH)
if(EXISTS "${LOC_PATH}")
message(FATAL_ERROR "您不能在源目录中构建(或任何包含 CMakeLists.txt 文件的目录)。请创建一个构建子目录。可以删除 CMakeCache.txt 和 CMakeFiles。")
endif()

获取包

find_package(Qt6 6.4.2 QUIET)

if(NOT Qt6_FOUND)

# 设置 Ninja 用于编译
set(CMAKE_GENERATOR "Ninja" CACHE STRING "CMake generator" FORCE)

# 初始消息
message(STATUS "未找到 Qt 6.4.2。正在下载和配置 Qt...")

# 下载和提取 Qt 6.4.2 的存档
set(QT_VERSION "6.4.2")
set(QT_ARCHIVE_URL "https://download.qt.io/official_releases/qt/6.4/${QT_VERSION}/submodules/qtbase-everywhere-src-${QT_VERSION}.tar.xz")
set(QT_ARCHIVE_FILE "${CMAKE_CURRENT_BINARY_DIR}/qtbase-everywhere-src-${QT_VERSION}.tar.xz")
set(QT_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/qtbase-everywhere-src-${QT_VERSION}")
message(STATUS "从官方存储库下载包...")
file(DOWNLOAD ${QT_ARCHIVE_URL} ${QT_ARCHIVE_FILE}
      SHOW_PROGRESS
      EXPECTED_HASH SHA256=a88bc6cedbb34878a49a622baa79cace78cfbad4f95fdbd3656ddb21c705525d)
message(STATUS "解压发行版...")
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ${QT_ARCHIVE_FILE}
                 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 
                 OUTPUT_QUIET
)

# 配置 Qt(跳过构建无用模块)
set(QT_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/qt-build")
file(MAKE_DIRECTORY ${QT_BUILD_DIR})
message(STATUS "配置中...")
execute_process(COMMAND ${QT_SOURCE_DIR}/configure -prefix ${QT_BUILD_DIR}
                 WORKING_DIRECTORY ${QT_BUILD_DIR})

# 检查系统是否支持并行处理
if(DEFINED ENV{NUMBER_OF_PROCESSORS})
    set(JOBS_OPTION "-j$ENV{NUMBER_OF_PROCESSORS}")
elseif(DEFINED ENV{PROCESSOR_COUNT})
    set(JOBS_OPTION "-j$ENV{PROCESSOR_COUNT}")
else()
    set(JOBS_OPTION "")
endif()

# 如果可能,使用 -j 选项进行编译(Qt 非常庞大)
if(JOBS_OPTION)
    message(STATUS "使用并行处理进行编译...")
    execute_process(COMMAND ninja ${JOBS_OPTION}
                 WORKING_DIRECTORY ${QT_BUILD_DIR})
else()
    message(STATUS "不使用并行处理进行编译...")
    execute_process(COMMAND ninja
                 WORKING_DIRECTORY ${QT_BUILD_DIR})
endif()

# 设置必要的环境变量以使用 Qt
set(ENV{QTDIR} ${QT_BUILD_DIR})
set(ENV{PATH} ${QT_BUILD_DIR}/bin:$ENV{PATH})

else()
message(STATUS "在系统中找到 Qt 6.4.2。")
endif()



<details>
<summary>英文:</summary>

I finally found a solution! This `CMakeLists.txt` works perfectly for this purpose:

Project settings

cmake_minimum_required( VERSION 3.15 )

project( key-manager-dependencies-qt6
VERSION 1.0
DESCRIPTION "Build system for key-manager Qt6 dependency."
LANGUAGES CXX
)

Error if building out of a build directory

file( TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/CMakeLists.txt" LOC_PATH )
if( EXISTS "${LOC_PATH}" )
message( FATAL_ERROR "You cannot build in a source directory (or any directory with "
"CMakeLists.txt file). Please make a build subdirectory. Feel free to "
"remove CMakeCache.txt and CMakeFiles." )
endif()

Fetch the package

find_package( Qt6 6.4.2 QUIET )

if( NOT Qt6_FOUND )

# Set Ninja for compilation
set( CMAKE_GENERATOR &quot;Ninja&quot; CACHE STRING &quot;CMake generator&quot; FORCE )

# Initial message
message( STATUS &quot;Qt 6.4.2 not found. Downloading and configuring Qt...&quot; )

# Download and extract archive of Qt 6.4.2
set( QT_VERSION &quot;6.4.2&quot; )
set( QT_ARCHIVE_URL &quot;https://download.qt.io/official_releases/qt/6.4/${QT_VERSION}/submodules/qtbase-everywhere-src-${QT_VERSION}.tar.xz&quot; )
set( QT_ARCHIVE_FILE &quot;${CMAKE_CURRENT_BINARY_DIR}/qtbase-everywhere-src-${QT_VERSION}.tar.xz&quot; )
set( QT_SOURCE_DIR &quot;${CMAKE_CURRENT_BINARY_DIR}/qtbase-everywhere-src-${QT_VERSION}&quot; )
message( STATUS &quot;Downloading the package from the official repository...&quot; )
file( DOWNLOAD ${QT_ARCHIVE_URL} ${QT_ARCHIVE_FILE}
      SHOW_PROGRESS
      EXPECTED_HASH SHA256=a88bc6cedbb34878a49a622baa79cace78cfbad4f95fdbd3656ddb21c705525d )
message( STATUS &quot;Unpacking the release...&quot; )
execute_process( COMMAND ${CMAKE_COMMAND} -E tar xvf ${QT_ARCHIVE_FILE}
                 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 
                 OUTPUT_QUIET
)

# Configure Qt (skip building of useless modules)
set( QT_BUILD_DIR &quot;${CMAKE_CURRENT_BINARY_DIR}/qt-build&quot; )
file( MAKE_DIRECTORY ${QT_BUILD_DIR} )
message( STATUS &quot;Configuring...&quot; )
execute_process( COMMAND ${QT_SOURCE_DIR}/configure -prefix ${QT_BUILD_DIR}
                 WORKING_DIRECTORY ${QT_BUILD_DIR} )

# Check if system supports parallelization
if( DEFINED ENV{NUMBER_OF_PROCESSORS} )
    set( JOBS_OPTION &quot;-j$ENV{NUMBER_OF_PROCESSORS}&quot; )
elseif( DEFINED ENV{PROCESSOR_COUNT} )
    set( JOBS_OPTION &quot;-j$ENV{PROCESSOR_COUNT}&quot; )
else()
    set( JOBS_OPTION &quot;&quot; )
endif()

# Use -j option to compile if possible (qt is very big)
if( JOBS_OPTION )
    message( STATUS &quot;Compiling with parallelization...&quot; )
    execute_process( COMMAND ninja ${JOBS_OPTION}
                 WORKING_DIRECTORY ${QT_BUILD_DIR} )
else()
    message( STATUS &quot;Compiling without parallelization...&quot; )
    execute_process( COMMAND ninja
                 WORKING_DIRECTORY ${QT_BUILD_DIR} )
endif()

# Set necessary environment variables to use Qt
set( ENV{QTDIR} ${QT_BUILD_DIR} )
set( ENV{PATH} ${QT_BUILD_DIR}/bin:$ENV{PATH})

else()
message( STATUS "Qt 6.4.2 found in the system." )
endif()


it is all well commented so hope this can be useful for other people.

**NOTE**: this script fetch Qt 6.4.2, but you can modify it with any required version.

**NOTE 2**: if you want to speed up the process you can ask to skip compilation of tests, examples and optional Qt modules by modifying this line:

execute_process( COMMAND ${QT_SOURCE_DIR}/configure -prefix ${QT_BUILD_DIR} WORKING_DIRECTORY ${QT_BUILD_DIR} )


</details>



huangapple
  • 本文由 发表于 2023年3月15日 18:33:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75743502.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定