【问题标题】:CMake - How to stop building every dependency every time I build my projectCMake - 每次构建项目时如何停止构建每个依赖项
【发布时间】:2021-10-21 07:44:03
【问题描述】:

我有一个 cmake 列表文件,它通过 ExternalProject_Add 引入依赖项。在我的项目(使用这些依赖项)的初始编译中,我希望它们被构建(或者如果配置更改从调试到发布)。这会发生,但是它会在项目源中的任何后续代码更改之后发生。因此,例如,如果我只是在终端中添加一行到 cout 的东西并构建我的项目,Visual Studio 会遍历与我的项目相关联的每个项目并重新构建它。当然,它会在不需要时跳过实际的重新编译,但是为每个依赖项完成整个构建步骤并不理想。

因此我想知道如何构建这个 cmake 项目以避免每次更改项目源时都必须构建每个依赖项?

下面是我的CMakeLists.txt 文件。这是一项正在进行的工作。我只是添加片段并进行测试,以确保收到我想要的结果(这里还有一些非跨平台的东西,目前只是为了测试目的而完成的):

cmake_minimum_required(VERSION 3.20.0)


# Define our project name
set(PROJECT_NAME test)
project(${PROJECT_NAME})

if(MSVC)
    get_filename_component(_vs_bin_path "${CMAKE_LINKER}" DIRECTORY)
    set(libexe "${_vs_bin_path}/lib.exe")
    message("LOOKHERE3:${libexe}")
endif()

# Make sure binary directory is not the same as source directory
if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
  message(
    FATAL_ERROR
      "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there."
  )
endif()


# This Project Depends on External Project(s) 
include(ExternalProject)

# SETUP GLFW
set(libGLFW glfw)
ExternalProject_Add(${libGLFW}
PREFIX          ${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLFW}
GIT_REPOSITORY  https://github.com/glfw/glfw.git
GIT_TAG         3.3.4
GIT_SHALLOW     ON
CMAKE_ARGS      -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLFW}/install
                -DGLFW_BUILD_DOCS:BOOL=OFF
                -DGLFW_BUILD_EXAMPLES:BOOL=OFF
                -DGLFW_BUILD_TESTS:BOOL=OFF
)

set(GLFW_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLFW}/install)
add_library(GLFW_LIBRARY STATIC IMPORTED)
set_target_properties(GLFW_LIBRARY PROPERTIES IMPORTED_LOCATION ${GLFW_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}glfw3${CMAKE_STATIC_LIBRARY_SUFFIX})
#message("LOOKHERE:${CMAKE_STATIC_LIBRARY_PREFIX}glfw3${CMAKE_STATIC_LIBRARY_SUFFIX}")


# SETUP GLAD
set(libGLAD glad)
ExternalProject_Add(${libGLAD}
PREFIX          ${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLAD}
GIT_REPOSITORY  https://github.com/Dav1dde/glad.git
GIT_TAG         origin/master
GIT_SHALLOW     ON
CMAKE_ARGS      -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLAD}/install
                -DGLAD_INSTALL:BOOL=ON
                -DGLAD_PROFILE:STRING="core"
                -DGLAD_ALL_EXTENSIONS:BOOL=ON
                -DUSE_MSVC_RUNTIME_LIBRARY_DLL:BOOL=OFF
)

set(GLAD_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLAD}/install)
add_library(GLAD_LIBRARY STATIC IMPORTED)
set_target_properties(GLAD_LIBRARY PROPERTIES IMPORTED_LOCATION ${GLAD_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}glad${CMAKE_STATIC_LIBRARY_SUFFIX})




