Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NDK link-time optimization fails missing llvmgold.so, but contains llvmgold.dylib #108

Closed
JakeWharton opened this issue May 27, 2016 · 36 comments
Assignees
Labels
Milestone

Comments

@JakeWharton
Copy link

I'm attempting to add -flto for link-time optimization to my cFlags and ldFlags (using the new Gradle experimental plugin) but receiving a failure to load LLVMgold.so at link time:

/Users/jw/android-sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/lib/gcc/aarch64-linux-android/4.9.x/../../../../aarch64-linux-android/bin/ld: /Users/jw/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/../lib64/LLVMgold.so: error loading plugin: dlopen(/Users/jw/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/../lib64/LLVMgold.so, 2): image not found

A quick look into the NDK reveals that the lib64/ folder contains an LLVMgold.dylib file, but not the .so:

$ find ~/android-sdk/ndk-bundle -name 'LLVMgold*'
/Users/jw/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/lib64/LLVMgold.dylib

Is the .so missing, or is there a different way to enable LTO that uses this dynamic lib instead?

@JakeWharton
Copy link
Author

This is using clang 3.8.

@DanAlbert
Copy link
Member

@stephenhines do we just configure something assuming everything is Linux when we build clang, or does upstream clang actually have the wrong? Maybe it's trying .so because the target is Linux?

@stephenhines
Copy link
Collaborator

We do only target baseline Linux for our configuration (multiple layers of config.h), so perhaps this is a misconfiguration issue. I am not sure whether we will update the existing configuration logic now that we are switching to a more upstream-like build process.

@stephenhines
Copy link
Collaborator

https://android-review.googlesource.com/233868 should be the fix for this. In the meantime, you might be able to workaround this by symlinking to a .so filename (i.e. LLVMGold.so -> LLVMGold.dylib in that directory).

@JakeWharton
Copy link
Author

Thanks!

That got me slightly farther along, but the linker now fails with an inability to recognize the format of the .o:

/Users/jw/dev/square/duktape-android/duktape/build/intermediates/objectFiles/arm64-v8aReleaseSharedLibrary/duktapeMainC/72j2t6goef75gvdzb76w4b6so/duktape.o: file not recognized: File format not recognized
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

If I had to guess it's because libLTO.so isn't included in the NDK? I'm not sure if that's something that usually comes standard with a native toolchain like this or not (vastly inexperienced with building native libraries).

@kneth
Copy link

kneth commented May 30, 2016

I have the same issue. Or to be more specific:

  • With ARM64, I get the same error message
  • With ARM v7a, I get "file format not recognized" for the .o files
  • With x86, I can compile and link, but the produced .so file does not work as the dynamic linker on my emulated device cannot find any methods

@suikki
Copy link

suikki commented May 31, 2016

On Windows if I specify -flto when using clang I get:

LLVMgold.so: could not load plugin library: unable to load dll

@DanAlbert
Copy link
Member

The Windows issue is also covered by the fix @stephenhines posted. Given the "file format not recognized" issues though, that probably isn't sufficient.

@thanm
Copy link

thanm commented Jun 1, 2016

@JakeWharton, @kneth -- are you 100% sure that the linker being used for your build is ld.gold and not ld.bfd? Looking at the default for prebuilts on the platform it looks like "ld" defaults to gold for linux but bfd for darwin/aarch64.

@kneth
Copy link

kneth commented Jun 3, 2016

I have tried with R12 today - using Linux (well, Ubuntu 14.04 under vagrant/OS X). I am able to compile and link but something is wrong with the produced .so files. The dynamic linker cannot find any symbols.

@DanAlbert DanAlbert added the clang label Jul 1, 2016
@DoDoENT
Copy link

DoDoENT commented Jul 11, 2016

After creating symlinks as @stephenhines suggested, I now get following linker errors:

/Users/dodo/android-sdks/android-ndk-r12/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/lib/gcc/aarch64-linux-android/4.9.x/../../../../aarch64-linux-android/bin/ld.gold: error: ./obj/local/arm64-v8a/libMyStaticLib.a: no archive symbol table (run ranlib)

for every static library in my project and

/var/folders/fc/38fp3j9x3dd74ng4fl8jhjtr0000gn/T/lto-llvm-2b6578.o:ld-temp.o:function myFunction: error: undefined reference to 'mySymbol'

for every single symbol in my entire code.

When disabling LTO or when using GCC, project compiles without errors.

Something is obviously wrong with clang.

@DanAlbert
Copy link
Member

DanAlbert commented Jul 11, 2016

