我的 qmake 构建在调试构建中的速度是 cmake 的两倍多,为什么?

My qmake build is more than twice as fast in debug build as cmake, why?

所以,我正在将我的项目从 qmake 转换为 cmake,我即将完成!但是,至少在调试模式下,我的 qmake 构建运行速度提高了一倍以上。我想在两个构建配置中设置相同的编译标志,以便我比较苹果与苹果。

不幸的是,我并没有多少运气来弄清楚到底是什么导致了性能差异!我的 qmake 标志解决了这个问题:

/MP
 /GS
 /analyze-
 /W3
 /wd"4577"
 /wd"4467"
 /Zc:wchar_t
 /I"."
 /I"qt_generated"
 /I"./qt_generated/Debug"
 /I"..\third_party\Python38-32\include"
 /I"..\third_party\PythonQt\src"
 /I"..\third_party\pybind11\include"
 /I"src\third_party\eigen"
 /I"src\third_party\eigen\Eigen"
 /I"..\third_party\assimp\assimp-5.0.0\include"
 /I"..\third_party\assimp\assimp-5.0.0\build\include"
 /I"..\..\PhysX\physx\include"
 /I"..\..\PhysX\pxshared\include"
 /I"..\third_party\freetype-2.10.1\include"
 /I"..\third_party\soloud\include"
 /I"..\third_party\Visual Leak Detector\include"
 /I"C:\Qt.12.2\msvc2017\include"
 /I"C:\Qt.12.2\msvc2017\include\QtOpenGL"
 /I"C:\Qt.12.2\msvc2017\include\QtWidgets"
 /I"C:\Qt.12.2\msvc2017\include\QtOpenGLExtensions"
 /I"C:\Qt.12.2\msvc2017\include\QtMultimedia"
 /I"C:\Qt.12.2\msvc2017\include\QtGamepad"
 /I"C:\Qt.12.2\msvc2017\include\QtGui"
 /I"C:\Qt.12.2\msvc2017\include\QtANGLE"
 /I"C:\Qt.12.2\msvc2017\include\QtConcurrent"
 /I"C:\Qt.12.2\msvc2017\include\QtNetwork"
 /I"C:\Qt.12.2\msvc2017\include\QtCore"
 /I"qt_generated\moc"
 /I"qt_generated\ui"
 /I"C:\VulkanSDK.0.51.0\include"
 /I"C:\Qt.12.2\msvc2017\mkspecs\win32-msvc"
 /I"C:\Program Files (x86)\Visual Leak Detector\include"
 /Zi
 /Gm-
 /Od
 /Fd"qt_generated\obj\vc141.pdb"
 /Zc:inline
 /fp:precise
 /D "_WINDOWS"
 /D "UNICODE"
 /D "_UNICODE"
 /D "WIN32"
 /D "_ENABLE_EXTENDED_ALIGNED_STORAGE"
 /D "DEBUG_MODE"
 /D "WIN64"
 /D "QT_DLL"
 /D "QT_OPENGL_LIB"
 /D "QT_OPENGLEXTENSIONS_LIB"
 /D "QT_WIDGETS_LIB"
 /D "DEVELOP_MODE"
 /D "LINALG_USE_EIGEN"
 /D "PYTHONQT_USE_RELEASE_PYTHON_FALLBACK"
 /D "PX_PHYSX_STATIC_LIB"
 /D "QT_MULTIMEDIA_LIB"
 /D "QT_GAMEPAD_LIB"
 /D "QT_GUI_LIB"
 /D "QT_CONCURRENT_LIB"
 /D "QT_NETWORK_LIB"
 /D "QT_CORE_LIB"
 /errorReport:prompt
 /WX-
 /Zc:forScope
 /Gd
 /Oy-
 /MDd
 /FC
 /Fa"qt_generated\obj\"
 /EHsc
 /nologo
 /Fo"qt_generated\obj\"
 /Fp"qt_generated\obj\grand_blue_d.pch"
 /diagnostics:classic 

在尝试尽可能接近匹配后,我的 cmake 标志解决了这个问题:

