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

How to compile a static library (libmpv.a) #7738

Closed
anesuc opened this issue May 18, 2020 · 19 comments
Closed

How to compile a static library (libmpv.a) #7738

anesuc opened this issue May 18, 2020 · 19 comments

Comments

@anesuc
Copy link

anesuc commented May 18, 2020

Hi all,

I have been trying for quite a while to build a static version of libmpv to be used in a module. For additional information as I was documenting what I was doing you can find out more here: Kagami/mpv.js#68 .

Long story short, after enabling --enable-libmpv-static it compiles successfully. But on the other side when trying to link it in a module I get the errors (taken the most important part):
libmpv.a(mp_image.c.26.o): relocation R_X86_64_PC32 against symbolmp_image_setfmt' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: final link failed: Bad value

This is after linking the libmpv.a in binding.gyp. Full error below:

CXX(target) Release/obj.target/mpvjs/index.o SOLINK_MODULE(target) Release/obj.target/mpvjs.node /usr/bin/ld: /home/extern/Downloads/test/lol/lib-retry/node_modules/mpv.js/mpv-build/mpv/build/libmpv.a(mp_image.c.26.o): relocation R_X86_64_PC32 against symbolmp_image_setfmt' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: final link failed: Bad value collect2: error: ld returned 1 exit status mpvjs.target.mk:158: recipe for target 'Release/obj.target/mpvjs.node' failed make: *** [Release/obj.target/mpvjs.node] Error 1 make: Leaving directory '/home/extern/Downloads/test/lol/lib-retry/node_modules/mpv.js/build' gyp ERR! build error gyp ERR! stack Error: make failed with exit code: 2 gyp ERR! stack at ChildProcess.onExit (/usr/lib/node_modules/node-gyp/lib/build.js:194:23) gyp ERR! stack at ChildProcess.emit (events.js:315:20) gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:275:12) gyp ERR! System Linux 5.3.0-51-generic gyp ERR! command "/usr/bin/node" "/usr/bin/node-gyp" "rebuild" gyp ERR! cwd /home/extern/Downloads/test/lol/lib-retry/node_modules/mpv.js gyp ERR! node -v v13.14.0 gyp ERR! node-gyp -v v6.1.0 gyp ERR! not ok

Thanks

@CounterPillow
Copy link
Contributor

As far as I know, the linker here is yelling at you correctly. If you're linking the static library into a shared object, you need position independent code. -fPIC in your CFLAGS should work.

@anesuc
Copy link
Author

anesuc commented May 18, 2020

So CFLAGS with the module? Or in MPV? From what I interpret you mean it should be at the module side but that doesn't seem to be doing anything. I might be doing something wrong though, so I'll keep looking into it. Incase it's the other side, where exactly do I add the CFLAGS in MPV? I tried --extra-cflags=-fPIC in ffmpeg_options but that didn't really do anything either.

@anesuc
Copy link
Author

anesuc commented May 18, 2020

Yeah I even put it in LDFlags just in case, still not working. You will see duplicates of this switch in the verbose output below, that was me testing things. Still same error (from the module side):

  g++ -shared -pthread -rdynamic -m64 -static-libstdc++ -fPIC -L/home/extern/Downloads/nacl_sdk/pepper_49//lib/linux_host/Release  -Wl,-soname=mpvjs.node -o Release/obj.target/mpvjs.node -Wl,--start-group Release/obj.target/mpvjs/index.o -Wl,--end-group -lppapi -lppapi_cpp -lppapi_gles2 /home/extern/Downloads/test/lol/lib-retry/node_modules/mpv.js/mpv-build/mpv/build/libmpv.a /home/extern/Downloads/test/lol/lib-retry/node_modules/mpv.js/mpv-build/ffmpeg_build/libavutil/libavutil.a