I've seen this happen before when ndk-build wrongly uses the system's ar (specifically on Darwin because it's BSD ar instead of GNU ar) instead of the one we ship in the NDK. Can you check that the correct ar was invoked for creating libMyStaticLib.a? I've certainly fixed bugs in ndk-build for that in the past.

@DoDoENT
Copy link

DoDoENT commented Jul 11, 2016

I can confirm that toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-ar was used for creating all my static libs (checked with ndk-build -n).

This happens with both r12, r12b and r11c. When GCC is used, LTO works.

@DoDoENT
Copy link

DoDoENT commented Jul 11, 2016

This confuses me a lot because 14 days ago I reported issue #137 and after suggestions from @DanAlbert, I've managed to enable LTO for clang on one of my projects (without symlinks suggested by @stephenhines). This means that either then I had a dirty build (actually built with gcc and then forgot to clean after changing compiler) or I was using NDK older than r11c (which I doubt).

Can anyone else reproduce this issue on MacOS X with their project?

@DoDoENT
Copy link

DoDoENT commented Jul 15, 2016

I reproduced the same error on ArchLinux using NDK r12b, so this is not MacOSX-specific error (I mean no archive symbol table linker errors).

@kneth
Copy link

kneth commented Jul 15, 2016

@DoDoENT I don't recall the actual error message but it sounds like you have reach the same conclusion as me :-(

@vvaldik
Copy link

vvaldik commented Aug 31, 2016

I have "no archive symbol table" error too
The strange thing is than toolchain is 'clang' and cpp's are compiled with clang, but when it comes to link, error shows:
.../android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld.gold: error: ./obj/local/armeabi-v7a/libui.a: no archive symbol table (run ranlib)

So looks like linker is taken from gcc 4.9 toolchain, but my toolchain is 'clang'

@ahyangyi
Copy link

@DoDoENT @kneth @vvaldik
Using -fuse-ld=gold and refraining from using ranlib by defining it to /bin/true should eliminate that problem.

@DoDoENT
Copy link

DoDoENT commented Oct 10, 2016

This issue is also present in r13.

@ahyangyi, setting CMAKE_RANLIB to /usr/bin/true does not help. I still get undefined reference to every single symbol in my code, as already mentioned in my previous comment. I am using cmake bundled with latest Android Studio (v3.6.3155560) and cmake toolchain bundled with NDK r13.

@DoDoENT
Copy link

DoDoENT commented Oct 10, 2016

I've also tried configuring cmake to use GCC instead of clang and then I get following output for each compilation unit:

BFD: CMakeFiles/path/to/source-file.o: plugin needed to handle lto object

And linker fails with undefined reference to each and every symbol in the code. BTW, I double checked that linker command line contains -fuse-ld=gold, yet above mentioned error indicates BFD is used when packing object files in static libraries. Any idea why that happens? Maybe it is also related to clang problem.

@DanAlbert
Copy link
Member

Our basic sample builds with r13b (might have worked earlier, don't have r12 on this machine atm), albeit not out of the box.

It looks like the only step necessary (that isn't also necessary on Linux) is that I had to ln -s LLVMgold.dylib LLVMgold.so in $NDK/toolchains/llvm/prebuilt/darwin-x86_64/lib64.

The remaining issues are caused by arm64 still defaulting to ld.bfd, and gold not being supported at all for mips/mips64. Example from #242 (comment)

# Gold does not support mips or mips64, but gold is needed for LTO with Clang.
ifeq (,$(filter $(TARGET_ARCH_ABI),mips mips64)
    LOCAL_CFLAGS += -flto
    LOCAL_LDFLAGS := -flto -fuse-ld=gold
endif

You'll have to ask someone else how to write that for gradle :)

@stephenhines: can you get the dlopen for LLVMgold.so fixed for darwin (and presumably Windows too)? It seems that's the only thing blocking this.

@stephenhines
Copy link
Collaborator

This has no chance of making r14, because we are having trouble stabilizing even the latest Clang currently for the platform, and we won't deploy again until that happens. I also still don't understand the actual problem here, so someone who has a better clue on Windows (and a working Windows environment) might have a better chance of resolving this.

@stephenhines
Copy link
Collaborator

https:/llvm-mirror/clang/blob/master/lib/Driver/Tools.cpp#L2155 is the problem, thanks to some help from Dan. We can fix this in upstream, but he might be able to just alter the filenames to get a quicker fix out.

@DanAlbert
Copy link
Member

QA started working on beta 1 this morning, so unfortunately we just missed that, but I'll have a hack (seems we can just ship with as LLVMgold.so and it'll be technically wrong but work fine) for this in beta 2.

@DoDoENT
Copy link

DoDoENT commented Nov 22, 2016

Well, just making symlink does not work for projects that have static libs. Here is the minimum example project which demonstrates the issue @kneth, @vvaldik and I have.

So, when LTO is enabled and gold is used, I get following error:

/Users/dodo/android-sdks/ndk-bundle/toolchains/x86_64-4.9/prebuilt/darwin-x86_64/lib/gcc/x86_64-linux-android/4.9.x/../../../../x86_64-linux-android/bin/ld.gold: error: libstring-provider.a: no archive symbol table (run ranlib)
/Users/dodo/Desktop/MyApplication/app/src/main/cpp/native-lib.cpp:12: error: undefined reference to 'StringProvider::provide_string()'

The example is minimal modification of JNI hello project which is created by Android Studio when creating new project and enabling C++ support.

@DanAlbert
Copy link
Member

Ah, that's right. Sorry, there's quite a lot in this thread and I missed that part in my re-read. I'll try to find some time to poke at that today.

Some gradle/NDK mismatch issues came up in testing, so I may end up getting the symlinks into beta 1 anyway. If I can find a workaround for the static library issue in time I'll do the same for that.

@DanAlbert
Copy link
Member

Okay, the static library issue reproduces even on Linux. I think I should have time to look at this today.

@DanAlbert
Copy link
Member

Expanded our test case to catch this: https://android-review.googlesource.com/307477

@DoDoENT
Copy link

DoDoENT commented Dec 21, 2016

Any progress on this?

@DanAlbert
Copy link
Member

Yes. It seems that we need to use the LLVMgold.so plugin for ar too: http://llvm.org/docs/GoldPlugin.html

I haven't tested this in the NDK yet, but it looks straightforward.

@DanAlbert DanAlbert added this to the r14 milestone Dec 21, 2016
@DanAlbert DanAlbert assigned DanAlbert and unassigned stephenhines Dec 21, 2016
@DanAlbert
Copy link
Member

Fix is up for review: https://android-review.googlesource.com/c/318721/

I'll cherry-pick into r14 for beta 2 once that gets approved.

@DoDoENT
Copy link

DoDoENT commented Jan 5, 2017

@DanAlbert, this change only refers to ndk-build. What about CMake toolchain? Will it work there too?

@DanAlbert
Copy link
Member

I was thinking that a non-android cmake project would need to modify it's CMakeLists.txt file to make it work anyway, and in general our goal is to just match a typical CMake use case, but it seems that in a non-Android case the gold plugin actually gets installed to a location that ar will automatically look in and load from, so I think we can actually do better than the fix I made yesterday. Working on something now.

@DanAlbert DanAlbert reopened this Jan 5, 2017
@DanAlbert
Copy link
Member

Okay, better implementation that is build-system agnostic: https://android-review.googlesource.com/c/319310/

@DanAlbert
Copy link
Member

(plus a cmake test)

@DanAlbert
Copy link
Member

Alright, fixes are in r14.

a252539783 pushed a commit to a252539783/aosp-platform-ndk that referenced this issue May 3, 2017
We previously hacked this up directly in the prebuilts directory.
Rather than continuing to do that, fix it in the build.

Test: ./run_tests.py --filter flto --abi armeabi-v7a
Test: ./run_tests.py --filter flto --abi armeabi-v7a --toolchain 4.9
Bug: android/ndk#108
Change-Id: Ib3f68d5a4768e142153441415505b2ff29933848
a252539783 pushed a commit to a252539783/aosp-platform-ndk that referenced this issue May 3, 2017
This gets LTO working for Clang on the supported hosts (no Windows
support yet) and targets (we don't have gold for MIPS).

This also switches us to the small code model when building
executables for non-Intel targets (to match the PIC options).

Test: ./validate.py --filter flto
Bug: android/ndk#108
Change-Id: I465e475282d17b2137dcebcbab53e53b9372c837
(cherry picked from commit 95d6a33)
a252539783 pushed a commit to a252539783/aosp-platform-ndk that referenced this issue May 3, 2017
ar will automatically load any plugins that are installed to
../lib/bfd-plugins. Rather than needing to fix all of our build
systems, we can make LTO Just Work if we copy the gold plugin (and
its dependencies) into the binutils directory.

I've also added a test for cmake LTO.

Test: ./validate.py --filter flto
Bug: android/ndk#108
Change-Id: I1db61b8ef3405474c64ff20478daa86ca41ab3b3
(cherry picked from commit ec60de8)
miodragdinic pushed a commit to MIPS/prebuilts-clang-host-darwin-x86 that referenced this issue Dec 8, 2017
Yes, Darwin binaries should be .dylib, but the original LTO code that
was submitted to LLVM apparently didn't know that so it `dlopen`s the
.so even on Darwin and Windows.

LTO on Darwin somewhat works (works for shared libraries, anyway) if
we just rename it, so do that until we can fix LLVM correctly.

Test: ndk/run_tests.py --filter flto
Bug: android/ndk#108
Change-Id: I01dc60da6431e9730dec352f80c04563fbe5e8d2
miodragdinic pushed a commit to MIPS/ndk that referenced this issue Apr 17, 2018
This gets LTO working for Clang on the supported hosts (no Windows
support yet) and targets (we don't have gold for MIPS).

This also switches us to the small code model when building
executables for non-Intel targets (to match the PIC options).

Test: ./validate.py --filter flto
Bug: android/ndk#108
Change-Id: I465e475282d17b2137dcebcbab53e53b9372c837
miodragdinic pushed a commit to MIPS/ndk that referenced this issue Apr 17, 2018
ar will automatically load any plugins that are installed to
../lib/bfd-plugins. Rather than needing to fix all of our build
systems, we can make LTO Just Work if we copy the gold plugin (and
its dependencies) into the binutils directory.

I've also added a test for cmake LTO.

Test: ./validate.py --filter flto
Bug: android/ndk#108
Change-Id: I1db61b8ef3405474c64ff20478daa86ca41ab3b3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

9 participants