/MP
 /GS
 /analyze-
 /W3
 /wd"4577"
 /wd"4467"
 /Zc:wchar_t
 /I"C:\Users\me\Documents\Projects\my-engine\app"
 /I"C:\Users\me\Documents\Projects\my-engine\my_engine"
 /I"C:\Users\me\Documents\Projects\my-engine\app\reverie_autogen\include_Debug"
 /I"C:\Users\me\Documents\Projects\my-engine\third_party\Python38-32\include"
 /I"C:\Users\me\Documents\Projects\my-engine\my_engine\..\third_party\pybind11\include"
 /I"C:\Users\me\Documents\Projects\my-engine\my_engine\src\third_party\eigen"
 /I"C:\Users\me\Documents\Projects\my-engine\my_engine\..\third_party\assimp\assimp-5.0.0\include"
 /I"C:\Users\me\Documents\Projects\my-engine\my_engine\..\third_party\assimp\assimp-5.0.0\build\include"
 /I"C:\Users\me\Documents\Projects\my-engine\my_engine\..\third_party\physx\physx\include"
 /I"C:\Users\me\Documents\Projects\my-engine\my_engine\..\third_party\physx\pxshared\include"
 /I"C:\Users\me\Documents\Projects\my-engine\my_engine\..\third_party\freetype-2.10.1\include"
 /I"C:\Users\me\Documents\Projects\my-engine\my_engine\..\third_party\soloud\include"
 /I"C:\Users\me\Documents\Projects\my-engine\my_engine\..\third_party\Visual Leak Detector\include"
 /I"C:\Qt.12.2\msvc2017\include"
 /I"C:\Qt.12.2\msvc2017\include\QtCore"
 /I"C:\Qt.12.2\msvc2017\.\mkspecs\win32-msvc"
 /I"C:\Qt.12.2\msvc2017\include\QtConcurrent"
 /I"C:\Qt.12.2\msvc2017\include\QtGamepad"
 /I"C:\Qt.12.2\msvc2017\include\QtGui"
 /I"C:\Qt.12.2\msvc2017\include\QtANGLE"
 /I"C:\Qt.12.2\msvc2017\include\QtOpenGLExtensions"
 /I"C:\Qt.12.2\msvc2017\include\QtMultimedia"
 /I"C:\Qt.12.2\msvc2017\include\QtNetwork"
 /I"C:\Qt.12.2\msvc2017\include\QtMultimediaWidgets"
 /I"C:\Qt.12.2\msvc2017\include\QtWidgets"
 /I"C:\Program Files (x86)\Visual Leak Detector\include"
 /Zi
 /Gm-
 /Od
 /Fd"reverie.dir\Debug\vc141.pdb"
 /Zc:inline
 /fp:precise
 /D "WIN32"
 /D "_WINDOWS"
 /D "DEBUG_MODE"
 /D "_UNICODE"
 /D "_ENABLE_EXTENDED_ALIGNED_STORAGE"
 /D "WIN64"
 /D "QT_DLL"
 /D "QT_OPENGL_LIB"
 /D "DEVELOP_MODE"
 /D "LINALG_USE_EIGEN"
 /D "_CRT_SECURE_NO_WARNINGS"
 /D "PX_PHYSX_STATIC_LIB"
 /D "QT_CORE_LIB"
 /D "QT_CONCURRENT_LIB"
 /D "QT_GAMEPAD_LIB"
 /D "QT_GUI_LIB"
 /D "QT_OPENGLEXTENSIONS_LIB"
 /D "QT_MULTIMEDIA_LIB"
 /D "QT_NETWORK_LIB"
 /D "QT_MULTIMEDIAWIDGETS_LIB"
 /D "QT_WIDGETS_LIB"
 /D "CMAKE_INTDIR=\"Debug\""
 /D "UNICODE"
 /errorReport:prompt
 /WX-
 /Zc:forScope
 /Gd
 /Oy-
 /MDd
 /std:c++latest
 /Fa"reverie.dir\Debug\"
 /EHsc
 /nologo
 /Fo"reverie.dir\Debug\"
 /Fp"reverie.dir\Debug\reverie.pch"
 /diagnostics:classic 

据我所知,这些应该具有相同的性能!关于我的 qmake 构建如何变得如此快,有什么想法吗?

编辑:为了更有趣,这是我的 qmake 项目文件:

