Llvm-link: symbol multiply defined

I am working on creating a single llvm ir file for the open source software ardupilot. They use a build system called waf, so I edited the wscript and changed g++ to clang++ and gcc to clang. I then added flags to emit ir llvm. This successfully goes through each file, creates the ir code and stores it in a .o file. I changed all the extensions to be .ll and then attempted to use llvm-link -S … to link the files into one ir file.

It is worth mentioning that ArduPilot consists of subprojects such as ArduCopter and ArduPlane etc. You can compile any of these projects individually for different systems such as a quadcopter or rc plane (where ArduCopter is for the quadcopter and ArduPlane is for fixed wing aircrafts). The project structure also has a bunch of libraries that are used by the main code for whatever you are compiling, be it ArduCopter or ArduPlane. (See below for a glimpse at the structure. Of particular note is ArduCopter and the libraries folder.)

I am personally working with ArduCopter. After running the build script, I get the ir files for the main ArduCopter code and the libraries.

However, when I use llvm-link -S folder_with_ir_files/*.ll -o file_name.ll, I get the following: “error: Linking globals named 'main': symbol multiply defined!
This is probably due to the fact that the libraries each have a main function leading to the symbol conflict.

If I try to resolve this issue by adding the flag --only-needed, all references to library functions get removed and instead simply a definition for the library class name appears. For example, references to a function selectHeightForFusion are removed and a define for AP_NavEKF3_PosVelFusion.cpp appears.

Ex. The function name is not found in the output ir file, but a reference to the class is.
define internal void @_GLOBAL__sub_I_AP_NavEKF3_PosVelFusion.cpp() #6 section ".text.startup" {

I instead tried using the flag --internalize to solve this problem. It seems to work where the references are now to the library functions themselves instead of the file, but it does not feel like the best way to go about solving this issue. (See below.)

Ex. These appear in the output ir file when searching for the function name.
call void @_ZN12NavEKF3_core21selectHeightForFusionEv(%class.NavEKF3_core.8709* %this1)
define internal void @_ZN12NavEKF3_core21selectHeightForFusionEv(%class.NavEKF3_core.8709* %this) #0 align 2 {

Ultimately, I wanted to get any feedback I could on the proper way to link multiple ir files in a project that uses libraries with multiple mains while not losing any ir code from the libraries.
It is also likely that I simply do not understand the process of linking these files and perhaps there is a reason for the references to selectHeightForFusion to be removed when using --only-needed.

Any guidance would be much appreciated.

I am working on creating a single llvm ir file for the open source software ardupilot.

Can you clarify what is the end-goal for this “single llvm IR” file?

Certainly. The end goal is to pass this file through SVF for data flow analysis. SVF can perform value flow and pointer analysis over an llvm ir file. We can dump the generated value flow graph as a dot file from SVF and then create python scripts to visualize how specific data is moved around in ArduCopter.

Have you solve this problem? Any update on how you solve the multiple define as I am currently facing the same problem

It has been a while, but I think I came up with the following work around.

Because I only cared about analyzing the output ir file and not particularly about the main functions from the library, I simply went to each ir file that had the conflicting main defined and changed the names to something like main1, main2, main3, etc.

I am not sure if this suits your problem or not, but hopefully it helps. It definitely isn’t a great way to do this, but oh well :frowning:

Other than that, I would recommend looking into the --internalize flag and see if that gives you good output.

Best of luck!

I am new to this. How do you know which IR file have conflicted main? Are there any flags that can show which one have conflicting main. I have try the internalize but it doesn’t work. But i will try the work around

I’m literally having the same problem, but in my case with an iOS project in Xcode made in swift / objective-c that has multiple modules.
I am using the single IR file to optimize and outlining the whole project instead of doing it in each module separately like Xcode does (I tested it in a small projects and it works for reduce the app size).
But I can’t link all IR files in this big projects with llvm-link because of ‘symbol multiply defined’
I inspected the IR of the files in conflict, and they have definitions for the same symbol in each one, but for some reason the regular clang linker works but the IR linker (LLVM-link) doesn’t.
Does anyone find a solution for this? it seems that changing the names is not a good work around for me.

I’m also getting the “symbol multiply defined” error when trying to create a single llvm IR file for SVF. I was thinking about editing the IR files (to specific, .ll files) and changing @global = dso_local global i32 0, align 4, !dbg !28 to @global = external dso_local global i32. Then I found that the --only-needed option for llvm-link solves the problem. I’m using llvm-link-13. Hope this helps.