[LLVMdev] compiler-rt CMake build

Alexey Samsonov samsonov at google.com
Sun Mar 23 11:17:18 PDT 2014


Hi Greg,

On Fri, Mar 21, 2014 at 11:18 PM, Greg Fitzgerald <garious at gmail.com> wrote:

> Hi Alexey,
>
> CMAKE_PREFIX_PATH is a convenient mechanism for exposing prebuilt
> install directories to a CMake build.  It contains a colon-separated
> list of paths.  Each path points to a directory that contains
> directory names that are meaningful to CMake, including 'bin', 'lib'
> and 'share'.
>
> If, for example, you want the path to 'llvm-config', instead of
> creating a new CMake variable, you instead write
> "find_program(LLVM_CONFIG_PATH llvm-config)".  CMake will search for
> an executable named 'llvm-config' in each 'bin' directory of each path
> in CMAKE_PREFIX_PATH.
>
> In a simplest case, where there is only one dependency, using
> CMAKE_PREFIX_PATH means we do not have to standardize on a variable
> name.  For llvm-config, should it be LLVM_CONFIG_PATH or
> COMPILER_RT_LLVM_CONFIG_PATH?  In a component build, the former is
> sufficient, but in the monolithic build, it makes more sense to
> namespace every variable.  We can avoid painting that bike shed using
> CMAKE_PREFIX_PATH.
>
> When one component has multiple dependencies from another, using
> CMAKE_PREFIX_PATH really starts saving keystrokes.  You can use it to
> find headers (sanitizer/asan_interface.h), binaries (FileCheck),
> libraries, or CMake modules.
>
> A good alternative to CMAKE_PREFIX_PATH is to create one variable per
> install directory.  So compiler-rt might accept LLVM_INSTALL_DIR, and
> clang accept COMPILER_RT_INSTALL_DIR and LLVM_INSTALL_DIR.  There are
> two advantages to this route:
>
> 1) No need for CMake features such as 'find_program'.  Instead, you
> can be explicit:
>     ${LLVM_INSTALL_DIR}/bin/llvm-config
> 2) No need to organize the install directory in any particular way.
> If a small component wants to combine its 'bin' and 'lib' directories
> into one top-level directory, that's no problem.
>
> The disadvantage of this system is the need to standardize across
> components on a naming convention.  COMPILER_RT_DIR, COMPILER-RT_DIR,
> COMPILER_RT_INSTALL_DIR, COMPILER-RT_SHIP_DIR?  Ideally you'd only
> have to write "deps = llvm compiler-rt" and a package manager could
> automatically translate that to names that match the CMake options
> (LLVM_DIR, COMPILER_RT_DIR).  But like before, using CMAKE_PREFIX_PATH
> avoids the issue.
>

Thanks for the great detailed explanations. I should check if we can
simplify
clang - compiler-rt build systems relationship with this.


>
> Regarding the use of ExternalProject within Clang, I think it could
> create more problems than it solves.  For one, it can't be used from
> within the monolithic build (unless you have a duplicate llvm build,
> or point CompilerRT to a subset of the currently-building LLVM build).
>

Could you elaborate on this? That's exactly what I'm trying to do now -
when I call "ExternalProject_Add(compiler-rt)" from Clang build tree, I
use just-built llvm-config to configure it, and set up the paths so that
"make compiler-rt" in compiler-rt build tree will build the libraries in the
proper locations, where Clang driver expects to find them. Maybe, I don't
understand what you mean when you say "monolithic build"



>  Secondly, it's not a general enough solution for other LLVM
> components.  Say, for example, you wanted to use ExternalProject to
> build LLVM from both Clang and CompilerRT.


Why would one want to build LLVM from Clang and CompilerRT? My approach
is targeted at solving a very specific problem.


>  If the parameters passed
> to LLVM were identical, CMake could detect that and not build a
> duplicate copy.  If they parameters are different in any way, you have
> a problem.  Do you duplicate the build or flag an error?  We can avoid
> this issue by allowing a super-project or package manager build LLVM
> and pass its path to both Clang and CompilerRT.
>
>
> Regarding the use of just-built-clang for both building CompilerRT and
> running its test suite, please consider relaxing that to a
> stage0-clang for building and a just-built-clang for testing.