/usr/bin/ld: /home/extern/Downloads/test/lol/lib-retry/node_modules/mpv.js/mpv-build/mpv/build/libmpv.a(mp_image.c.26.o): relocation R_X86_64_PC32 against symbol `mp_image_setfmt' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
mpvjs.target.mk:160: recipe for target 'Release/obj.target/mpvjs.node' failed
make: *** [Release/obj.target/mpvjs.node] Error 1
make: Leaving directory '/home/extern/Downloads/test/lol/lib-retry/node_modules/mpv.js/build'

@CounterPillow
Copy link
Contributor

the mpv build needs to have -fPIC enabled, not just FFmpeg and not the LDFLAGS. though I'm not sure if there isn't some other smarter way to go about what you're trying to do (making a dynamic lib from a static lib seems a bit weird)

@anesuc
Copy link
Author

anesuc commented May 18, 2020

How do I add the flag to mpv? As I mentioned in the comment above I only figured how to do it for the ffmpeg side. I don't want to manually edit the wrong files since this process seems very intertwined. I did just try appending it to the wscript_build.py under wrapctx.env.CFLAGS but that doesn't seem to have worked.

(Also yeah I know about the LDFLAGS, I just did it since it didn't seem to change anything when I added CFLAGS, besides it wasn't working anyway so may as well try it temporarily. The worst case it fails to compile anyway but with a different error.)

@CounterPillow
Copy link
Contributor

Usually by setting a CFLAGS environment variable, e.g.:

CFLAGS="-fPIC" ./waf configure
./waf build

(the CFLAGS should stick during the build step, as the configure step picked them up)

@anesuc
Copy link
Author

anesuc commented May 18, 2020

Thanks for your input in all of this! Really appreciate it.

When I ran the first command there were a few reds but the one at the bottom seems a bit concerning:

Checking for FFmpeg library : no ('libavutil >= 56.12.100 libavcodec >= 58.16.100 libavformat >= 58.9.100 libswscale >= 5.0.101 libavfilter >= 7.14.100 libswresample >= 3.0.100' not found) Unable to find development files for some of the required FFmpeg libraries. Git master is recommended.
I do have those installed using -dev packages on my Linux globally. I assume I need to somehow add them directly in here somehow?

Either way, didn't change the result sadly

@anesuc
Copy link
Author

anesuc commented May 18, 2020

I want to add the generated build/libmpv.a has always been around 16.3 MB. In case the size might give some hints.

@ghost
Copy link

ghost commented May 18, 2020

The -fPIC warning is because all code linked to a shared lib, or a PIE executable, must be built with PIC. So you need to add -fPIC to all libs statically linked to libmpv.a.

If the ffmpeg check fails, look at build/config.log.

@anesuc
Copy link
Author

anesuc commented May 19, 2020

@wm4 Ok I'll have a go at that

@rubyFeedback
Copy link

This may seem quite useful I think; there are situations where a static library can be useful. For example, I often end up breaking some stuff on my system and I need mpv to play good music so I am motivated to fix anything. :D

@Traneptora
Copy link
Member

Traneptora commented Aug 31, 2020

Linking a static library to a shared one is not difficult - you can just run gcc -shared -o libmpv.so libmpv.a along with desired linker flags (such as -ljpeg-turbo -lz etc.). You do need to make sure that any compiled code in libmpv.a is position-independent code, which means it had to have been compiled originally with -fPIC. This is not something the linker can fix - and if you didn't do it then you won't be able to make it a shared library.

@nathanfranke
Copy link

I am getting a ton of undefined references trying to link to libmpv

/usr/bin/ld: modules/gdmpv/mpv-build/mpv/build/libmpv.a(f_swresample.c.27.o): in function `resample_frame':
/home/nathanfranke/workspace/godot/modules/gdmpv/mpv-build/mpv/build/../filters/f_swresample.c:395: undefined reference to `swr_convert'
/usr/bin/ld: modules/gdmpv/mpv-build/mpv/build/libmpv.a(f_swscale.c.27.o): in function `mp_sws_supports_input':
/home/nathanfranke/workspace/godot/modules/gdmpv/mpv-build/mpv/build/../filters/f_swscale.c:68: undefined reference to `sws_isSupportedInput'
/usr/bin/ld: modules/gdmpv/mpv-build/mpv/build/libmpv.a(dither.c.27.o): in function `makegauss':
/home/nathanfranke/workspace/godot/modules/gdmpv/mpv-build/mpv/build/../video/out/dither.c:61: undefined reference to `av_lfg_init'

This is how I'm building it:

echo "--enable-libmpv-static" > mpv_options

CFLAGS="-fPIC" ./rebuild

And scons:

env.Append(LIBPATH=["#modules/gdmpv/mpv-build/mpv/build"])
env.Append(LIBS=["mpv"])

(By the way, this is on my https://github.com/nathanfranke/gdmpv repo)

@CounterPillow
Copy link
Contributor

Sounds like it's not linking to libswresample.

@nathanfranke
Copy link

Sounds like it's not linking to libswresample.

This is one of hundreds of errors, many of which are not libswresample. https://pastebin.com/1HcFDdkR

@CounterPillow
Copy link
Contributor

Sounds like it's not linking to any library it needs to link to.

@nathanfranke
Copy link

Do you know of a way to fix this? I need to statically link every dependency.

@nathanfranke
Copy link

Looks like libmpv.a contains swresample (There's other linker errors, just using this one as an example)

$ ar tv mpv-build/mpv/build/libmpv.a | grep resample
rw-r--r-- 0/0  91776 Dec 31 18:00 1969 f_swresample.c.27.o

I get the same errors even if I manually link every other library (which I shouldn't need to do)

env.Append(LIBPATH=["#modules/gdmpv/mpv-build/build_libs/lib"])
env.Append(LIBPATH=["#modules/gdmpv/mpv-build/mpv/build"])
env.Append(LIBS=["ass", "avcodec", "avdevice", "avfilter", "avformat", "avutil", "postproc", "swresample", "swscale", "mpv"])

(fyi, I also added --enable-static to ffmpeg_options)

@toasterofbread
Copy link

toasterofbread commented Feb 5, 2024

@nathanfranke I have the exact same issue trying to statically link libmpv to a Kotlin/Native application. Undefined references to methods in several ffmpeg dependencies, even when statically linking to those dependencies as well. Dynamic linking works fine.

Did you ever find a solution to this issue? Sorry to revive this thread again.

Edit: I should note that I'm using v0.35.0 since Kotlin/Native requires static libs to be compiled using an older version of glibc

Edit: Fast-forward three months, and I've rediscovered this comment while trying to accomplish this again, this time with v0.38.0 but with the same result.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants