使用Emscripten构建SVT-AV1 v1.4.1用于FFmpeg时链接报错求助
noexecstack: No such file or directory 我正尝试用Emscripten 3.1.32为FFmpeg构建SVT-AV1 v1.4.1,遵循官方Build-Guide执行了以下命令:
cd Build BUILD_DIR=/home/jozefchutka/ffmpeg-wasm/build/ TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake emmake cmake .. -G"Unix Makefiles" -DCMAKE_INSTALL_PREFIX=$BUILD_DIR -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN_FILE -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DCMAKE_HAVE_LIBC_PTHREAD=On -DCMAKE_C_FLAGS="-O3 -I/home/jozefchutka/ffmpeg-wasm/build/include -s USE_PTHREADS=1 -msimd128" emmake make -j
但构建在链接阶段失败,报错如下:
... [ 95%] Building C object Source/App/EncApp/CMakeFiles/SvtAv1EncApp.dir/EbTime.c.o [ 96%] Linking C executable ../../../../Bin/Release/SvtAv1EncApp.js emcc: error: noexecstack: No such file or directory ("noexecstack" was expected to be an input file, based on the commandline arguments provided) make[2]: *** [Source/App/EncApp/CMakeFiles/SvtAv1EncApp.dir/build.make:213: ../Bin/Release/SvtAv1EncApp.js] Error 1 make[1]: *** [CMakeFiles/Makefile2:574: Source/App/EncApp/CMakeFiles/SvtAv1EncApp.dir/all] Error 2 make[1]: *** Waiting for unfinished jobs....
生成的build.make相关内容:
211: ../Bin/Release/SvtAv1EncApp.js: Source/App/EncApp/CMakeFiles/SvtAv1EncApp.dir/link.txt 212: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/jozefchutka/ffmpeg-wasm/modules/svtav1/Build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_8) "Linking C executable ../../../../Bin/Release/SvtAv1EncApp.js" 213: cd /home/jozefchutka/ffmpeg-wasm/modules/svtav1/Build/Source/App/EncApp && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/SvtAv1EncApp.dir/link.txt --verbose=$(VERBOSE)
link.txt中的链接命令:
/home/jozefchutka/ffmpeg-wasm/modules/emsdk/upstream/emscripten/emcc -O3 -I/home/jozefchutka/ffmpeg-wasm/build/include -s USE_PTHREADS=1 -msimd128 -O3 -DNDEBUG -z noexecstack -z relro -z now @CMakeFiles/SvtAv1EncApp.dir/objects1.rsp -o ../../../../Bin/Release/SvtAv1EncApp.js @CMakeFiles/SvtAv1EncApp.dir/linklibs.rsp
我对C/C++构建体系不熟悉,不确定问题出在构建配置、SVT-AV1源码还是Emscripten上,希望能定位原因并解决,方便后续在对应问题追踪器提交反馈。
原因分析
报错的核心是:-z noexecstack -z relro -z now是GCC链接器针对ELF二进制文件的安全选项,但Emscripten的emcc链接器生成的是WebAssembly/JavaScript文件,完全不支持这类选项。当emcc看到这些参数时,会把它们当成要链接的输入文件,自然找不到名为noexecstack的文件,从而报错。
这些选项应该是SVT-AV1的CMake配置中针对Linux平台添加的,没有考虑Emscripten交叉编译的场景。
解决方案
方法1:修改CMake命令,覆盖链接器参数
在cmake命令中添加-DCMAKE_EXE_LINKER_FLAGS,指定Emscripten支持的链接选项,同时排除那些不兼容的-z参数:
emmake cmake .. -G"Unix Makefiles" \ -DCMAKE_INSTALL_PREFIX=$BUILD_DIR \ -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN_FILE \ -DBUILD_SHARED_LIBS=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_TESTING=OFF \ -DCMAKE_HAVE_LIBC_PTHREAD=On \ -DCMAKE_C_FLAGS="-O3 -I/home/jozefchutka/ffmpeg-wasm/build/include -s USE_PTHREADS=1 -msimd128" \ -DCMAKE_EXE_LINKER_FLAGS="-O3 -s USE_PTHREADS=1 -msimd128"
然后重新执行emmake make -j。
方法2:手动修改生成的链接脚本
直接编辑Source/App/EncApp/CMakeFiles/SvtAv1EncApp.dir/link.txt,删除其中的-z noexecstack -z relro -z now这三个参数,保存后重新执行emmake make -j。
方法3:修改SVT-AV1的CMake配置(适合长期修复)
找到SVT-AV1源码中添加这些-z选项的CMake代码(通常在根目录或App目录的CMakeLists.txt里),添加条件判断,当检测到Emscripten工具链时不添加这些选项:
if(NOT EMSCRIPTEN) target_link_options(SvtAv1EncApp PRIVATE -z noexecstack -z relro -z now) endif()
重新执行cmake和make即可。
内容的提问来源于stack exchange,提问作者Yoz