# ----------------------------------------------------
# This file is generated by the Qt Visual Studio Tools.
# ------------------------------------------------------
# See: https://www.toptal.com/qt/vital-guide-qmake
# NOTE: Debug build should use /MDd runtime library, and release should use /MD (may be default for Qt)
# TODO: Convert to cmake: https://www.executionunit.com/blog/2014/01/22/moving-from-qmake-to-cmake/

message("Beginning qmake build of my_project.pro")

TEMPLATE = app
TARGET = my_project
QT += core \
      opengl \ 
      gui \
      widgets \
      concurrent \ # Mutexes/multithreading
      openglextensions \
      multimedia \
      gamepad \ # Controller support
      network # TCP/IP

# Set compiler flags /////////////////////////////////////////////////////////////
QMAKE_CXXFLAGS += /MP # Multiprocess compile, much faster

# MSVC versions after 15.3 are fickle with the flags required to use more modern c++ variants
QMAKE_CXXFLAGS *= /std:c++17 # Add if not there, this may be the ticket
# QMAKE_CXXFLAGS += -std=c++17 # For GCC/Clang
# QMAKE_CXXFLAGS += -std=c++1z

# Set general configuration options /////////////////////////////////////////////////
CONFIG += c++latest # Add support for c++17.
# CONFIG += c++1z # another attempt at C++17 support
CONFIG += qt # console # The target is a Qt application or library and requires the Qt library and header files
CONFIG += thread # Thread support is enabled. This is enabled when CONFIG includes qt, which is the default.
CONFIG += debug_and_release # Creates additional debug and release folders, but need it for debug

CONFIG(debug, debug|release){
    DESTDIR = ../app/debug
    DEFINES += DEBUG_MODE
} 
else {
    DESTDIR = ../app/release
}

# Replace O2 flag with O3 flag
#CONFIG(release, debug|release) {
#    QMAKE_CXXFLAGS_RELEASE -= -O1
#   QMAKE_CXXFLAGS_RELEASE -= -O2
#   QMAKE_CXXFLAGS_RELEASE *= -O3
#}

# Do not display debug output in release mode
CONFIG(debug, debug|release) : CONFIG += debug_info
CONFIG(release, debug|release) : DEFINES += QT_NO_DEBUG_OUTPUT

CONFIG += no_lflags_merge # Ensures that the list of libraries stored in the LIBS variable is not reduced to a list of unique values before it is used.
# CONFIG += CONSOLE # makes this a console application
CONFIG -= flat # flattens file hierarchy, subtract if this is not desired

# Defines //////////////////////////////////////////////////////////////////////////
DEFINES += _UNICODE _ENABLE_EXTENDED_ALIGNED_STORAGE WIN64 QT_DLL QT_OPENGL_LIB QT_OPENGLEXTENSIONS_LIB QT_WIDGETS_LIB
DEFINES += DEVELOP_MODE
DEFINES += LINALG_USE_EIGEN
INCLUDEPATH += ./qt_generated \
    . \
    ./qt_generated/$(ConfigurationName) 
    
LIBS += -lopengl32 \
    -lglu32 
DEPENDPATH += .


# Add Libraries ////////////////////////////////////////////////////////////////////
INCLUDEPATH += ../third_party/pybind11/include


# Compile against release version of python
CONFIG(debug, debug|release) : DEFINES += PYTHONQT_USE_RELEASE_PYTHON_FALLBACK

# Eigen
INCLUDEPATH += $$PWD/src/third_party/eigen \
               $$PWD/src/third_party/eigen/Eigen

# ASSIMP
# To be able to write <module.h>
INCLUDEPATH += ../third_party/assimp/assimp-5.0.0/include
INCLUDEPATH += ../third_party/assimp/assimp-5.0.0/build/include
CONFIG(debug, debug|release) : LIBS += -L$$PWD/lib/assimp -lassimp_d
CONFIG(release, debug|release) : LIBS += -L$$PWD/lib/assimp -lassimp

# PhysX
DEFINES += PX_PHYSX_STATIC_LIB
INCLUDEPATH += ../../PhysX/physx/include \
               ../../PhysX/pxshared/include
