我正在尝试为一个简单的Qt应用程序编写一个可移植的CMake脚本。目标平台是Win和Mac OSX。但是正如您所看到的,它已经是一个庞然大物了。

有没有CMake教授?您能看到此脚本中使用的任何实质上错误的方法吗?我敢打赌,有几个。

CMAKE_MINIMUM_REQUIRED( VERSION 2.8.6 )

##################################################################################################################################

MACRO( CHOOSE_QT path )
    FILE( GLOB QTROOTS "${path}/bin" )
    FIND_PROGRAM( QT_QMAKE_EXECUTABLE NAMES qmake qmake4 qmake-qt4 qmake-mac PATHS ${QTROOTS} )
ENDMACRO( CHOOSE_QT path )

MACRO( ADD_FILES_TO_FILTER rootFilterName rootFilterPath files )
    FOREACH( curFile ${files} )
        FILE( RELATIVE_PATH curFilter "${CMAKE_CURRENT_SOURCE_DIR}/${rootFilterPath}" "${CMAKE_CURRENT_SOURCE_DIR}/${curFile}" )
        FILE( RELATIVE_PATH test "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/${curFile}" )
        GET_FILENAME_COMPONENT( curFilter ${curFilter} PATH )
        SET( curFilter "${rootFilterName}/${curFilter}" )
        STRING( REPLACE "/" "\\" curFilter ${curFilter} )
        SOURCE_GROUP( ${curFilter} FILES ${curFile} )
    ENDFOREACH( curFile )
ENDMACRO( ADD_FILES_TO_FILTER rootFilterName rootFilterPath files )

MACRO( TO_RELATIVE_PATHS filePaths )
    SET( resPaths "" )
    FOREACH( curPath ${${filePaths}} )
        FILE( RELATIVE_PATH relPath ${CMAKE_CURRENT_SOURCE_DIR} ${curPath} )
        SET( resPaths ${resPaths} ${relPath} )
    ENDFOREACH( curPath )
    SET( ${filePaths} ${resPaths} )
ENDMACRO( TO_RELATIVE_PATHS filePaths )

MACRO( COPY_TO_BUNDLE resourcePath bundlePath )
    LIST( APPEND BUNDLE_COPY_RESOURCES ${resourcePath} )
    SET_SOURCE_FILES_PROPERTIES( ${resourcePath} PROPERTIES MACOSX_PACKAGE_LOCATION ${bundlePath} )
ENDMACRO( COPY_TO_BUNDLE )

MACRO( ADD_FRAMEWORK fwname fwpath appname )
    TARGET_LINK_LIBRARIES( ${appname} ${fwpath}/${fwname} )
    MESSAGE( STATUS "Framework ${fwname} found at ${fwpath}" )
ENDMACRO()

MACRO( ADD_SYSTEM_FRAMEWORK fwname appname )
    FIND_LIBRARY( FRAMEWORK_${fwname} NAMES ${fwname} PATHS ${CMAKE_OSX_SYSROOT}/System/Library PATH_SUFFIXES Frameworks NO_DEFAULT_PATH )
    if( ${FRAMEWORK_${fwname}} STREQUAL FRAMEWORK_${fwname}-NOTFOUND )
        MESSAGE( ERROR ": Framework ${fwname} not found" )
    else()
        ADD_FRAMEWORK( ${fwname} ${FRAMEWORK_${fwname}} ${appname} )
    endif()
ENDMACRO( ADD_SYSTEM_FRAMEWORK )

##################################################################################################################################

# Define project settings
PROJECT( TrackerSoftware )
SET( APP_NAME "TRACKer" )

# Find Qt library
if( WIN32 )
    CHOOSE_QT( "${CMAKE_CURRENT_SOURCE_DIR}/cxx/thirdparty/Qt" )
endif( WIN32 )
SET( CMAKE_AUTOMOC TRUE )
FIND_PACKAGE( Qt4 REQUIRED )

# Find Boost library
if( WIN32 )
    SET( BOOST_ROOT "cxx/thirdparty/boost" )
elseif( APPLE )
    SET( BOOST_ROOT "osx/FRP/vendors/libraries/include/boost" )
endif( WIN32 )
FIND_PACKAGE( Boost REQUIRED )

