[求助]打包 mit-scheme 9.2 遇到的问题

mit-scheme 的项目地址在这里:MIT/GNU Scheme - GNU Project - Free Software Foundation 我打包的是最新出的 9.2 版本,刚出没多久和之前版本的编译有些不同

我用的源码包是 Portable C 这个。mit-scheme 9.2 为 Linux 提供了 Unix binary(i386、x86_64 两种)、Portable C 和 Source (.tar.gz) 三种包。Source 需要你的电脑上有一个 mit-scheme 才能编译。貌似他是用 scheme 写了一个 scheme 的解释器,那个我们安装前我们肯定没有 scheme,所以编译不了。Unix binary 是编译了一部分的(具体编译到哪里就不了解),发现 Arch 的包就是用他们编译的,写了一个 if 语句来区分不同的架构,只需要 gcc 就可以编译。虽然可以套用他们的在方法但是在 OBS 里包含二进制的软件不太好是吧。

所以最后选择 Portable C 这个包,这个东西是先编译出一个用 c 语言写的 mit-scheme-c 然后再用这个编译出来的 mit-scheme-c 编译一个「真正的」 mit-scheme。编译的指南在这里:http://www.gnu.org/software/mit-scheme/liarc-build.html,根据这个指南我写的 specfile 在这里:https://build.opensuse.org/package/show/home:PaleFire/mit-scheme

本地编译的时候遇到了第一个问题: x86_64 位上无法找到编译好的 mit-scheme-c 需要的 lib :

我为这个问题打了一個补丁(也可以在上面提供的地址里找到):

diff -uNr mit-scheme-9.2.orig/src/Makefile.in mit-scheme-9.2/src/Makefile.in
--- mit-scheme-9.2.orig/src/Makefile.in	2014-07-15 21:46:29.900138132 +0800
+++ mit-scheme-9.2/src/Makefile.in	2014-07-15 20:10:31.000000000 +0800
@@ -21,7 +21,7 @@
 # 02110-1301, USA.
 
 # **** BEGIN BOILERPLATE ****
-
+ARCH = $(shell uname -m)
 SHELL = @SHELL@
 
 @SET_MAKE@
@@ -897,8 +897,13 @@
 	echo "done" > $@
 
 stamp_liarc-compile-scheme:
+ifeq ($(ARCH),x86_64)
+	@$(top_srcdir)/etc/c-compile.sh boot-root/bin/mit-scheme-c \
+	    --library boot-root/lib64/mit-scheme-c --band boot-compiler.com 
+else
 	@$(top_srcdir)/etc/c-compile.sh boot-root/bin/mit-scheme-c \
 	    --library boot-root/lib/mit-scheme-c --band boot-compiler.com
+endif	    
 	echo "done" > $@
 
 stamp_compile-liarc-bundles: stamp_liarc-compile-scheme compile-liarc-bundles

问题出在这个源代码提供的 Makefile 里直接写 mit-scheme-c 需要的 lib 的在 boot-root/lib/mit-scheme-c ,但是我发现在 64 位的系统上 mit-scheme-c 需要 lib 所在的目录位置其实是 boot-root/lib64/mit-scheme-c。所以我让 Makefile 在遇到是 64 位的机子的时候使用 boot-root/lib64/mit-scheme-c。这个补丁在本地是可以用的,而且最后顺利编译出了 rpm 包,但是这个补丁在 OBS 上却不能用。我发现 在 OBS 上无论是 X86_64 还是 i586 出来的 mit-scheme-c 所要的 lib 都是在 boot-root/lib 这个目录里的 。这是我第一个困惑,为什么 OBS 和本地编译会出现这样的不同呢?

于是我在本地使用了这个补丁最后编译成功了 rpm 包,在 OBS 上没有使用这个补丁。在 OBS 上顺利通过了在本地卡住的这一步,可以看 log 里记录:

这步没有出错。但是在后面不远的地方那遇到了 第二个问题 :

完整的 log 在这里:Welcome - openSUSE Build Service
我比较过了,openSUSE 不同的架构版本里错误都是一样的。

搜索了一下「No rule to make target」发现这样的错误可能是缺少依赖的库(本地安装了它但没有写进 specfile 里,结果本地有 OBS 上没有导致 OBS 上编译不过)。所以这几天找了一些关于编译 mit-scheme 的文章,凡是可能的不可能的依赖我都写上了。可还是不行。现在已经完全没有思路了,猜想以为和上面的 lib64 变成 lib 有关,但是那个也不知道是什么原因。不清楚问题到底出在哪里,按理说编译 mit-scheme 只需要很少的依赖。而且本地编译是很顺利通过了的。

