diff mbox

[v2] Make external toolchain relocatable

Message ID 1341087767-20528-1-git-send-email-arnout@mind.be
State Superseded
Headers show

Commit Message

Arnout Vandecappelle June 30, 2012, 8:22 p.m. UTC
The external toolchain wrapper sets sysroot etc. to an absolute path.
By changing this to a relative path, it is possible to move the host
directory to a different location and still have a working build
system.

This only works for a downloaded external toolchain.  For a pre-installed
external toolchain, it is possible to move the host directory to a
different location, but not the external toolchain directory (it does work
if the external toolchain directory lies within the host directory).  For
an internal or crosstool-ng toolchain, there is no wrapper so updating the
sysroot path should be done in a different way.

See http://lists.busybox.net/pipermail/buildroot/2012-February/050371.html
for information about others things to do to make the host directory
relocatable.

Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
---
v2: rebased against current master (dc1d20acb)

 package/Makefile.in                                |    4 +-
 toolchain/toolchain-external/ext-tool.mk           |   14 ++++-
 .../toolchain-external/ext-toolchain-wrapper.c     |   64 ++++++++++++++------
 3 files changed, 60 insertions(+), 22 deletions(-)

Comments

Samuel Martin July 7, 2012, 9:18 p.m. UTC | #1
Hi Arnout, all,

2012/6/30 Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>:
> The external toolchain wrapper sets sysroot etc. to an absolute path.
> By changing this to a relative path, it is possible to move the host
> directory to a different location and still have a working build
> system.

I've just tested your patch on top of my branch, it seems working well
but doesn't do all the job.
You have probably focused on the wrapper code and forgot to update
target of the symlinks of all other tools, pointing to the relative
location of them instead of the absolute one.


> This only works for a downloaded external toolchain.  For a pre-installed
> external toolchain, it is possible to move the host directory to a
> different location, but not the external toolchain directory (it does work
> if the external toolchain directory lies within the host directory).  For
> an internal or crosstool-ng toolchain, there is no wrapper so updating the
> sysroot path should be done in a different way.

For internal and crosstool-ng toolchains, I think if we want to ensure
the tools are called with the correct sysroot argument, tehn we should
use  the wrapper too.
Unless someone is confident enough to patch gcc sources to compute
sysroot path in the same way the wrapper does; it looks like, even
CodeSourcery guys didn't! ;-)


Cheers,
Arnout Vandecappelle July 15, 2012, 11:16 a.m. UTC | #2
On 07/07/12 23:18, Samuel Martin wrote:
> Hi Arnout, all,
>
> 2012/6/30 Arnout Vandecappelle (Essensium/Mind)<arnout@mind.be>:
> > The external toolchain wrapper sets sysroot etc. to an absolute path.
> > By changing this to a relative path, it is possible to move the host
> > directory to a different location and still have a working build
> > system.
>
> I've just tested your patch on top of my branch, it seems working well
> but doesn't do all the job.
> You have probably focused on the wrapper code and forgot to update
> target of the symlinks of all other tools, pointing to the relative
> location of them instead of the absolute one.

  I just sent a v3.  Care to test it again?

> > This only works for a downloaded external toolchain.  For a pre-installed
> > external toolchain, it is possible to move the host directory to a
> > different location, but not the external toolchain directory (it does work
> > if the external toolchain directory lies within the host directory).  For
> > an internal or crosstool-ng toolchain, there is no wrapper so updating the
> > sysroot path should be done in a different way.
>
> For internal and crosstool-ng toolchains, I think if we want to ensure
> the tools are called with the correct sysroot argument, tehn we should
> use  the wrapper too.

   Good idea.  But then it should be installed in a different place as well.  But
on the other hand, we don't want to go and copy the sysroot directory for
internal/crosstool-NG toolchains...  Bottom line: I'm not going to try it :-)

  Regards,
  Arnout
diff mbox

Patch

diff --git a/package/Makefile.in b/package/Makefile.in
index c5ad00a..a9609f9 100644
--- a/package/Makefile.in
+++ b/package/Makefile.in
@@ -56,8 +56,8 @@  TARGET_ABI+=-mabi=spe -mfloat-gprs=double -Wa,-me500mc
 endif
 endif
 
-STAGING_DIR=$(HOST_DIR)/usr/$(GNU_TARGET_NAME)/sysroot
-
+STAGING_SUBDIR = usr/$(GNU_TARGET_NAME)/sysroot
+STAGING_DIR    = $(HOST_DIR)/$(STAGING_SUBDIR)
 TARGET_OPTIMIZATION:=$(call qstrip,$(BR2_TARGET_OPTIMIZATION))
 
 ifeq ($(BR2_OPTIMIZE_0),y)
