On Thu, Feb 20, 2020 at 4:45 PM Kees Cook <
kees...@chromium.org> wrote:
>
> On Thu, Feb 20, 2020 at 03:48:58PM -0800, 'Nick Desaulniers' via Clang Built Linux wrote:
> > Prior to this patch, building the Linux kernel with Clang
> > looked like:
> >
> > $ make CC=clang
> >
> > or when cross compiling:
> >
> > $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make CC=clang
> >
> > which got very verbose and unwieldy when using all of LLVM's substitutes
> > for GNU binutils:
> >
> > $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make CC=clang AS=clang \
> > LD=ld.lld AR=llvm-ar NM=llvm-nm STRIP=llvm-strip \
> > OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump OBJSIZE=llvm-objsize \
> > READELF=llvm-readelf HOSTCC=clang HOSTCXX=clang++ HOSTAR=llvm-ar \
> > HOSTLD=ld.lld
> >
> > This change adds a new Makefile under scripts/ which will be included in
> > the top level Makefile AFTER CC and friends are set, in order to make
> > the use of LLVM utilities when building a Linux kernel more ergonomic.
> >
> > With this patch, the above now looks like:
> >
> > $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make LLVM=1
>
> I like this idea, but I think it might not be happening in the right
> place... but I'm not sure what that place is. This will collide, for
> example, with the Clang LTO series from Sami, as that _requires_ the
> LLVM utilities in many places. I think some coordination with Kconfig
> will be needed to not make this kind of crazy.
>
> e.g. Sami currently has to hard-code this logic:
>
>
https://github.com/samitolvanen/linux/commit/42572f50c5f951cac7ea4720658d9abd2b995529#diff-b67911656ef5d18c4ae36cb6741b7965R652
Thanks for the link. I don't think Sami's patch should hard code
these values. My change will set these values BEFORE Sami's first
hunk (my Makefile change is L472, his is L652. I think with my patch,
Sami could:
1. drop the first hunk outright.
2. use `$(NM)` in scripts/Makefile.build. (Notice how it does this
with `$(AR)`, and does not export `LLVM_AR`).
3. require the use of LLVM=1 for CONFIG_LTO_CLANG, either via
documentation, or build time test.
I don't think we should have to suffer at the command line for tools
that need additional test coverage, for an out of tree patch (sorry
Sami, I'll still do whatever I can to help rectify that). I want
`make LLVM=1` to be the default way we build things going forward; if
that complicates some workflows somewhere, sorry, and we'll help you
fix it, but we're not going to hold up the train over it.
Nathan & Masahiro, I was really hoping to get your thoughts on this RFC.
>
> -Kees
>
> >
> > Then you can "opt out" of certain LLVM utilities explicitly:
> >
> > $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make LLVM=1 AS=as
> >
> > will instead invoke arm-linux-gnueabihf-as in place of clang for AS.
> >
> > This would make it more verbose to opt into just one tool from LLVM, but
> > this patch doesn't actually break the old style; just leave off LLVM=1.
> > Also, LLVM=1 CC=clang would wind up prefixing clang with $CROSS_COMPILE.
> > In that case, it's recommended to just drop LLVM=1 and use the old
> > style. So LLVM=1 can be thought of as default to LLVM with explicit opt
> > ins for GNU, vs the current case of default to GNU and opt in for LLVM.
> >
> > A key part of the design of this patch is to be minimally invasive to
> > the top level Makefile and not break existing workflows. We could get
> > more aggressive, but I'd prefer to save larger refactorings for another
> > day.
> >
> > About the script:
> > The pattern used in the script is in the form:
> >
> > ifeq "$(origin $(CC))" "file"
> > $(CC) := $(clang)
> > else
> > override $(CC) := $(CROSS_COMPILE)$(CC)
> > endif
> >
> > "Metaprogramming" (eval) is used to template the above to make it more
> > concise for specifying all of the substitutions.
> >
> > The "origin" of a variable tracks whether a variable was explicitly set
> > via "command line", "environment", was defined earlier via Makefile
> > "file", was provided by "default", or was "undefined".
> >
> > Variable assignment in GNU Make has some special and complicated rules.
> >
> > If the variable was set earlier explicitly in the Makefile, we can
> > simply reassign a new value to it. If a variable was unspecified, then
> > earlier assignments were executed and change the origin to file.
> > Otherwise, the variable was explicitly specified.
> >
> > If a variable's "origin" was "command line" or "environment",
> > non-"override" assignments are not executed. The "override" directive
> > forces the assignment regardless of "origin".
> >
> > Some tips I found useful for debugging for future travelers:
> >
> > $(info $$origin of $$CC is $(origin CC))
> >
> > at the start of the new script for all of the variables can help you
> > understand "default" vs "undefined" variable origins.
> >
> > $(info $$CC is [${CC}])
> >
> > in the top level Makefile after including the new script, for all of the
> > variables can help you check that they're being set as expected.
> >
> > Link:
https://www.gnu.org/software/make/manual/html_node/Eval-Function.html
> > Link:
https://www.gnu.org/software/make/manual/html_node/Origin-Function.html
> > Link:
https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html
> > Link:
https://www.gnu.org/software/make/manual/html_node/Override-Directive.html
> > Makefile | 4 ++++
> > scripts/Makefile.llvm | 24 ++++++++++++++++++++++++
> > 2 files changed, 28 insertions(+)
> > create mode 100644 scripts/Makefile.llvm
> >
> > diff --git a/Makefile b/Makefile
> > index b954c304c479..8c8888ebb822 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -472,6 +472,10 @@ KBUILD_LDFLAGS :=
> > GCC_PLUGINS_CFLAGS :=
> > CLANG_FLAGS :=
> >
> > +ifeq ($(LLVM),1)
> > +include scripts/Makefile.llvm
> > +endif
> > +
> > export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC
> > export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE READELF PAHOLE LEX YACC AWK INSTALLKERNEL
> > export PERL PYTHON PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
> > diff --git a/scripts/Makefile.llvm b/scripts/Makefile.llvm
> > new file mode 100644
> > index 000000000000..a4401c8677dc
> > --- /dev/null
> > +++ b/scripts/Makefile.llvm
> > @@ -0,0 +1,24 @@
> > +define META_set =
> > +ifeq "$(origin $(1))" "file"
> > +$(1) := $(2)
> > +else
> > +override $(1) := $(CROSS_COMPILE)$($(1))
> > +endif
> > +endef
> > +
> > +$(eval $(call META_set,CC,clang))
> > +$(eval $(call META_set,AS,clang))
> > +$(eval $(call META_set,LD,ld.lld))
> > +$(eval $(call META_set,AR,llvm-ar))
> > +$(eval $(call META_set,NM,llvm-nm))
> > +$(eval $(call META_set,STRIP,llvm-strip))
> > +$(eval $(call META_set,OBJCOPY,llvm-objcopy))
> > +$(eval $(call META_set,OBJDUMP,llvm-objdump))
> > +$(eval $(call META_set,OBJSIZE,llvm-objsize))
> > +$(eval $(call META_set,READELF,llvm-readelf))
> > +$(eval $(call META_set,HOSTCC,clang))
> > +$(eval $(call META_set,HOSTCXX,clang++))
> > +$(eval $(call META_set,HOSTAR,llvm-ar))
> > +$(eval $(call META_set,HOSTLD,ld.lld))
> > +
> > +## TODO: HOSTAR, HOSTLD in tools/objtool/Makefile
> > --
> > 2.25.0.265.gbab2e86ba0-goog
> >
> > -
--
Thanks,
~Nick Desaulniers