Search code examples
cmakellvmstatic-librariesllvm-irbitcode

How to have an intermediate compile statement when generating a static library using cmake


I am successfully compiling, using clang, from source code to IR bitcode and generating a static library. The problem I need to solve is that the IR refers to external global variables in their library internal global name. I need to modify these internal global names to the external global name. For example, in libc.a, in LLVM format:

@atoi = alias i32 (i8*), i32 (i8*)* @__GI_atoi

define hidden i32 @__GI_atoi(i8* nonnull) #0 {
  ...
  %4 call i64 @__GI_strtol(i8* %3, i8** null, i32 10) #2
  ...
}

declare hidden i64 @__GI_strtol(i8*, i8**, i32) #1

The __GI_strtol is external to the atoi module, but is internal to the libc.a archive. The strtol module has a @strtol = alias ... @__GI_strtol definition and a hidden function called GI_strtol.

What I need to do is when compiling the source files (atoi.c in the above example), I need to do the following:

  1. Compile the source file to .ll (LLVM) format.
  2. Convert all declare hiddens that do not have an associated alias statement, to their external global value (basically, hidden --> dso_local and __GI_* to just *).
  3. Convert the resulting .ll file to its IR bitcode (.bc) equivalent.
  4. Insert the .bc file into the libc.a archive.

Is this possible?

I have a number of add_custom_targets and add_custom_commands in the CMake file, but none when compiling from .c to .bc.

If this were a make build, I'd simply add definitions to compile from .c to .ll and .ll to .bc, and in the last stage perform the changes indicated above.

I expect to be able to perform the above steps in the most efficient way possible using CMake. I'd like to be able to do it without having to have, literally, 1000s of add_custom_command/targets.


Solution

  • I could not find a way to be able to do the conversion as part of the compilation. So, I used add_custom_command with a POST_LINK on the archive itself. Then I process each entry in the archive, doing the required conversion, and then updating the archive.

    It is a sort of get a bigger hammer solution, but it works and does not add 100s of custom targets.