mailarchive of the ptxdist mailing list
 help / color / mirror / Atom feed
From: Ladislav Michl <oss-lists@triops.cz>
To: ptxdist@pengutronix.de
Subject: [ptxdist] [PATCH 1/6] scripts: add ptxdist_bootstrap.sh with out-of-tree build support
Date: Tue, 13 Oct 2026 13:16:52 +0200	[thread overview]
Message-ID: <as4TJOUIN2862imu@lenoch> (raw)
In-Reply-To: <as4S9kELLgKY9wdR@lenoch>

From: Ladislav Michl <ladis@triops.cz>

The bootstrap script makes ready everything PTXdist needs from the host:
- links to the GNU tools in <builddir>/bin
- kconfig in <builddir>/scripts/kconfig
All the missing prerequisites are reported at once.

Add support for out-of-tree builds to the Makefile; all generated files
ends in the build directory, 'install' and 'dist' targets are only
supported in-tree.

Signed-off-by: Ladislav Michl <ladis@triops.cz>
---
 .gitignore                   |   1 +
 Makefile.in                  |  65 +++-------
 configure.ac                 |   2 +-
 scripts/ptxdist_bootstrap.sh | 230 +++++++++++++++++++++++++++++++++++
 4 files changed, 250 insertions(+), 48 deletions(-)
 create mode 100755 scripts/ptxdist_bootstrap.sh

diff --git a/.gitignore b/.gitignore
index 1e2cd1c31..79657ecab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,4 @@ man/ptxdist.1.gz
 /env/
 
 /scripts/report/__pycache__/
+/build.log
diff --git a/Makefile.in b/Makefile.in
index da8cb9d7c..5eb7b407b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,9 +1,10 @@
-version		:= $(shell . ./scripts/ptxdist_version.sh && echo $${PTXDIST_VERSION_FULL})
+version		:= $(shell PTXDIST_TOPDIR=@abs_srcdir@ && . @abs_srcdir@/scripts/ptxdist_version.sh && echo $${PTXDIST_VERSION_FULL})
 project		:= ptxdist-$(version)
 
 prefix		:= @prefix@
 exec_prefix	:= @exec_prefix@
 abs_srcdir 	:= @abs_srcdir@
+abs_builddir	:= @abs_builddir@
 libdir	 	:= @libdir@
 bindir	 	:= @bindir@
 instdir		:= $(libdir)/$(project)
@@ -13,49 +14,13 @@ RST2MAN		:= @RST2MAN@
 
 export SHELL
 
-all: kconfig environment
-	@touch .done
-
-kconfig:
-	@echo "building conf and mconf ..."
-	$(MAKE) -C "$(abs_srcdir)/scripts/kconfig"
+all:
+	@echo "preparing PTXdist host tools ..."
+	@CC="@CC@" CFLAGS="@CFLAGS@" CPPFLAGS="@CPPFLAGS@" LDFLAGS="@LDFLAGS@" \
+		LEX="@LEX@" YACC="@YACC@" \
+		"@BASH@" "$(abs_srcdir)/scripts/ptxdist_bootstrap.sh" "$(abs_builddir)"
 	@echo "done."
 
