[v3,3/3] toolchain-external: calculation of the symlink to the arch sysroot
diff mbox

Message ID 1415919806-13005-4-git-send-email-romain.naour@openwide.fr
State Rejected
Headers show

Commit Message

Romain Naour Nov. 13, 2014, 11:03 p.m. UTC
When copying external toolchain sysroot to staging, we need to
create the symbolic link that matches the name of the subdirectory
for the architecture variant in the original sysroot.
(ex: sgxx-glibc for CodeSourcery Standard edition)
To do that, SYSROOT_DIR must be different than ARCH_SYSROOT_DIR.

In the case where ARCH_SYSROOT_DIR is used as SYSROOT_DIR  we need
to check again the path to the main sysroot directory.
if SYSROOT_DIR returned by toolchain_find_sysroot without
TOOLCHAIN_EXTERNAL_CFLAGS is empty/invalid, then compute the common
part between SYSROOT_DIR and ARCH_SYSROOT_DIR returned by
toolchain_print_sysroot in order to get the "base sysroot".
This "base sysroot" is used as SYSROOT_DIR to create the symlink
in the staging directory.

Signed-off-by: Romain Naour <romain.naour@openwide.fr>

---
v3: Rework the end of string detection (Yann E. Morin)
    Handle a second argument in toolchain_print_sysroot
    Detect if the main sysroot is the same as arch sysroot,
    then return the main_sysroot

v2: new	patch
---
 toolchain/helpers.mk | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

Comments

Romain Naour Nov. 29, 2014, 12:49 p.m. UTC | #1
Hi Yann, all,

Le 14/11/2014 00:03, Romain Naour a écrit :
> When copying external toolchain sysroot to staging, we need to
> create the symbolic link that matches the name of the subdirectory
> for the architecture variant in the original sysroot.
> (ex: sgxx-glibc for CodeSourcery Standard edition)
> To do that, SYSROOT_DIR must be different than ARCH_SYSROOT_DIR.
> 
> In the case where ARCH_SYSROOT_DIR is used as SYSROOT_DIR  we need
> to check again the path to the main sysroot directory.
> if SYSROOT_DIR returned by toolchain_find_sysroot without
> TOOLCHAIN_EXTERNAL_CFLAGS is empty/invalid, then compute the common
> part between SYSROOT_DIR and ARCH_SYSROOT_DIR returned by
> toolchain_print_sysroot in order to get the "base sysroot".
> This "base sysroot" is used as SYSROOT_DIR to create the symlink
> in the staging directory.
> 
> Signed-off-by: Romain Naour <romain.naour@openwide.fr>
> 
> ---
> v3: Rework the end of string detection (Yann E. Morin)
>     Handle a second argument in toolchain_print_sysroot
>     Detect if the main sysroot is the same as arch sysroot,
>     then return the main_sysroot
> 
> v2: new	patch
> ---
>  toolchain/helpers.mk | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
> 
> diff --git a/toolchain/helpers.mk b/toolchain/helpers.mk
> index 7d7af5f..dd7bcac 100644
> --- a/toolchain/helpers.mk
> +++ b/toolchain/helpers.mk
> @@ -97,6 +97,36 @@ toolchain_create_arch_sysroot_symlink = \
>  	ln -s $${relpath} $(STAGING_DIR)/$${ARCH_SUBDIR} ; \
>  	echo "Symlinking $(STAGING_DIR)/$${ARCH_SUBDIR} -> $${relpath}"
>  
> +# Returns the location of the sysroot for the given compiler + flags using
> +# -print-sysroot gcc option (gcc > 4.3 is needed)
> +define toolchain_print_sysroot
> +$$(readlink -f $$(LANG=C $(1) $(2) -print-sysroot))
> +endef

For now, we can't use -print-sysroot gcc option (which is available since gcc
4.4) for toolchain_find_arch_sysroot() and toolchain_find_sysroot() because we
need to support toolchains that use gcc < 4.4 (avr32 targets).

But the support for these toolchains can be dropped after avr32 removal which
is planned for the 2015.02 release, so toolchain_print_sysroot() can be replaced
by toolchain_find_arch_sysroot() or toolchain_find_sysroot().


