<div dir="ltr"><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Mar 25, 2014 at 6:36 AM, Greg Fitzgerald <span dir="ltr"><<a href="mailto:garious@gmail.com" target="_blank">garious@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Hi Alexey,<br>
<br>
> What if we don't have stage0-clang?<br>
<br>
I'd like to answer this question in detail.  I think if we're on the<br>
same page about which compiler to use to build CompilerRT and where it<br>
comes from, then the rest will, with any luck, fall into place.<br>
<br>
Here is a dependency diagram for building and running the sanitizer test suite:<br></blockquote><div><br></div><div>Why do you state that Clang depends on compiler-rt libs? Currently it doesn't:</div><div>compiler-rt libs are not necessary to link "clang" binary (as LLVM libs are).</div>
<div>фтв compiler-rt libs are optional in the sense that "clang" binary works perfectly fine if</div><div>they are missing (though not all of the features are supported).</div><div><br></div><div>IMO, the dependency diagram for sanitizer tests (in LLVM/Clang/compiler-rt build tree)</div>
<div>should be: <a href="http://yuml.me/27f7eca5">http://yuml.me/27f7eca5</a></div><div><br></div><div>It's also interesting that "sanitizer test suite" might be used as a standalone test suite</div><div>for any compiler with a gcc-style commandline-interface: <a href="http://yuml.me/e984f26f">http://yuml.me/e984f26f</a></div>
<div>In particular, we can use sanitizer test suite from compiler-rt repository</div><div>to test sanitizers in GCC (this can be done already, and we will probably perform such a</div><div>testing during the next merge of sanitizer runtimes to GCC).</div>
<div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<a href="http://yuml.me/0324b101" target="_blank">http://yuml.me/0324b101</a><br>
<br>
Note that it mentions 3 compilers: Clang, the C++ compiler used to<br>
build Clang, and a C++ cross-compiler used to build CompilerRT.  If no<br>
cross-compiler exists, we can bootstrap by building a Stage-0 Clang<br>
with a C++ compiler.  The full dependency diagram then becomes:<br>
<br>
<a href="http://yuml.me/2633fbbd" target="_blank">http://yuml.me/2633fbbd</a><br>
<br>
When a C++ cross-compiler already exists (either by building it or<br>
using clang-3.4), the dependency graph can be reduced by using the<br>
same compiler to build Clang, LLVM and CompilerRT:<br>
<br>
<a href="http://yuml.me/4b0473ae" target="_blank">http://yuml.me/4b0473ae</a><br>
<br>
<a href="http://yuml.me/9ff774bc" target="_blank">http://yuml.me/9ff774bc</a><br>
<br>
When building in this way, CompilerRT can expect the<br>
CMAKE_CXX_COMPILER to be a cross-compiler with the same command-line<br>
interface as Clang (cross-compile using -target and --sysroot flags).<br>
This Stage-0 compiler cannot be used to run the Sanitizer test suite.<br>
Instead, the Clang build should use add_subdirectory() to add the<br>
CompilerRT 'test' directory to its build.  No need for the CMake's<br>
ExternalProject feature.<br>
<span class=""><font color="#888888"><br>
-Greg<br>
</font></span><div class=""><div class="h5"><br>
<br>
On Sun, Mar 23, 2014 at 11:17 AM, Alexey Samsonov <<a href="mailto:samsonov@google.com">samsonov@google.com</a>> wrote:<br>
> Hi Greg,<br>
><br>
> On Fri, Mar 21, 2014 at 11:18 PM, Greg Fitzgerald <<a href="mailto:garious@gmail.com">garious@gmail.com</a>> wrote:<br>
>><br>
>> Hi Alexey,<br>
>><br>
>> CMAKE_PREFIX_PATH is a convenient mechanism for exposing prebuilt<br>
>> install directories to a CMake build.  It contains a colon-separated<br>
>> list of paths.  Each path points to a directory that contains<br>
>> directory names that are meaningful to CMake, including 'bin', 'lib'<br>
>> and 'share'.<br>
>><br>
>> If, for example, you want the path to 'llvm-config', instead of<br>
>> creating a new CMake variable, you instead write<br>
>> "find_program(LLVM_CONFIG_PATH llvm-config)".  CMake will search for<br>
>> an executable named 'llvm-config' in each 'bin' directory of each path<br>
>> in CMAKE_PREFIX_PATH.<br>
>><br>
>> In a simplest case, where there is only one dependency, using<br>
>> CMAKE_PREFIX_PATH means we do not have to standardize on a variable<br>
>> name.  For llvm-config, should it be LLVM_CONFIG_PATH or<br>
>> COMPILER_RT_LLVM_CONFIG_PATH?  In a component build, the former is<br>
>> sufficient, but in the monolithic build, it makes more sense to<br>
>> namespace every variable.  We can avoid painting that bike shed using<br>
>> CMAKE_PREFIX_PATH.<br>
>><br>
>> When one component has multiple dependencies from another, using<br>
>> CMAKE_PREFIX_PATH really starts saving keystrokes.  You can use it to<br>
>> find headers (sanitizer/asan_interface.h), binaries (FileCheck),<br>
>> libraries, or CMake modules.<br>
>><br>
>> A good alternative to CMAKE_PREFIX_PATH is to create one variable per<br>
>> install directory.  So compiler-rt might accept LLVM_INSTALL_DIR, and<br>
>> clang accept COMPILER_RT_INSTALL_DIR and LLVM_INSTALL_DIR.  There are<br>
>> two advantages to this route:<br>
>><br>
>> 1) No need for CMake features such as 'find_program'.  Instead, you<br>
>> can be explicit:<br>
>>     ${LLVM_INSTALL_DIR}/bin/llvm-config<br>
>> 2) No need to organize the install directory in any particular way.<br>
>> If a small component wants to combine its 'bin' and 'lib' directories<br>
>> into one top-level directory, that's no problem.<br>
>><br>
>> The disadvantage of this system is the need to standardize across<br>
>> components on a naming convention.  COMPILER_RT_DIR, COMPILER-RT_DIR,<br>
>> COMPILER_RT_INSTALL_DIR, COMPILER-RT_SHIP_DIR?  Ideally you'd only<br>
>> have to write "deps = llvm compiler-rt" and a package manager could<br>
>> automatically translate that to names that match the CMake options<br>
>> (LLVM_DIR, COMPILER_RT_DIR).  But like before, using CMAKE_PREFIX_PATH<br>
>> avoids the issue.<br>
><br>
><br>
> Thanks for the great detailed explanations. I should check if we can<br>
> simplify<br>
> clang - compiler-rt build systems relationship with this.<br>
><br>
>><br>
>><br>
>> Regarding the use of ExternalProject within Clang, I think it could<br>
>> create more problems than it solves.  For one, it can't be used from<br>
>> within the monolithic build (unless you have a duplicate llvm build,<br>
>> or point CompilerRT to a subset of the currently-building LLVM build).<br>
><br>
><br>
> Could you elaborate on this? That's exactly what I'm trying to do now -<br>
> when I call "ExternalProject_Add(compiler-rt)" from Clang build tree, I<br>
> use just-built llvm-config to configure it, and set up the paths so that<br>
> "make compiler-rt" in compiler-rt build tree will build the libraries in the<br>
> proper locations, where Clang driver expects to find them. Maybe, I don't<br>
> understand what you mean when you say "monolithic build"<br>
><br>
><br>
>><br>
>>  Secondly, it's not a general enough solution for other LLVM<br>
>> components.  Say, for example, you wanted to use ExternalProject to<br>
>> build LLVM from both Clang and CompilerRT.<br>
><br>
><br>
> Why would one want to build LLVM from Clang and CompilerRT? My approach<br>
> is targeted at solving a very specific problem.<br>
><br>
>><br>
>>  If the parameters passed<br>
>> to LLVM were identical, CMake could detect that and not build a<br>
>> duplicate copy.  If they parameters are different in any way, you have<br>
>> a problem.  Do you duplicate the build or flag an error?  We can avoid<br>
>> this issue by allowing a super-project or package manager build LLVM<br>
>> and pass its path to both Clang and CompilerRT.<br>
>><br>
>><br>
>> Regarding the use of just-built-clang for both building CompilerRT and<br>
>> running its test suite, please consider relaxing that to a<br>
>> stage0-clang for building and a just-built-clang for testing.<br>
><br>
><br>
> What if we don't have stage0-clang, and use gcc as a host compiler?<br>
><br>
>><br>
>>  Using<br>
>> the just-built-clang to build compiler-rt is rough on package<br>
>> managers.  You're basically stating that the compiler-rt build depends<br>
>> on some unreleased feature of clang to *build* compiler-rt.<br>
><br>
><br>
> No, I want "use just-built clang" to be the default workflow. Currently, you<br>
> may use any host compiler to build compiler-rt sources (gcc, Clang, MSVC),<br>
> and we certainly want to keep it that way and not rely on some non-standard<br>
> or Clang-specific features. But we probably want to ship/release Clang with<br>
> a set of compiler-rt libraries that are built with *this* Clang. Again, one<br>
> use case<br>
> when this can be necessary is targeting different platforms. For example, if<br>
> you use linux-x86 and you build LLVM/Clang capable of targeting both x86 and<br>
> arm,<br>
> it certainly makes sense to build necessary compiler-rt libraries for all<br>
> arches that Clang<br>
> can target. But you host compiler will most likely not be able to build arm<br>
> version of<br>
> compiler-rt libs.<br>
><br>
>><br>
>>  To a<br>
>> package manager, that means it should first build clang, then use that<br>
>> clang to build compiler-rt, and then build a version of clang that<br>
>> includes compiler-rt.<br>
><br>
><br>
> As I mentioned earlier, it's enough to build clang, and use it to build<br>
> compiler-rt<br>
> in a proper location, no futher steps will be necessary.<br>
><br>
>><br>
>>  It implies that every time there is a new<br>
>> commit to clang, compiler-rt should be rebuilt and retested.  If the<br>
>> compiler-rt build depended only a just-released-clang, then a commit<br>
>> to clang would imply only that the sanitizer tests should be rebuilt<br>
>> and tested.<br>
>><br>
>> -Greg<br>
>><br>
>><br>
>><br>
>> On Fri, Mar 21, 2014 at 3:59 AM, Alexey Samsonov <<a href="mailto:samsonov@google.com">samsonov@google.com</a>><br>
>> wrote:<br>
>> > On Thu, Mar 20, 2014 at 10:12 PM, Greg Fitzgerald <<a href="mailto:garious@gmail.com">garious@gmail.com</a>><br>
>> > wrote:<br>
>> >><br>
>> >> > ExternalProject_Add(compiler-rt ...)<br>
>> >><br>
>> >> So that was quite the experiment.  Looking at<br>
>> >> clang/runtime/CMakeLists.txt, I'm not seeing a lot of bang for buck<br>
>> >> here, and it looks like this file is prone to bit rot.<br>
>> ><br>
>> ><br>
>> > Could you please elaborate on this? In fact, I don't plan to give up on<br>
>> > this<br>
>> > experiment.<br>
>> > On the contrary, I wanted to move LLVM_BUILD_EXTERNAL_COMPILER_RT to the<br>
>> > bots, migrate the workflow of our team to use this mode, and eventually<br>
>> > make<br>
>> > it the default.<br>
>> ><br>
>> > The problem is that we want top-level targets from compiler-rt build<br>
>> > tree be<br>
>> > visible in the llvm/clang<br>
>> > top-level build tree. I thought this could be achieved by ugly<br>
>> > propagation<br>
>> > of top-level compiler-rt<br>
>> > targets with add_custom_target() command. (like I did this for<br>
>> > check-compiler-rt command).<br>
>> ><br>
>> ><br>
>> >><br>
>> >>  I think we<br>
>> >> should consider punting on this one and looking for a more incremental<br>
>> >> strategy.  For instance, how about starting by moving the call<br>
>> >> 'add_llvm_external_project(compiler-rt)' from<br>
>> >> llvm/projects/CMakesLists.txt to clang/runtime?  We can tweak this<br>
>> >> macro (or a clang variant) to optionally do something like:<br>
>> >><br>
>> >>     include(AddCompilerRt)<br>
>> >><br>
>> >> That way if CMAKE_PREFIX_PATH includes a path to the compiler-rt<br>
>> >> install directory, it can import all the same build targets that would<br>
>> >> be created by add_subdirectory(compiler-rt).<br>
>> ><br>
>> ><br>
>> > Probably I don't understand how CMAKE_PREFIX_PATH works. How can<br>
>> > top-level<br>
>> > targets from one build tree be visible in another build tree?<br>
>> ><br>
>> >><br>
>> >><br>
>> >> If I were to use CMake's ExternalProject feature, it would be from a<br>
>> >> top-level superproject.  I would use it to manage dependencies and to<br>
>> >> populate CMAKE_PREFIX_PATH for each dependency.  CMake, Make or a<br>
>> >> package manager, it wouldn't matter which you used for this part (I've<br>
>> >> used Make for this).  Ultimately, you want to end up with a top-level<br>
>> >> build that performs the following:<br>
>> >><br>
>> >>     mkdir -p llvm/out && cd llvm/out<br>
>> >>     cmake .. -DCMAKE_INSTALL_PREFIX=ship<br>
>> >>     ninja check-all install<br>
>> >>     cd -<br>
>> >><br>
>> >>     mkdir -p compiler-rt/out && cd compiler-rt/out<br>
>> >>     cmake .. -DCMAKE_PREFIX_PATH=`pwd`/../../llvm/out/ship<br>
>> >> -DCMAKE_INSTALL_PREFIX=ship<br>
>> >>     ninja check-all install<br>
>> >>     cd -<br>
>> >><br>
>> >>     mkdir -p clang/out && cd clang/out<br>
>> >>     cmake ..<br>
>> >><br>
>> >> -DCMAKE_PREFIX_PATH=`pwd`/../../llvm/out/ship:`pwd`/../../compiler-rt/out/ship<br>
>> >> -DCMAKE_INSTALL_PREFIX=ship<br>
>> >>     ninja check-all install<br>
>> >>     cd -<br>
>> >><br>
>> >> In this scenario, the compiler-rt build creates a cmake module that<br>
>> >> clang includes.  It uses that cmake module to find the compiler-rt<br>
>> >> install targets and copy them into "lib/clang/<version>".  The clang<br>
>> >> build then calls 'add_subdirectory' on the compiler-rt 'test'<br>
>> >> directory, pointing it to the just-built-clang.  So the dependency<br>
>> >> tree for clang is:<br>
>> >><br>
>> >>     sanitizer-tests -> clang -> compiler-rt -> c-compiler<br>
>> ><br>
>> ><br>
>> ><br>
>> > ... But we want to build compiler-rt libraries with just-built Clang as<br>
>> > well. This is what<br>
>> > Makefile-based build does, and what we can benefit from.<br>
>> ><br>
>> >><br>
>> >><br>
>> >> Thoughts?<br>
>> >><br>
>> >> Thanks,<br>
>> >> Greg<br>
>> >><br>
>> >><br>
>> >> On Thu, Feb 27, 2014 at 1:19 AM, Alexey Samsonov <<a href="mailto:samsonov@google.com">samsonov@google.com</a>><br>
>> >> wrote:<br>
>> >> ><br>
>> >> > On Wed, Feb 26, 2014 at 9:58 PM, Brad King <<a href="mailto:brad.king@kitware.com">brad.king@kitware.com</a>><br>
>> >> > wrote:<br>
>> >> >><br>
>> >> >> On 02/26/2014 12:43 PM, Alexey Samsonov wrote:<br>
>> >> >> > Do you think it makes sense to land my ExternalProject_Add patch<br>
>> >> >> > so that others can experiment with it? I can add quit with a<br>
>> >> >> > fatal_error/warning if the build tree rules are generated with<br>
>> >> >> > Ninja.<br>
>> >> >><br>
>> >> >> Since it is conditional on LLVM_BUILD_EXTERNAL_COMPILER_RT, yes.<br>
>> >> ><br>
>> >> ><br>
>> >> > Submitted as r202367.<br>
>> >> ><br>
>> >> >><br>
>> >> >><br>
>> >> >> > parallelism doesn't work when I run "make check-compiler-rt -j8"<br>
>> >> >> > in the original build tree, presumably because we call<br>
>> >> >> > "cd /path/to/compiler-rt/build/tree && make check-all" there.<br>
>> >> >><br>
>> >> >> Right.  The ExternalProject module has a special case for the<br>
>> >> >> Makefile generators to make with $(MAKE) instead of "make":<br>
>> >> >><br>
>> >> >><br>
>> >> >><br>
>> >> >><br>
>> >> >> <a href="http://cmake.org/gitweb?p=cmake.git;a=blob;f=Modules/ExternalProject.cmake;hb=v2.8.12.2#l846" target="_blank">http://cmake.org/gitweb?p=cmake.git;a=blob;f=Modules/ExternalProject.cmake;hb=v2.8.12.2#l846</a><br>