因为 mit-scheme 编译时间实在太长了(四五十分钟的样子),已经放弃自己不断试错了,成本太高,所以在这里请教大家了,先谢过。

我还是把原来的 log 贴一下好了,私人车库那边继续试错。。。。mit_scheme_log.txt (312 KB)

还有原来的 specfile:

#
# spec file for package 
#
# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.

# Please submit bugfixes or comments via http://bugs.opensuse.org/
#

Name:           mit-scheme
Version:	9.2
Release:	0
License:	GPL-2.0+
Summary:	MIT implementation of the Scheme programming language
Url:	        http://www.gnu.org/software/mit-scheme
Group:	        Development/Languages/Scheme 
Source:	        %{name}-%{version}.tar.gz
BuildRequires:	libtool
BuildRequires:  m4
BuildRequires:  automake
BuildRequires:  autoconf
BuildRequires:  libpq5
BuildRequires:  libopenssl-devel
BuildRequires:  ncurses-devel
BuildRequires:  libX11-devel
BuildRequires:  libXt-devel
BuildRequires:  libltdl7
BuildRequires:  mhash-devel
BuildRequires:  libmcrypt-devel
BuildRequires:  libgdbm4
BuildRequires:  libdb-4_8-devel
BuildRequires:  makeinfo
BuildRequires:  gcc
BuildRequires:  gdbm-devel
BuildRequires:  zlib-devel
BuildRequires:  glibc-devel
BuildRequires:  pkg-config
BuildRoot:      %{_tmppath}/%{name}-%{version}-build

%description
MIT/GNU Scheme is an implementation othe Scheme programming language,
providing an interpreter, compiler, source-code debugger, integrated 
Emacs-like editor, and a large runtime library. MIT/GNU Scheme is 
best suited to programming large applications with a rapid development cycle. 

%prep
%setup -q

%build
pushd src
etc/make-liarc.sh --prefix=/usr
popd

pushd doc
./configure  --prefix=/usr
make
popd

%install
pushd src
%make_install
popd


pushd doc
%make_install
popd

%post -p /sbin/ldconfig

%postun -p /sbin/ldconfig

%files
%defattr(-,root,root)
%doc changelog.txt
%{_bindir}/bchscheme
%{_bindir}/mit-scheme
%{_bindir}/mit-scheme-c
%{_bindir}/scheme
%{_libdir}/mit-scheme-c
%{_libdir}/mit-scheme
%{_infodir}/mit-scheme-doc-config.scm.gz
%{_infodir}/mit-scheme-ffi.info.gz
%{_infodir}/mit-scheme-imail.info.gz
%{_infodir}/mit-scheme-ref.info-1.gz
%{_infodir}/mit-scheme-ref.info-2.gz
%{_infodir}/mit-scheme-ref.info-3.gz
%{_infodir}/mit-scheme-ref.info-4.gz
%{_infodir}/mit-scheme-ref.info-5.gz
%{_infodir}/mit-scheme-ref.info.gz
%{_infodir}/mit-scheme-sos.info.gz
%{_infodir}/mit-scheme-user.info.gz
%{_mandir}/man1/scheme.1.gz


%changelog

因为你的 src/runtime/runtime-unix.c 根本就不存在啊。

你可以改下 Makefile 让它在编译 microcode 目录之前先

find …/runtime/ -name “runtime-unix.c” -print || echo “runtime-unix.c not found”

然后再编译失败就可以去 log 里直接看到有没有了。

@PaleFire

我发现不止 runtime-unix.c 不存在,compinit.c 也不存在。

于是我怀疑它们是半路生成了,grep 了一下 compinit.c

发现了这样一个神奇的文件夹:

src/microcode/makegen

的确是半路生成的,又看到你有这个错误:

;Aborting!: out of memory

很可能是生成的时候失败,然后默认多线程编译,其它线程找不到生成的东西。

主要问题还是生成东西的时候内存不足,所以你也许需要我之前编译 libkkc 时候的一个技巧来突破内存上限:

lists.opensuse.org/opensuse-buildservice/2013-04/msg00146.html

确实有 ;Aborting!: out of memory 呢,之前没有发现。另外这个文件其实是叫 runtime-unx.c(没有 i),不过我刚编译了一轮发现他确实也是不存在:

大概应该就是这个原因了吧,感觉很接近了:-)我去研究一下要怎么弄。这样的错误之前是绝对想不到的。。。

不过我还是很困惑为什么本地 64 位的系统是 lib64,到了 OBS 上就变成 lib 了呢。