CONFIG(debug, debug|release) { 
    LIBS += -L$$PWD/lib/physx/debug -lPhysX_static_32
    LIBS += -L$$PWD/lib/physx/debug -lPhysXCharacterKinematic_static_32
    LIBS += -L$$PWD/lib/physx/debug -lPhysXCommon_static_32
    LIBS += -L$$PWD/lib/physx/debug -lPhysXCooking_static_32
    LIBS += -L$$PWD/lib/physx/debug -lPhysXExtensions_static_32
    LIBS += -L$$PWD/lib/physx/debug -lPhysXFoundation_static_32
    LIBS += -L$$PWD/lib/physx/debug -lPhysXPvdSDK_static_32
    LIBS += -L$$PWD/lib/physx/debug -lPhysXVehicle_static_32
}
CONFIG(release, debug|release) { 
    # Always needed
    LIBS += -L$$PWD/lib/physx/release -lPhysXCommon_static_32
    
    # Always needed
    LIBS += -L$$PWD/lib/physx/release -lPhysX_static_32
    
    # Always needed
    LIBS += -L$$PWD/lib/physx/release -lPhysXFoundation_static_32
    
    # To cook geometry data on the fly
    LIBS += -L$$PWD/lib/physx/release -lPhysXCooking_static_32
    
    # Other
    LIBS += -L$$PWD/lib/physx/release -lPhysXCharacterKinematic_static_32
    LIBS += -L$$PWD/lib/physx/release -lPhysXExtensions_static_32
    LIBS += -L$$PWD/lib/physx/release -lPhysXPvdSDK_static_32
    LIBS += -L$$PWD/lib/physx/release -lPhysXVehicle_static_32
}

# FreeType
INCLUDEPATH +=  ../third_party/freetype-2.10.1/include
CONFIG(debug, debug|release) : LIBS += -L$$PWD/lib/freetype/debug -lfreetype
CONFIG(release, debug|release) : LIBS += -L$$PWD/lib/freetype/release -lfreetype

# SoLoud
INCLUDEPATH += ../third_party/soloud/include
CONFIG(debug, debug|release) { 
    LIBS += -L$$PWD/lib/soloud/debug -lsoloud_x86_d
    LIBS += -L$$PWD/lib/soloud/debug -lsoloud_static_x86_d
}
CONFIG(release, debug|release) { 
    LIBS += -L$$PWD/lib/soloud/release -lsoloud_x86
    LIBS += -L$$PWD/lib/soloud/release -lsoloud_static_x86
}


# Include Visual Leak Detector //////////////////////////////////////////////////////////////////
INCLUDEPATH += "../third_party/Visual Leak Detector/include/"
LIBS        += -L"../third_party/Visual Leak Detector/lib/Win32"    
    
               
# Set directories //////////////////////////////////////////////////////////////////
MOC_DIR += ./qt_generated/moc
OBJECTS_DIR += ./qt_generated/obj
UI_DIR += ./qt_generated/ui
RCC_DIR += ./qt_generated

message("Loaded .pro files, now loading .pri")

# Load in library files for project
include(my_project.pri)

message("Loaded .pri files")

和我的 cmake 项目文件:

# CMake build for the Reverie Engine
# To run cmake, add cmake/bin directory to system path
## TODO:
## Implement source_group, for organizing in IDE, see: 
## TODO: Remove DLLs from this folder, as they are not needed

message( STATUS "---------Beginning cmake build of Reverie Engine---------")

# MACROS =================================================================
macro(remove_flag_from_target _target _flag)
    get_target_property(_target_cxx_flags ${_target} COMPILE_OPTIONS)
    if(_target_cxx_flags)
        list(REMOVE_ITEM _target_cxx_flags ${_flag})
        set_target_properties(${_target} PROPERTIES COMPILE_OPTIONS "${_target_cxx_flags}")
    endif()
endmacro()

# Project-level setup ====================================================
project( Reverie ) # TODO: Set version
cmake_minimum_required( VERSION 3.16 )
set(TARGET_NAME "reverie") # See: 

message (STATUS "--------- Set target ${TARGET_NAME}---------")

# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)

# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON) # Saves having to use QT5_WRAP_CPP
set(CMAKE_AUTORCC ON) # Saves having to use QT5_ADD_RESOURCES
set(CMAKE_AUTOUIC ON) # Saves having to use QT5_WRAP_UI


# Set compiler flags =====================================================
# Use C++20
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Multiprocess compiler, disable specific warnings
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /wd4577 /wd4467")