>> >> >><br>
>> >> >> so that flags like -j propagate automatically.  You could do<br>
>> >> >> that too:<br>
>> >> >><br>
>> >> >>   if(CMAKE_GENERATOR MATCHES "Make")<br>
>> >> >>     set(check_compiler_rt "$(MAKE)" "check-all")<br>
>> >> >>   else()<br>
>> >> >>     set(check_compiler_rt ${CMAKE_COMMAND} --build .<br>
>> >> >>       --target check-all --config $<CONFIGURATION>)<br>
>> >> >>   endif()<br>
>> >> >><br>
>> >> >>   ExternalProject_Get_Property(compiler-rt BINARY_DIR)<br>
>> >> >>   add_custom_target(check-compiler-rt<br>
>> >> >>     COMMAND ${check_compiler_rt}<br>
>> >> >>     DEPENDS compiler-rt<br>
>> >> >>     WORKING_DIRECTORY ${BINARY_DIR}<br>
>> >> >>     VERBATIM<br>
>> >> >>     )<br>
>> >> >><br>
>> >> ><br>
>> >> > This worked, thanks! Currently I also print fatal_error message if I<br>
>> >> > detect<br>
>> >> > Ninja as a CMAKE_GENERATOR.<br>
>> >> ><br>
>> >> ><br>
>> >> > --<br>
>> >> > Alexey Samsonov, MSK<br>
>> >> ><br>
>> >> > _______________________________________________<br>
>> >> > LLVM Developers mailing list<br>
>> >> > <a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
>> >> > <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
>> >> ><br>
>> ><br>
>> ><br>
>> ><br>
>> ><br>
>> > --<br>
>> > Alexey Samsonov, MSK<br>
><br>
><br>
><br>
><br>
> --<br>
> Alexey Samsonov, MSK<br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div>Alexey Samsonov, MSK</div>
</div></div>