compiler-rt CMake build

Regarding Brad King's CMake patches for LLVM:

  http://thread.gmane.org/gmane.comp.compilers.llvm.cvs/173517

If compiler-rt could follow suit, the packaging for the toolchain
becomes a nice, clean package-manager-friendly DAG. Currently, the
compiler-rt CMake build depends on the just-built-clang to run its
test suite. It's more intuitive to me that either:

1) compiler-rt's sanitizer tests would live inside the clang project
2) compiler-rt would export a test suite that clang could optionally import

The former is simpler, but the latter allows the compiler-rt
developers to retain control over those tests, which are typically
updated alongside changes to compiler-rt's sanitizers. Thoughts?

Thanks,
Greg

Regarding Brad King's CMake patches for LLVM:

  http://thread.gmane.org/gmane.comp.compilers.llvm.cvs/173517

If compiler-rt could follow suit, the packaging for the toolchain
becomes a nice, clean package-manager-friendly DAG. Currently, the
compiler-rt CMake build depends on the just-built-clang to run its
test suite. It's more intuitive to me that either:

1) compiler-rt's sanitizer tests would live inside the clang project
2) compiler-rt would export a test suite that clang could optionally
import

The former is simpler, but the latter allows the compiler-rt
developers to retain control over those tests, which are typically
updated alongside changes to compiler-rt's sanitizers. Thoughts?

I'm pretty sure the compiler-rt tests should live in the compiler-rt
project. You're right:
these tests should generally be updated in sync with the runtimes. I'm fine
with creating
a large test suite comprising all individual tool-specific test suites we
have now. I'm not
sure how we can "export" this to clang, though, and why the current
situation is bad.

The trouble is that the sanitizer tests are not really compiler-rt
tests. The original compiler-rt tests are, but not the sanitizer
tests. The sanitizer tests are "compiler-rt tests via clang". The
sanitizer runtime is a C++ library requiring only a C++ compiler to
build it (and to *unit* test it). The ASan lit tests, however,
require clang, because they are testing those C++ functions in the
context of a particular C/C++ compiler's instrumentation. I believe
these tests should not be called "compiler-rt tests". They are clang
tests. In fact, they are just-built-clang tests. They don't, for
example, verify the C++ library is useful to another compiler, another
version of clang, or simply as a C++ library. They are integration
tests (tests clang+asan), as opposed to unit tests (tests only the
asan runtime).

I understand that the integration tests are more relevant to the
sanitizers than they are clang, and so it make sense to me that they
reside in the compiler-rt repo alongside the sanitizers. But rather
than build them in the compiler-rt build, I think the directory should
be exported so that clang can optionally import it. The clang build
can then add those tests to the clang tests suite, and install the
runtime in whatever location is most appropriate for clang.

Why is this important now? The CMake developers are trying to make
the LLVM toolchain easy to build for package managers. Compiler-rt's
dependency on the just-built-clang makes that difficult. Without that
dependency, Compiler-rt could be built and tested against only an LLVM
package. And likewise, a Clang package would depend on Compiler-rt
(and do further testing on compiler-rt with those lit tests). But
with the dependency on the just-built-clang, there needs to be an
additional top-level package, let's call it ClangAndFriends.
ClangAndFriends would depend on Clang and Compiler-rt. Compiler-rt
would depend on the Clang package as well. Once both are built,
ClangAndFriends would copy the Clang install directory and then copy
the Compiler-rt install directory into it. This extra package and
extra copy would be unnecessary if the Compiler-rt build dropped its
dependency on the just-built-clang. After testing the sanitizers, the
Clang package would copy the runtime into its own install directory.

So what next? Wait for Brad King's LLVM patches to be integrated.
Then we tweak the compiler-rt build to optionally build against the
LLVM install directory (instead of in the context of the LLVM source
directory). Next, we use CMake to export the Sanitizer lit tests.
Lastly, Clang optionally imports the test suite and adds the sanitizer
runtime to its install directory. What do you think? Squeaky clean?

Thanks,
Greg

Hi Greg,

This is possible with CMake using the ExternalProject module:

http://www.cmake.org/cmake/help/v2.8.12/cmake.html#module:ExternalProject

The add_llvm_external_project macro already in LLVM could be taught
to call ExternalProject_Add instead of add_subdirectory. This could
create a custom target with dependencies appropriately configured to
build after Clang. The custom target would run CMake to configure the
project like an outside build and then launch the build.

IIUC there is a desire for Clang to be able to be built externally to
LLVM rather than subsumed into its build process. The top-level
CMakeLists.txt file of Clang already has code to do that, though it
can be much cleaner after my patches to LLVM to provide LLVMConfig.cmake
are integrated. Then it will even be possible to build Clang using
CMake against a LLVM that was built and installed using configure+make.

If one would like to drive compiler-rt as part of testing a Clang built
outside of LLVM then the appropriate place for the ExternalProject_Add
call would be inside the build of Clang.

Either way, from a quick glance at the top-level CMakeLists.txt file
in compiler-rt it appears to want to know a bunch of information about
Clang rather than LLVM. In this case having Clang export enough info
for applications to write find_package(Clang) would make sense. This
is possible to do an can be implemented using techniques similar to
that in my proposed LLVMConfig.cmake patch series.

-Brad

Please note that it makes a lot of sense to built compiler-rt (and sanitizers) with just-built
Clang. In fact, even though we should support building it with another compilers (gcc, MSVC),
using just-built-Clang should be a default scenario, like it is in configure+make build.

This is possible with CMake using the ExternalProject module:

http://www.cmake.org/cmake/help/v2.8.12/cmake.html#module:ExternalProject

The add_llvm_external_project macro already in LLVM could be taught
to call ExternalProject_Add instead of add_subdirectory. This could
create a custom target with dependencies appropriately configured to
build after Clang. The custom target would run CMake to configure the
project like an outside build and then launch the build.

IIUC there is a desire for Clang to be able to be built externally to
LLVM rather than subsumed into its build process. The top-level
CMakeLists.txt file of Clang already has code to do that, though it
can be much cleaner after my patches to LLVM to provide LLVMConfig.cmake
are integrated. Then it will even be possible to build Clang using
CMake against a LLVM that was built and installed using configure+make.

If one would like to drive compiler-rt as part of testing a Clang built
outside of LLVM then the appropriate place for the ExternalProject_Add
call would be inside the build of Clang.

Look like what we need to build compiler-rt. Actually the makefile responsible to launch the compiler-rt build is in clang/runtime/compiler-rt.
Using ExternalProject_Add, we can probably add the CMake part beside that existing file, so everything will be at the same place.

Either way, from a quick glance at the top-level CMakeLists.txt file
in compiler-rt it appears to want to know a bunch of information about
Clang rather than LLVM. In this case having Clang export enough info
for applications to write find_package(Clang) would make sense. This
is possible to do an can be implemented using techniques similar to
that in my proposed LLVMConfig.cmake patch series.

-Brad

_______________________________________________
LLVM Developers mailing list
LLVMdev@cs.uiuc.edu http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev

-- Jean-Daniel

>> Please note that it makes a lot of sense to built compiler-rt (and
sanitizers) with just-built
>> Clang. In fact, even though we should support building it with another
compilers (gcc, MSVC),
>> using just-built-Clang should be a default scenario, like it is in
configure+make build.
>
> This is possible with CMake using the ExternalProject module:
>
>
http://www.cmake.org/cmake/help/v2.8.12/cmake.html#module:ExternalProject
>
> The add_llvm_external_project macro already in LLVM could be taught
> to call ExternalProject_Add instead of add_subdirectory. This could
> create a custom target with dependencies appropriately configured to
> build after Clang. The custom target would run CMake to configure the
> project like an outside build and then launch the build.
>
> IIUC there is a desire for Clang to be able to be built externally to
> LLVM rather than subsumed into its build process. The top-level
> CMakeLists.txt file of Clang already has code to do that, though it
> can be much cleaner after my patches to LLVM to provide LLVMConfig.cmake
> are integrated. Then it will even be possible to build Clang using
> CMake against a LLVM that was built and installed using configure+make.
>
> If one would like to drive compiler-rt as part of testing a Clang built
> outside of LLVM then the appropriate place for the ExternalProject_Add
> call would be inside the build of Clang.

Look like what we need to build compiler-rt. Actually the makefile
responsible to launch the compiler-rt build is in clang/runtime/compiler-rt.
Using ExternalProject_Add, we can probably add the CMake part beside that
existing file, so everything will be at the same place.

OK, I feel like I need to learn more about ExternalProject_Add magic. I
have a few
quick questions for people with knowledge - currently:
1) "compiler-rt"'s CMake needs to know about targets in the Clang build
tree ("clang") and
in LLVM build tree ("FileCheck", llvm-* command-line tools, googletest
etc.), and uses common
macro from LLVM's CMake modules like "configute_lit_site_cfg",
"parse_arguments".
2) top-level targets from compiler-rt's CMake files are visible at the root
of LLVM's build tree,
so that I can run "make check-asan" or even "make clang_rt.asan-x86_64"
from the root of
the build tree.

Will we easily retain all these capabilities if we turn compiler-rt into an
external project?

OK, I feel like I need to learn more about ExternalProject_Add magic.

It is the CMake equivalent to a configure+make build target that
runs configure+make for another project.

I have a few quick questions for people with knowledge - currently:
1) "compiler-rt"'s CMake needs to know about targets in the Clang build tree ("clang") and
in LLVM build tree ("FileCheck", llvm-* command-line tools, googletest etc.), and uses common
macro from LLVM's CMake modules like "configute_lit_site_cfg", "parse_arguments".

This will be possible once LLVM and Clang are taught to provide proper
content in LLVMConfig.cmake and ClangConfig.cmake package configuration
files. The patch series I proposed in the thread Greg linked at the
start of this thread is the first step to do that.

2) top-level targets from compiler-rt's CMake files are visible at the root of LLVM's build tree,
so that I can run "make check-asan" or even "make clang_rt.asan-x86_64" from the root of
the build tree.

This would not work with ExternalProject_Add because the CMake
running on LLVM or Clang would not see the targets in compiler-rt
since the project will not even be processed until build (make) time.
In return the compiler-rt would be able to build using the just-built
Clang because it will now be available when CMake runs on compiler-rt.
(IIUC this is currently the case for configure+make.) Also compiler-rt
could now be built outside of a LLVM/Clang that was built unaware of
compiler-rt.

It is also possible to make project/compiler-rt build optionally
with add_subdirectory instead of ExternalProject_Add, as it does now,
with the cost of not using the just-built Clang.

-Brad

I see the benefit in using just-built Clang, but it's a pity to lose the
ability to
add convenient top-level targets from compiler-rt project. It also means
that we'd need to add "fake" top-level custom targets (that would configure

Just to try and share some perspective of developers on Clang and LLVM...

IIUC there is a desire for Clang to be able to be built externally to
LLVM rather than subsumed into its build process. The top-level
CMakeLists.txt file of Clang already has code to do that, though it
can be much cleaner after my patches to LLVM to provide LLVMConfig.cmake
are integrated.

While there is a strong desire to do this by some developers, it is purely
for pragmatic reasons: it makes their builds *significantly* faster because
xcode doesn't load the entire project, etc.

I don't believe there is *any* interest in breaking the hard version lock
between LLVM and Clang. We rely on that heavily, and it's likely never
going away.

I think the default and expected build mode should still be a merged tree
where the bits and pieces desired are checked out into an LLVM checkout,
and the build system can handle whatever partial build there is provided
the dependencies are in place.

Then it will even be possible to build Clang using
CMake against a LLVM that was built and installed using configure+make.

I actually doubt that this is a particularly interesting build
configuration. Perhaps it is for distributions or packagers, but frankly, I
expect it to bitrot immediately. I don't think any devs will realistically
use it. Maybe I'm wrong though...

At best, we would have some buildbots using this configuration (we could switch existing onces to this scheme).

I don't think we need it for clang, but many external projects would like to use cmake to build against LLVM as installed by debian e.g. In this case, it is great if even an autoconf installation of LLVM provides the relevant cmake pieces.

Cheers,
Tobias

While there is a strong desire to do this by some developers, it is purely
for pragmatic reasons

[snip]

I think the default and expected build mode should still be a merged tree

Okay, thanks for the clarification.

Hi Brad,

I have a few questions regarding ExternalProject_Add. For me it doesn’t really work as expected.
I add the following code to the tools/clang/runtime/CMakeLists.txt to configure compiler-rt as external project:

ExternalProject_Add(compiler-rt
#DEPENDS clang clang++ llvm-config
PREFIX ${CMAKE_BINARY_DIR}/projects/compiler-rt
SOURCE_DIR ${COMPILER_RT_SRC_ROOT}
CMAKE_ARGS -DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang
-DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++
-DCMAKE_BUILD_TYPE=Release
-DLLVM_CONFIG_PATH=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-config
-DCOMPILER_RT_OUTPUT_DIR=${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}
-DCOMPILER_RT_INSTALL_PATH=lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}

-DCOMPILER_RT_INCLUDE_TESTS=ON

INSTALL_COMMAND “”
)
add_dependencies(compiler-rt clang clang++ llvm-config)

  1. Looks like “DEPENDS” option is just broken - docs here (http://www.kitware.com/media/html/BuildingExternalProjectsWithCMake2.8.html)
    state that you can pass CMake targets there, but if I uncomment that line, I get errors like:

CMake Error at /usr/local/share/cmake-2.8/Modules/ExternalProject.cmake:720 (message):
External project “clang” has no stamp_dir
Call Stack (most recent call first):
/usr/local/share/cmake-2.8/Modules/ExternalProject.cmake:932 (ExternalProject_Get_Property)
/usr/local/share/cmake-2.8/Modules/ExternalProject.cmake:1488 (_ep_get_step_stampfile)
/usr/local/share/cmake-2.8/Modules/ExternalProject.cmake:1702 (_ep_add_configure_command)
tools/clang/runtime/CMakeLists.txt:18 (ExternalProject_Add)

as if “clang” was supposed to be another external project. FTR, I use cmake 2.8.10.2.

  1. The dependencies don’t act as expected: if I run “make compiler-rt”, it builds Clang, uses it to configure
    compiler-rt and builds compiler-rt. But if I then change the Clang sources, and re-run “make compiler-rt”,
    Clang is re-built, but compiler-rt is not re-configured or re-built, while I definitely want this.

  2. The same doc (http://www.kitware.com/media/html/BuildingExternalProjectsWithCMake2.8.html) states that
    “One drawback, however, is ExternalProject’s lack of full dependency analysis. Changes in header files of an external project may
    not cause an incremental rebuild of the affected sources that depend on those headers.”

Looks like even if I modify sources under projects/compiler-rt, and re-run “make compiler-rt” from the build
directory, it doesn’t re-build the compiler-rt libraries. This makes incremental development simply impossible.

What am I doing wrong?

Hm, this thread: http://cmake.3232098.n2.nabble.com/ExternalProject-Add-Automatic-Incremental-Rebuilds-Add-Sources-to-IDE-td7585544.html
suggests that ExternalProject is not good at all for tracking source file changes, and suggests to use add_subdirectory approach and pass
information around in variables. Looks like we just can’t express rules like “use this just-built compiler to build those libraries” in terms of CMake sigh
We can try to configure new build trees with CMake manually, though, similar to the way it’s done in add_tablegen() macro.

1) Looks like "DEPENDS" option is just broken
I use cmake 2.8.10.2.

Dependencies on normal targets were accidentally broken in 2.8.9 and
later fixed in 2.8.11 (along with a test case to keep it working):

http://www.cmake.org/Bug/view.php?id=13849
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c0f1af92

if I then change the Clang sources, and re-run "make compiler-rt",
Clang is re-built, but compiler-rt is *not* re-configured or re-built

[snip]

even if I modify *sources* under projects/compiler-rt
it doesn't re-build the compiler-rt libraries.

ExternalProject was originally designed for two purposes:

* Build third-party dependences on which local development will
  not be done

* Manage a "superbuild" project that has no binaries of its own
  but has a bunch of ExternalProject_Add calls to drive set up
  of a bunch of build trees. Local development then occurs in
  each tree manually.

Using ExternalProject for a recursive-make-like structure was
only later proposed as a use case. In order to make the build
step always run you need to make it depend on an extra step that
is always out of date:

ExternalProject_Add_Step(compiler-rt always-build
  COMMENT "Always building MyCOnly..."
  DEPENDERS build
  ALWAYS 1
  )

-Brad

Using ExternalProject for a recursive-make-like structure was
only later proposed as a use case. In order to make the build
step always run you need to make it depend on an extra step that
is always out of date:

ExternalProject_Add_Step(compiler-rt always-build
  COMMENT "Always building MyCOnly..."

s/MyCOnly/compiler-rt/

  DEPENDERS build
  ALWAYS 1
  )

In order to simplify this in the future, I've looked at adding
a BUILD_ALWAYS option to ExternalProject_Add:

ExternalProject: Add option to always run the build step
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=73e5c6ae

This would allow one to request that the external build step run
on every build of the main project without adding an extra step
manually.

-Brad

> 1) Looks like "DEPENDS" option is just broken
> I use cmake 2.8.10.2.