我打了个补丁。

diff -uNr mit-scheme-9.2.orig/src/etc/functions.sh mit-scheme-9.2/src/etc/functions.sh
--- mit-scheme-9.2.orig/src/etc/functions.sh	2014-05-17 17:10:05.000000000 +0800
+++ mit-scheme-9.2/src/etc/functions.sh	2014-07-20 20:33:08.768236378 +0800
@@ -37,7 +37,7 @@
 
 run_make ()
 {
-    run_cmd make "${@}"
+    run_cmd make -j1 "${@}"
 }
 
 run_cmd_in_dir ()

编译看看这次能不能过。

microcode/scheme:
        (cd microcode && $(MAKE) all)

看下这里,Makefile.in 的 toolchain 部分,也许要把这里的 $(MAKE) 全部改为 make -j1 才会有效。

嗯,刚才那个失败了,还是出现了 out of memory,估计我之前那个不改也可以。我先把 $(MAKE) 改了试试看。但是那个错误是出现在运行

cat ./BUILD/mit-scheme-9.2/src/etc/c-compile.sh

set -e

. etc/functions.sh

run_cmd "${@}" --heap 6000 --stack 200 <<EOF
(begin
  (load "etc/compile.scm")
  (c-compile))
EOF

的时候,要是内存不足是出现在运行这段 scheme 代码的时候怎么办。。。。那个就不会改了。。。。

不知道这样改对不对。

diff -uNr mit-scheme-9.2.orig/src/Makefile.in mit-scheme-9.2/src/Makefile.in
--- mit-scheme-9.2.orig/src/Makefile.in	2014-05-17 17:10:04.000000000 +0800
+++ mit-scheme-9.2/src/Makefile.in	2014-07-20 21:39:57.046965880 +0800
@@ -25,7 +25,7 @@
 SHELL = @SHELL@
 
 @SET_MAKE@
-
+MAKE = make -j1
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
 VPATH = @srcdir@

改了还是一样的效果。

今天先这样吧,临睡前试一试用 _constraints 的方法。看看明天早上会出来什么结果。也许睡一觉就有灵感了。。。。

添加了一个 _constraints 文件,内容是:

<constraints>
  <hardware>
    <memory>
      <size unit="G">6</size>
    </memory>
  </hardware>
</constraints> 

但是还是没有什么效果,是不是我哪里弄得不对?

@PaleFire

看你最新的 log,里面有个

1053s] making c-clean in runtime

这个步骤把 runtime-unx.c 删除了。要不你试试把 c-clean 的步骤都注释掉?

啧啧:

ndex: mit-scheme-9.2/src/etc/make-liarc.sh
===================================================================
--- mit-scheme-9.2.orig/src/etc/make-liarc.sh
+++ mit-scheme-9.2/src/etc/make-liarc.sh
 run_configure --prefix=`pwd`/boot-root --enable-native-code=c \
     --disable-host-scheme-test
-run_make stamp_install-liarc-boot-compiler c-clean distclean
+run_make stamp_install-liarc-boot-compiler

之前那个找不到 runtime-unx.c 的错误过了。microcode 目录编译成功。

然后到了 edwin 目录又出现:

make[1]: *** No rule to make target ‘edwin-os2.c’, needed by ‘edwin-init.c’. Stop.

有点奇怪,runtime-unx.c 这个文件是之前就是有的。为什么后来反而会被删掉。

怎么看也不是需要修改源代码的错误,毕竟本地是通过了的。。。。我再去仔细看一蛤那一长串编译用的 shell 脚本到底干了什么。。。。。。

我试过打补丁增加了 heap 和 stack 也没用,始终是 conpkg.scm 到 conpkg.bin 这一步 out of memory,这会不会是代码的 bug 呢。不知道 mit-scheme 编译代码会不会有 log。你去官方问问呢?

确实很奇怪,特别我本地编译是通过了的,rpmlint 也没有查出什么错误。原来以为在 OBS 上编译通过应该问题不大。

好的:-)我先查查有没有什么资料。不行我再试着去官方问问好了。。。(用 E 语交流还有点拿不出手。。。)

看了一下其它发行版怎么给 mit-scheme 打包的。发现 Slackware、Archlinux 和 FreeBSD 都是用了那个 「Unix binary」给包的(实在不行就只能效法他们了)。话说会不会和几个编译选项有关?不太明白具体的意思比如 Arch 给加了一个 --enable-native-code,不过我记得这个加不加都一样的。

