1. 程式人生 > 實用技巧 >移植GNU Make到riscv64架構

移植GNU Make到riscv64架構

為了可以使在嵌入式平臺編譯使用make工具,本文介紹GNU Make工具移植到riscv64架構平臺的完整流程

1、GNU Make簡介

  首先要了解的是,Make是一種工具,是用於從程式碼原始檔生成可執行檔案和其他非原始檔。Make是根據makefile中制定的規則而執行一系列命令,將原始檔構建為目標檔案,makefile也指定了目標檔案的依賴關係列表。Make不限於任何特定語言。對於程式中的每個非原始檔,makefile指定用於計算它的shell命令。這些shell命令可以執行編譯器以生成目標檔案,連結器以生成可執行檔案, ar以更新庫,或執行TeXMakeinfo來格式化文件。Make

不限於構建包裝。還可以使用Make來控制軟體包的安裝或解除安裝,為其生成標籤表,或者我們經常做的其他任何事情,會使得我們工作和學習起來更加方便。在編寫程式是,應為其編寫一個makefile,以便可以使用Make來生成和安裝程式。

2、下載Make原始碼的三種方式

目前主要有三種方式下載Make原始碼:

2.1、通過GNU mirrors下載Make

[注]:既然官方提倡通過映象下載,本文就介紹已該途徑下載Make程式碼
開啟GNU mirrors網址,可以看到如下羅列的各種版本的Make原始碼包,直接下載最新版本make-4.3.tar.gz (筆者訪問時間為2021/01/08)。

3、編譯生成Make二進位制檔案

3.1、開啟原始碼壓縮包

解壓並開啟Make原始碼包並建立Make安裝目錄:

imaginemiracle@:make_install$ ls
make-4.3.tar.gz
imaginemiracle@:make_install$ tar -zxvf make-4.3.tar.gz
imaginemiracle@:make_install$ ls
make-4.3  make-4.3.tar.gz
imaginemiracle@:make_install$ mkdir install_4.3		//建立Make安裝目錄
imaginemiracle@:make_install$ ls
install_4.3

3.2、配置並編譯安裝Make

通過configure配置make工程:

imaginemiracle@:make_install$ cd make-4.3/
imaginemiracle@:make-4.3$ ls
ABOUT-NLS   build-aux     build_w32.bat  COPYING  Makefile.am   NEWS          README.customs  README.W32  vms_export_symbol_test.com
aclocal.m4  build.cfg.in  ChangeLog      doc      makefile.com  po            README.DOS      SCOPTIONS
AUTHORS     builddos.bat  configure      lib      Makefile.in   README        README.OS2      src
Basic.mk    build.sh      configure.ac   m4       mk            README.Amiga  README.VMS      tests
##[注]:這裡的prefix引數,是配置make的安裝目錄,必須寫成絕對路徑
imaginemiracle@:make-4.3$ ./configure --prefix=/home/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/Initramfs_Create/busybox/make_install/install_4.3 --build=x86_64-unknown-linux-gnu --host=riscv64-unknown-linux-gnu
################################省略部分輸出####################################
#############看到一下輸出且沒有報錯,則表示configure成功生成接下來make命令所需檔案##############
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating build.cfg
config.status: creating lib/Makefile
config.status: creating po/Makefile.in
config.status: creating doc/Makefile
config.status: creating tests/config-flags.pm
config.status: creating src/config.h
config.status: executing depfiles commands
config.status: executing po-directories commands
config.status: creating po/POTFILES
config.status: creating po/Makefile

執行make;make install(編譯並安裝):

imaginemiracle@:make-4.3$ make;make install
imaginemiracle@:make-4.3$ ls ../install_4.3/
bin  include  share
imaginemiracle@:make-4.3$ ls ../install_4.3/bin/
make
imaginemiracle@:make-4.3$ file ../install_4.3/bin/make 
../install_4.3/bin/make: ELF 64-bit LSB executable, UCB RISC-V, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-riscv64-lp64d.so.1, for GNU/Linux 3.0.0, with debug_info, not stripped

