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

Fix missing symbols when libtiff depends on libjpeg #7270

Merged
merged 1 commit into from
Jul 9, 2023

Conversation

heitbaum
Copy link
Contributor

@heitbaum heitbaum commented Jul 8, 2023

when compiling Pillow with libtiff and libjpeg (with jpeg12 enabled - which is the default with libjpeg-3.0.0) the libtiff object tif_jpeg_12.c.o uses the following libjpeg12 functions: jpeg12_read_raw_data, jpeg12_read_scanlines, jpeg12_write_raw_data, jpeg12_write_scanlines.

update the ordering of libs.append(feature.tiff) to be before libs.append(feature.jpeg) to allow the linker to include the required functions.

this issue occurs when the libtiff and libjpeg libraries are static (not shared.)

Fixes #7269.

Changes proposed in this pull request:

  • reorder libraries due to dependency of tiff on jpeg

before - missing functions in _imaging.so

readelf -Ws build.LibreELEC-Generic.x86_64-12.0-devel/install_pkg/Pillow-10.0.0/usr/lib/python3.11/site-packages/PIL/_imaging.so | grep jpeg12_[rw]
    10: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND jpeg12_write_scanlines
    11: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND jpeg12_read_scanlines
    12: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND jpeg12_read_raw_data
    13: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND jpeg12_write_raw_data

after - functions in _imaging.so

readelf -Ws build.LibreELEC-Generic.x86_64-12.0-devel/install_pkg/Pillow-10.0.0/usr/lib/python3.11/site-packages/PIL/_imaging.so | grep jpeg12_[rw]
   287: 00000000000a1d70   218 FUNC    GLOBAL DEFAULT   11 jpeg12_write_scanlines
   369: 00000000000a1e50   276 FUNC    GLOBAL DEFAULT   11 jpeg12_write_raw_data
   688: 00000000000a2aa0   292 FUNC    GLOBAL DEFAULT   11 jpeg12_read_raw_data
   929: 00000000000a2280   240 FUNC    GLOBAL DEFAULT   11 jpeg12_read_scanlines

when compiling Pillow with libtiff and libjpeg (with jpeg12 enabled -
which is the default with libjpeg-3.0.0) the libtiff object
tif_jpeg_12.c.o uses the following libjpeg12 functions:
jpeg12_read_raw_data, jpeg12_read_scanlines, jpeg12_write_raw_data,
jpeg12_write_scanlines.

update the ordering of libs.append(feature.tiff) to be before
libs.append(feature.jpeg) to allow the linker to include the required
functions.

this issue occurs when the libtiff and libjpeg libraries are static
(not shared.)

Signed-off-by: Rudi Heitbaum <[email protected]>
@homm
Copy link
Member

homm commented Jul 8, 2023

to allow the linker to include the required functions.

Could you explain how does it work? Why the order does matter?

@heitbaum
Copy link
Contributor Author

heitbaum commented Jul 8, 2023

to allow the linker to include the required functions.

Could you explain how does it work? Why the order does matter?

the existing setup.py will be compiling the _imaging.so with a line something like: cc _imaging.c -ljpeg -ltiff

as the libtiff:tif_jpeg_12.c.o uses the following libjpeg12 functions: jpeg12_read_raw_data, jpeg12_read_scanlines, jpeg12_write_raw_data, jpeg12_write_scanlines

as seen in the nm -g libtiff.a

…
tif_jpeg_12.c.o:
�����������������U fprintf
�����������������U getenv
�����������������U _GLOBAL_OFFSET_TABLE_
�����������������U jpeg12_read_raw_data
�����������������U jpeg12_read_scanlines
�����������������U jpeg12_write_raw_data
�����������������U jpeg12_write_scanlines
…

this means that _imaging.so can’t resolve the dependencies for these jpeg12_*

whereas compiling with cc _imaging.c -ltiff -ljpeg will resolve the dependencies.

this could also be fixes with a line such as cc _imaging.c -ljpeg -ltiff -ljpeg but this is not necessary, as tiff depends on jpeg (not the other way around) when libtiff is compiled with -Djpeg=ON

References:

@homm
Copy link
Member

homm commented Jul 8, 2023

this means that _imaging.so can’t resolve the dependencies for these jpeg12_*

Ok, but why linker can’t resolve the dependencies? Is it related to extern symbols like in Stackoverflow answer?

I'm asking because it's not clear for me why this particular order is more correct than another and what if we'll have some symbols from libjpeg which we are using which is not present in libtiff's version.

@heitbaum
Copy link
Contributor Author

heitbaum commented Jul 8, 2023

this means that _imaging.so can’t resolve the dependencies for these jpeg12_*

Ok, but why linker can’t resolve the dependencies? Is it related to extern symbols like in Stackoverflow answer?

Yes. In that tiff uses jpeg12 (which is in jpeg). The “library providing the symbol should always be on the right” and the “user of the symbol on the left”

I'm asking because it's not clear for me why this particular order is more correct than another.

as above - in that libtiff needs libjpeg.

libjpeg is a standalone library that does not use other libraries (specifically in this case libtiff) as in https://github.com/libjpeg-turbo/libjpeg-turbo/blob/main/BUILDING.md and https://github.com/libjpeg-turbo/libjpeg-turbo/blob/main/CMakeLists.txt there are no references to libtiff (or other libraries)

whereas libtiff is using libjpeg in https://gitlab.com/libtiff/libtiff/-/blob/master/configure.ac#L548

and what if we'll have some symbols from libjpeg which we are using which is not present in libtiff's version.

probably a little confusion in that libtiff is NOT providing any libjpeg (or libjpeg12) symbols. Libtiff needs the libjpeg symbols. So changing the order will not impact Pillow’s use of libjpeg.

@homm
Copy link
Member

homm commented Jul 8, 2023

@heitbaum thanks for explanations!

@radarhere radarhere merged commit e96f217 into python-pillow:main Jul 9, 2023
@radarhere radarhere changed the title Fix missing symbols as libtiff can depend on libjpeg Fix missing symbols when libtiff depends on libjpeg Jul 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Pillow built with libjpeg-turbo 3.0.0 errors with _imaging.so: undefined symbol: jpeg12_write_raw_data
3 participants