# Collect all required files for build
FILE( GLOB_RECURSE headers RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "cxx/src/RTCS/include/*.h" )
FILE( GLOB_RECURSE sources RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "cxx/src/RTCS/src/*.cpp" )
FILE( GLOB_RECURSE resources RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "cxx/src/*.qrc" )
FILE( GLOB_RECURSE win_resources RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "cxx/src/*.rc" )
FILE( GLOB_RECURSE forms RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "cxx/src/*.ui" )
SET( thirdparty_sources "cxx/thirdparty/SimpleCrypt/simplecrypt.cpp" )
if( APPLE )
    FILE( GLOB_RECURSE mac_sources RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "cxx/src/RTCS/src/*.m" )
    LIST( APPEND sources ${mac_sources} )
endif( APPLE )

# Preprocess forms
FILE( RELATIVE_PATH buildDir ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} )
QT4_WRAP_UI( form_headers ${forms} )
TO_RELATIVE_PATHS( form_headers )
ADD_FILES_TO_FILTER( "Forms" "${buildDir}/src/RTCS/include" "${form_headers}" )

# Preprocess resources
QT4_ADD_RESOURCES( resources_rcc ${resources} )
TO_RELATIVE_PATHS( resources_rcc )
ADD_FILES_TO_FILTER( "Resources" "${buildDir}" "${resources_rcc}" )

# Mark all sources as ObjectiveC++
if( APPLE )
    foreach( curSource ${sources} )
        SET_SOURCE_FILES_PROPERTIES( ${curSource} PROPERTIES COMPILE_FLAGS "-x objective-c++" )
    endforeach( curSource )
endif( APPLE )

# Set all link libraries directories - it should be specified Before any targets creation
if( WIN32 )
    LINK_DIRECTORIES( "${CMAKE_CURRENT_SOURCE_DIR}/cxx/thirdparty/boost/lib" )
    LINK_DIRECTORIES( "${CMAKE_CURRENT_SOURCE_DIR}/cxx/thirdparty/libtwitcurl/lib/x86" )
    LINK_DIRECTORIES( "${CMAKE_CURRENT_SOURCE_DIR}/cxx/thirdparty/id3lib/lib/x86" )
    LINK_DIRECTORIES( "${CMAKE_CURRENT_SOURCE_DIR}/cxx/thirdparty/curl/curl/lib/lib/x86" )
    LINK_DIRECTORIES( "${CMAKE_CURRENT_SOURCE_DIR}/cxx/thirdparty/log4qt/lib/x86" )
    LINK_DIRECTORIES( "${CMAKE_CURRENT_SOURCE_DIR}/cxx/thirdparty/WinSparkle/lib/x86/$(ConfigurationName)" )
    LINK_DIRECTORIES( "${CMAKE_CURRENT_SOURCE_DIR}/cxx/thirdparty/fervor-auto/lib/$(Configuration)" )
    LINK_DIRECTORIES( "${CMAKE_CURRENT_SOURCE_DIR}/cxx/thirdparty/quazip/lib/$(Configuration)" )
elseif( APPLE )
    LINK_DIRECTORIES( "${CMAKE_CURRENT_SOURCE_DIR}/osx/FRP/vendors/libraries/lib" )
endif( WIN32 )

