<div dir="ltr">Hi Greg,<div class="gmail_extra"><br><div class="gmail_quote">On Fri, Mar 21, 2014 at 11:18 PM, 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:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">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></blockquote><div><br></div><div>Thanks for the great detailed explanations. I should check if we can simplify</div><div>clang - compiler-rt build systems relationship with this.</div><div><br></div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<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></blockquote><div><br></div><div>Could you elaborate on this? That's exactly what I'm trying to do now -</div><div>when I call "ExternalProject_Add(compiler-rt)" from Clang build tree, I</div>
<div>use just-built llvm-config to configure it, and set up the paths so that</div><div>"make compiler-rt" in compiler-rt build tree will build the libraries in the</div><div>proper locations, where Clang driver expects to find them. Maybe, I don't</div>
<div>understand what you mean when you say "monolithic build"</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
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.</blockquote><div><br></div><div>Why would one want to build LLVM from Clang and CompilerRT? My approach</div><div>is targeted at solving a very specific problem.</div><div> </div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> 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.</blockquote><div><br></div><div>What if we don't have stage0-clang, and use gcc as a host compiler?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
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.</blockquote><div><br></div><div>No, I want "use just-built clang" to be the default workflow. Currently, you</div><div>may use any host compiler to build compiler-rt sources (gcc, Clang, MSVC),</div>
<div>and we certainly want to keep it that way and not rely on some non-standard</div><div>or Clang-specific features. But we probably want to ship/release Clang with</div><div>a set of compiler-rt libraries that are built with *this* Clang. Again, one use case</div>
<div>when this can be necessary is targeting different platforms. For example, if</div><div>you use linux-x86 and you build LLVM/Clang capable of targeting both x86 and arm,</div><div>it certainly makes sense to build necessary compiler-rt libraries for all arches that Clang</div>
<div>can target. But you host compiler will most likely not be able to build arm version of</div><div>compiler-rt libs.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
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.</blockquote><div><br></div><div>As I mentioned earlier, it's enough to build clang, and use it to build compiler-rt</div><div>in a proper location, no futher steps will be necessary.</div><div> </div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> 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>
<span class="HOEnZb"><font color="#888888"><br>
-Greg<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
<br>
On Fri, Mar 21, 2014 at 3:59 AM, Alexey Samsonov <<a href="mailto:samsonov@google.com">samsonov@google.com</a>> wrote:<br>
> On Thu, Mar 20, 2014 at 10:12 PM, Greg Fitzgerald <<a href="mailto:garious@gmail.com">garious@gmail.com</a>> 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 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 make<br>
> it the default.<br>
><br>
> The problem is that we want top-level targets from compiler-rt build tree be<br>
> visible in the llvm/clang<br>
> top-level build tree. I thought this could be achieved by ugly 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 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>
>> -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 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>
>> >> <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>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div>Alexey Samsonov, MSK</div>
</div></div>