# Remove unwanted flags
STRING (REGEX REPLACE "[/|-]RTC(su|[1su])" "" CMAKE_CXX_FLAGS_DEBUG  "${CMAKE_CXX_FLAGS_DEBUG}")
STRING (REGEX REPLACE "[/|-]Ob0" "" CMAKE_CXX_FLAGS_DEBUG  "${CMAKE_CXX_FLAGS_DEBUG}")
STRING (REGEX REPLACE "[/|-]GR" "" CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS}")

# Set paths to find Qt ===================================================
# Find Qt itself
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
    set(CMAKE_PREFIX_PATH "C:\Qt\5.12.2\msvc2017")
else()
    message (WARNING "-------- System not supported ---------")
endif()

# Find UI files
# See: 
set(CMAKE_AUTOUIC_SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/ui")

# Find Required Qt Libraries =============================================
find_package(Qt5 COMPONENTS Core REQUIRED)# Core stuff
find_package(Qt5 COMPONENTS Concurrent REQUIRED) # For threading
find_package(Qt5 COMPONENTS Gamepad REQUIRED) # Controller support
find_package(Qt5 COMPONENTS Gui REQUIRED) # For OpenGL integration
find_package(Qt5 COMPONENTS OpenGLExtensions REQUIRED)
# find_package(Qt5OpenGL) # OpenGL should come from GUI
find_package(Qt5 COMPONENTS Multimedia REQUIRED) # Multimedia capabilities
find_package(Qt5 COMPONENTS MultimediaWidgets REQUIRED)
find_package(Qt5 COMPONENTS Widgets REQUIRED) # For widgets

# OpenGL libraries
# See: 
find_package(OpenGL REQUIRED) # enforces as a requirement
# find_library(OPENGL_LIB names opengl32) # Also valid
# find_library(GLU_LIB names glu32) # Also valid

# Set build mode directory options ========================================
# add_definitions(-DAPPLETTUTORIAL1_LIBRARY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/debug)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/release)

# Set directories to find libraries, need to do this before add_executable for desired target
# link_directories(${CMAKE_SOURCE_DIR} "${CMAKE_SOURCE_DIR}/lib")
file(TO_CMAKE_PATH "$ENV{PYTHON_LIB}" ENV_PYTHON_LIB)
message(STATUS "Setting link directory ${ENV_PYTHON_LIB}")
link_directories(${ENV_PYTHON_LIB})

# Works as alternative, but does not solve any of my runtime problems
# set(PYTHON_QT_PATH "${CMAKE_SOURCE_DIR}/../third_party/PythonQt")
# set(PYTHON_QT_LIB_PATH "${PYTHON_QT_PATH}/lib")
# link_directories(${PYTHON_QT_LIB_PATH})

# Build EXE ===============================================================
# Get all source files, headers, resources, and UI (forms) from src subdirectory
# See: 
## TODO: Maybe don't include headers as source?, see 
message (STATUS "-------- Finding source, header, resource, UI files relative to  ${CMAKE_SOURCE_DIR} ---------")
file(GLOB_RECURSE MY_SOURCES RELATIVE ${CMAKE_SOURCE_DIR} "src/*.cpp"  "src/*.h"
"resources/*.qrc" "ui/*.ui")

message (STATUS "=========== FOUND FILES =============")
message (STATUS "${MY_SOURCES}")
message (STATUS "=========== END FILES ===============")

# Generate release PDB
# 
add_compile_options("$<$<NOT:$<CONFIG:Debug>>:/Zi>")
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/DEBUG>")
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/OPT:REF>")
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/OPT:ICF>")

# Add an executable to be built from sources variable
add_executable(${TARGET_NAME} ${MY_SOURCES})

# Add compile definitions to the target ===================================
# Set options based on debug or release mode
# Generator expression, see: 
# 
# https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html
set(DEBUG_DEFINITIONS "DEBUG_MODE")
set(RELEASE_DEFINITIONS "QT_NO_DEBUG_OUTPUT")
target_compile_definitions(${TARGET_NAME} PUBLIC
    $<$<CONFIG:DEBUG>:${DEBUG_DEFINITIONS}>
    $<$<CONFIG:RELEASE>:${RELEASE_DEFINITIONS}>
)

# Remove unwanted flags ===================================================
# Doesn't work
# remove_flag_from_target(${TARGET_NAME} -RTC1)

# Pre-processor Defines ===================================================
add_definitions(-D_UNICODE -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_DLL -DQT_OPENGL_LIB)
add_definitions(-DDEVELOP_MODE)
add_definitions(-DLINALG_USE_EIGEN)

# Disable warnings about deprecated things, like using strcpy (sorry, not sorry)
if(MSVC)
    add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()

# Add compile options to the target =======================================
# target_compile_options(${TARGET_NAME} PUBLIC "$<$<CONFIG:DEBUG>:${MY_DEBUG_OPTIONS}>")
# target_compile_options(${TARGET_NAME} PUBLIC "$<$<CONFIG:RELEASE>:${MY_RELEASE_OPTIONS}>")

# Link Required Qt modules to main target =================================
# This MUST come after add_executable and find_package for each module
# Essentially, target_link_libraries links the two specified libraries
# 
target_link_libraries(${TARGET_NAME} OpenGL::GL OpenGL::GLU)
target_link_libraries(${TARGET_NAME} Qt5::Core)
target_link_libraries(${TARGET_NAME} Qt5::Concurrent) 
target_link_libraries(${TARGET_NAME} Qt5::Gamepad)
target_link_libraries(${TARGET_NAME} Qt5::Gui)
target_link_libraries(${TARGET_NAME} Qt5::OpenGLExtensions) # TODO: Probably unnecessary, remove
target_link_libraries(${TARGET_NAME} Qt5::Multimedia)
target_link_libraries(${TARGET_NAME} Qt5::MultimediaWidgets)
target_link_libraries(${TARGET_NAME} Qt5::Widgets)

# Add additional libraries ================================================
# Add a default search locations
# TODO: link_directories takes generators, so maybe split into debug and release that way
message(STATUS "Default library search directories: ${CMAKE_SOURCE_DIR}/lib ${CMAKE_SOURCE_DIR}/lib/assimp")

# Include directories:
# 
# Linking libraries:
# **** 
# 

# Python
message (STATUS "=========== Including Python =============")
# To eliminate conflict with "slots" keyword: PyType_Slot *slots; /* terminated by slot==0. */
# Equivalent to CONFIG += no_keywords in qmake
# add_definitions(-DQT_NO_KEYWORDS)

# For system versions, see: 
# 
if(DEFINED ENV{PYTHON_VERSION})
    set(PYTHON_VERSION $ENV{PYTHON_VERSION})
else()
    if(WIN32)
        # for Windows operating system in general
        # if(MSVC OR MSYS OR MINGW) # for detecting Windows compilers
        set(PYTHON_VERSION 38)
    elseif(APPLE)
        # for MacOS X or iOS, watchOS, tvOS (since 3.10.3)
    elseif(UNIX AND NOT APPLE)
        # For Linux, BSD, Solaris, Minix
        message(STATUS "Setting UNIX python version")
        set(PYTHON_VERSION 3.8)
    else()
        message( WARNING "Unrecognized operating system")
    endif()
endif()
message (STATUS "PYTHON VERSION $ENV{PYTHON_VERSION}")

# Set up include paths and libraries for Python itself
if(WIN32)
    # for Windows operating system in general
    # if(MSVC OR MSYS OR MINGW) # for detecting Windows compilers
    
    # Convert paths to CMAKE-friendly versions
    file(TO_CMAKE_PATH "$ENV{PYTHON_PATH}" ENV_PYTHON_PATH)
    
    # Link Python
    # Debug DLL fails to import third party modules, so always use release
    target_include_directories(${TARGET_NAME} PRIVATE "${ENV_PYTHON_PATH}/include")
    message(STATUS "Python include path for windows is ${ENV_PYTHON_PATH}/include")
    message(STATUS "Python path is ${ENV_PYTHON_PATH}")
    # find_library(PYTHON_DEBUG_LIB NAMES "python${PYTHON_VERSION}_d" HINTS ${ENV_PYTHON_LIB})
    find_library(PYTHON_RELEASE_LIB NAMES "python${PYTHON_VERSION}" HINTS ${ENV_PYTHON_LIB})
    # message(STATUS "Linking Python with debug path ${PYTHON_DEBUG_LIB} and release path ${PYTHON_RELEASE_LIB}")
    target_link_libraries(${TARGET_NAME}
        debug ${PYTHON_RELEASE_LIB} optimized ${PYTHON_RELEASE_LIB}
    )
elseif(APPLE)
    # for MacOS X or iOS, watchOS, tvOS (since 3.10.3)
    message (STATUS "BUILDING FOR APPLE")
    # Include library directory
    target_include_directories(${TARGET_NAME} PRIVATE "/System/Library/Frameworks/Python.framework/Headers")
    
    # Find library with name Python, and link
    find_library(PYTHON_LIBRARY_PATH NAMES "Python")
    target_link_libraries(${TARGET_NAME}
        ${PYTHON_LIBRARY_PATH}
    )
elseif(UNIX AND NOT APPLE)
    # For Linux, BSD, Solaris, Minix
    message (STATUS "BUILDING FOR UNIX")
    execute_process(COMMAND python${PYTHON_VERSION}-config --embed --libs
        OUTPUT_VARIABLE PYTHON_LIBRARY_PATH
        RESULT_VARIABLE FAILED_TO_DETECT_PYTHON
    )
    if(FAILED_TO_DETECT_PYTHON)
        message (WARNING "Failed to detect Python")
    else()
        # Set library path
        target_link_libraries(${TARGET_NAME} ${PYTHON_LIBRARY_PATH})
    endif()
else()
    message( WARNING "Unrecognized operating system")
endif()


# PYBIND
message (STATUS "=========== Including PYBIND =============")
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_SOURCE_DIR}/../third_party/pybind11/include")