What if we don't have stage0-clang, and use gcc as a host compiler?


>  Using
> the just-built-clang to build compiler-rt is rough on package
> managers.  You're basically stating that the compiler-rt build depends
> on some unreleased feature of clang to *build* compiler-rt.


No, I want "use just-built clang" to be the default workflow. Currently, you
may use any host compiler to build compiler-rt sources (gcc, Clang, MSVC),
and we certainly want to keep it that way and not rely on some non-standard
or Clang-specific features. But we probably want to ship/release Clang with
a set of compiler-rt libraries that are built with *this* Clang. Again, one
use case
when this can be necessary is targeting different platforms. For example, if
you use linux-x86 and you build LLVM/Clang capable of targeting both x86
and arm,
it certainly makes sense to build necessary compiler-rt libraries for all
arches that Clang
can target. But you host compiler will most likely not be able to build arm
version of
compiler-rt libs.


>  To a
> package manager, that means it should first build clang, then use that
> clang to build compiler-rt, and then build a version of clang that
> includes compiler-rt.


As I mentioned earlier, it's enough to build clang, and use it to build
compiler-rt
in a proper location, no futher steps will be necessary.


>  It implies that every time there is a new
> commit to clang, compiler-rt should be rebuilt and retested.  If the
> compiler-rt build depended only a just-released-clang, then a commit
> to clang would imply only that the sanitizer tests should be rebuilt
> and tested.
>
> -Greg
>
>
>
> On Fri, Mar 21, 2014 at 3:59 AM, Alexey Samsonov <samsonov at google.com>
> wrote:
> > On Thu, Mar 20, 2014 at 10:12 PM, Greg Fitzgerald <garious at gmail.com>
> wrote:
> >>
> >> > ExternalProject_Add(compiler-rt ...)
> >>
> >> So that was quite the experiment.  Looking at
> >> clang/runtime/CMakeLists.txt, I'm not seeing a lot of bang for buck
> >> here, and it looks like this file is prone to bit rot.
> >
> >
> > Could you please elaborate on this? In fact, I don't plan to give up on
> this
> > experiment.
> > On the contrary, I wanted to move LLVM_BUILD_EXTERNAL_COMPILER_RT to the
> > bots, migrate the workflow of our team to use this mode, and eventually
> make
> > it the default.
> >
> > The problem is that we want top-level targets from compiler-rt build
> tree be
> > visible in the llvm/clang
> > top-level build tree. I thought this could be achieved by ugly
> propagation
> > of top-level compiler-rt
> > targets with add_custom_target() command. (like I did this for
> > check-compiler-rt command).
> >
> >
> >>
> >>  I think we
> >> should consider punting on this one and looking for a more incremental
> >> strategy.  For instance, how about starting by moving the call
> >> 'add_llvm_external_project(compiler-rt)' from
> >> llvm/projects/CMakesLists.txt to clang/runtime?  We can tweak this
> >> macro (or a clang variant) to optionally do something like:
> >>
> >>     include(AddCompilerRt)
> >>
> >> That way if CMAKE_PREFIX_PATH includes a path to the compiler-rt
> >> install directory, it can import all the same build targets that would
> >> be created by add_subdirectory(compiler-rt).
> >
> >
> > Probably I don't understand how CMAKE_PREFIX_PATH works. How can
> top-level
> > targets from one build tree be visible in another build tree?
> >
> >>
> >>
> >> If I were to use CMake's ExternalProject feature, it would be from a
> >> top-level superproject.  I would use it to manage dependencies and to
> >> populate CMAKE_PREFIX_PATH for each dependency.  CMake, Make or a
> >> package manager, it wouldn't matter which you used for this part (I've
> >> used Make for this).  Ultimately, you want to end up with a top-level
> >> build that performs the following:
> >>
> >>     mkdir -p llvm/out && cd llvm/out
> >>     cmake .. -DCMAKE_INSTALL_PREFIX=ship
> >>     ninja check-all install
> >>     cd -
> >>
> >>     mkdir -p compiler-rt/out && cd compiler-rt/out
> >>     cmake .. -DCMAKE_PREFIX_PATH=`pwd`/../../llvm/out/ship
> >> -DCMAKE_INSTALL_PREFIX=ship
> >>     ninja check-all install
> >>     cd -
> >>
> >>     mkdir -p clang/out && cd clang/out
> >>     cmake ..
> >>
> -DCMAKE_PREFIX_PATH=`pwd`/../../llvm/out/ship:`pwd`/../../compiler-rt/out/ship
> >> -DCMAKE_INSTALL_PREFIX=ship
> >>     ninja check-all install
> >>     cd -
> >>
> >> In this scenario, the compiler-rt build creates a cmake module that
> >> clang includes.  It uses that cmake module to find the compiler-rt
> >> install targets and copy them into "lib/clang/<version>".  The clang
> >> build then calls 'add_subdirectory' on the compiler-rt 'test'
> >> directory, pointing it to the just-built-clang.  So the dependency
> >> tree for clang is:
> >>
> >>     sanitizer-tests -> clang -> compiler-rt -> c-compiler
> >
> >
> >
> > ... But we want to build compiler-rt libraries with just-built Clang as
> > well. This is what
> > Makefile-based build does, and what we can benefit from.
> >
> >>
> >>
> >> Thoughts?
> >>
> >> Thanks,
> >> Greg
> >>
> >>
> >> On Thu, Feb 27, 2014 at 1:19 AM, Alexey Samsonov <samsonov at google.com>
> >> wrote:
> >> >
> >> > On Wed, Feb 26, 2014 at 9:58 PM, Brad King <brad.king at kitware.com>
> >> > wrote:
> >> >>
> >> >> On 02/26/2014 12:43 PM, Alexey Samsonov wrote:
> >> >> > Do you think it makes sense to land my ExternalProject_Add patch
> >> >> > so that others can experiment with it? I can add quit with a
> >> >> > fatal_error/warning if the build tree rules are generated with
> Ninja.
> >> >>
> >> >> Since it is conditional on LLVM_BUILD_EXTERNAL_COMPILER_RT, yes.
> >> >
> >> >
> >> > Submitted as r202367.
> >> >
> >> >>
> >> >>
> >> >> > parallelism doesn't work when I run "make check-compiler-rt -j8"
> >> >> > in the original build tree, presumably because we call
> >> >> > "cd /path/to/compiler-rt/build/tree && make check-all" there.
> >> >>
> >> >> Right.  The ExternalProject module has a special case for the
> >> >> Makefile generators to make with $(MAKE) instead of "make":
> >> >>
> >> >>
> >> >>
> >> >>
> http://cmake.org/gitweb?p=cmake.git;a=blob;f=Modules/ExternalProject.cmake;hb=v2.8.12.2#l846
> >> >>
> >> >> so that flags like -j propagate automatically.  You could do
> >> >> that too:
> >> >>
> >> >>   if(CMAKE_GENERATOR MATCHES "Make")
> >> >>     set(check_compiler_rt "$(MAKE)" "check-all")
> >> >>   else()
> >> >>     set(check_compiler_rt ${CMAKE_COMMAND} --build .
> >> >>       --target check-all --config $<CONFIGURATION>)
> >> >>   endif()
> >> >>
> >> >>   ExternalProject_Get_Property(compiler-rt BINARY_DIR)
> >> >>   add_custom_target(check-compiler-rt
> >> >>     COMMAND ${check_compiler_rt}
> >> >>     DEPENDS compiler-rt
> >> >>     WORKING_DIRECTORY ${BINARY_DIR}
> >> >>     VERBATIM
> >> >>     )
> >> >>
> >> >
> >> > This worked, thanks! Currently I also print fatal_error message if I
> >> > detect
> >> > Ninja as a CMAKE_GENERATOR.
> >> >
> >> >
> >> > --
> >> > Alexey Samsonov, MSK
> >> >
> >> > _______________________________________________
> >> > LLVM Developers mailing list
> >> > LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> >> > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
> >> >
> >
> >
> >
> >
> > --
> > Alexey Samsonov, MSK
>



-- 
Alexey Samsonov, MSK
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140323/7cb8c577/attachment.html>


More information about the llvm-dev mailing list