-environment:
-	@echo -n "preparing PTXdist environment ..."
-	@ln -sf @AWK@ "$(abs_srcdir)/bin/awk"
-	@ln -sf @GNU_chmod@ "$(abs_srcdir)/bin/chmod"
-	@ln -sf @GNU_chown@ "$(abs_srcdir)/bin/chown"
-	@ln -sf @GNU_mv@ "$(abs_srcdir)/bin/mv"
-	@ln -sf @GNU_cp@ "$(abs_srcdir)/bin/cp"
-	@ln -sf @GNU_rm@ "$(abs_srcdir)/bin/rm"
-	@ln -sf @GNU_ln@ "$(abs_srcdir)/bin/ln"
-	@ln -sf @GNU_rmdir@ "$(abs_srcdir)/bin/rmdir"
-	@ln -sf @GNU_md5sum@ "$(abs_srcdir)/bin/md5sum"
-	@ln -sf @GNU_mkdir@ "$(abs_srcdir)/bin/mkdir"
-	@ln -sf @GNU_mktemp@ "$(abs_srcdir)/bin/mktemp"
-	@ln -sf @GNU_install@ "$(abs_srcdir)/bin/install"
-	@ln -sf @GNU_stat@ "$(abs_srcdir)/bin/stat"
-	@ln -sf @GNU_mknod@ "$(abs_srcdir)/bin/mknod"
-	@ln -sf @GNU_tty@ "$(abs_srcdir)/bin/tty"
-	@ln -sf @GNU_tar@ "$(abs_srcdir)/bin/tar"
-	@ln -sf @GNU_find@ "$(abs_srcdir)/bin/find"
-	@ln -sf @PTXDIST_FILE@ "$(abs_srcdir)/bin/file"
-	@ln -sf @GNU_cat@ "$(abs_srcdir)/bin/cat"
-	@ln -sf @GNU_dirname@ "$(abs_srcdir)/bin/dirname"
-	@ln -sf @GNU_readlink@ "$(abs_srcdir)/bin/readlink"
-	@ln -sf @GNU_realpath@ "$(abs_srcdir)/bin/realpath"
-	@ln -sf @GNU_sort@ "$(abs_srcdir)/bin/sort"
-	@ln -sf @SED@ "$(abs_srcdir)/bin/sed"
-	@ln -sf @GNU_xargs@ "$(abs_srcdir)/bin/xargs"
-	@ln -sf @BASH@  "$(abs_srcdir)/bin/bash"
-	@ln -sf @SYSCTL@ "$(abs_srcdir)/bin/sysctl"
-	@ln -sf @MAKE@ "$(abs_srcdir)/bin/make"
-	@if [ @SPHINX@ != "sphinx-build" ]; then \
-		ln -sf @SPHINX@ "$(abs_srcdir)/bin/sphinx-build"; \
-	fi
-	@echo " done"
-
 man: man/ptxdist.1.gz
 man/ptxdist.1: doc/ptxdist.man doc/ref_parameter.rst
 	@mkdir -pv man
@@ -66,16 +31,22 @@ man/ptxdist.1.gz: man/ptxdist.1
 	gzip -f $<
 
 clean:
-	@rm -f .done
-	@find "$(abs_srcdir)/bin" -type l -print0 | xargs -0 rm -f
-	@$(MAKE) -C "$(abs_srcdir)/scripts/kconfig" clean
+	@rm -f "$(abs_builddir)/.done"
+	@find "$(abs_builddir)/bin" -type l -print0 | xargs -0 rm -f
+	@$(MAKE) -C "$(abs_builddir)/scripts/kconfig" \
+		-f "$(abs_srcdir)/scripts/kconfig/Makefile" clean
+
+intree-check:
+	@if [ "$(abs_srcdir)" != "$(abs_builddir)" ]; then \
+		echo "install and dist are only supported for in-tree builds!" ; exit 1 ; \
+	fi
 
-dirty-check:
+dirty-check: intree-check
 	@case "$(version)" in \
 		*-dirty) echo "refusing to install or package a dirty git tree!" ; exit 1 ;; \
 	esac
 
-install: all dirty-check
+install: intree-check all dirty-check
 	@echo "installing PTXdist to $(DESTDIR)$(prefix)..."
 	@rm -fr   "$(DESTDIR)$(instdir)"
 	@mkdir -p "$(DESTDIR)$(instdir)"
diff --git a/configure.ac b/configure.ac
index c368e46b1..2590ebbed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -15,7 +15,7 @@ dnl
 dnl Check if the user has extracted the patches archive
 dnl
 AC_MSG_CHECKING(for ptxdist patches)
-if test -d `dirname $0`/patches
+if test -d "$srcdir/patches"
 then
 	AC_MSG_RESULT(yes)
 else