> +
> +# Returns the common path between the main sysroot and arch sysroot returned by
> +# toolchain_print_sysroot. This is required to calculate the depth of the symlink
> +# in the staging directory when the main sysroot directory is empty/bogus.
> +define toolchain_calculate_base_sysroot
> +$$(common_sysroot_path="" ; \
> +main_sysroot_path=$(call toolchain_print_sysroot,$(TOOLCHAIN_EXTERNAL_CC)); \
> +arch_sysroot_path=$(call toolchain_print_sysroot,$(TOOLCHAIN_EXTERNAL_CC),$(TOOLCHAIN_EXTERNAL_CFLAGS)); \

So:

main_sysroot_path=$(call toolchain_find_sysroot,$(TOOLCHAIN_EXTERNAL_CC)); \
arch_sysroot_path=$(call toolchain_find_arch_sysroot,$(TOOLCHAIN_EXTERNAL_CC),$(TOOLCHAIN_EXTERNAL_CFLAGS)); \

> +if [ "$${main_sysroot_path}" = "$${arch_sysroot_path}" ]; then \
> +	common_sysroot_path="$${main_sysroot_path}"; \
> +else \
> +	index=0 ; \
> +	while [ "$${main_sysroot_path:$${index}:1}" = "$${arch_sysroot_path:$${index}:1}" ] ; do \
> +		if [ "$${main_sysroot_path:$${index}:1}" = "/" ]; then \
> +			common_sysroot_path="$${main_sysroot_path:0:$${index}+1}"; \
> +		fi ; \
> +		if [ $${index} -gt $${#main_sysroot_path} ] || [ $${index} -gt $${#arch_sysroot_path} ]; then \
> +			break; \
> +		fi ; \
> +		: $$((index++)) ; \
> +	done ; \
> +fi ; \
> +echo -n $${common_sysroot_path})
> +endef
> +
>  #
>  # Copy the full external toolchain sysroot directory to the staging
>  # dir. The operation of this function is rendered a little bit
> @@ -130,6 +160,17 @@ toolchain_create_arch_sysroot_symlink = \
>  #    non-default architecture variant is used. Without this, the
>  #    compiler fails to find libraries and headers.
>  #
> +# Some toolchain (i.e CodeSourcery Standard edition) doesn't have
> +# a main sysroot directory and use the arch sysroot as fallback.
> +# In this case we need to check again the path to the main sysroot
> +# directory when SYSROOT_DIR == ARCH_SYSROOT_DIR.
> +# if SYSROOT_DIR returned by toolchain_find_sysroot without
> +# TOOLCHAIN_EXTERNAL_CFLAGS point to valid directory.
> +# If SYSROOT_DIR is empty/invalid, compute the common part between
> +# SYSROOT_DIR and ARCH_SYSROOT_DIR returned by toolchain_print_sysroot
> +# in order to get the "base sysroot". This "base sysroot" is used
> +# to create the symlink in the staging directory.
> +#
>  # Some toolchains (i.e Linaro binary toolchains) store support
>  # libraries (libstdc++, libgcc_s) outside of the sysroot, so we simply
>  # copy all the libraries from the "support lib directory" into our
> @@ -163,6 +204,16 @@ copy_toolchain_sysroot = \
>  			cp -a $${SYSROOT_DIR}/usr/include $(STAGING_DIR)/usr ; \
>  		fi ; \
>  		$(call toolchain_create_arch_sysroot_symlink,$${ARCH_SUBDIR}) ; \
> +	else \

Question by Yann on IRC:
"y_morin: I was wondering why you would re-do the sysroot detection in copy_toolchain_sysroot,
and why you would not do it in TOOLCHAIN_EXTERNAL_INSTALL_CORE."

You're right I can do it in TOOLCHAIN_EXTERNAL_INSTALL_CORE but, as discussed during the meeting
at Dusseldorf, we don't want to use a "dummy" path as SYSROOT_DIR like I did previously in this
series (v1).
http://lists.busybox.net/pipermail/buildroot/2014-October/108641.html

"y_morin: Why is it not possible to set SYSROOT_DIR to the "default" sysroot for the CS toolchain,
and set ARCH_SYSROOT_DIR to the one you want ?"

I can't use the default/base sysroot as SYSROOT_DIR everywhere because it will break, for example,
during toolchain checks check_kernel_headers_version() or check_glibc() (find -maxdepth 2).

So, to be safe, we need to check if it's really the main_sysroot that is used as SYSROOT_DIR, and
that why $(TOOLCHAIN_EXTERNAL_CFLAGS) is not passed.

> +		if ! test -d "$(call toolchain_find_sysroot,$(TOOLCHAIN_EXTERNAL_CC))" ; then \

Here, the main_sysroot doesn't exist, ARCH_SYSROOT was used as SYSROOT_DIR.

> +			SYSROOT_DIR="$(call toolchain_calculate_base_sysroot)"; \

I think it would be better if toolchain_calculate_base_sysroot() can use the $${ARCH_SYSROOT_DIR}
and the path returned by "$(call toolchain_find_sysroot,$(TOOLCHAIN_EXTERNAL_CC))" as arguments,
instead of recall toolchain_find_arch_sysroot() and toolchain_find_sysroot() internally.

> +			if ! test -d $${SYSROOT_DIR} ; then \
> +				echo "ERROR: Unable to find the main sysroot directory." ; \
> +				exit 1; \
> +			fi ; \

Here, we need to overwrite ARCH_SUBDIR since SYSROOT_DIR may have been modified by
toolchain_calculate_base_sysroot()

> +			ARCH_SUBDIR=`echo $${ARCH_SYSROOT_DIR} | sed -r -e "s:^$${SYSROOT_DIR}(.*)/$$:\1:"` ; \
> +			$(call toolchain_create_arch_sysroot_symlink,$${ARCH_SUBDIR}) ; \
> +		fi ; \
>  	fi ; \
>  	if test -n "$${SUPPORT_LIB_DIR}" ; then \
>  		cp -a $${SUPPORT_LIB_DIR}/* $(STAGING_DIR)/lib/ ; \
> 

Best regards,

Patch
diff mbox

diff --git a/toolchain/helpers.mk b/toolchain/helpers.mk
index 7d7af5f..dd7bcac 100644
--- a/toolchain/helpers.mk
+++ b/toolchain/helpers.mk
@@ -97,6 +97,36 @@  toolchain_create_arch_sysroot_symlink = \
 	ln -s $${relpath} $(STAGING_DIR)/$${ARCH_SUBDIR} ; \
 	echo "Symlinking $(STAGING_DIR)/$${ARCH_SUBDIR} -> $${relpath}"
 
+# Returns the location of the sysroot for the given compiler + flags using
+# -print-sysroot gcc option (gcc > 4.3 is needed)
+define toolchain_print_sysroot
+$$(readlink -f $$(LANG=C $(1) $(2) -print-sysroot))
+endef
+
+# Returns the common path between the main sysroot and arch sysroot returned by
+# toolchain_print_sysroot. This is required to calculate the depth of the symlink
+# in the staging directory when the main sysroot directory is empty/bogus.
+define toolchain_calculate_base_sysroot
+$$(common_sysroot_path="" ; \
+main_sysroot_path=$(call toolchain_print_sysroot,$(TOOLCHAIN_EXTERNAL_CC)); \
+arch_sysroot_path=$(call toolchain_print_sysroot,$(TOOLCHAIN_EXTERNAL_CC),$(TOOLCHAIN_EXTERNAL_CFLAGS)); \
+if [ "$${main_sysroot_path}" = "$${arch_sysroot_path}" ]; then \
+	common_sysroot_path="$${main_sysroot_path}"; \
+else \
+	index=0 ; \
+	while [ "$${main_sysroot_path:$${index}:1}" = "$${arch_sysroot_path:$${index}:1}" ] ; do \
+		if [ "$${main_sysroot_path:$${index}:1}" = "/" ]; then \
+			common_sysroot_path="$${main_sysroot_path:0:$${index}+1}"; \
+		fi ; \
+		if [ $${index} -gt $${#main_sysroot_path} ] || [ $${index} -gt $${#arch_sysroot_path} ]; then \
+			break; \
+		fi ; \
+		: $$((index++)) ; \
+	done ; \
+fi ; \
+echo -n $${common_sysroot_path})
+endef
+
 #
 # Copy the full external toolchain sysroot directory to the staging
 # dir. The operation of this function is rendered a little bit
@@ -130,6 +160,17 @@  toolchain_create_arch_sysroot_symlink = \
 #    non-default architecture variant is used. Without this, the
 #    compiler fails to find libraries and headers.
 #
+# Some toolchain (i.e CodeSourcery Standard edition) doesn't have
+# a main sysroot directory and use the arch sysroot as fallback.
+# In this case we need to check again the path to the main sysroot
+# directory when SYSROOT_DIR == ARCH_SYSROOT_DIR.
+# if SYSROOT_DIR returned by toolchain_find_sysroot without
+# TOOLCHAIN_EXTERNAL_CFLAGS point to valid directory.
+# If SYSROOT_DIR is empty/invalid, compute the common part between
+# SYSROOT_DIR and ARCH_SYSROOT_DIR returned by toolchain_print_sysroot
+# in order to get the "base sysroot". This "base sysroot" is used
+# to create the symlink in the staging directory.
+#
 # Some toolchains (i.e Linaro binary toolchains) store support
 # libraries (libstdc++, libgcc_s) outside of the sysroot, so we simply
 # copy all the libraries from the "support lib directory" into our
@@ -163,6 +204,16 @@  copy_toolchain_sysroot = \
 			cp -a $${SYSROOT_DIR}/usr/include $(STAGING_DIR)/usr ; \
 		fi ; \
 		$(call toolchain_create_arch_sysroot_symlink,$${ARCH_SUBDIR}) ; \
+	else \
+		if ! test -d "$(call toolchain_find_sysroot,$(TOOLCHAIN_EXTERNAL_CC))" ; then \
+			SYSROOT_DIR="$(call toolchain_calculate_base_sysroot)"; \
+			if ! test -d $${SYSROOT_DIR} ; then \
+				echo "ERROR: Unable to find the main sysroot directory." ; \
+				exit 1; \
+			fi ; \
+			ARCH_SUBDIR=`echo $${ARCH_SYSROOT_DIR} | sed -r -e "s:^$${SYSROOT_DIR}(.*)/$$:\1:"` ; \
+			$(call toolchain_create_arch_sysroot_symlink,$${ARCH_SUBDIR}) ; \
+		fi ; \
 	fi ; \
 	if test -n "$${SUPPORT_LIB_DIR}" ; then \
 		cp -a $${SUPPORT_LIB_DIR}/* $(STAGING_DIR)/lib/ ; \