可以看到已經成功生成riscv64架構的make可執行檔案,將其放在riscv64架構平臺下即可使用。

到此,Make工具的移植過程介紹完畢!!!

4、編譯Make可能會遇到的問題以及解決方案

筆者之前在編譯make4.1版本時遇到以下錯誤:
<1>問題 make-4.1/config/missing: line 81: makeinfo: command not found
<1>解決方案

sudo apt-get install texinfo

<2>問題 make-4.1/glob/glob.c:1342: undefined reference to `__alloca'

gcc -DLOCALEDIR=\"/home/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/Initramfs_Create/busybox/make_install/install/share/locale\" -DLIBDIR=\"/home/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/Initramfs_Create/busybox/make_install/install/lib\" -DINCLUDEDIR=\"/home/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/Initramfs_Create/busybox/make_install/install/include\" -DHAVE_CONFIG_H -I.  -I./glob    -g -O2 -MT remote-stub.o -MD -MP -MF .deps/remote-stub.Tpo -c -o remote-stub.o remote-stub.c
mv -f .deps/remote-stub.Tpo .deps/remote-stub.Po
gcc  -g -O2 -Wl,--export-dynamic  -o make ar.o arscan.o commands.o default.o dir.o expand.o file.o function.o getopt.o getopt1.o guile.o implicit.o job.o load.o loadapi.o main.o misc.o output.o read.o remake.o rule.o signame.o strcache.o variable.o version.o vpath.o hash.o remote-stub.o glob/libglob.a   -ldl 
/usr/bin/ld: glob/libglob.a(glob.o): in function `glob_in_dir':
/home/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/Initramfs_Create/busybox/make_install/make-4.1/glob/glob.c:1367: undefined reference to `__alloca'
/usr/bin/ld: /home/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/Initramfs_Create/busybox/make_install/make-4.1/glob/glob.c:1342: undefined reference to `__alloca'
/usr/bin/ld: /home/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/Initramfs_Create/busybox/make_install/make-4.1/glob/glob.c:1256: undefined reference to `__alloca'
/usr/bin/ld: /home/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/Initramfs_Create/busybox/make_install/make-4.1/glob/glob.c:1283: undefined reference to `__alloca'
/usr/bin/ld: glob/libglob.a(glob.o): in function `glob':
/home/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/Initramfs_Create/busybox/make_install/make-4.1/glob/glob.c:581: undefined reference to `__alloca'
/usr/bin/ld: glob/libglob.a(glob.o):/home/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/Initramfs_Create/busybox/make_install/make-4.1/glob/glob.c:732: more undefined references to `__alloca' follow
collect2: error: ld returned 1 exit status
make[2]: *** [Makefile:621: make] Error 1
make[2]: Leaving directory '/media/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/Initramfs_Create/busybox/make_install/make-4.1'
make[1]: *** [Makefile:762: all-recursive] Error 1
make[1]: Leaving directory '/media/imaginemiracle/Disk_D/Linux_Workspace/riscv-project/Initramfs_Create/busybox/make_install/make-4.1'
make: *** [Makefile:514: all] Error 2

<2>解決方案

# define    realloc my_realloc
# endif /* __SASC */
#endif /* __GNU_LIBRARY__ || __DJGPP__ */

//============================Alter by me===========================
//#if !defined __alloca && !defined __GNU_LIBRARY__
#if !defined __alloca && defined __GNU_LIBRARY__                    
//=============================End Alter============================                                                                                  

# ifdef __GNUC__
#  undef alloca
#  define alloca(n) __builtin_alloca (n)
# else  /* Not GCC.  */
#  ifdef HAVE_ALLOCA_H
#   include <alloca.h>
#  else /* Not HAVE_ALLOCA_H.  */
#   ifndef _AIX
#    ifdef WINDOWS32
#     include <malloc.h>
#    else
extern char *alloca ();
#    endif /* WINDOWS32 */
#   endif /* Not _AIX.  */
#  endif /* sparc or HAVE_ALLOCA_H.  */
# endif /* GCC.  */

# define __alloca   alloca

#endif