# EIGEN 
message (STATUS "=========== Including Eigen at ${CMAKE_SOURCE_DIR}/src/third_party/eigen =============")
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_SOURCE_DIR}/src/third_party/eigen")


# ASSIMP
message (STATUS "=========== Including ASSIMP =============")
target_include_directories(${TARGET_NAME} PRIVATE 
"${CMAKE_SOURCE_DIR}/../third_party/assimp/assimp-5.0.0/include" 
"${CMAKE_SOURCE_DIR}/../third_party/assimp/assimp-5.0.0/build/include")
find_library(ASSIMP_DEBUG_LIB NAMES assimp_d HINTS "${CMAKE_SOURCE_DIR}/lib/assimp")
find_library(ASSIMP_LIB NAMES assimp HINTS "${CMAKE_SOURCE_DIR}/lib/assimp")
target_link_libraries(${TARGET_NAME} 
    debug ${ASSIMP_DEBUG_LIB} optimized ${ASSIMP_LIB})

# PhysX
message (STATUS "=========== Including PhysX as a static library =============")
add_definitions(-DPX_PHYSX_STATIC_LIB)
target_include_directories(${TARGET_NAME} PRIVATE 
"${CMAKE_SOURCE_DIR}/../third_party/physx/physx/include" 
"${CMAKE_SOURCE_DIR}/../third_party/physx/pxshared/include")
set( PHYSX_LIBRARY_DEBUG_DIR "${CMAKE_SOURCE_DIR}/lib/physx/debug")
set( PHYSX_LIBRARY_RELEASE_DIR "${CMAKE_SOURCE_DIR}/lib/physx/release")
message (STATUS "Debug directory is ${PHYSX_LIBRARY_DEBUG_DIR}")
target_link_libraries(${TARGET_NAME} 
    debug "${PHYSX_LIBRARY_DEBUG_DIR}/PhysX_static_32.lib" optimized "${PHYSX_LIBRARY_RELEASE_DIR}/PhysX_static_32.lib"
    debug "${PHYSX_LIBRARY_DEBUG_DIR}/PhysXCharacterKinematic_static_32.lib" optimized "${PHYSX_LIBRARY_RELEASE_DIR}/PhysXCharacterKinematic_static_32.lib" 
    debug "${PHYSX_LIBRARY_DEBUG_DIR}/PhysXCommon_static_32.lib" optimized "${PHYSX_LIBRARY_RELEASE_DIR}/PhysXCommon_static_32.lib"
    debug "${PHYSX_LIBRARY_DEBUG_DIR}/PhysXCooking_static_32.lib" optimized "${PHYSX_LIBRARY_RELEASE_DIR}/PhysXCooking_static_32.lib"
    debug "${PHYSX_LIBRARY_DEBUG_DIR}/PhysXExtensions_static_32.lib" optimized "${PHYSX_LIBRARY_RELEASE_DIR}/PhysXExtensions_static_32.lib"
    debug "${PHYSX_LIBRARY_DEBUG_DIR}/PhysXFoundation_static_32.lib" optimized "${PHYSX_LIBRARY_RELEASE_DIR}/PhysXFoundation_static_32.lib"
    debug "${PHYSX_LIBRARY_DEBUG_DIR}/PhysXPvdSDK_static_32.lib" optimized "${PHYSX_LIBRARY_RELEASE_DIR}/PhysXPvdSDK_static_32.lib"
    debug "${PHYSX_LIBRARY_DEBUG_DIR}/PhysXVehicle_static_32.lib" optimized "${PHYSX_LIBRARY_RELEASE_DIR}/PhysXVehicle_static_32.lib"
    )

