[LLVMdev] compiler-rt CMake build

Alexey Samsonov samsonov at google.com
Tue Mar 25 06:24:47 PDT 2014


On Tue, Mar 25, 2014 at 4:57 PM, Alexey Samsonov <samsonov at google.com>wrote:

>
>
> On Tue, Mar 25, 2014 at 6:36 AM, Greg Fitzgerald <garious at gmail.com>wrote:
>
>> Hi Alexey,
>>
>> > What if we don't have stage0-clang?
>>
>> I'd like to answer this question in detail.  I think if we're on the
>> same page about which compiler to use to build CompilerRT and where it
>> comes from, then the rest will, with any luck, fall into place.
>>
>> Here is a dependency diagram for building and running the sanitizer test
>> suite:
>>
>
> Why do you state that Clang depends on compiler-rt libs? Currently it
> doesn't:
> compiler-rt libs are not necessary to link "clang" binary (as LLVM libs
> are).
> фтв compiler-rt libs are optional in the sense that "clang" binary works
> perfectly fine if
> they are missing (though not all of the features are supported).
>

Sorry, I meant "and compiler-rt libs are optional".


>
> IMO, the dependency diagram for sanitizer tests (in LLVM/Clang/compiler-rt
> build tree)
> should be: http://yuml.me/27f7eca5
>
> It's also interesting that "sanitizer test suite" might be used as a
> standalone test suite
> for any compiler with a gcc-style commandline-interface:
> http://yuml.me/e984f26f
> In particular, we can use sanitizer test suite from compiler-rt repository
> to test sanitizers in GCC (this can be done already, and we will probably
> perform such a
> testing during the next merge of sanitizer runtimes to GCC).
>
>
> http://yuml.me/0324b101
>>
>> Note that it mentions 3 compilers: Clang, the C++ compiler used to
>> build Clang, and a C++ cross-compiler used to build CompilerRT.  If no
>> cross-compiler exists, we can bootstrap by building a Stage-0 Clang
>> with a C++ compiler.  The full dependency diagram then becomes:
>>
>> http://yuml.me/2633fbbd
>>
>> When a C++ cross-compiler already exists (either by building it or
>> using clang-3.4), the dependency graph can be reduced by using the
>> same compiler to build Clang, LLVM and CompilerRT:
>>
>> http://yuml.me/4b0473ae
>>
>> http://yuml.me/9ff774bc
>>
>> When building in this way, CompilerRT can expect the
>> CMAKE_CXX_COMPILER to be a cross-compiler with the same command-line
>> interface as Clang (cross-compile using -target and --sysroot flags).
>> This Stage-0 compiler cannot be used to run the Sanitizer test suite.
>> Instead, the Clang build should use add_subdirectory() to add the
>> CompilerRT 'test' directory to its build.  No need for the CMake's
>> ExternalProject feature.
>>
>> -Greg
>>
>>
>> On Sun, Mar 23, 2014 at 11:17 AM, Alexey Samsonov <samsonov at google.com>
>> wrote:
>> > 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
>>
>
>
>
> --
> Alexey Samsonov, MSK
>



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


More information about the llvm-dev mailing list