# Set up Bundle settings for the Mac OSX
if( APPLE )
    SET( MACOSX_BUNDLE true )
    SET( MACOSX_BUNDLE_SHORT_VERSION_STRING 0.7-beta2 )
    SET( MACOSX_BUNDLE_VERSION 0.7-beta2 )
    SET( MACOSX_BUNDLE_LONG_VERSION_STRING Version 0.7-beta2 )
    #SET( CMAKE_OSX_ARCHITECTURES ppc;i386 ) #Comment out if not universal binary

    # Add a bundle icon
    SET( MACOSX_BUNDLE_ICON_FILE multimonIcon.icns )
    COPY_TO_BUNDLE( "osx/FRP/${MACOSX_BUNDLE_ICON_FILE}" Resources )

    # Copy all private frameworks into the bundle
    #COPY_TO_BUNDLE( "osx/FRP/vendors/libraries/lib/Sparkle.framework" Frameworks )
    #foreach( curFramework ${QT_LIBRARIES} )
        #COPY_TO_BUNDLE( "${curFramework}" Frameworks )
    #endforeach( curFramework )

    # Fixup bundle, copy dynamic libraries into app bundle
    SET( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/out )
    MESSAGE( STATUS "!!! BUNDLE PATH: ${EXECUTABLE_OUTPUT_PATH}/${APP_NAME}.app" )
    SET( APPS "${CMAKE_INSTALL_PREFIX}/${APP_NAME}.app" ) # paths to executables
    SET( DIRS "${CMAKE_SOURCE_DIR}/osx/FRP/vendors/libraries/lib" ) # directories to search for prerequisites
    INSTALL( CODE "
        include(BundleUtilities)
        fixup_bundle(\"${APPS}\" \"\" \"${DIRS}\")
    ")
endif( APPLE )

# Create executable
if( WIN32 )
    ADD_EXECUTABLE( Tracker WIN32 ${headers} ${sources} ${form_headers} ${resources_rcc} ${thirdparty_sources} ${win_resources} )
    SET_TARGET_PROPERTIES( Tracker PROPERTIES OUTPUT_NAME "tracker" )
    SET_TARGET_PROPERTIES( Tracker PROPERTIES COMPILE_FLAGS "/Zc:wchar_t-" )
elseif( APPLE )
    ADD_EXECUTABLE( Tracker MACOSX_BUNDLE ${headers} ${sources} ${form_headers} ${resources_rcc} ${thirdparty_sources} ${BUNDLE_COPY_RESOURCES} )
    SET_TARGET_PROPERTIES( Tracker PROPERTIES OUTPUT_NAME ${APP_NAME} )
    SET( CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0" )
endif( WIN32 )

# Set filters for project according to its namespaces
ADD_FILES_TO_FILTER( "Headers" "cxx/src/RTCS/include" "${headers}" )
ADD_FILES_TO_FILTER( "Sources" "cxx/src/RTCS/src" "${sources}" )
ADD_FILES_TO_FILTER( "Resources" "cxx/src/RTCS/rc" "${win_resources}" )
ADD_FILES_TO_FILTER( "Thirdparty" "cxx/thirdparty" "${thirdparty_sources}" )

# Set additional include directories
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} )
INCLUDE_DIRECTORIES( "cxx/src" )
INCLUDE_DIRECTORIES( "cxx/src/RTCS/include" )
INCLUDE_DIRECTORIES( "cxx/thirdparty" )

# Configure Qt
SET( QT_USE_QTNETWORK TRUE )
SET( QT_USE_QTSQL TRUE )
SET( QT_USE_QTSCRIPT TRUE )
SET( QT_USE_QTXML TRUE )
SET( QT_USE_QTWEBKIT TRUE )
INCLUDE( ${QT_USE_FILE} )
ADD_DEFINITIONS( ${QT_DEFINITIONS} )
TARGET_LINK_LIBRARIES( Tracker ${QT_LIBRARIES} )
TARGET_LINK_LIBRARIES( Tracker ${QT_QTMAIN_LIBRARY} )

# Add boost support
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} )
TARGET_LINK_LIBRARIES( Tracker ${Boost_LIBRARIES} )

# Add other libs include dirs
INCLUDE_DIRECTORIES( "cxx/thirdparty/SimpleCrypt" )
INCLUDE_DIRECTORIES( "cxx/thirdparty/id3lib/include" )
INCLUDE_DIRECTORIES( "cxx/thirdparty/libtwitcurl" )
INCLUDE_DIRECTORIES( "cxx/thirdparty/curl/curl/include" )
INCLUDE_DIRECTORIES( "cxx/thirdparty/log4qt/include" )
INCLUDE_DIRECTORIES( "cxx/thirdparty/fervor-auto" )

# Add other libs to link
if( WIN32 )
    TARGET_LINK_LIBRARIES( Tracker debug "twitcurlD.lib" )
    TARGET_LINK_LIBRARIES( Tracker debug "id3libD.lib" )
    TARGET_LINK_LIBRARIES( Tracker debug "libcurlD.lib" )
    TARGET_LINK_LIBRARIES( Tracker debug "log4qtD.lib" )

    TARGET_LINK_LIBRARIES( Tracker optimized "twitcurl.lib" )
    TARGET_LINK_LIBRARIES( Tracker optimized "id3lib.lib" )
    TARGET_LINK_LIBRARIES( Tracker optimized "libcurl.lib" )
    TARGET_LINK_LIBRARIES( Tracker optimized "log4qt.lib" )

    TARGET_LINK_LIBRARIES( Tracker "fervor.lib" )
    TARGET_LINK_LIBRARIES( Tracker "quazip.lib" )

    TARGET_LINK_LIBRARIES( Tracker "Wininet.lib" )
    TARGET_LINK_LIBRARIES( Tracker "ws2_32.lib" )
    TARGET_LINK_LIBRARIES( Tracker "winmm.lib" )
    TARGET_LINK_LIBRARIES( Tracker "wldap32.lib" )
    TARGET_LINK_LIBRARIES( Tracker "Shell32.lib" )
    TARGET_LINK_LIBRARIES( Tracker "Version.lib" )