# FreeType
message (STATUS "=========== Including FreeType =============")
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_SOURCE_DIR}/../third_party/freetype-2.10.1/include")
find_library(FREETYPE_DEBUG_LIB NAMES freetype HINTS "${CMAKE_SOURCE_DIR}/lib/freetype/debug")
find_library(FREETYPE_RELEASE_LIB NAMES freetype HINTS "${CMAKE_SOURCE_DIR}/lib/freetype/release")
target_link_libraries(${TARGET_NAME} 
    debug ${FREETYPE_DEBUG_LIB} optimized ${FREETYPE_RELEASE_LIB})

# SoLoud
message (STATUS "=========== Including SoLoud =============")
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_SOURCE_DIR}/../third_party/soloud/include")
find_library(SOLOUD_DEBUG_LIB NAMES soloud_x86_d HINTS "${CMAKE_SOURCE_DIR}/lib/soloud/debug")
find_library(SOLOUD_RELEASE_LIB NAMES soloud_x86 HINTS "${CMAKE_SOURCE_DIR}/lib/soloud/release")
find_library(SOLOUD_STATIC_DEBUG_LIB NAMES soloud_static_x86_d HINTS "${CMAKE_SOURCE_DIR}/lib/soloud/debug")
find_library(SOLOUD_STATIC_RELEASE_LIB NAMES soloud_static_x86 HINTS "${CMAKE_SOURCE_DIR}/lib/soloud/release")
target_link_libraries(${TARGET_NAME} 
    debug ${SOLOUD_DEBUG_LIB} optimized ${SOLOUD_RELEASE_LIB}
    debug ${SOLOUD_STATIC_DEBUG_LIB} optimized ${SOLOUD_STATIC_RELEASE_LIB}
    )
    