# CREATE OUR LIBRARY
file(GLOB_RECURSE headers CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/inc/*.h")
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")

add_library(${PROJECT_NAME} STATIC ${headers} ${sources})
add_dependencies(${PROJECT_NAME} ${libGLFW} ${libGLAD})


# Add all include file paths
target_include_directories(${PROJECT_NAME}
    PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/inc
    PUBLIC ${GLFW_INSTALL_DIR}/include
    PUBLIC ${GLAD_INSTALL_DIR}/include
)


# JOIN ALL LIBS
set(LIBNAME "${CMAKE_CURRENT_BINARY_DIR}/final/combinedLib.lib")

add_custom_command(
    OUTPUT ${LIBNAME}
    COMMAND ${libexe} /OUT:${LIBNAME} $<TARGET_FILE:GLFW_LIBRARY> $<TARGET_FILE:GLAD_LIBRARY> $<TARGET_FILE:${PROJECT_NAME}>
    DEPENDS GLFW_LIBRARY GLAD_LIBRARY ${PROJECT_NAME}
    COMMENT "Combining libs..."
)

add_custom_target(combinedLibGenerator
    DEPENDS ${LIBNAME}
)

add_library(combinedLib STATIC IMPORTED)
set_property(TARGET combinedLib PROPERTY IMPORTED_LOCATION ${LIBNAME})
add_dependencies(combinedLib combinedLibGenerator)

这是我在每次构建后在 Visual Studio 中收到的输出:

1>------ Build started: Project: ZERO_CHECK, Configuration: Release x64 ------
2>------ Build started: Project: glad, Configuration: Release x64 ------
2>Performing update step for 'glad'
2>HEAD is now at 71b2aa6... readme: updates conan link
2>No patch step for 'glad'
2>Performing configure step for 'glad'
2>-- Selecting Windows SDK version 10.0.16299.0 to target Windows 10.0.18362.
2>-- Configuring done
2>-- Generating done
2>-- Build files have been written to: C:/Users/myuserid/Desktop/test/build/dep/glad/src/glad-build
2>Performing build step for 'glad'
2>Microsoft (R) Build Engine version 15.5.180.51428 for .NET Framework
2>Copyright (C) Microsoft Corporation. All rights reserved.
2>
2>  glad.vcxproj -> C:\Users\myuserid\Desktop\test\build\dep\glad\src\glad-build\Release\glad.lib
2>Performing install step for 'glad'
2>Microsoft (R) Build Engine version 15.5.180.51428 for .NET Framework
2>Copyright (C) Microsoft Corporation. All rights reserved.
2>
2>  glad.vcxproj -> C:\Users\myuserid\Desktop\test\build\dep\glad\src\glad-build\Release\glad.lib
2>  -- Install configuration: "Release"
2>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glad/install/lib/glad.lib
2>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glad/install/include/glad/glad.h
2>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glad/install/include/KHR/khrplatform.h
2>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glad/install/lib/cmake/glad/gladConfig.cmake
2>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glad/install/lib/cmake/glad/gladConfigVersion.cmake
2>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glad/install/lib/cmake/glad/gladTargets.cmake
2>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glad/install/lib/cmake/glad/gladTargets-release.cmake
2>Completed 'glad'
3>------ Build started: Project: glfw, Configuration: Release x64 ------
3>Performing update step for 'glfw'
3>No patch step for 'glfw'
3>Performing configure step for 'glfw'
3>-- Selecting Windows SDK version 10.0.16299.0 to target Windows 10.0.18362.
3>-- Using Win32 for window creation
3>-- Configuring done
3>-- Generating done
3>-- Build files have been written to: C:/Users/myuserid/Desktop/test/build/dep/glfw/src/glfw-build
3>Performing build step for 'glfw'
3>Microsoft (R) Build Engine version 15.5.180.51428 for .NET Framework
3>Copyright (C) Microsoft Corporation. All rights reserved.
3>
3>  glfw.vcxproj -> C:\Users\myuserid\Desktop\test\build\dep\glfw\src\glfw-build\src\Release\glfw3.lib
3>Performing install step for 'glfw'
3>Microsoft (R) Build Engine version 15.5.180.51428 for .NET Framework
3>Copyright (C) Microsoft Corporation. All rights reserved.
3>
3>  glfw.vcxproj -> C:\Users\myuserid\Desktop\test\build\dep\glfw\src\glfw-build\src\Release\glfw3.lib
3>  -- Install configuration: "Release"
3>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glfw/install/include/GLFW
3>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glfw/install/include/GLFW/glfw3.h
3>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glfw/install/include/GLFW/glfw3native.h
3>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glfw/install/lib/cmake/glfw3/glfw3Config.cmake
3>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glfw/install/lib/cmake/glfw3/glfw3ConfigVersion.cmake
3>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glfw/install/lib/cmake/glfw3/glfw3Targets.cmake
3>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glfw/install/lib/cmake/glfw3/glfw3Targets-release.cmake
3>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glfw/install/lib/pkgconfig/glfw3.pc
3>  -- Up-to-date: C:/Users/myuserid/Desktop/test/build/dep/glfw/install/lib/glfw3.lib
3>Completed 'glfw'
4>------ Build started: Project: test, Configuration: Release x64 ------
4>Test.cpp
4>test.vcxproj -> C:\Users\myuserid\Desktop\test\build\Release\test.lib
========== Build: 4 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

【问题讨论】:

  • 这是由 MS Visual Studio 的 msbuild 执行的,而不是由 cmake 执行的。卸载您不想尝试构建的项目。
  • @S.M.您是说在构建项目后简单地从解决方案中删除项目吗?如果构建配置从 Debug 更改为 Release 并且实际上需要重新构建怎么办?还是您只是为每个配置预先构建,然后删除项目……这似乎有点迟钝。还是我没有捡起你放下的东西?
  • 删除那些add_dependenices并用正确的target_link_libraries替换它们。
  • @GuillaumeRacicot 这确实有效!然而,在最初的ALL_BUILD 构建失败,说明它找不到依赖项目的包含文件。有没有一种方法可以在不使用add_dependencies 的情况下设置构建顺序?
  • 在一个典型的 CMake 项目中,您只使用 find_package(glfw3 REQUIRED) 管理依赖项,然后您执行 target_link_libraries(my-exe PUBLIC glfw) 链接到目标将添加链接、标题和定义。

标签: c++ visual-studio cmake


【解决方案1】:

CMake 中有一个错误会导致 ExternalProject_Add 与 GIT_TAG 总是重建,因为它不知道 git 更新是否改变了任何东西。见:

https://gitlab.kitware.com/cmake/cmake/-/issues/16419 https://gitlab.kitware.com/cmake/cmake/-/issues/19703

正如 whitwhoa 的回答,使用 UPDATE_COMMAND 可能会解决这个问题。

【讨论】:

    【解决方案2】:

    将UPDATE_COMMAND "" 添加到ExternalProject_Add 实现了我所追求的行为。这可以防止构建系统遍历每个依赖项并在每次构建依赖于它的东西时检查它的更改。切换配置(即调试/发布)会按预期触发重建。然后,如果您需要重新构建,您只需重新构建特定的依赖项。

    # SETUP GLFW
    set(libGLFW glfw)
    ExternalProject_Add(${libGLFW}
    PREFIX          ${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLFW}
    GIT_REPOSITORY  https://github.com/glfw/glfw.git
    GIT_TAG         3.3.4
    GIT_SHALLOW     ON
    CMAKE_ARGS      -
    # BEGIN ADD THIS
    UPDATE_COMMAND  ""
    # END ADD THIS
    DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLFW}/install
                    -DGLFW_BUILD_DOCS:BOOL=OFF
                    -DGLFW_BUILD_EXAMPLES:BOOL=OFF
                    -DGLFW_BUILD_TESTS:BOOL=OFF
    )
    

    【讨论】:

      【解决方案3】:

      CMake ("CeeMake") 只是项目的构建配置脚本,在它生成MakeFile、.xcproj 等之后,CeeMake 完全无法控制重建的内容和不重建的内容。

      但好消息是 VisualStudio、ExCode 甚至基于 MakeFile 的 Make 总是检查更改并且不会真正重建(除非手动触发)。

      例如,VisualStudio 的 msbuild 可能会说正在构建,但它会跳过任何被检测为未更改的内容。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多