完整代码
为cmake添加emsdk环境
安装emsdk的详细步骤此处省略,可在上一篇文章阅读
以下是我的CMakeUserPresets.json配置,你只需要把地址改成你的qt、emsdk的地址的开头即可
{
"version": 3,
"configurePresets": [
{
"name": "wasm-emscripten",
"displayName": "wasm-emscripten",
"binaryDir": "${sourceDir}/out/build/wasm-emscripten",
"generator": "Ninja",
"architecture": {
"strategy": "external",
"value": "x64"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_TOOLCHAIN_FILE": "C:/Qt/6.7.2/wasm_multithread/lib/cmake/Qt6/qt.toolchain.cmake",
"QT_CHAINLOAD_TOOLCHAIN_FILE": "G:/dev_programs/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake",
"EMSDK": "G:/dev_programs/emsdk",
"Qt6_DIR": "C:/Qt/6.7.2/wasm_multithread/lib/cmake/Qt6",
"CMAKE_DEPENDS_USE_COMPILER": false,
"CMAKE_C_DEPENDS_USE_COMPILER": false,
"CMAKE_CXX_DEPENDS_USE_COMPILER": false
},
"environment": {
"EM_CONFIG": "G:/dev_programs/emsdk/.emscripten",
"EMSDK": "G:/dev_programs/emsdk",
"EMSDK_NODE": "G:/dev_programs/emsdk/node/22.16.0_64bit/bin/node.exe",
"EMSDK_PYTHON": "G:/dev_programs/emsdk/python/3.13.3_64bit/python.exe",
"EMSCRIPTEN": "G:/dev_programs/emsdk/upstream/emscripten",
"QTDIR": "C:/Qt/6.7.2/msvc2019_64",
"PATH": "G:/dev_programs/emsdk;G:/dev_programs/emsdk/upstream/emscripten;G:/dev_programs/emsdk/upstream/bin;G:/dev_programs/emsdk/node/22.16.0_64bit/bin;$penv{PATH}"
}
}
],
"vendor": {
"qt-project.org/Presets": {
"checksum": "l0FLWNDHovohW6ZdDZ7Ub+feYVQ="
}
}
}
编辑:项目根目录/CMakeLists.txt
此处为Emscripten添加了egl符号导出,因为Emscripten默认不导出egl符号,而qt需要使用。
启用webasm的多线程支持
cmake_minimum_required(VERSION 3.5)
project(ElaFramework VERSION 0.1 LANGUAGES CXX)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
if(EMSCRIPTEN)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s GL_ENABLE_GET_PROC_ADDRESS")
endif()
if(EMSCRIPTEN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s USE_PTHREADS=1 -matomics -mbulk-memory")
endif()
#在这里配置QT路径 例如 D:/Qt/6.6.2/msvc2019_64 D:/Qt/5.15.2/msvc2019_64 /home/liniyous/Qt/5.15.2/gcc_64
SET(QT_SDK_DIR C:/Qt/6.7.2/wasm_multithread CACHE PATH "QT SDK DIR" FORCE)
message("在CMAKE中配置 QT_SDK_DIR 选项指定QT路径; 当前路径: ${QT_SDK_DIR}")
SET(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/Install CACHE PATH "Installation path" FORCE)
option(BUILD_ELAPACKETIO "Build ElaPacketIO" OFF)
list(APPEND CMAKE_PREFIX_PATH ${QT_SDK_DIR})
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
add_subdirectory(ElaWidgetTools)
if (WIN32 AND BUILD_ELAPACKETIO)
add_definitions(-DBUILD_WITH_ELAPACKETIO)
add_subdirectory(ElaPacketIO)
endif ()
add_subdirectory(ElaWidgetToolsExample)
if (${QT_VERSION} VERSION_LESS 6.1.0)
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.ElaWidgetTools)
endif ()
if(EMSCRIPTEN)
set_target_properties(ElaWidgetTools PROPERTIES
LINK_FLAGS "-s USE_PTHREADS=1 -matomics -mbulk-memory -s MODULARIZE=1 -s EXPORT_NAME=ElaWidgetTools_entry"
)
endif()
更改部分如图所示:
编辑:项目根目录/ElaWidgetTools/CMakeLists.txt
此处设置ElaWidgetTools为静态库,这么做是因为WebASM不支持动态库,会报很多错误
cmake_minimum_required(VERSION 3.5)
project(ElaWidgetTools VERSION 2.0.0 LANGUAGES CXX)
add_definitions(-DELAWIDGETTOOLS_LIBRARY)
option(ELAWIDGETTOOLS_BUILD_STATIC_LIB "Build static library." OFF)
FILE(GLOB ORIGIN *.h *.cpp)
FILE(GLOB PRIVATE private/*.h private/*.cpp)
FILE(GLOB DEVELOPER DeveloperComponents/*.h DeveloperComponents/*.cpp)
source_group(include FILES ${INCLUDE})
source_group(private FILES ${PRIVATE})
source_group(DeveloperComponents FILES ${DEVELOPER})
set(PROJECT_SOURCES
${ORIGIN}
${PRIVATE}
${DEVELOPER}
${CMAKE_CURRENT_SOURCE_DIR}/ElaWidgetTools.qrc
)
if(EMSCRIPTEN)
set(LIB_TYPE "STATIC")
else()
option(ELAWIDGETTOOLS_BUILD_STATIC_LIB "Build static library." OFF)
if (ELAWIDGETTOOLS_BUILD_STATIC_LIB)
set(LIB_TYPE "STATIC")
else ()
set(LIB_TYPE "SHARED")
endif ()
endif()
if (${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_library(${PROJECT_NAME} ${LIB_TYPE}
${PROJECT_SOURCES}
)
else ()
add_library(${PROJECT_NAME} ${LIB_TYPE}
${PROJECT_SOURCES}
)
endif ()
FILE(GLOB EXPORT_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
target_include_directories(${PROJECT_NAME} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/private>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/DeveloperComponents>
$<INSTALL_INTERFACE:${PROJECT_NAME}/include>
)
if (MINGW)
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
endif ()
if (MSVC)
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "d")
endif ()
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PROJECT_NAME})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PROJECT_NAME})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PROJECT_NAME})
if (WIN32)
target_link_libraries(${PROJECT_NAME} PUBLIC
Qt${QT_VERSION_MAJOR}::Widgets
D3D11
DXGI
)
else ()
target_link_libraries(${PROJECT_NAME} PUBLIC
Qt${QT_VERSION_MAJOR}::Widgets
)
endif ()
install(
TARGETS ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}
ARCHIVE DESTINATION ${PROJECT_NAME}/lib
LIBRARY DESTINATION ${PROJECT_NAME}/lib
RUNTIME DESTINATION ${PROJECT_NAME}/bin
)
install(TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/ElaWidgetToolsExample
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/ElaWidgetToolsExample
)
if (MSVC AND NOT LIB_TYPE STREQUAL "STATIC")
install(
FILES $<TARGET_PDB_FILE:${PROJECT_NAME}>
DESTINATION ${CMAKE_INSTALL_PREFIX}/ElaWidgetToolsExample OPTIONAL)
endif ()
install(FILES ${EXPORT_HEADERS} DESTINATION ${PROJECT_NAME}/include)
set(INCLUDE_DIRS include)
set(LIBRARIES ${PROJECT_NAME})
set(LIB_DIR lib)
install(
EXPORT ${PROJECT_NAME}
FILE ${PROJECT_NAME}Targets.cmake
DESTINATION ${PROJECT_NAME}/lib/cmake
)
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
VERSION 2.0.0
COMPATIBILITY SameMajorVersion
)
configure_package_config_file(
${PROJECT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in
${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
INSTALL_DESTINATION lib/cmake
PATH_VARS INCLUDE_DIRS LIBRARIES LIB_DIR
INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}
)
install(
FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake ${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake DESTINATION ${PROJECT_NAME}/lib/cmake
)
更改部分如图所示:
添加中文字体支持
qt webasm默认不支持中文字体,也无法从浏览器环境获取字体,因此需要自己嵌入一个字体
参考以下方法添加字体:
编辑:项目根目录/ElaWidgetToolsExample/CMakeLists.txt
添加.ttf字体遍历
cmake_minimum_required(VERSION 3.5)
cmake_policy(SET CMP0087 NEW)
project(ElaWidgetToolsExample VERSION 0.1 LANGUAGES CXX)
FILE(GLOB ORIGIN *.cpp *.h)
FILE(GLOB MODELVIEW ModelView/*.h ModelView/*.cpp)
FILE(GLOB EAXMPLEPAGE ExamplePage/*.h ExamplePage/*.cpp)
source_group(ModelView FILES ${MODELVIEW})
source_group(ExamplePage FILES ${EAXMPLEPAGE})
set(PROJECT_SOURCES
${ORIGIN}
${MODELVIEW}
${EAXMPLEPAGE}
)
if (${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(${PROJECT_NAME}
MANUAL_FINALIZATION
${PROJECT_SOURCES}
)
#遍历所有资源文件
file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp *.js *.ttf)
foreach (filepath ${RES_PATHS})
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
list(APPEND resource_files ${filename})
endforeach (filepath)
qt_add_resources(${PROJECT_NAME} "ElaWidgetToolsExample"
RESOURCES PREFIX "/"
FILES
${resource_files}
)
else ()
qt5_add_big_resources(PROJECT_SOURCES
ElaWidgetToolsExample.qrc
)
add_executable(${PROJECT_NAME}
${PROJECT_SOURCES}
)
endif ()
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PROJECT_NAME})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PROJECT_NAME})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PROJECT_NAME})
if (WIN32)
target_include_directories(${PROJECT_NAME} PUBLIC
ExamplePage
ModelView
)
if (BUILD_ELAPACKETIO)
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
ElaWidgetTools
ElaPacketIO
)
else ()
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
ElaWidgetTools
)
endif ()
else ()
target_include_directories(${PROJECT_NAME} PUBLIC
ExamplePage
ModelView
)
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
ElaWidgetTools
)
endif ()
if (${QT_VERSION} VERSION_LESS 6.1.0)
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.${PROJECT_NAME})
endif ()
set_target_properties(${PROJECT_NAME} PROPERTIES
${BUNDLE_ID_OPTION}
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}"
VS_DEBUGGER_COMMAND "${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/${PROJECT_NAME}.exe"
)
if (QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(${PROJECT_NAME})
endif ()
include(GNUInstallDirs)
install(TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}
)
if (MSVC)
install(
FILES $<TARGET_PDB_FILE:${PROJECT_NAME}>
DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME} OPTIONAL)
endif ()
find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${QT_SDK_DIR}/bin")
if (WIN32)
install(CODE "
if(EXISTS \"${WINDEPLOYQT_EXECUTABLE}\" AND NOT EXISTS \"${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/platforms\")
execute_process(
COMMAND \"${CMAKE_COMMAND}\" -E env PATH=\"${QT_SDK_DIR}/bin\"
\"${WINDEPLOYQT_EXECUTABLE}\"
\"$<TARGET_FILE_DIR:${PROJECT_NAME}>/$<TARGET_FILE_NAME:${PROJECT_NAME}>\"
--dir \"${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}\"
--no-compiler-runtime
--no-system-d3d-compiler
--no-opengl-sw
--verbose 1
)
endif()"
)
endif ()
更改部分如图所示:
编译并部署
经过以上步骤,此时应该能成功编译了。
部署步骤,需要把输出目录中ElaWidgetTools、ElaWidgetToolsExample两个文件夹的内容复制到同一个文件夹中,
并且把ElaWidgetToolsExample.html改名为index.html,然后部署到如nginx等http服务器中即可。
需要在nginx的server块中添加配置:
server {
省略。
add_header Cross-Origin-Opener-Policy same-origin;
add_header Cross-Origin-Embedder-Policy require-corp;
}