【问题标题】:How to cross-compile neovim for Synology NAS如何为 Synology NAS 交叉编译 neovim
【发布时间】:2020-02-25 19:34:18
【问题描述】:

正如标题所示,我在为我的 Synology NAS 交叉编译 neovim 时遇到问题。

主持人:

$ uname -srm
Linux 4.12.14-lp151.28.36-default x86_64

目标:

$ uname -srm
Linux 3.2.40 armv7l

我做了什么:

我下载了工具链armadaxp-gcc493_glibc220_hard-GPL.txz并将内容解压到~/devel/SynologyNAS/armadaxp-gcc493_glibc220_hard-GPL/

我下载了 Synology Nas GPL 源 Synology Nas GPL source 并将内容提取到 ~/devel/SynologyNAS/SynologyNASGPLSource/

(以上均根据this文章。)

我将 neovim source 克隆到 ~/devel/neovim/

我知道我首先需要运行 CMake 来生成 Makefile,然后运行 ​​make 来实际构建软件。 (至少那是我发现的here。)因此,我编写了一个工具链文件,如CMake Documentation 中所述。

$ cat ~/devel/SynologyNAS/armadaxp-toolchain-file.cmake 
# this one is important
SET(CMAKE_SYSTEM_NAME Linux)
#this one not so much
SET(CMAKE_SYSTEM_VERSION 3.2.40)

# specify the cross compiler
SET(CMAKE_C_COMPILER /home/jonas/devel/SynologyNAS/armadaxp-gcc493_glibc220_hard-GPL/bin/arm-unknown-linux-gnueabi-gcc-4.9.3) 
SET(CMAKE_CXX_COMPILER /home/jonas/devel/SynologyNAS/armadaxp-gcc493_glibc220_hard-GPL/bin/arm-unknown-linux-gnueabi-g++) 

# where is the target environment
SET(CMAKE_FIND_ROOT_PATH  /home/jonas/devel/SynologyNAS/armadaxp-gcc493_glibc220_hard-GPL/ /home/jonas/devel/SynologyNAS/SynologyNASGPLSource/)

# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

然后我尝试编译第三方依赖:

$ mkdir -p ~/devel/NeovimBuildForSynologyNAS/deps
$ cd -p ~/devel/NeovimBuildForSynologyNAS/deps
$ cmake -DCMAKE_TOOLCHAIN_FILE=../../SynologyNAS/armadaxp-toolchain-file.cmake ../../neovim/third-party/

-- The C compiler identification is GNU 4.9.3
-- Check for working C compiler: /home/jonas/devel/SynologyNAS/armadaxp-gcc493_glibc220_hard-GPL/bin/arm-unknown-linux-gnueabi-gcc-4.9.3
-- Check for working C compiler: /home/jonas/devel/SynologyNAS/armadaxp-gcc493_glibc220_hard-GPL/bin/arm-unknown-linux-gnueabi-gcc-4.9.3 -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Performing Test HAS_OG_FLAG
-- Performing Test HAS_OG_FLAG - Success
-- Found GNU Make at /usr/bin/gmake
-- The CXX compiler identification is GNU 4.9.3
-- Check for working CXX compiler: /home/jonas/devel/SynologyNAS/armadaxp-gcc493_glibc220_hard-GPL/bin/arm-unknown-linux-gnueabi-g++
-- Check for working CXX compiler: /home/jonas/devel/SynologyNAS/armadaxp-gcc493_glibc220_hard-GPL/bin/arm-unknown-linux-gnueabi-g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.2") 
-- Performing Test HAS_NO_STACK_CHECK
-- Performing Test HAS_NO_STACK_CHECK - Success
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jonas/devel/NeovimBuildForSynologyNAS/deps

在我看来应该是天真的想法,但是运行 make 它会给出一个错误,提示无法执行 host/minilua,我知道它不应该这样做,因为它未编译为在主机上运行。

$ make
Scanning dependencies of target luajit
[  1%] Creating directories for 'luajit'
[  2%] Performing download step for 'luajit'
-- file: /home/jonas/devel/NeovimBuildForSynologyNAS/deps/build/downloads/luajit/f0e865dd4861520258299d0f2a56491bd9d602e1.tar.gz
-- downloading...
     src='https://github.com/LuaJIT/LuaJIT/archive/f0e865dd4861520258299d0f2a56491bd9d602e1.tar.gz'
     dst='/home/jonas/devel/NeovimBuildForSynologyNAS/deps/build/downloads/luajit/f0e865dd4861520258299d0f2a56491bd9d602e1.tar.gz'
     timeout='none'
-- downloading... done
-- extracting...
     src='/home/jonas/devel/NeovimBuildForSynologyNAS/deps/build/downloads/luajit/f0e865dd4861520258299d0f2a56491bd9d602e1.tar.gz'
     dst='/home/jonas/devel/NeovimBuildForSynologyNAS/deps/build/src/luajit'
-- extracting... [tar xfz]
-- extracting... [analysis]
-- extracting... [rename]
-- extracting... [clean binary dir]
-- extracting... [clean up]
-- extracting... done
[  3%] No patch step for 'luajit'
[  4%] No update step for 'luajit'
[  5%] No configure step for 'luajit'
[  6%] No build step for 'luajit'
[  7%] Performing install step for 'luajit'
==== Building LuaJIT 2.1.0-beta3 ====
HOSTCC    host/minilua.o
HOSTLINK  host/minilua
DYNASM    host/buildvm_arch.h
host/minilua: host/minilua: Kann die Datei nicht ausführen.
make[4]: *** [Makefile:641: host/buildvm_arch.h] Fehler 126
make[3]: *** [Makefile:113: src/luajit] Fehler 2
make[2]: *** [CMakeFiles/luajit.dir/build.make:74: build/src/luajit-stamp/luajit-install] Fehler 2
make[1]: *** [CMakeFiles/Makefile2:223: CMakeFiles/luajit.dir/all] Fehler 2
make: *** [Makefile:84: all] Fehler 2

