在CMake中提前设置CMAKE_EXECUTABLE_SUFFIX后,Emscripten无法生成HTML文件的原因及解决方法
我来帮你拆解下问题:从你贴出的ninja命令能明显看到,链接阶段出现了两次冲突的-o参数——先是指定输出emscripten_project.html,后面又被追加了-o emscripten_project.js,这直接导致Emscripten最终只生成了js和wasm文件,覆盖了原本要生成的html输出。
问题根源
你在CMake配置最开头就设置了CMAKE_EXECUTABLE_SUFFIX ".html",但Emscripten的CMake工具链会在project()执行阶段初始化一套默认配置,其中就包含针对Emscripten目标的输出后缀规则。你提前设置的全局后缀会被工具链的后续逻辑干扰甚至覆盖,最终导致链接命令出现冲突的输出参数。
解决方法
我给你整理了几个经过验证的可行方案,任选其一即可:
方案一:调整CMAKE_EXECUTABLE_SUFFIX的设置时机
把全局后缀的设置放到project()命令之后,等Emscripten工具链完成初始化后再设置,这样你的配置就不会被覆盖:
cmake_minimum_required(VERSION 3.2.1) # 先指定工具链文件 set(CMAKE_TOOLCHAIN_FILE $ENV{EMSDK_HOME}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake) # 先执行project初始化工具链 project(emscripten_project) # 再设置全局可执行文件后缀 set(CMAKE_EXECUTABLE_SUFFIX ".html") set(LINK_OPTIONS -sWASM=1 -sALLOW_MEMORY_GROWTH=1 -sNO_EXIT_RUNTIME=0 -sASSERTIONS=1) add_executable(emscripten_project main.cpp) target_link_options(emscripten_project PUBLIC ${LINK_OPTIONS})
方案二:为单个目标单独设置后缀(推荐)
不修改全局的CMAKE_EXECUTABLE_SUFFIX,只给你的目标设置SUFFIX属性,这样更精准,不会影响其他可能存在的目标:
cmake_minimum_required(VERSION 3.2.1) set(CMAKE_TOOLCHAIN_FILE $ENV{EMSDK_HOME}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake) project(emscripten_project) set(LINK_OPTIONS -sWASM=1 -sALLOW_MEMORY_GROWTH=1 -sNO_EXIT_RUNTIME=0 -sASSERTIONS=1) add_executable(emscripten_project main.cpp) # 只为当前目标设置html后缀 set_target_properties(emscripten_project PROPERTIES SUFFIX ".html") target_link_options(emscripten_project PUBLIC ${LINK_OPTIONS})
方案三:直接指定带后缀的目标名
在add_executable时直接把目标名设为emscripten_project.html,让CMake直接使用这个作为输出文件名,避开后缀设置的冲突:
cmake_minimum_required(VERSION 3.2.1) set(CMAKE_TOOLCHAIN_FILE $ENV{EMSDK_HOME}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake) project(emscripten_project) set(LINK_OPTIONS -sWASM=1 -sALLOW_MEMORY_GROWTH=1 -sNO_EXIT_RUNTIME=0 -sASSERTIONS=1) # 直接指定输出文件名带.html后缀 add_executable(emscripten_project.html main.cpp) target_link_options(emscripten_project.html PUBLIC ${LINK_OPTIONS})
验证效果
修改后重新执行cmake . -G Ninja && ninja,查看ninja的verbose输出,链接命令应该只会保留一个-o emscripten_project.html参数,此时Emscripten就会正常生成html、js和wasm三个文件了。
备注:内容来源于stack exchange,提问作者Techie-Guy