build() {
  cd $pkgname-$pkgver/src
  ./configure --prefix=/usr \
    --with-x \
    --enable-native-code
  make
}

只有 Gentoo 是用了 mit-scheme-c 来打包的,虽然版本有点早 9.0.1(也是第一个有 mit-scheme-c 的版本),我看到有这样一段:

src_prepare() {
	sed "s:@for:@+for:" -i \
		Makefile || die "sed failed"
	sed "s:make:make -j1:" -i \
		src/etc/make-in-subdirs.sh || die "sed failed"
	sed "s:CFLAGS=\"\${CFLAGS} -O3\":CFLAGS=\"${CFLAGS}\":" -i \
		{src/lib/include,src/microcode}/configure{,.ac} || die "sed failed"
} 

看到他是 把 make-in-subdirs.sh 里的 make 改成了 make -j1 ,我回头试试这样可不可以。

整个 ebuild 是这样的:

# Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $

EAPI="3"

inherit multilib flag-o-matic #elisp-common

DESCRIPTION="GNU/MIT-Scheme"
HOMEPAGE="http://www.swiss.ai.mit.edu/projects/scheme/"
SRC_URI="http://ftp.gnu.org/gnu/mit-scheme/stable.pkg/${PV}/${P}.tar.gz"

LICENSE="GPL-2"
SLOT="0"
KEYWORDS="~amd64 ~x86"
IUSE="doc" # emacs"

#SITEFILE="50mitscheme-gentoo.el"

RDEPEND="app-crypt/mhash
	dev-db/postgresql-base
	dev-libs/libmcrypt
	dev-libs/openssl
	sys-libs/gdbm
	sys-libs/ncurses
	x11-libs/libX11"

DEPEND="${RDEPEND}
	doc? ( dev-texlive/texlive-texinfo )"

src_prepare() {
	sed "s:@for:@+for:" -i \
		Makefile || die "sed failed"
	sed "s:make:make -j1:" -i \
		src/etc/make-in-subdirs.sh || die "sed failed"
	sed "s:CFLAGS=\"\${CFLAGS} -O3\":CFLAGS=\"${CFLAGS}\":" -i \
		{src/lib/include,src/microcode}/configure{,.ac} || die "sed failed"
}

src_configure() {
	if use doc; then
		cd "${S}"/doc
		econf
	fi
}

src_compile() {
	cd "${S}"/src
	./etc/make-liarc.sh --prefix=/usr --exec-prefix=/usr --libdir=/usr/$(get_libdir) || die "making liar C failed"

	if use doc ; then
		cd "${S}"/doc
		emake -j1 || die "emake doc failed"
	fi

	cd ..

#    if use emacs ; then
#        elisp-compile etc/*.el || die
#    fi
}

src_install() {
	cd "${S}"/src
	emake DESTDIR="${D}" install || die "make install failed"

	cd "${S}"/doc
	doman scheme.1 || die "doman failed"
	if use doc ; then
		dohtml index.html || die "dhtml failed"
		doinfo ref-manual/mit-scheme-ref.info* || die "doinfo failed"
		dodoc ref-manual/mit-scheme-ref.{pdf,ps} || die "dodoc failed"
		doinfo user-manual/mit-scheme-user.info || die "doinfo failed"
		dodoc user-manual/mit-scheme-user.{pdf,ps} || die "dodoc failed"
		doinfo sos/mit-scheme-sos.info || die "doinfo failed"
		dodoc sos/mit-scheme-sos.{pdf,ps} || die "dodoc failed"
		doinfo imail/mit-scheme-imail.info || die "doinfo failed"
		dodoc imail/mit-scheme-imail.{pdf,ps} || die "dodoc failed"

		cd ref-manual
		docinto html/mit-scheme-ref
		dohtml mit-scheme-ref/* || die "dhtml failed"

		cd ../user-manual
		docinto html/mit-scheme-user
		dohtml mit-scheme-user/* || die "dhtml failed"

		cd ../sos
		docinto html/mit-scheme-sos
		dohtml mit-scheme-sos/* || die "dhtml failed"

		cd ../imail
		docinto html/mit-scheme-imail
		dohtml mit-scheme-imail/* || die "dhtml failed"
		cd ../
	fi
}

#pkg_postinst() {
#    use emacs && elisp-site-regen
#}

#pkg_postrm() {
#    use emacs && elisp-site-regen
#}

好吧还是不行。。。。哎

暂时先改用 Unix binary 蒙混过关。。。。

回头看会不会是 Portable C 编译用的 sh 脚本写的有问题啊,要不不使用他的脚本在 specfile 里一步一步的 make?