When CROSS_COMPILE is set (e.g. aarch64-linux-gnu-), if $(CROSS_COMPILE)elfedit is found at /usr/bin/aarch64-linux-gnu-elfedit, GCC_TOOLCHAIN_DIR will be set to /usr/bin/. --prefix= will be set to /usr/bin/ and Clang as of 11 will search for both $(prefix)aarch64-linux-gnu-$needle and $(prefix)$needle.
GCC searchs for $(prefix)aarch64-linux-gnu/$version/$needle, $(prefix)aarch64-linux-gnu/$needle and $(prefix)$needle. In practice, $(prefix)aarch64-linux-gnu/$needle rarely contains executables.
To better model how GCC's -B/--prefix takes in effect in practice, newer Clang (since https://github.com/llvm/llvm-project/commit/3452a0d8c17f7166f479706b293caf6a...) only searches for $(prefix)$needle. Currently it will find /usr/bin/as instead of /usr/bin/aarch64-linux-gnu-as.
Set --prefix= to $(GCC_TOOLCHAIN_DIR)$(CROSS_COMPILE) (/usr/bin/aarch64-linux-gnu-) so that newer Clang can find the appropriate cross compiling GNU as (when -no-integrated-as is in effect).
Cc: stable@vger.kernel.org Reported-by: Nathan Chancellor natechancellor@gmail.com Signed-off-by: Fangrui Song maskray@google.com Reviewed-by: Nathan Chancellor natechancellor@gmail.com Tested-by: Nathan Chancellor natechancellor@gmail.com Tested-by: Nick Desaulniers ndesaulniers@google.com Link: https://github.com/ClangBuiltLinux/linux/issues/1099 --- Changes in v2: * Updated description to add tags and the llvm-project commit link. * Fixed a typo.
Changes in v3: * Add Cc: stable@vger.kernel.org --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile index 0b5f8538bde5..3ac83e375b61 100644 --- a/Makefile +++ b/Makefile @@ -567,7 +567,7 @@ ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),) ifneq ($(CROSS_COMPILE),) CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%)) GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit)) -CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR) +CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(CROSS_COMPILE) GCC_TOOLCHAIN := $(realpath $(GCC_TOOLCHAIN_DIR)/..) endif ifneq ($(GCC_TOOLCHAIN),)
On Tue, Jul 21, 2020 at 10:31 AM Fangrui Song maskray@google.com wrote:
When CROSS_COMPILE is set (e.g. aarch64-linux-gnu-), if $(CROSS_COMPILE)elfedit is found at /usr/bin/aarch64-linux-gnu-elfedit, GCC_TOOLCHAIN_DIR will be set to /usr/bin/. --prefix= will be set to /usr/bin/ and Clang as of 11 will search for both $(prefix)aarch64-linux-gnu-$needle and $(prefix)$needle.
GCC searchs for $(prefix)aarch64-linux-gnu/$version/$needle, $(prefix)aarch64-linux-gnu/$needle and $(prefix)$needle. In practice, $(prefix)aarch64-linux-gnu/$needle rarely contains executables.
To better model how GCC's -B/--prefix takes in effect in practice, newer Clang (since https://github.com/llvm/llvm-project/commit/3452a0d8c17f7166f479706b293caf6a...) only searches for $(prefix)$needle. Currently it will find /usr/bin/as instead of /usr/bin/aarch64-linux-gnu-as.
Set --prefix= to $(GCC_TOOLCHAIN_DIR)$(CROSS_COMPILE) (/usr/bin/aarch64-linux-gnu-) so that newer Clang can find the appropriate cross compiling GNU as (when -no-integrated-as is in effect).
Cc: stable@vger.kernel.org Reported-by: Nathan Chancellor natechancellor@gmail.com Signed-off-by: Fangrui Song maskray@google.com Reviewed-by: Nathan Chancellor natechancellor@gmail.com Tested-by: Nathan Chancellor natechancellor@gmail.com Tested-by: Nick Desaulniers ndesaulniers@google.com
Reviewed-by: Nick Desaulniers ndesaulniers@google.com
Link: https://github.com/ClangBuiltLinux/linux/issues/1099
Changes in v2:
- Updated description to add tags and the llvm-project commit link.
- Fixed a typo.
Changes in v3:
- Add Cc: stable@vger.kernel.org
Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile index 0b5f8538bde5..3ac83e375b61 100644 --- a/Makefile +++ b/Makefile @@ -567,7 +567,7 @@ ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),) ifneq ($(CROSS_COMPILE),) CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%)) GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit)) -CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR) +CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(CROSS_COMPILE) GCC_TOOLCHAIN := $(realpath $(GCC_TOOLCHAIN_DIR)/..) endif ifneq ($(GCC_TOOLCHAIN),) -- 2.28.0.rc0.105.gf9edc3c819-goog
On Wed, Jul 22, 2020 at 2:31 AM 'Fangrui Song' via Clang Built Linux clang-built-linux@googlegroups.com wrote:
When CROSS_COMPILE is set (e.g. aarch64-linux-gnu-), if $(CROSS_COMPILE)elfedit is found at /usr/bin/aarch64-linux-gnu-elfedit, GCC_TOOLCHAIN_DIR will be set to /usr/bin/. --prefix= will be set to /usr/bin/ and Clang as of 11 will search for both $(prefix)aarch64-linux-gnu-$needle and $(prefix)$needle.
GCC searchs for $(prefix)aarch64-linux-gnu/$version/$needle, $(prefix)aarch64-linux-gnu/$needle and $(prefix)$needle. In practice, $(prefix)aarch64-linux-gnu/$needle rarely contains executables.
To better model how GCC's -B/--prefix takes in effect in practice, newer Clang (since https://github.com/llvm/llvm-project/commit/3452a0d8c17f7166f479706b293caf6a...) only searches for $(prefix)$needle. Currently it will find /usr/bin/as instead of /usr/bin/aarch64-linux-gnu-as.
Set --prefix= to $(GCC_TOOLCHAIN_DIR)$(CROSS_COMPILE) (/usr/bin/aarch64-linux-gnu-) so that newer Clang can find the appropriate cross compiling GNU as (when -no-integrated-as is in effect).
Cc: stable@vger.kernel.org Reported-by: Nathan Chancellor natechancellor@gmail.com Signed-off-by: Fangrui Song maskray@google.com Reviewed-by: Nathan Chancellor natechancellor@gmail.com Tested-by: Nathan Chancellor natechancellor@gmail.com Tested-by: Nick Desaulniers ndesaulniers@google.com Link: https://github.com/ClangBuiltLinux/linux/issues/1099
Changes in v2:
- Updated description to add tags and the llvm-project commit link.
- Fixed a typo.
Changes in v3:
- Add Cc: stable@vger.kernel.org
Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile index 0b5f8538bde5..3ac83e375b61 100644 --- a/Makefile +++ b/Makefile @@ -567,7 +567,7 @@ ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),) ifneq ($(CROSS_COMPILE),) CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%)) GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit)) -CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR) +CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(CROSS_COMPILE)
CROSS_COMPILE may contain the directory path to the cross toolchains.
For example, I use aarch64-linux-gnu-* installed in /home/masahiro/tools/aarch64-linaro-7.5/bin
Basically, there are two ways to use it.
[1] PATH=$PATH:/home/masahiro/tools/aarch64-linaro-7.5/bin CROSS_COMPILE=aarch64-linux-gnu-
[2] Without setting PATH, CROSS_COMPILE=~/tools/aarch64-linaro-7.5/bin/aarch64-linux-gnu-
I usually do [2] (and so does intel's 0day bot).
This patch works for the use-case [1] but if I do [2], --prefix is set to a strange path:
--prefix=/home/masahiro/tools/aarch64-linaro-7.5/bin//home/masahiro/tools/aarch64-linaro-7.5/bin/aarch64-linux-gnu-
Interestingly, the build is still successful. Presumably Clang searches for more paths when $(prefix)$needle is not found ?
I applied your patch and added -v option to see which assembler was internally invoked:
"/home/masahiro/tools/aarch64-linaro-7.5/lib/gcc/aarch64-linux-gnu/7.5.0/../../../../aarch64-linux-gnu/bin/as" -EL -I ./arch/arm64/include -I ./arch/arm64/include/generated -I ./include -I ./arch/arm64/include/uapi -I ./arch/arm64/include/generated/uapi -I ./include/uapi -I ./include/generated/uapi -o kernel/smp.o /tmp/smp-2ec2c7.s
Ok, it looks like Clang found an alternative path to the correct 'as'.
But, to keep the original behavior for both [1] and [2], how about this?
CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
Then, I can get this:
"/home/masahiro/tools/aarch64-linaro-7.5/bin/aarch64-linux-gnu-as" -EL -I ./arch/arm64/include -I ./arch/arm64/include/generated -I ./include -I ./arch/arm64/include/uapi -I ./arch/arm64/include/generated/uapi -I ./include/uapi -I ./include/generated/uapi -o kernel/smp.o /tmp/smp-16d76f.s
GCC_TOOLCHAIN := $(realpath $(GCC_TOOLCHAIN_DIR)/..) endif ifneq ($(GCC_TOOLCHAIN),) -- 2.28.0.rc0.105.gf9edc3c819-goog
-- You received this message because you are subscribed to the Google Groups "Clang Built Linux" group. To unsubscribe from this group and stop receiving emails from it, send an email to clang-built-linux+unsubscribe@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/clang-built-linux/20200721173125.1273884-1....
-- Best Regards Masahiro Yamada
On 2020-07-22, Masahiro Yamada wrote:
On Wed, Jul 22, 2020 at 2:31 AM 'Fangrui Song' via Clang Built Linux clang-built-linux@googlegroups.com wrote:
When CROSS_COMPILE is set (e.g. aarch64-linux-gnu-), if $(CROSS_COMPILE)elfedit is found at /usr/bin/aarch64-linux-gnu-elfedit, GCC_TOOLCHAIN_DIR will be set to /usr/bin/. --prefix= will be set to /usr/bin/ and Clang as of 11 will search for both $(prefix)aarch64-linux-gnu-$needle and $(prefix)$needle.
GCC searchs for $(prefix)aarch64-linux-gnu/$version/$needle, $(prefix)aarch64-linux-gnu/$needle and $(prefix)$needle. In practice, $(prefix)aarch64-linux-gnu/$needle rarely contains executables.
To better model how GCC's -B/--prefix takes in effect in practice, newer Clang (since https://github.com/llvm/llvm-project/commit/3452a0d8c17f7166f479706b293caf6a...) only searches for $(prefix)$needle. Currently it will find /usr/bin/as instead of /usr/bin/aarch64-linux-gnu-as.
Set --prefix= to $(GCC_TOOLCHAIN_DIR)$(CROSS_COMPILE) (/usr/bin/aarch64-linux-gnu-) so that newer Clang can find the appropriate cross compiling GNU as (when -no-integrated-as is in effect).
Cc: stable@vger.kernel.org Reported-by: Nathan Chancellor natechancellor@gmail.com Signed-off-by: Fangrui Song maskray@google.com Reviewed-by: Nathan Chancellor natechancellor@gmail.com Tested-by: Nathan Chancellor natechancellor@gmail.com Tested-by: Nick Desaulniers ndesaulniers@google.com Link: https://github.com/ClangBuiltLinux/linux/issues/1099
Changes in v2:
- Updated description to add tags and the llvm-project commit link.
- Fixed a typo.
Changes in v3:
- Add Cc: stable@vger.kernel.org
Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile index 0b5f8538bde5..3ac83e375b61 100644 --- a/Makefile +++ b/Makefile @@ -567,7 +567,7 @@ ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),) ifneq ($(CROSS_COMPILE),) CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%)) GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit)) -CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR) +CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(CROSS_COMPILE)
CROSS_COMPILE may contain the directory path to the cross toolchains.
For example, I use aarch64-linux-gnu-* installed in /home/masahiro/tools/aarch64-linaro-7.5/bin
Basically, there are two ways to use it.
[1] PATH=$PATH:/home/masahiro/tools/aarch64-linaro-7.5/bin CROSS_COMPILE=aarch64-linux-gnu-
[2] Without setting PATH, CROSS_COMPILE=~/tools/aarch64-linaro-7.5/bin/aarch64-linux-gnu-
I usually do [2] (and so does intel's 0day bot).
This patch works for the use-case [1] but if I do [2], --prefix is set to a strange path:
--prefix=/home/masahiro/tools/aarch64-linaro-7.5/bin//home/masahiro/tools/aarch64-linaro-7.5/bin/aarch64-linux-gnu-
Thanks. I did not know the use-case [2]. This explains why there is a `$(notdir ...)` in `CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%))`
Interestingly, the build is still successful. Presumably Clang searches for more paths when $(prefix)$needle is not found ?
The priority order is:
-B(--prefix), COMPILER_PATH, detected gcc-cross paths
(In GCC, -B paths get prepended to the COMPILER_PATH list. Clang<=11 incorrectly adds -B to the COMPILER_PATH list. I have fixed it for 12.0.0)
If -B fails, the detected gcc-cross paths may still be able to find /usr/bin/aarch64-linux-gnu-
For example, on my machine (a variant of Debian testing), Clang finds $(realpath /usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/as), which is /usr/bin/aarch64-linux-gnu-as
I applied your patch and added -v option to see which assembler was internally invoked:
"/home/masahiro/tools/aarch64-linaro-7.5/lib/gcc/aarch64-linux-gnu/7.5.0/../../../../aarch64-linux-gnu/bin/as" -EL -I ./arch/arm64/include -I ./arch/arm64/include/generated -I ./include -I ./arch/arm64/include/uapi -I ./arch/arm64/include/generated/uapi -I ./include/uapi -I ./include/generated/uapi -o kernel/smp.o /tmp/smp-2ec2c7.s
Ok, it looks like Clang found an alternative path to the correct 'as'.
But, to keep the original behavior for both [1] and [2], how about this?
CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
Then, I can get this:
"/home/masahiro/tools/aarch64-linaro-7.5/bin/aarch64-linux-gnu-as" -EL -I ./arch/arm64/include -I ./arch/arm64/include/generated -I ./include -I ./arch/arm64/include/uapi -I ./arch/arm64/include/generated/uapi -I ./include/uapi -I ./include/generated/uapi -o kernel/smp.o /tmp/smp-16d76f.s
This looks good.
Agreed that `--prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))` should work for both [1] and [2].
Shall I send a v4? Or you are kind enough that you'll just add your Signed-off-by: tag and fix that for me? :)
GCC_TOOLCHAIN := $(realpath $(GCC_TOOLCHAIN_DIR)/..) endif ifneq ($(GCC_TOOLCHAIN),) -- 2.28.0.rc0.105.gf9edc3c819-goog
-- You received this message because you are subscribed to the Google Groups "Clang Built Linux" group. To unsubscribe from this group and stop receiving emails from it, send an email to clang-built-linux+unsubscribe@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/clang-built-linux/20200721173125.1273884-1....
-- Best Regards Masahiro Yamada
On Wed, Jul 22, 2020 at 9:14 AM Fangrui Song maskray@google.com wrote:
On 2020-07-22, Masahiro Yamada wrote:
On Wed, Jul 22, 2020 at 2:31 AM 'Fangrui Song' via Clang Built Linux clang-built-linux@googlegroups.com wrote:
When CROSS_COMPILE is set (e.g. aarch64-linux-gnu-), if $(CROSS_COMPILE)elfedit is found at /usr/bin/aarch64-linux-gnu-elfedit, GCC_TOOLCHAIN_DIR will be set to /usr/bin/. --prefix= will be set to /usr/bin/ and Clang as of 11 will search for both $(prefix)aarch64-linux-gnu-$needle and $(prefix)$needle.
GCC searchs for $(prefix)aarch64-linux-gnu/$version/$needle, $(prefix)aarch64-linux-gnu/$needle and $(prefix)$needle. In practice, $(prefix)aarch64-linux-gnu/$needle rarely contains executables.
To better model how GCC's -B/--prefix takes in effect in practice, newer Clang (since https://github.com/llvm/llvm-project/commit/3452a0d8c17f7166f479706b293caf6a...) only searches for $(prefix)$needle. Currently it will find /usr/bin/as instead of /usr/bin/aarch64-linux-gnu-as.
Set --prefix= to $(GCC_TOOLCHAIN_DIR)$(CROSS_COMPILE) (/usr/bin/aarch64-linux-gnu-) so that newer Clang can find the appropriate cross compiling GNU as (when -no-integrated-as is in effect).
Cc: stable@vger.kernel.org Reported-by: Nathan Chancellor natechancellor@gmail.com Signed-off-by: Fangrui Song maskray@google.com Reviewed-by: Nathan Chancellor natechancellor@gmail.com Tested-by: Nathan Chancellor natechancellor@gmail.com Tested-by: Nick Desaulniers ndesaulniers@google.com Link: https://github.com/ClangBuiltLinux/linux/issues/1099
Changes in v2:
- Updated description to add tags and the llvm-project commit link.
- Fixed a typo.
Changes in v3:
- Add Cc: stable@vger.kernel.org
Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile index 0b5f8538bde5..3ac83e375b61 100644 --- a/Makefile +++ b/Makefile @@ -567,7 +567,7 @@ ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),) ifneq ($(CROSS_COMPILE),) CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%)) GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit)) -CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR) +CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(CROSS_COMPILE)
CROSS_COMPILE may contain the directory path to the cross toolchains.
For example, I use aarch64-linux-gnu-* installed in /home/masahiro/tools/aarch64-linaro-7.5/bin
Basically, there are two ways to use it.
[1] PATH=$PATH:/home/masahiro/tools/aarch64-linaro-7.5/bin CROSS_COMPILE=aarch64-linux-gnu-
[2] Without setting PATH, CROSS_COMPILE=~/tools/aarch64-linaro-7.5/bin/aarch64-linux-gnu-
I usually do [2] (and so does intel's 0day bot).
This patch works for the use-case [1] but if I do [2], --prefix is set to a strange path:
--prefix=/home/masahiro/tools/aarch64-linaro-7.5/bin//home/masahiro/tools/aarch64-linaro-7.5/bin/aarch64-linux-gnu-
Thanks. I did not know the use-case [2]. This explains why there is a `$(notdir ...)` in `CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%))`
Interestingly, the build is still successful. Presumably Clang searches for more paths when $(prefix)$needle is not found ?
The priority order is:
-B(--prefix), COMPILER_PATH, detected gcc-cross paths
(In GCC, -B paths get prepended to the COMPILER_PATH list. Clang<=11 incorrectly adds -B to the COMPILER_PATH list. I have fixed it for 12.0.0)
If -B fails, the detected gcc-cross paths may still be able to find /usr/bin/aarch64-linux-gnu-
For example, on my machine (a variant of Debian testing), Clang finds $(realpath /usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/as), which is /usr/bin/aarch64-linux-gnu-as
I applied your patch and added -v option to see which assembler was internally invoked:
"/home/masahiro/tools/aarch64-linaro-7.5/lib/gcc/aarch64-linux-gnu/7.5.0/../../../../aarch64-linux-gnu/bin/as" -EL -I ./arch/arm64/include -I ./arch/arm64/include/generated -I ./include -I ./arch/arm64/include/uapi -I ./arch/arm64/include/generated/uapi -I ./include/uapi -I ./include/generated/uapi -o kernel/smp.o /tmp/smp-2ec2c7.s
Ok, it looks like Clang found an alternative path to the correct 'as'.
But, to keep the original behavior for both [1] and [2], how about this?
CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
Then, I can get this:
"/home/masahiro/tools/aarch64-linaro-7.5/bin/aarch64-linux-gnu-as" -EL -I ./arch/arm64/include -I ./arch/arm64/include/generated -I ./include -I ./arch/arm64/include/uapi -I ./arch/arm64/include/generated/uapi -I ./include/uapi -I ./include/generated/uapi -o kernel/smp.o /tmp/smp-16d76f.s
This looks good.
Agreed that `--prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))` should work for both [1] and [2].
Shall I send a v4? Or you are kind enough that you'll just add your Signed-off-by: tag and fix that for me? :)
I fixed it up and applied to linux-kbuild/fixes. Thanks.
While I am here, could you teach me a bit more?
The top Makefile sets the following option as well:
CLANG_GCC_TC := --gcc-toolchain=$(GCC_TOOLCHAIN)
I checked the manual: https://clang.llvm.org/docs/ClangCommandLineReference.html
-B<dir>, --prefix <arg>, --prefix=<arg> Add <dir> to search path for binaries and object files used implicitly
--gcc-toolchain=<arg>, -gcc-toolchain <arg> Use the gcc toolchain at the given directory
It is not clear to me how they work differently when clang searches for toolchains.
If I delete --gcc-toolchain from the top Makefile, clang fails to link standalone programs because it wrongly invokes /usr/bin/ld instead of aarch64-linux-gnu-ld.
Does Clang search for gnu assembler based on --prefix option?
And, searches for a linker based on --gcc-toolchain ?
On 2020-07-22, Masahiro Yamada wrote:
On Wed, Jul 22, 2020 at 9:14 AM Fangrui Song maskray@google.com wrote:
On 2020-07-22, Masahiro Yamada wrote:
On Wed, Jul 22, 2020 at 2:31 AM 'Fangrui Song' via Clang Built Linux clang-built-linux@googlegroups.com wrote:
When CROSS_COMPILE is set (e.g. aarch64-linux-gnu-), if $(CROSS_COMPILE)elfedit is found at /usr/bin/aarch64-linux-gnu-elfedit, GCC_TOOLCHAIN_DIR will be set to /usr/bin/. --prefix= will be set to /usr/bin/ and Clang as of 11 will search for both $(prefix)aarch64-linux-gnu-$needle and $(prefix)$needle.
GCC searchs for $(prefix)aarch64-linux-gnu/$version/$needle, $(prefix)aarch64-linux-gnu/$needle and $(prefix)$needle. In practice, $(prefix)aarch64-linux-gnu/$needle rarely contains executables.
To better model how GCC's -B/--prefix takes in effect in practice, newer Clang (since https://github.com/llvm/llvm-project/commit/3452a0d8c17f7166f479706b293caf6a...) only searches for $(prefix)$needle. Currently it will find /usr/bin/as instead of /usr/bin/aarch64-linux-gnu-as.
Set --prefix= to $(GCC_TOOLCHAIN_DIR)$(CROSS_COMPILE) (/usr/bin/aarch64-linux-gnu-) so that newer Clang can find the appropriate cross compiling GNU as (when -no-integrated-as is in effect).
Cc: stable@vger.kernel.org Reported-by: Nathan Chancellor natechancellor@gmail.com Signed-off-by: Fangrui Song maskray@google.com Reviewed-by: Nathan Chancellor natechancellor@gmail.com Tested-by: Nathan Chancellor natechancellor@gmail.com Tested-by: Nick Desaulniers ndesaulniers@google.com Link: https://github.com/ClangBuiltLinux/linux/issues/1099
Changes in v2:
- Updated description to add tags and the llvm-project commit link.
- Fixed a typo.
Changes in v3:
- Add Cc: stable@vger.kernel.org
Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile index 0b5f8538bde5..3ac83e375b61 100644 --- a/Makefile +++ b/Makefile @@ -567,7 +567,7 @@ ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),) ifneq ($(CROSS_COMPILE),) CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%)) GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit)) -CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR) +CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(CROSS_COMPILE)
CROSS_COMPILE may contain the directory path to the cross toolchains.
For example, I use aarch64-linux-gnu-* installed in /home/masahiro/tools/aarch64-linaro-7.5/bin
Basically, there are two ways to use it.
[1] PATH=$PATH:/home/masahiro/tools/aarch64-linaro-7.5/bin CROSS_COMPILE=aarch64-linux-gnu-
[2] Without setting PATH, CROSS_COMPILE=~/tools/aarch64-linaro-7.5/bin/aarch64-linux-gnu-
I usually do [2] (and so does intel's 0day bot).
This patch works for the use-case [1] but if I do [2], --prefix is set to a strange path:
--prefix=/home/masahiro/tools/aarch64-linaro-7.5/bin//home/masahiro/tools/aarch64-linaro-7.5/bin/aarch64-linux-gnu-
Thanks. I did not know the use-case [2]. This explains why there is a `$(notdir ...)` in `CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%))`
Interestingly, the build is still successful. Presumably Clang searches for more paths when $(prefix)$needle is not found ?
The priority order is:
-B(--prefix), COMPILER_PATH, detected gcc-cross paths
(In GCC, -B paths get prepended to the COMPILER_PATH list. Clang<=11 incorrectly adds -B to the COMPILER_PATH list. I have fixed it for 12.0.0)
If -B fails, the detected gcc-cross paths may still be able to find /usr/bin/aarch64-linux-gnu-
For example, on my machine (a variant of Debian testing), Clang finds $(realpath /usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/as), which is /usr/bin/aarch64-linux-gnu-as
I applied your patch and added -v option to see which assembler was internally invoked:
"/home/masahiro/tools/aarch64-linaro-7.5/lib/gcc/aarch64-linux-gnu/7.5.0/../../../../aarch64-linux-gnu/bin/as" -EL -I ./arch/arm64/include -I ./arch/arm64/include/generated -I ./include -I ./arch/arm64/include/uapi -I ./arch/arm64/include/generated/uapi -I ./include/uapi -I ./include/generated/uapi -o kernel/smp.o /tmp/smp-2ec2c7.s
Ok, it looks like Clang found an alternative path to the correct 'as'.
But, to keep the original behavior for both [1] and [2], how about this?
CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
Then, I can get this:
"/home/masahiro/tools/aarch64-linaro-7.5/bin/aarch64-linux-gnu-as" -EL -I ./arch/arm64/include -I ./arch/arm64/include/generated -I ./include -I ./arch/arm64/include/uapi -I ./arch/arm64/include/generated/uapi -I ./include/uapi -I ./include/generated/uapi -o kernel/smp.o /tmp/smp-16d76f.s
This looks good.
Agreed that `--prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))` should work for both [1] and [2].
Shall I send a v4? Or you are kind enough that you'll just add your Signed-off-by: tag and fix that for me? :)
I fixed it up and applied to linux-kbuild/fixes. Thanks.
Thanks!
The description 'Set --prefix= to $(GCC_TOOLCHAIN_DIR)$(CROSS_COMPILE)' should probably be fixed to say '$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))'
While I am here, could you teach me a bit more?
The top Makefile sets the following option as well:
CLANG_GCC_TC := --gcc-toolchain=$(GCC_TOOLCHAIN)
I checked the manual: https://clang.llvm.org/docs/ClangCommandLineReference.html
-B<dir>, --prefix <arg>, --prefix=<arg> Add <dir> to search path for binaries and object files used implicitly
--gcc-toolchain=<arg>, -gcc-toolchain <arg> Use the gcc toolchain at the given directory
It is not clear to me how they work differently when clang searches for toolchains.
If I delete --gcc-toolchain from the top Makefile, clang fails to link standalone programs because it wrongly invokes /usr/bin/ld instead of aarch64-linux-gnu-ld.
Does Clang search for gnu assembler based on --prefix option?
And, searches for a linker based on --gcc-toolchain ?
-- Best Regards Masahiro Yamada
While GCC seems to encourage distributions to apply various environment settings, Clang encourages downstream users to contribute their configurations to the upstream clangDriver library... So, clang works seemingly on many operating systems and many distributions without much additional customization, but the host/target environment detection code is very messy.
Freestanding builds (if you use integrated assembler/LLD) do not need --gcc-toolchain.
-fhosted builds need --gcc-toolchain to reuse libstdc++ include paths and runtime libraries (crt1.o libgcc.a libgcc_s.so.1 etc). I think on most Linux distributions, with distribution shipped GCC packages, the only meaningful value is --gcc-toolchain=/usr
Clang will find 'lib' or 'lib64' under --gcc-toolchain= (e.g. /usr/lib), then locate common cross-compiling GCC installations (e.g. /usr/lib + gcc-cross/aarch-linux-gnu (Debian uses gcc-cross/), or just /usr/lib + gcc/aarch-linux-gnu). You can see that with an incorrect --gcc-toolchain=/ (or some other arbitrary path): (https://github.com/llvm/llvm-project/blob/master/clang/lib/Driver/ToolChains... )
* `clang -v` does not print `Found candidate GCC installation: ` * There is no libstdc++ search path in `#include <...> search starts here:` for a C++ compile * In the linking stage, ld reports a number of issues like 'cannot find crt1.o'
When --gcc-toolchain is not specified, in many cases Clang can guess the correct value (usually /usr). So clang++ --target=aarch64-linux-gnu works just fine.
(As you can see from the code, the code --gcc-toolchain= is tangled with environment detection, which is ugly: specifying a wrong --gcc-toolchain= can remove a lot of file stats... You can find that the number of syscalls changes with different --gcc-toolchain: `strace -fe file clang`)
External programs like 'as' and 'ld' use the bin/ directory somewhere relative to the GCC installation directory (they are appended to getProgramPaths). clang::driver::Driver::GetProgramPath locates these programs. https://github.com/llvm/llvm-project/blob/master/clang/lib/Driver/ToolChains... As you see from the code, -B and COMPILER_PATH take precedence over getProgramPaths. You can print the 'programs' path with `clang --print-search-dirs [--target=...] [-B...] [--gcc-toolchain=...]` Latest clang will be closer to GCC.
linux-stable-mirror@lists.linaro.org