2012-03-04 81 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