diff --git a/toolchain/toolchain-external/ext-tool.mk b/toolchain/toolchain-external/ext-tool.mk
index 3f58aad..2a8a978 100644
--- a/toolchain/toolchain-external/ext-tool.mk
+++ b/toolchain/toolchain-external/ext-tool.mk
@@ -122,9 +122,17 @@  endif
 TOOLCHAIN_EXTERNAL_CROSS=$(TOOLCHAIN_EXTERNAL_BIN)/$(TOOLCHAIN_EXTERNAL_PREFIX)-
 TOOLCHAIN_EXTERNAL_CC=$(TOOLCHAIN_EXTERNAL_CROSS)gcc
 TOOLCHAIN_EXTERNAL_CXX=$(TOOLCHAIN_EXTERNAL_CROSS)g++
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS = \
-	-DBR_CROSS_PATH='"$(TOOLCHAIN_EXTERNAL_BIN)/"' \
-	-DBR_SYSROOT='"$(STAGING_DIR)"'
+TOOLCHAIN_EXTERNAL_WRAPPER_ARGS = -DBR_SYSROOT='"$(STAGING_SUBDIR)"'
+
+ifeq ($(filter $(HOST_DIR)/%,$(TOOLCHAIN_EXTERNAL_BIN)),)
+# TOOLCHAIN_EXTERNAL_BIN points outside HOST_DIR => absolute path
+TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += \
+	-DBR_CROSS_PATH_ABS='"$(TOOLCHAIN_EXTERNAL_BIN)"'
+else
+# TOOLCHAIN_EXTERNAL_BIN points inside HOST_DIR => relative path
+TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += \
+	-DBR_CROSS_PATH_REL='"$(TOOLCHAIN_EXTERNAL_BIN:$(HOST_DIR)/%=%)"'
+endif
 
 CC_TARGET_TUNE_:=$(call qstrip,$(BR2_GCC_TARGET_TUNE))
 CC_TARGET_CPU_:=$(call qstrip,$(BR2_GCC_TARGET_CPU))
diff --git a/toolchain/toolchain-external/ext-toolchain-wrapper.c b/toolchain/toolchain-external/ext-toolchain-wrapper.c
index 82595ea..a92bada 100644
--- a/toolchain/toolchain-external/ext-toolchain-wrapper.c
+++ b/toolchain/toolchain-external/ext-toolchain-wrapper.c
@@ -2,9 +2,12 @@ 
  * Buildroot wrapper for external toolchains. This simply executes the real
  * toolchain with a number of arguments (sysroot/arch/..) hardcoded,
  * to ensure the external toolchain uses the correct configuration.
+ * The hardcoded path arguments are defined relative to the actual location
+ * of the binary.
  *
  * (C) 2011 Peter Korsgaard <jacmet@sunsite.dk>
  * (C) 2011 Daniel Nyström <daniel.nystrom@timeterminal.se>
+ * (C) 2012 Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
  *
  * This file is licensed under the terms of the GNU General Public License
  * version 2.  This program is licensed "as is" without any warranty of any
@@ -17,11 +20,12 @@ 
 #include <unistd.h>
 #include <stdlib.h>
 
-static char path[PATH_MAX] = BR_CROSS_PATH;
+static char path[PATH_MAX];
+static char sysroot[PATH_MAX];
 
 static char *predef_args[] = {
 	path,
-	"--sysroot", BR_SYSROOT,
+	"--sysroot", sysroot,
 #ifdef BR_ARCH
 	"-march=" BR_ARCH,
 #endif /* BR_ARCH */
@@ -48,22 +52,50 @@  static char *predef_args[] = {
 #endif
 };
 
-static const char *get_basename(const char *name)
-{
-	const char *base;
-
-	base = strrchr(name, '/');
-	if (base)
-		base++;
-	else
-		base = name;
-
-	return base;
-}
-
 int main(int argc, char **argv)
 {
 	char **args, **cur;
+	char *relbasedir, *absbasedir;
+	char *progpath = argv[0];
+	char *basename;
+	int ret;
+
+	/* Calculate the relative paths */
+	basename = strrchr(progpath, '/');
+	if (basename) {
+		*basename = '\0';
+		basename++;
+		relbasedir = malloc(strlen(progpath) + 7);
+		if (relbasedir == NULL) {
+			perror(__FILE__ ": malloc");
+			return 2;
+		}
+		sprintf(relbasedir, "%s/../..", argv[0]);
+		absbasedir = realpath(relbasedir, NULL);
+	} else {
+		basename = progpath;
+		absbasedir = realpath("../..", NULL);
+	}
+	if (absbasedir == NULL) {
+		perror(__FILE__ ": realpath");
+		return 2;
+	}
+
+	/* Fill in the relative paths */
+#ifdef BR_CROSS_PATH_REL
+	ret = snprintf(path, sizeof(path), "%s/" BR_CROSS_PATH_REL "/%s", absbasedir, basename);
+#else /* BR_CROSS_PATH_ABS */
+	ret = snprintf(path, sizeof(path), BR_CROSS_PATH_ABS "/%s", basename);
+#endif
+	if (ret >= sizeof(path)) {
+		perror(__FILE__ ": overflow");
+		return 3;
+	}
+	ret = snprintf(sysroot, sizeof(sysroot), "%s/" BR_SYSROOT, absbasedir);
+	if (ret >= sizeof(sysroot)) {
+		perror(__FILE__ ": overflow");
+		return 3;
+	}
 
 	cur = args = malloc(sizeof(predef_args) + (sizeof(char *) * argc));
 	if (args == NULL) {
@@ -82,8 +114,6 @@  int main(int argc, char **argv)
 	/* finish with NULL termination */
 	*cur = NULL;
 
-	strcat(path, get_basename(argv[0]));
-
 	if (execv(path, args))
 		perror(path);