16

Suppose I have a third party library called somelib.a on a Mac running Mountain Lion with Xcode 4.4 installed. I want to get a dynamic library out of it called somelib.dylib. An appropriate Linux command would be:

g++ -fpic -shared -Wl,-whole-archive somelib.a -Wl,-no-whole-archive -o somelib.so

where -whole-archive and -no-whole-archive are passed to the linker. When I do the equivalent for Mac:

g++ -fpic -shared -Wl,-whole-archive somelib.a -Wl,-no-whole-archive -o somelib.dylib

ld fails with an error:

ld: unknown option: -whole-archive

It seems that the ld on OSX is different from GNU ld. How do I have to modify above command so I will get the desired result?

Thank you in advance!

hanslovsky
  • 870
  • 6
  • 21

3 Answers3

18

I found out the solution to my problem:

g++ -fpic -shared -Wl,-force_load somelib.a -o somelib.dylib

The required argument is -force_load:

  • Which needs to be followed by a single library you wanna ensure gets loaded.
  • I mean, it needs to be repeated for each library (unlike -noall_load approach, which wrapped them).
  • For example, -Wl,-force_load libYetAnotherFile.a (where -Wl, part is only required because we don't pass parameter directly to linker).

Note that Old answer (before edit) was using -noall_load instead, but nowadays that causes a linker error (as -noall_load has been removed, was obsolete previously).

Top-Master
  • 7,611
  • 5
  • 39
  • 71
hanslovsky
  • 870
  • 6
  • 21
  • What's the most likely diagnosis if this — with or without `-force_load` substituted for `-all_load` apparently condenses a 1.2mb .a into a 4kb .dylib? – Tommy Aug 18 '15 at 19:51
  • @Tommy I just saw your comment now. I would guess that it extracts only the symbols that you actually use and you use only a very small part of that archive. – hanslovsky Mar 21 '17 at 20:45
  • getting error - `ld: symbol(s) not found for architecture x86_64` – Balasubramanian Feb 03 '21 at 09:17
  • 1
    Nowadays `-force_load` is the only solution!! Because `-noall_load` causes a nice linker error (as it's been removed, was obsolete previously). – Top-Master Jul 10 '21 at 19:32
  • @Top-Master is that a simple one-to-one replacement in the original answer? I would gladly update my answer bu I do not have a mac to test on. – hanslovsky Jul 22 '21 at 15:57
  • 1
    The only difference is that `-force_load` requires to be repeated for each library (like "`-force_load libA.a -force_load -lB -force_load libC.a`", where `-lB` is same as `libB.a`). – Top-Master Jul 23 '21 at 06:37
5

Note: A link for the documentation of the OSX ld linker.

http://www.unix.com/man-page/osx/1/ld/

I know it is late to give an answer for this, but I do not have enough reputation to make a comment on @hanslovsky answer. However, it helps me a lot to have the docs of the options too. It helps what the options do exactly, and that other options the ld linker also has. So I just wanted to share with others who finds linking an issue.

UPDATE:

After the comment from @GhostCat I have decided to expand my answer.

The docs for -all_load is:

-all_load

Loads all members of static archive libraries.

So it loads for all static libraries that you note. If you want something similar to --whole-archive and --no-whole-archive, then you need to use -force_load and -noall_load.

-force_load "path_to_archive"

Loads all members of the specified static archive library. Note: - all_load forces all members of all archives to be loaded.
This option allows you to target a specific archive.

-noall_load

This is the default. This option is obsolete.

Then you can define which libraries to fully load with -force_load and then later turn it off again with -noall_load.

3

According to the ld manual, -noall_load is the default and is ignored. (If you use it, you get an error message: ld: warning: option -noall_load is obsolete and being ignored)

Apparently the way to get -all_load to apply to only one library is as follows:

-Wl,-force_load,somelib.a
ptomato
  • 56,175
  • 13
  • 112
  • 165