Qt + CMake + VC ++产生命令提示符

时间:2012-03-04 13:44:25

标签: c++ qt visual-c++ qt4 cmake

我正在尝试从qt教程运行窗口布局示例时使用标题中提到的组合。主要看起来像这样:

#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})

构建和编译工作正常,但是当我运行应用程序时,它总是显示命令提示符。我该如何避免?

4 个答案:

答案 0 :(得分: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

答案 1 :(得分: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 _WinMain@16 referenced in function ___tmainCRTStartup

修复它与CMakeLists.txt文件中的QT_QTMAIN_LIBRARY链接

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

现在您甚至不必像以前的解决方案那样更改您的来源。

答案 2 :(得分:4)

在使用Qt4的CMakeFile中,您无需在编译时更改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})

另外,您不需要包含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)

答案 3 :(得分:-1)

在pro文件中,删除以下控制台定义,它将消失

CONFIG += console