diff --git a/scripts/ptxdist_bootstrap.sh b/scripts/ptxdist_bootstrap.sh
new file mode 100755
index 000000000..b9f4c7a5c
--- /dev/null
+++ b/scripts/ptxdist_bootstrap.sh
@@ -0,0 +1,230 @@
+#!/bin/sh
+#
+# Prepare the host tools PTXdist needs:
+# - links to sane (GNU) tools found on the host in <builddir>/bin
+# - kconfig (conf, mconf and, if possible, nconf) in <builddir>/scripts/kconfig
+#
+# All missing prerequisites are reported at once. Only tools that PTXdist
+# itself needs are checked, everything required by some packages only is
+# left to the package build.
+#
+# usage: ptxdist_bootstrap.sh <builddir>
+#
+# CC, CFLAGS, CPPFLAGS, LDFLAGS, LEX, YACC and PKG_CONFIG from the
+# environment are used if set.
+#
+
+PTXDIST_LOG_PROMPT="ptxdist: "
+
+#
+# Everything up to the bash version check must be plain POSIX sh: the
+# script may be started by any shell and re-executes itself with bash.
+#
+if [ -z "${BASH_VERSION}" ]; then
+	bash="$(command -v bash)" || {
+		echo "${PTXDIST_LOG_PROMPT}error: bash >= 4.2 is required, please install it" >&2
+		exit 1
+	}
+	exec "${bash}" "${0}" "${@}"
+fi
+
+case "${BASH_VERSION}" in
+[0-3].*|4.[01].*)
+	echo "${PTXDIST_LOG_PROMPT}error: bash >= 4.2 is required, found ${BASH_VERSION} as '${BASH}'" >&2
+	exit 1
+	;;
+esac
+
+# e.g. when started as 'sh' with /bin/sh -> bash
+set +o posix
+
+topdir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" || exit
+builddir="${1}"
+if [ -z "${builddir}" ]; then
+	echo "usage: ${0} <builddir>" >&2
+	exit 1
+fi
+
+declare -A links
+declare -a missing
+
+#
+# $1: version found, $2: version required
+#
+version_ge() {
+	local -a have want
+	local i
+
+	IFS=. read -r -a have <<< "${1}"
+	IFS=. read -r -a want <<< "${2}"
+	for (( i = 0; i < ${#want[@]}; i++ )); do
+		if [ "${have[i]:-0}" -gt "${want[i]}" ]; then
+			return 0
+		elif [ "${have[i]:-0}" -lt "${want[i]}" ]; then
+			return 1
+		fi
+	done
+}
+
+#
+# find a GNU tool and register a link for it
+#
+# $1: link name
+# $2: expected '--version' output, e.g. 'GNU coreutils'
+# $3: minimum version, may be empty
+# $4: package that provides it (to print the hint)
+# $5...: names to look for in PATH
+#
+find_gnu() {
+	local link="${1}" id="${2}" min="${3}" pkg="${4}"
+	local name path version
+	shift 4
+
+	for name in "${@}"; do
+		path="$(type -P "${name}")" || continue
+		version="$("${path}" --version 2>/dev/null | head -n 1)"
+		[[ "${version}" =~ ${id} ]] || continue
+		if [ -n "${min}" ]; then
+			[[ "${version}" =~ ([0-9]+(\.[0-9]+)+) ]] &&
+			version_ge "${BASH_REMATCH[1]}" "${min}" || continue
+		fi
+		links[${link}]="${path}"
+		return
+	done
+	missing+=( "${id}${min:+ >= ${min}} as '${link}' (package: ${pkg})" )
+}
+
+for tool in cat chmod chown cp dirname install ln md5sum mkdir mknod \
+		mktemp mv readlink realpath rm rmdir sort stat tty; do
+	find_gnu "${tool}" "GNU coreutils" "" coreutils "g${tool}" "${tool}"
+done
+find_gnu tar	"GNU tar"	""	tar		gtar tar
+find_gnu find	"GNU findutils"	4	findutils	gfind find
+find_gnu xargs	"GNU findutils"	4	findutils	gxargs xargs
+find_gnu sed	"GNU sed"	4	sed		gsed sed
+find_gnu awk	"GNU Awk"	""	gawk		gawk awk
+find_gnu make	"GNU Make"	3.81	make		gmake gnumake make
+
+links[bash]="${BASH}"
+
+if path="$(type -P file)"; then
+	links[file]="${path}"
+else
+	missing+=( "'file' (package: file)" )
+fi
+
+# optional
+links[sysctl]="$(type -P sysctl || type -P false)"
+if path="$(type -P sphinx-build)"; then
+	links[sphinx-build]="${path}"
+fi
+
+#
+# kconfig
+#
+if [ -z "${CC}" ]; then
+	CC="$(type -P gcc || type -P cc)" || CC=cc
+fi
+if ! type -P "${CC%% *}" > /dev/null; then
+	missing+=( "C compiler '${CC}' (package: gcc)" )
+fi
+: ${LEX:=flex} ${YACC:=bison} ${PKG_CONFIG:=pkg-config}
+if ! type -P "${LEX%% *}" > /dev/null; then
+	missing+=( "'${LEX}' (package: flex)" )
+fi
+if ! type -P "${YACC%% *}" > /dev/null; then
+	missing+=( "'${YACC}' (package: bison)" )
+fi
+
+#
+# $1: test program; possibly followed by compiler and linker flags
+#
+try_link() {
+	local prog="${1}"
+	shift
+	echo "${prog}" |
+		${CC} ${CFLAGS} ${CPPFLAGS} -x c - -o /dev/null ${LDFLAGS} "${@}" > /dev/null 2>&1
+}
+
+#
+# $1: pkg-config modules (space separated, all required)
+# $2: fallback libs
+# $3: test program
+# out: libs_cflags, libs_libs
+#
+find_libs() {
+	local modules="${1}" fallback="${2}" prog="${3}"
+
+	if ${PKG_CONFIG} --exists ${modules} 2>/dev/null; then
+		libs_cflags="$(${PKG_CONFIG} --cflags ${modules})"
+		libs_libs="$(${PKG_CONFIG} --libs ${modules})"
+	else
+		libs_cflags=""
+		libs_libs="${fallback}"
+	fi
+	try_link "${prog}" ${libs_cflags} ${libs_libs}
+}
+
+ncurses_prog='#include <ncurses.h>
+int main(void) { initscr(); endwin(); return 0; }'
+nconf_prog='#include <ncurses.h>
+#include <menu.h>
+#include <panel.h>
+int main(void) { initscr(); new_panel(stdscr); free_menu(NULL); return 0; }'
+
+if type -P "${CC%% *}" > /dev/null; then
+	if find_libs "ncursesw" "-lncursesw" "${ncurses_prog}" ||
+		find_libs "ncurses" "-lncurses" "${ncurses_prog}"; then
+		mconf_cflags="${libs_cflags}"
+		mconf_libs="${libs_libs}"
+	else
+		missing+=( "ncurses development files (package: libncurses-dev or ncurses-devel)" )
+	fi
+	# nconf is optional
+	if find_libs "ncursesw menuw panelw" "-lmenuw -lpanelw -lncursesw" "${nconf_prog}" ||
+		find_libs "ncurses menu panel" "-lmenu -lpanel -lncurses" "${nconf_prog}"; then
+		nconf=nconf
+		nconf_libs="${libs_libs}"
+	fi
+fi
+
+if [ ${#missing[@]} -gt 0 ]; then
+	{
+		echo
+		echo "${PTXDIST_LOG_PROMPT}error: missing host tools, please install:"
+		echo
+		printf "  - %s\n" "${missing[@]}"
+		echo
+	} >&2
+	exit 1
+fi
+
+#
+# all prerequisites are there, set up the build directory
+#
+mkdir -p "${builddir}/bin" "${builddir}/scripts/kconfig" &&
+for link in "${!links[@]}"; do
+	ln -sfn "${links[${link}]}" "${builddir}/bin/${link}" || exit
+done
+
+if ! "${links[make]}" -C "${builddir}/scripts/kconfig" \
+	-f "${topdir}/scripts/kconfig/Makefile" \
+	CC="${CC}" \
+	${CFLAGS:+CFLAGS="${CFLAGS}"} \
+	${CPPFLAGS:+CPPFLAGS="${CPPFLAGS}"} \
+	${LDFLAGS:+LDFLAGS="${LDFLAGS}"} \
+	LEX="${LEX}" \
+	YACC="${YACC}" \
+	MCONF_CFLAGS="${mconf_cflags}" \
+	MCONF_LIBS="${mconf_libs}" \
+	NCONF_LIBS="${nconf_libs}" \
+	NCONF="${nconf}" \
+	> "${builddir}/build.log" 2>&1; then
+	tail -n 20 "${builddir}/build.log" >&2
+	echo >&2
+	echo "${PTXDIST_LOG_PROMPT}error: building kconfig failed, see '${builddir}/build.log'" >&2
+	echo >&2
+	exit 1
+fi
+
+echo "${topdir}" > "${builddir}/.done"
-- 
2.47.3




  reply	other threads:[~2026-10-13 11:17 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-13 11:16 [ptxdist] [PATCH 0/6] New BSP from template Ladislav Michl
2026-10-13 11:16 ` Ladislav Michl [this message]
2026-10-13 11:17 ` [ptxdist] [PATCH 2/6] ptxdist: introduce PTXDIST_HOSTTOOLS_DIR Ladislav Michl
2026-10-13 11:17 ` [ptxdist] [PATCH 3/6] ptxdist: prepare host tools on demand Ladislav Michl
2026-10-13 11:18 ` [ptxdist] [PATCH 4/6] ptxdist: don't depend on bash being /bin/bash Ladislav Michl
2026-10-13 11:18 ` [ptxdist] [PATCH 5/6] configure: use ptxdist_bootstrap.sh to check the host Ladislav Michl
2026-10-13 11:18 ` [ptxdist] [PATCH 6/6] ptxdist: let new project raise from template Ladislav Michl

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=as4TJOUIN2862imu@lenoch \
    --to=oss-lists@triops.cz \
    --cc=ptxdist@pengutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox