2

I've built a Linux system running on an ARMv7 chip and it works surprisingly well, but I have run into a problem with native builds.

First I bootstrapped by cross-compiling on an x86-64 system, and now I thought I'd rebuild everything natively and run tests, etc.

The issue I'm running into affects projects which do certain things which autoconf projects tend to do. I've run into this issue in several components, like gmake and m4, but I'll focus on gmake here (the behavior is exactly the same for the other affected projects).  Python, nginx, uwsgi, perl, etc., build without any issues.

This is the basic order of things I'm doing:

$ tar xjf ~/download/make-4.2.1.tar.bz2
$ cd make-4.2.1
$ ./configure

Up until this point everything works great — it finds the native compiler I built with the cross-compiler, and it also finds all the cross-built tools (sed, gawk, etc). The issue is that when I run "make" it immediately throws an error:

$ make
make  all-recursive
make[1]: Entering directory '/home/jan/tmp/make-4.2.1'
Making all in glob
make[1]: *** [Makefile:798: all-recursive] Error 1
make[1]: Leaving directory '/home/jan/tmp/make-4.2.1'
make: *** [Makefile:534: all] Error 2

As one can see, it essentially doesn't do anything at all; it claims to be going into the glob subdirectory, but it never gets there.

Running

$ make --trace

.. yields:

Makefile:573: update target 'config.h' due to: stamp-h1
test -f config.h || rm -f stamp-h1
test -f config.h || make  stamp-h1
Makefile:534: update target 'all' due to: config.h
make  all-recursive
make[1]: Entering directory '/home/jan/tmp/make-4.2.1'
Makefile:798: target 'all-recursive' does not exist
fail=; \
if (target_option=k; case ${target_option-} in ?) ;; *) echo "am__make_running_with_option: internal error: invalid" "target option '${target_option-}' specified" >&2; exit 1;; esac; has_opt=no; sane_makeflags=$MAKEFLAGS; if { if test -z '1'; then false; elif test -n 'armv7l-unknown-linux-gnueabihf'; then true; elif test -n '4.2.1' && test -n '/home/jan/tmp/make-4.2.1'; then true; else false; fi; }; then sane_makeflags=$MFLAGS; else case $MAKEFLAGS in *\\[\ \ ]*) bs=\\; sane_makeflags=`printf '%s\n' "$MAKEFLAGS" | sed "s/$bs$bs[$bs $bs ]*//g"`;; esac; fi; skip_next=no; strip_trailopt () { flg=`printf '%s\n' "$flg" | sed "s/$1.*$//"`; }; for flg in $sane_makeflags; do test $skip_next = yes && { skip_next=no; continue; }; case $flg in *=*|--*) continue;; -*I) strip_trailopt 'I'; skip_next=yes;; -*I?*) strip_trailopt 'I';; -*O) strip_trailopt 'O'; skip_next=yes;; -*O?*) strip_trailopt 'O';; -*l) strip_trailopt 'l'; skip_next=yes;; -*l?*) strip_trailopt 'l';; -[dEDm]) skip_next=yes;; -[JT]) skip_next=yes;; esac; case $flg in *$target_option*) has_opt=yes; break;; esac; done; test $has_opt = yes); then \
  failcom='fail=yes'; \
else \
  failcom='exit 1'; \
fi; \
dot_seen=no; \
target=`echo all-recursive | sed s/-recursive//`; \
case "all-recursive" in \
  distclean-* | maintainer-clean-*) list='glob config po doc w32' ;; \
  *) list='glob config po doc ' ;; \
esac; \
for subdir in $list; do \
  echo "Making $target in $subdir"; \
  if test "$subdir" = "."; then \
    dot_seen=yes; \
    local_target="$target-am"; \
  else \
    local_target="$target"; \
  fi; \
  (CDPATH="${ZSH_VERSION+.}:" && cd $subdir && make  $local_target) \
  || eval $failcom; \
done; \
if test "$dot_seen" = "no"; then \
  make  "$target-am" || exit 1; \
fi; test -z "$fail"
Making all in glob
make[1]: *** [Makefile:798: all-recursive] Error 1
make[1]: Leaving directory '/home/jan/tmp/make-4.2.1'
make: *** [Makefile:534: all] Error 2

I kind of know where this fails, but I don't understand why. Near the bottom there's a section:

(CDPATH="${ZSH_VERSION+.}:" && cd $subdir && make $local_target)

If I change that to:

(printf "hello\n" && CDPATH="${ZSH_VERSION+.}:" && printf "world\n" && cd $subdir && make $local_target)

.. and rerun the whole line, then it outputs:

Making all in glob
hello
exit

In other words, it doesn't seem to be getting past the CDPATH=... part, which is confusing to me. I checked at least one other project in detail and it's the same logic which fails in that too.

All components are newish (if not the very latest stable version, it's just one or two versions behind (GCC 7.2.0, gmake 4.2.1, bash 4.4, etc)). I'm using glibc and, although it's a busybox system, several of the tools have been replaced by coreutils tools.  And, as I mentioned previously, I'm using bash (with SHELL set to /bin/bash).

I've googled around quite a bit to look for solutions; the only tip I found was for a problem which was only vaguely similar to mine and the solution was to run autoreconf. I obviously tried that, but it made no difference.

What could be causing the build to fail?

2

It turns out this was caused by bash being cross-built. Fortunately the problem didn't affect building bash itself natively on the ARM platform, so once I build a native build, run all the tests, install the new bash binary and reboot then the problem disappears.

  • You may have made the problem go away, but I’m not sure you’ve really solved it, unless you can explain why the cross-built bash failed the way it did.  But I applaud you on your diagnostic skills; we get soooo many questions where the OP (i.e., the question’s author) presents the equivalent of the first 30% of your question — up to the “it immediately throws an error” part — and then just says “solve my problem for me!” – G-Man Oct 8 '17 at 18:43
  • This is too much of a mystery for me to let go, so I'm not done with it. Now that I have gdb I can debug bash and find out what's wrong. I did discover that if I replace the "&&" with ";" it builds, so it seems like it's either 1) the boolean evaluation is screwed up, 2) the "cd" returns error. Neither of these make any sense. gdb will have the answers. – cypheratheist Oct 9 '17 at 15:23
  • Well, isn’t it clear that the CDPATH="${ZSH_VERSION+.}:" is failing?  It’s not doing the printf "world\n", so it’s not even getting to the cd. – G-Man Oct 9 '17 at 19:04
  • Yes but it's just a variable expansion/assignment (they seem to work in other places) and if I run that exact variable declaration alone it doesn't fail. (I verified that the script's CDPATH expands to ":" as does my standalone test), hence why I was thinking it might be somewhere in between the two. Though it's probably just more of a contextual issue; I'm going to try to keep adding stuff to the testcase and see at what point it fails and then debug it. – cypheratheist Oct 11 '17 at 2:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.