elseif( APPLE )
    TARGET_LINK_LIBRARIES( Tracker "libiconv.a" )
    TARGET_LINK_LIBRARIES( Tracker "libid3.a" )
    TARGET_LINK_LIBRARIES( Tracker "liblibtwitcurl.a" )
    TARGET_LINK_LIBRARIES( Tracker "libLog4Qt.a" )
    TARGET_LINK_LIBRARIES( Tracker "libz.a" )
    TARGET_LINK_LIBRARIES( Tracker "libboost_date_time.a" )
    TARGET_LINK_LIBRARIES( Tracker "libboost_iostreams.a" )
    TARGET_LINK_LIBRARIES( Tracker "libboost_serialization.a" )
    TARGET_LINK_LIBRARIES( Tracker "libboost_thread-mt.a" )
    TARGET_LINK_LIBRARIES( Tracker "curl" )

    # Add frameworks
    ADD_FRAMEWORK( "Sparkle.framework" "${CMAKE_CURRENT_SOURCE_DIR}/osx/FRP/vendors/libraries/lib" Tracker )

    # Add system frameworks
    ADD_SYSTEM_FRAMEWORK( Foundation Tracker )
    ADD_SYSTEM_FRAMEWORK( CoreFoundation Tracker )
    ADD_SYSTEM_FRAMEWORK( AppKit Tracker )
endif( WIN32 )

# Add defines
ADD_DEFINITIONS( -DQUAZIP_STATIC )
ADD_DEFINITIONS( -DBUILDING_LIBCURL )
ADD_DEFINITIONS( -DID3LIB_LINKOPTION=1 )
ADD_DEFINITIONS( -DUNICODE -D_UNICODE ) #enable unicode support


评论

[Win x64]会属于Win32分支吗?

我记得@retailcoder,是的,它会而且确实如此。这些是Windows,Linux和Mac等平台之间的选择器。

人们没有通常使用的名为qmake的工具吗?

我使用了一个CMake文件,该文件在脚本的早期调用了FIND_PACKAGE(Qt4 4.8.0组件QtCore QtNetwork必需)和INCLUDE($ {QT_USE_FILE}),一次调用了QT4_WRAP_CPP,并将$ {QT_LIBRARIES}作为输入参数之一TARGET_LINK_LIBRARIES。除此之外,似乎不需要提及Qt,尤其是没有类似CHOOSE_QT(“ $ {CMAKE_CURRENT_SOURCE_DIR} / cxx / thirdparty / Qt”)的东西。但这可能取决于您如何安装Qt。

@DavidK我们不安装Qt,我们保留几个不同Qt构建的存储库,并将它们用作子存储库,或者只是克隆某个位置并为路径设置env变量。因此,所有脚本均支持该方案。我们之所以这样做,是因为我们有多个使用不同Qts的项目,并且我们不想将某些旧项目移植到新的Qt中,因为它偶尔会引入错误。您可以在这里了解有关在stackoverflow上选择Qt实例的所有问题,在这里stackoverflow.com/questions/12511370/…

#1 楼

我的CMake-fu有点生锈-可能和这个问题一样古老-但我仍然看到一些可以改进的地方:


CMake不需要else()endif()不再包含原始的if()表达式。似乎这种限制很久以前就消失了,因此您可以通过保留空的else()endif()表达式来简化代码。您的缩进已经很好地记录了if()的结束位置。
上面的注释也适用于endmacro()endforeach,更普遍地适用于任何endxxx()指令。请注意,它甚至适用于您的版本:您将endmacro()留空了,而不是ADD_FRAMEWORK
您的大小写不一致。有时使用FOREACH,而有时使用foreach。我知道CMake并不是真正区分大小写的,但是保持一致并不会损害代码编辑器中的区分大小写的搜索。
"${CMAKE_CURRENT_SOURCE_DIR}/cxx/thirdparty的出现过多。您应该定义一个${THIRD_PARTY_DIR}变量或类似的东西来重复一次完整的路径。如果路径更改,它将避免许多问题。似乎没有一种可移植的方法来使它同时适用于WIN32APPLE,但是针对WIN32进行操作已经有所帮助。
您应该删除注释掉的代码。如果您需要旧版本的代码,则应仅依靠修订控制软件。如果您有诸如“注释以做某事”之类的注释,则通常意味着所涉及的“某事”应为命令行选项。