# Visual Leak Detector
# See: 
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_SOURCE_DIR}/../third_party/Visual Leak Detector/include/")
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
    message(STATUS "=========== Including 64 Bit VLD =============")
    # Is 64 bit
    find_library(VLD_LIB NAMES vld HINTS "${CMAKE_SOURCE_DIR}/../third_party/Visual Leak Detector/lib/Win64")
    target_link_libraries(${TARGET_NAME} ${VLD_LIB})
else()
    # Is 32 Bit
    message(STATUS "=========== Including 32 Bit VLD =============")
    find_library(VLD_LIB NAMES vld HINTS "${CMAKE_SOURCE_DIR}/../third_party/Visual Leak Detector/lib/Win32")
    target_link_libraries(${TARGET_NAME} ${VLD_LIB})
endif()

编辑:所以,已经过去几周了,我在弄清楚这里发生了什么方面完全没有取得任何进展。我已经为这两个构建系统生成了一些详细的报告,which can be found here. 到目前为止,没有任何线索对我来说很突出。事实上,我什至没有在报告中看到任何表明我的新构建系统速度变慢的信息​​!如果我没看错,应该会更快。

编辑 2:这也是我的链接器选项。 The old way, and the new way.

我明白了!! cmake 将我的应用程序构建为控制台应用程序,而不是 Windows 应用程序。在我的 cmake 构建中用 add_executable(${TARGET_NAME} WIN32 ${MY_SOURCES}) 替换 add_executable(${TARGET_NAME} ${MY_SOURCES}) 使性能匹配。今天学到了新东西,谢谢大家