我发现无论错误如何,我都可以强制 make 继续。然后它会遍历这些包,直到无法构建 gperf

$ make -k
[...]
[ 72%] Performing configure step for 'gperf'
configure: loading site script /usr/share/site/x86_64-unknown-linux-gnu
checking whether make sets $(MAKE)... yes
configure: creating ./config.status
config.status: creating Makefile
=== configuring in lib (/home/jonas/devel/NeovimBuildForSynologyNAS/deps/build/src/gperf/lib)
configure: running /bin/sh ./configure --disable-option-checking '--prefix=/home/jonas/devel/NeovimBuildForSynologyNAS/deps/usr'  'MAKE=make' 'CC=/home/jonas/devel/SynologyNAS/armadaxp-gcc493_glibc220_hard-GPL/bin/arm-unknown-linux-gnueabi-gcc-4.9.3' 'CXX=/home/jonas/devel/SynologyNAS/armadaxp-gcc493_glibc220_hard-GPL/bin/arm-unknown-linux-gnueabi-g++' 'LD=/home/jonas/devel/SynologyNAS/armadaxp-gcc493_glibc220_hard-GPL/bin/arm-unknown-linux-gnueabi-gcc-4.9.3' --cache-file=/dev/null --srcdir=.
configure: loading site script /usr/share/site/x86_64-unknown-linux-gnu
checking whether make sets $(MAKE)... yes
checking for gcc... /home/jonas/devel/SynologyNAS/armadaxp-gcc493_glibc220_hard-GPL/bin/arm-unknown-linux-gnueabi-gcc-4.9.3
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... configure: error: in `/home/jonas/devel/NeovimBuildForSynologyNAS/deps/build/src/gperf/lib':
configure: error: cannot run C compiled programs.
If you meant to cross compile, use `--host'.
See `config.log' for more details
configure: error: ./configure failed for lib
make[2]: *** [CMakeFiles/gperf.dir/build.make:106: build/src/gperf-stamp/gperf-configure] Fehler 1
make[2]: Das Ziel „CMakeFiles/gperf.dir/build“ wurde wegen Fehlern nicht aktualisiert.
make[1]: *** [CMakeFiles/Makefile2:435: CMakeFiles/gperf.dir/all] Fehler 2
make[1]: Das Ziel „all“ wurde wegen Fehlern nicht aktualisiert.
make: *** [Makefile:84: all] Fehler 2
make: Das Ziel „default_target“ wurde wegen Fehlern nicht aktualisiert.

显然,特定的configure 命令无法识别我想要交叉编译并且我不知道如何告诉它,因为我没有手动调用它来传递 --host 选项。除此之外,我认为整个 CMake 事情应该已经解决了这个问题。我还查找了 configure.log,但不知道在哪里可以找到它。

我应该注意到我能够在本地编译这个软件(即在我的主机上运行)。

正如您可能已经猜到的那样,我对这件事毫无经验,因此甚至无法找出编译失败的实际潜在问题。因此,我非常感谢您的帮助,并希望能更好地了解这里发生的事情。

这也是我的第一篇文章,虽然我尝试遵守指南,但我可能没有达到预期。

取得的进展

按照 vsh 提供的提示,我只是将 --host=arm 添加到 cmake 命令中,据我所知,它被复制到 CONFIGURE_COMMAND 变量中。 gperf 确实编译成功,但 make 之后由于错误而停止

[...]
[ 75%] Completed 'gperf'
[ 75%] Built target gperf
make[1]: Das Ziel „all“ wurde wegen Fehlern nicht aktualisiert.
make: *** [Makefile:84: all] Fehler 2
make: Das Ziel „default_target“ wurde wegen Fehlern nicht aktualisiert.

在 vsh 评论的指导下,我还检查了 neovim/third-party/cmake/BuildGperf.cmakeneovim/third-party/CMakeLists.txt。在这两个文件中都有涉及交叉编译的 cmets。

来自BuildGperf.cmake

# Gperf recipe. Gperf is only required when building Neovim, when
# cross compiling we still want to build for the HOST system, whenever
# writing a recipe that is meant for cross-compile, use the HOSTDEPS_* variables
# instead of DEPS_* - check the main CMakeLists.txt for a list.

来自CMakeLists.txt

# Cross compiling: use these for dependencies built for the
# HOST system, when not crosscompiling these should be the
# same as DEPS_*. Except when targeting Unix in which case
# want all the dependencies to use the same compiler.

我对此感到很困惑。显然,所有依赖项都应该由我的工具链提供的相同编译器构建(因为我的目标是 Unix 系统),这当然会使它们在我的主机上无法执行,从而导致上述错误。

无论如何我都会尝试指定HOSTDEPS_* 变量,看看是否有任何改变。

【问题讨论】:

    标签: cmake cross-compiling neovim synology


    【解决方案1】:

    简单看一下我找到的回购BuildGperf,它声明了函数BuildGperf,它接受CONFIGURE_COMMAND。您可以尝试在调用 BuildGperf 的源以及给出的 CONFIGURE_COMMAND 的源中查找。在那里您可以尝试添加--host 选项以允许交叉编译Gperf

    我第一次非常简短地查看))在我提到的文件中,您可以看到调用

        CONFIGURE_COMMAND ${DEPS_BUILD_DIR}/src/gperf/configure
      --prefix=${HOSTDEPS_INSTALL_DIR}
      MAKE=${MAKE_PRG} ${GPERF_BUILDARGS}
    

    我想你可以添加你需要的所有东西来正确配置gperf

    【讨论】: