2

TLDR

I want to build the LLVM project monorepo as a subdirectory to a larger CMake project. But the usual paradigm of add_subdirectory(llvm-project/llvm) doesn't give the desired results. How can I add LLVM to my CMake project so that building the project also builds LLVM?

Background

I have project tree that looks like this (some files and subdirectories omitted for brevity) :

.
├── build/
├── CMakeLists.txt
├── cunit/
│   ├── CUnit/
│   │   └── CMakeLists.txt
│   └── CMakeLists.txt
├── hayai/
│   └── CMakeLists.txt
├── install/
├── llvm-project/
│   ├── clang/
│   ├── clang-tools-extra/
│   ├── compiler-rt/
│   ├── debuginfo-tests/
│   ├── libcxx/
│   ├── libcxxabi/
│   ├── libunwind/
│   ├── lld/
│   ├── lldb/
│   ├── llvm/
│   │   └── CMakeLists.txt
│   ├── openmp/
│   └── polly/
└── mylib/
    └── CMakeLists.txt

As you can see, I have four subdirectories, all of which are CMake projects in their own right, and all of which build individually with no problems. Both CUnit and Hayai are unmodified. Mylib is the product of my research, and uses CUnit and Hayai as git submodules/dependencies. I have also modified the LLVM Project monorepo to use Mylib for instrumentation as part of my research, but it builds on its own. I would like to unify all four of these subprojects as one CMake-driven build.

The content of the top-level CMakeLists.txt is:

cmake_minimum_required(VERSION 3.2)
project (myproject)
set(CMAKE_BUILD_TYPE Debug)

add_subdirectory(cunit/CUnit)
add_subdirectory(hayai)
add_subdirectory(mylib)
add_subdirectory(llvm-project/llvm)

Problem

When I try to generate the build using the following command:

cd build
cmake .. -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=Debug -DBUILD_HAYAI_SAMPLES=false -DBUILD_HAYAI_TESTS=false

I get an error from CMake once it recurses into the LLVM subproject (shortened for brevity):

-- LLVM host triple: x86_64-unknown-linux-gnu
-- LLVM default target triple: x86_64-unknown-linux-gnu
-- Building with -fPIC
-- Constructing LLVMBuild project information
-- Linker detection: GNU ld
CMake Error: File ./llvm-project/llvm/include/llvm/module.modulemap.build does not exist.
CMake Error at ./llvm-project/llvm/include/llvm/CMakeLists.txt:7 (configure_file):
  configure_file Problem configuring file


-- Targeting AArch64
-- Targeting AMDGPU
-- Targeting ARM
-- Targeting BPF
-- Targeting Hexagon
-- Targeting Lanai
-- Targeting Mips
-- Targeting MSP430
-- Targeting NVPTX
-- Targeting PowerPC
-- Targeting Sparc
-- Targeting SystemZ
-- Targeting X86
-- Targeting XCore
-- Configuring incomplete, errors occurred!
See also "./build/CMakeFiles/CMakeOutput.log".
See also "./build/CMakeFiles/CMakeError.log".

llvm-project/llvm/include/llvm/CMakeLists.txt contains:

add_subdirectory(IR)
add_subdirectory(Support)

# If we're doing an out-of-tree build, copy a module map for generated
# header files into the build area.
if (NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
  configure_file(module.modulemap.build module.modulemap COPYONLY)
endif (NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")

I checked the two files at the end of the output, but neither had messages relevant to the problem.

Questions

  • What does the error from CMake really mean? Why doesn't module.modulemap.build exist, or more accurately, why does it exist when building just LLVM?
  • How can I fix this so that my top level project can build all four subprojects?

Potentially Related

  • This StackOverflow question asks a similar question using a lot of the same keywords, but has a different task in mind: she/he wants to link to libraries from an existing LLVM build, not build LLVM itself.
  • Likewise this StackOverflow question and the accepted answer's reference to this LLVM documentation page is about embedding LLVM libraries out of tree into a standalone project. It's not quite what I want since I need to build my entire modified LLVM compiler toolchain.
  • This llvm-dev mailing list thread sounds like exactly what I'm doing, but the suggested answer doesn't work, as stated above.
Matthew Cole
  • 602
  • 5
  • 21
  • 1
    "What does the error from CMake really mean?" - Message `File ./llvm-project/llvm/include/llvm/module.modulemap.build does not exist` obviously means that given file doesn't exist or CMake cannot access it for some reason. Have you checked existence of this file on your machine? (It should be near `llvm-project/llvm/include/llvm/CMakeLists.txt` script which you show us). – Tsyvarev Aug 01 '19 at 08:02
  • 1
    From what I though LLVM is meant to be a CMake project itself, so I don't know how ready it is to become a simple "subdirectory". On top of that, LLVM has lots of CMake machinery, that could make addressing this issue really hard. Did you consider adding your project inside the LLVM CMake? Did you know you can isolate other CMake projects with [CMake External Projects](https://cmake.org/cmake/help/latest/module/ExternalProject.html)? – Daniel Otero Aug 01 '19 at 09:04
  • 1
    Just a wild guess: could you try adding it as `add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/llvm-project/llvm)`. This is the only difference I see from my project, in which it works just fine. Also, which version/commit of LLVM do you use? – AlexDenisov Aug 01 '19 at 11:50
  • @AlexDenisov I tried it, but the "module.modulemap.build does not exist" error persists. Thanks for the suggestion though! – Matthew Cole Aug 01 '19 at 15:03
  • @Tsyvarev I understand the high-level meaning of the error message. What I don't fully understand is that when I build LLVM independently, prior to CMake generating its build, module.modulemap.build doesn't exist (the same as my problem), but no error is raised. It exists after generation at the specified path, and CMake is ready to build. Although I see the clear difference, I don't understand why there is a difference between the "LLVM alone" build and my "LLVM as a subproject" build. I'd appreciate any followup you might have. – Matthew Cole Aug 01 '19 at 15:33
  • @DanielOtero, I was not previously aware of the CMake ExternalProject facilities, but it looks promising. I'll take a look at the manual page for it, and I also have a copy of the official Kitware book. The only problem I foresee is that in this case, `llvm-project/` isn't an external project, strictly speaking. I've modified LLVM 8.0, especially in the architecture-specific backend components. It's not something that a user would download from the canonical LLVM repository because of those changes. I'm providing the changed codebase through my repository under the LLVM license. – Matthew Cole Aug 01 '19 at 15:38
  • @AlexDenisov also, I noticed your request for my CMake version. It's 3.10.2, provided through the apt package manager for Ubuntu 18.04 Bionic. – Matthew Cole Aug 01 '19 at 15:40
  • 1
    So file `./llvm-project/llvm/include/llvm/module.modulemap.build` **actually** doesn't exist. This is strange by itself, because the file [exists in the repo](https://github.com/llvm/llvm-project/blob/master/llvm/include/llvm/module.modulemap.build). Note, that `configure_file` isn't called in case of **in-source builds** (when CMAKE_SOURCE_DIR equals to CMAKE_BINARY_DIR). "It exists after generation at the specified path, and CMake is ready to build." - Are you sure that you talk about exactly `module.modulemap.build` file, and not about `module.modulemap` one, which also exists in the repo? – Tsyvarev Aug 01 '19 at 15:44
  • @Tsyvarev you may be onto something here. I just downloaded an archive of the [8.0.1 release](https://github.com/llvm/llvm-project/releases/tag/llvmorg-8.0.1), based on commit [19a71f6](https://github.com/llvm/llvm-project/tree/19a71f6bdf2dddb10764939e7f0ec2b98dba76c9). `module.modulemap.build` is not present in the archive, but it is present in the repo. Let me see if manually adding the necessary file fixes my problem. – Matthew Cole Aug 01 '19 at 19:25
  • @Tsyvarev: copying the missing file from the repository to the archive I had downloaded worked. If you want to say that in an answer so I can accept it, go ahead and do it. If not, I'll add an answer in a few days. – Matthew Cole Aug 02 '19 at 17:27

1 Answers1

1

What does the error from CMake really mean?

@Tsyvarev correctly identified that the problem was in fact that llvm-project/llvm/include/llvm/module.modulemap.build didn't exist. This was because I downloaded an archive of the project through Github, which appears to have excluded .build files by default. When cloning or forking the project, the missing files are present.

The problem is reproducible, but I don't know why Github behaves the way it does. That is beyond the scope of the question.

How can I fix this so that my top level project can build all four subprojects?

Using add_subdirectory(llvm-project/llvm) command in the top-level CMakeLists.txt file is sufficient, but you must also specify LLVM's options at generate time, of course.

Matthew Cole
  • 602
  • 5
  • 21