环境
Clion :2019.3.6
Qt :5.12.12(MinGW 7.3.0)
CEF:cef_binary_87.1.14+ga29e9a3+chromium-87.0.4280.141_windows32
编译libcef_dll_wrapper
修改cmake 文件
修改根目录下的CMakeLists.txt
# 修改cmake 版本
cmake_minimum_required(VERSION 2.8.12.1...3.20.0)# 设置c++标准
add_definitions("-std=c++11")# 注释掉测试工程
#if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests")
# add_subdirectory(tests/cefsimple)
# add_subdirectory(tests/gtest)
# add_subdirectory(tests/ceftests)
#endif()#if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/cefclient")
# add_subdirectory(tests/cefclient)
#endif()
修改cef_variables.cmake
cef_variables.cmake文件在cmake目录下
主要是修改if(OS_WINDOWS)…endif()节点,因为是用MinGW编译,根据if(OS_LINUX)…endif()内容进行修改。修改原则:删除linux特有的内容,将if(OS_WINDOWS)…endif()节点下windows特有的属性合并进入。最后用修改后的的内容替换if(OS_WINDOWS)…endif()节点。
修改示例:
if(OS_WINDOWS)# Platform-specific compiler/linker flags.set(CEF_LIBTYPE STATIC)list(APPEND CEF_COMPILER_FLAGS-fno-strict-aliasing # Avoid assumptions regarding non-aliasing of objects of different types-fPIC # Generate position-independent code for shared libraries-funwind-tables # Support stack unwinding for backtrace()-fvisibility=hidden # Give hidden visibility to declarations that are not explicitly marked as visible--param=ssp-buffer-size=4 # Set the minimum buffer size protected by SSP (security feature, related to stack-protector)-pipe # Use pipes rather than temporary files for communication between build stages-pthread # Use the pthread library-Wall # Enable all warnings-Werror # Treat warnings as errors-Wno-missing-field-initializers # Don't warn about missing field initializers-Wno-unused-parameter # Don't warn about unused parameters-Wno-error=comment # Don't warn about code in comments-Wno-comment # Don't warn about code in comments)list(APPEND CEF_C_COMPILER_FLAGS-std=c99 # Use the C99 language standard)list(APPEND CEF_CXX_COMPILER_FLAGS-fno-exceptions # Disable exceptions-fno-rtti # Disable real-time type information-fno-threadsafe-statics # Don't generate thread-safe statics-fvisibility-inlines-hidden # Give hidden visibility to inlined class member functions-std=gnu++11 # Use the C++11 language standard including GNU extensions-Wsign-compare # Warn about mixed signed/unsigned type comparisons)list(APPEND CEF_COMPILER_FLAGS_DEBUG-O0 # Disable optimizations-g # Generate debug information)list(APPEND CEF_COMPILER_FLAGS_RELEASE-O2 # Optimize for maximum speed-fdata-sections # Enable linker optimizations to improve locality of reference for data sections-ffunction-sections # Enable linker optimizations to improve locality of reference for function sections-fno-ident # Ignore the #ident directive-U_FORTIFY_SOURCE # Undefine _FORTIFY_SOURCE in case it was previously defined-D_FORTIFY_SOURCE=2 # Add memory and string function protection (security feature, related to stack-protector))list(APPEND CEF_LINKER_FLAGS-fPIC # Generate position-independent code for shared libraries-pthread # Use the pthread library-Wl,--disable-new-dtags # Don't generate new-style dynamic tags in ELF-Wl,--fatal-warnings # Treat warnings as errors-Wl,-rpath,. # Set rpath so that libraries can be placed next to the executable-Wl,-z,noexecstack # Mark the stack as non-executable (security feature)-Wl,-z,now # Resolve symbols on program start instead of on first use (security feature)-Wl,-z,relro # Mark relocation sections as read-only (security feature))list(APPEND CEF_LINKER_FLAGS_RELEASE-Wl,-O1 # Enable linker optimizations-Wl,--as-needed # Only link libraries that export symbols used by the binary-Wl,--gc-sections # Remove unused code resulting from -fdata-sections and -function-sections)list(APPEND CEF_COMPILER_DEFINES_FILE_OFFSET_BITS=64 # Allow the Large File Support (LFS) interface to replace the old interface)list(APPEND CEF_COMPILER_DEFINES_RELEASENDEBUG # Not a debug build)include(CheckCCompilerFlag)include(CheckCXXCompilerFlag)CHECK_CXX_COMPILER_FLAG(-Wno-undefined-var-template COMPILER_SUPPORTS_NO_UNDEFINED_VAR_TEMPLATE)if(COMPILER_SUPPORTS_NO_UNDEFINED_VAR_TEMPLATE)list(APPEND CEF_CXX_COMPILER_FLAGS-Wno-undefined-var-template # Don't warn about potentially uninstantiated static members)endif()CHECK_C_COMPILER_FLAG(-Wno-unused-local-typedefs COMPILER_SUPPORTS_NO_UNUSED_LOCAL_TYPEDEFS)if(COMPILER_SUPPORTS_NO_UNUSED_LOCAL_TYPEDEFS)list(APPEND CEF_C_COMPILER_FLAGS-Wno-unused-local-typedefs # Don't warn about unused local typedefs)endif()CHECK_CXX_COMPILER_FLAG(-Wno-literal-suffix COMPILER_SUPPORTS_NO_LITERAL_SUFFIX)if(COMPILER_SUPPORTS_NO_LITERAL_SUFFIX)list(APPEND CEF_CXX_COMPILER_FLAGS-Wno-literal-suffix # Don't warn about invalid suffixes on literals)endif()CHECK_CXX_COMPILER_FLAG(-Wno-narrowing COMPILER_SUPPORTS_NO_NARROWING)if(COMPILER_SUPPORTS_NO_NARROWING)list(APPEND CEF_CXX_COMPILER_FLAGS-Wno-narrowing # Don't warn about type narrowing)endif()if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")list(APPEND CEF_CXX_COMPILER_FLAGS-Wno-attributes # The cfi-icall attribute is not supported by the GNU C++ compiler)endif()if(PROJECT_ARCH STREQUAL "x86_64")# 64-bit architecture.list(APPEND CEF_COMPILER_FLAGS-m64-march=x86-64)list(APPEND CEF_LINKER_FLAGS-m64)elseif(PROJECT_ARCH STREQUAL "x86")# 32-bit architecture.list(APPEND CEF_COMPILER_FLAGS-msse2-mfpmath=sse-mmmx-m32)list(APPEND CEF_LINKER_FLAGS-m32)endif()# Standard libraries.set(CEF_STANDARD_LIBSX11)# Standard libraries.set(CEF_STANDARD_LIBScomctl32.librpcrt4.libshlwapi.libws2_32.lib)# CEF directory paths.set(CEF_RESOURCE_DIR "${_CEF_ROOT}/Resources")set(CEF_BINARY_DIR "${_CEF_ROOT}/$<CONFIGURATION>")set(CEF_BINARY_DIR_DEBUG "${_CEF_ROOT}/Debug")set(CEF_BINARY_DIR_RELEASE "${_CEF_ROOT}/Release")# CEF library paths.set(CEF_LIB_DEBUG "${CEF_BINARY_DIR_DEBUG}/libcef.lib")set(CEF_LIB_RELEASE "${CEF_BINARY_DIR_RELEASE}/libcef.lib")# List of CEF binary files.set(CEF_BINARY_FILESchrome_elf.dlld3dcompiler_47.dlllibcef.dlllibEGL.dlllibGLESv2.dllsnapshot_blob.binv8_context_snapshot.binswiftshader)# List of CEF resource files.set(CEF_RESOURCE_FILEScef.pakcef_100_percent.pakcef_200_percent.pakcef_extensions.pakdevtools_resources.pakicudtl.datlocales)
endif()
修改部分代码
include\internal\cef_string_wrappers.h
// 36行增加
#if defined(__MINGW32__)
#include <cstring>
#endif
include\base\internal\cef_atomicops_x86_msvc.h
// 82行修改
#if !(defined(_MSC_VER) && _MSC_VER >= 1400) && !defined(__MINGW32__)
include\base\cef_atomicops.h
// 179行修改
#if defined(OS_WIN) && (defined(COMPILER_MSVC) || defined(__MINGW32__)) && defined(ARCH_CPU_X86_FAMILY)
include\base\cef_bind_helpers.h
// 275 行修改
#if defined(OS_WIN) && defined (COMPILER_MSVC)
// 280 行修改
#if defined(OS_WIN) && defined (COMPILER_MSVC)// 两外一种修改方式:注释掉宏判断
//#if defined(OS_WIN)
//#pragma warning(push)
//#pragma warning(disable : 4624)
//#endifstruct Base : public T, public BaseMixin {};
//#if defined(OS_WIN)
//#pragma warning(pop)
//#endif
如果需要编译64位版本,将__MINGW32__宏改为__MINGW64__即可(前提是你下载的是win64版源码)
如果需要编译高版本的CEF库,可以先编译,然后根据错误提示修改。(原则:CEF没有提供MinGW的编译方式,需要在原来的MSVC的基础行修改,错误一般是由于MSVC宏引起的)
编译
做完以上工作后可以直接编译了,我这里选择的是编译Relese版,编译完成后可以在cmake-build-release\libcef_dll_wrapper目录下找到libcef_dll_wrapper.a文件。
使用
- 新建Qt工程cef_client,将CEF中tests\cefsimple目录下的simple_app.cc,simple_app.h,simple_handler.cc,simple_handler.h,simple_handler_win.cc文件复制到cef_client目录下
- 将CEF下的inclue目录复制到cef_client/cef目录下
- 将libcef_dll_wrapper.a复制到cef_client/cef目录下
- 将CEF中Release目录下的libcef.lib复制到cef_client/cef目录下并修改扩展名为.a(是不是很意外,其实MinGW的链文件.a与VC的连接文件.lib本质上差不多,MinGW可以兼容.lib连接文件(前提是.lib中不包含vc特有的特性),如果要使用高版本的CEF库,可能需要升级MinGW的版本)
.pro文件
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++14INCLUDEPATH +=$$PWD/cef/includeSOURCES += \main.cpp \MainWindow.cpp \simple_app.cc \simple_handler.cc \simple_handler_win.ccHEADERS += \MainWindow.h \simple_app.h \simple_handler.hFORMS += \MainWindow.uiwin32: LIBS += -L$$PWD/cef/ -lcef_dll_wrapper
win32: LIBS += -L$$PWD/cef/ -lcefINCLUDEPATH += $$PWD/cef
DEPENDPATH += $$PWD/cef
编译完成后将CEF资源文件,和libcef.dll等相关库(Release目录下除过.lib文件)复制到编译好的程序目录
simple_app.cc文件中的OnContextInitialized函数,修改如下
void SimpleApp::OnContextInitialized() {return;
}
否则启动后会出现两个浏览器窗口
## main.cpp
#include "MainWindow.h"
#include "simple_app.h"
#include "simple_handler.h"#include <QApplication>bool CefInit()
{CefEnableHighDPISupport();CefSettings settings;settings.no_sandbox = true;settings.multi_threaded_message_loop = true;HINSTANCE inc = GetModuleHandle(NULL);CefMainArgs mainArgs(inc);CefRefPtr<CefApp> app;app = new SimpleApp;return CefInitialize(mainArgs, settings, app.get(), NULL);
}int main(int argc, char *argv[])
{QApplication a(argc, argv);CefInit();MainWindow w;w.showMaximized();a.exec();return 0;
}
MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) {ui->setupUi(this);initBrowser();
}MainWindow::~MainWindow() {delete ui;
}void MainWindow::initBrowser() {CefWindowInfo cefWndInfo;QString strUrl = "https://www.baidu.com/";HWND wnd = (HWND)ui->fmBrowser->winId();RECT winRect;QDesktopWidget* pDeskTop = QApplication::desktop();QRect qtRect = pDeskTop->screenGeometry();winRect.left = qtRect.left();winRect.top = qtRect.top();winRect.right = qtRect.right();winRect.bottom = qtRect.bottom();cefWndInfo.SetAsChild(wnd, winRect);CefBrowserSettings cefBrowSetting;cef_browser_ev_ = CefRefPtr<SimpleHandler>(new SimpleHandler(true));CefBrowserHost::CreateBrowser(cefWndInfo, cef_browser_ev_, strUrl.toStdString(), cefBrowSetting, nullptr,nullptr);emit resize(qtRect.width(), qtRect.height());
}void MainWindow::resizeEvent(QResizeEvent *event) {if (cef_browser_ev_.get() == NULL) {return;}QRect qtRect = ui->fmBrowser->rect();const BrowserList browList = cef_browser_ev_->GetBrowserList();if (!browList.empty()) {HWND wnd = browList.front()->GetHost()->GetWindowHandle();::MoveWindow(wnd, qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height(), true);}
}