2012-03-04 47 views
1

我正在使用標題中提到的組合來嘗試運行qt教程中的窗口布局示例。主要如下所示:Qt + CMake + VC++生成命令提示符

#include <QtGui> 

int main(int argc, char **argv) { 
    QApplication app(argc, argv); 
    QWidget window; 
    QLabel *label = new QLabel(QApplication::translate("windowlayout", "Name:")); 
    QLineEdit *lineEdit = new QLineEdit(); 

    QHBoxLayout *layout = new QHBoxLayout(); 
    layout->addWidget(label); 
    layout->addWidget(lineEdit); 
    window.setLayout(layout); 
    window.setWindowTitle(
     QApplication::translate("windowlayout", "Window layout")); 
    window.show(); 
    return app.exec(); 
} 

而且的CMakeLists.txt這樣的:

PROJECT(test) 
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0) 

FIND_PACKAGE(Qt4 REQUIRED) 
INCLUDE_DIRECTORIES(${QT_INCLUDE_DIR} ${QT_QTCORE_INCLUDE_DIR} ${QT_QTGUI_INCLUDE_DIR}) 

SET(test_SRCS main.cc) 

QT4_AUTOMOC(${test_SRCS}) 

ADD_EXECUTABLE(test ${test_SRCS}) 

TARGET_LINK_LIBRARIES(test ${QT_QTGUI_LIBRARIES} ${QT_QTCORE_LIBRARIES}) 

的建設和編制工作正常,但是當我運行應用程序,它始終顯示命令提示符。我如何避免這種情況?

回答

3

在您的CMakeFile與Qt4中,您不需要更改您的CPP代碼或在編譯時添加標誌。只需使用

set(QT_USE_QTMAIN TRUE) 

它會自動鏈接qtmain.lib與您的可執行文件。這個庫定義了其他常見的main()簽名,包括WinMain()。

使用這個技巧,您的應用程序可以在Windows下使用MSVC進行編譯,而不必在您的IDE之外運行應用程序(例如QtCreator)時無需顯示原始main()函數,也不顯示控制檯。

最終導致的CMakeLists.txt可以是:

PROJECT(test) 
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0) 

FIND_PACKAGE(Qt4 REQUIRED) 
if(WIN32) 
    SET(QT_USE_QTMAIN TRUE) 
endif(WIN32) 

INCLUDE(${QT_USE_FILE}) 

SET(test_SRCS main.cc) 

QT4_AUTOMOC(${test_SRCS}) 

ADD_EXECUTABLE(test ${test_SRCS}) 

TARGET_LINK_LIBRARIES(test ${QT_LIBRARIES}) 

Additionnaly,你並不需要包括QtCore和QtGui,他們在默認情況下QT_USE_FILE(用於包括文件夾)和QT_LIBRARIES包括(圖書館) 。

你只需要設置你用,或者你不(對GUI)使用的模塊:

# Use Network and Sql modules 
set(QT_USE_QTNETWORK TRUE) 
set(QT_USE_QTSQL TRUE) 
# Do not use Gui module 
set(QT_DONT_USE_QTGUI TRUE) 
+0

我需要爲Qt5設置什麼選項? – 2013-03-10 22:30:16

+0

您可以在此主題上找到回覆:http://stackoverflow.com/questions/14115024/how-to-link-qtmain-in-cmake-with-qt5/14164144#14164144 'target_link_libraries(myExecutable Qt5 :: WinMain函數)' – Antwane 2013-03-15 17:13:05

8

你需要告訴CMake的你想要一個GUI應用程序:

# GUI Type 
if(WIN32) 
    set(GUI_TYPE WIN32) 
endif(WIN32) 
if(APPLE) 
    set(GUI_TYPE MACOSX_BUNDLE) 
endif(APPLE) 

ADD_EXECUTABLE(test ${GUI_TYPE} ${test_SRCS}) 

注意,當您在Windows上編譯,這將main()程序的入口改到WinMain(),所以你需要修改來源也是如此。 這是我平時做的:

#ifdef _WIN32 
class Win32CommandLineConverter; 

int CALLBACK WinMain(HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */, LPSTR /* lpCmdLine */, int /* nCmdShow */) 
{ 
    Win32CommandLineConverter cmd_line; 
    return main(cmd_line.argc(), cmd_line.argv()); 
} 


class Win32CommandLineConverter { 
private: 
    std::unique_ptr<char*[]> argv_; 
    std::vector<std::unique_ptr<char[]>> storage_; 
public: 
    Win32CommandLineConverter() 
    { 
     LPWSTR cmd_line = GetCommandLineW(); 
     int argc; 
     LPWSTR* w_argv = CommandLineToArgvW(cmd_line, &argc); 
     argv_ = std::unique_ptr<char*[]>(new char*[argc]); 
     storage_.reserve(argc); 
     for(int i=0; i<argc; ++i) { 
      storage_.push_back(ConvertWArg(w_argv[i])); 
      argv_[i] = storage_.back().get(); 
     } 
     LocalFree(w_argv); 
    } 
    int argc() const 
    { 
     return static_cast<int>(storage_.size()); 
    } 
    char** argv() const 
    { 
     return argv_.get(); 
    } 
    static std::unique_ptr<char[]> ConvertWArg(LPWSTR w_arg) 
    { 
     int size = WideCharToMultiByte(CP_UTF8, 0, w_arg, -1, nullptr, 0, nullptr, nullptr); 
     std::unique_ptr<char[]> ret(new char[size]); 
     WideCharToMultiByte(CP_UTF8, 0, w_arg, -1, ret.get(), size, nullptr, nullptr); 
     return ret; 
    } 
}; 
#endif 
+0

的條件句非必需的;在其不適用的平臺上忽略'WIN32'和'MACOSX_BUNDLE'選項,因此您可以隨時使用它們:'add_executable(myApp WIN32 MACOSX_BUNDLE $ {sources})''。而且(正如其他人所指出的)如果你使用Qt,你可以鏈接到'$ {QT_QTMAIN_LIBRARY}',以避免也提供一個'WinMain'。 – Matthew 2015-12-09 16:46:53

6

我想要一個發佈版本來隱藏控制檯,但其他所有構建表現出來。要做到這一點使用:

if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") 
    SET_TARGET_PROPERTIES(MyApp PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE") 
    SET_TARGET_PROPERTIES(MyApp PROPERTIES RELWITHDEBINFO "/SUBSYSTEM:CONSOLE") 
    SET_TARGET_PROPERTIES(MyApp PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") 
    SET_TARGET_PROPERTIES(MyApp PROPERTIES MINSIZEREL "/SUBSYSTEM:WINDOWS") 
endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") 

這將介紹以下鏈接錯誤: error LNK2019: unresolved external symbol [email protected] referenced in function ___tmainCRTStartup

修復它與QT_QTMAIN_LIBRARY鏈接在你的CMakeLists.txt文件

TARGET_LINK_LIBRARIES(MyApp ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY} ${OTHER_STUFF_TO_LINK}) 

現在你不甚至必須像以前的解決方案中那樣更改源代碼。

+0

如果您不使用FindQt4.cmake,此解決方案是否正常工作?這是CMAKE功能還是QMAKE功能? – cppguy 2013-02-11 21:50:12