Dependencies on normal targets were accidentally broken in 2.8.9 and
later fixed in 2.8.11 (along with a test case to keep it working):

http://www.cmake.org/Bug/view.php?id=13849
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c0f1af92

> if I then change the Clang sources, and re-run "make compiler-rt",
> Clang is re-built, but compiler-rt is *not* re-configured or re-built
[snip]
> even if I modify *sources* under projects/compiler-rt
> it doesn't re-build the compiler-rt libraries.

ExternalProject was originally designed for two purposes:

* Build third-party dependences on which local development will
  not be done

* Manage a "superbuild" project that has no binaries of its own
  but has a bunch of ExternalProject_Add calls to drive set up
  of a bunch of build trees. Local development then occurs in
  each tree manually.

Using ExternalProject for a recursive-make-like structure was
only later proposed as a use case. In order to make the build
step always run you need to make it depend on an extra step that
is always out of date:

ExternalProject_Add_Step(compiler-rt always-build
  COMMENT "Always building MyCOnly..."
  DEPENDERS build
  ALWAYS 1
  )

Great, thanks for suggestion! We can even use "DEPENDERS configure" instead
of "DEPENDERS build" here.

And we'd better "clobber" the compiler-rt build tree if any of the
dependencies change (we need to rebuild
every compiler-rt source from scratch if clang has changed).

I will also try to add support for running tests in compiler-rt build tree.
I think this can be achieved by smth. like:
add_custom_target(check-compiler-rt
  COMMAND ${CMAKE_BUILD_TOOL} check-all
  DEPENDS compiler-rt
  WORKING_DIRECTORY ${COMPILER_RT_BUILD_DIR})

Just "build" should be sufficient because the generated build system
in compiler-rt knows how to re-run CMake if any of the inputs have
changed. This is just as you do not need to re-run "cmake ." by hand
after editing CMakeLists.txt and can just type "make".

-Brad

> We can even use "DEPENDERS configure" instead of "DEPENDERS build" here.

Just "build" should be sufficient because the generated build system
in compiler-rt knows how to re-run CMake if any of the inputs have
changed. This is just as you do not need to re-run "cmake ." by hand
after editing CMakeLists.txt and can just type "make".

I am not convinced. Suppose LLVMConfig.cmake (which we read in standalone
compiler-rt build system) has changed.
Then we should re-run cmake for standalone compiler-rt even though none of
its cmake or source files was changed.

Could you take a look if http://llvm-reviews.chandlerc.com/D2868 looks
reasonable?

    Just "build" should be sufficient because the generated build system
    in compiler-rt knows how to re-run CMake if any of the inputs have
    changed.

Suppose LLVMConfig.cmake has changed.

Every file CMake processes as part of configuring the project ends up in
the build-time dependencies to re-run CMake.

Could you take a look if http://llvm-reviews.chandlerc.com/D2868 looks reasonable?

It looks pretty good to me. I added some inline comments.

-Brad