In addition to building an executable binary of my application, I also use SWIG to wrap my program to be called from Python.
SWIG sets up a shared object library that gets loaded by Python. ...
When we create this shared object, we try to statically link everything we can -- including FLTK. So, we're statically linking FLTK into a shared library.
For some reason, on RHEL9, when I go to link the Python wrapper with FLTK into the shared object, I get the following error:
/usr/bin/ld: crt1.0: in function `_start': (.text+0x1b): undefined reference to `main’
collect2: error: ld returned 1 exit status
Of course, since this is a shared object, I don't have a main().
I dug into the details of the linker command and eventually discovered that it included a '-no-pie' that if removed, linking would proceed as desired.
After considerable digging, I figured out that the '-no-pie' is coming from fltk:fltk. I used this utility (discussed previously here) to peer into everything in this target. The output is below:
[...]
fltk::fltk INTERFACE_LINK_LIBRARIES = /usr/lib64/libdl.a;/usr/lib64/libX11.so;/usr/lib64/libXext.so;/usr/lib64/libXinerama.so;/usr/lib64/libXfixes.so;/usr/lib64/libXcursor.so;/usr/lib64/libXrender.so;/usr/lib64/libpango-1.0.so;/usr/lib64/libpangocairo-1.0.so;/usr/lib64/libcairo.so;/usr/lib64/libgobject-2.0.so;/usr/lib64/libpangoxft-1.0.so;/usr/lib64/libXft.so;/usr/lib64/libfontconfig.so;-lwayland-egl -lEGL;-L/usr/lib64;-lgtk-3;-lgdk-3;-lpangocairo-1.0;-lpango-1.0;-lharfbuzz;-latk-1.0;-lcairo-gobject;-lcairo;-lgdk_pixbuf-2.0;-lgio-2.0;-lgobject-2.0;-lglib-2.0;-lwayland-cursor -lwayland-client -lxkbcommon -ldl;-L/usr/lib64;-ldbus-1;-no-pie
[...]
Notice that INTERFACE_LINK_LIBRARIES contains -no-pie. Notably, this is a linker option, not a library.
The FLTKConfig.cmake.in file contains no reference to -no-pie. So I dug into the FLTK source, and there are three hits. One in ./configure.ac, one in libdecor, and the relevant one in /src/CMakeLists.txt:768.if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" AND NOT FLTK_BUILD_SHARED_LIBS)
list(APPEND OPTIONAL_LIBS "-no-pie")
endif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" AND NOT FLTK_BUILD_SHARED_LIBS)
This is perhaps a reasonable thing to do if you assume that fltk is going to be statically linked into an executable program. It does not work in my situation where fltk is statically linked into a shared library.
I am also not certain how appropriate it is that this 'leaks' its way into the fltk:fltk target.
Perhaps it must be this way. I don't fully understand all the mechanisms at work.
At a minimum, I'm pretty sure this should be assigned to a target LINK_OPTIONS property. Or, perhaps even better, a target POSITION_INDEPENDENT_CODE property (rather than appended to a string list of library names).
I don't know the long-term fix for this.
In the short term, I'm going to attempt something likeget_target_property(templist fltk:fltk INTERFACE_LINK_LIBRARIES)
list(REMOVE_ITEM templist "-no-pie")
set_target_properties(fltk:fltk PROPERTIES INTERFACE_LINK_LIBRARIES ${templist})
Or something like that.
Noted, but I can't comment on anything related to SWIG or Python.
That's probably due to some "old code" leaking into the "Modern CMake" approach. I didn't have the time yet to rewrite everything and I'm aware that there's still something to do.
At a minimum, I'm pretty sure this should be assigned to a target LINK_OPTIONS property. Or, perhaps even better, a target POSITION_INDEPENDENT_CODE property (rather than appended to a string list of library names).Yep, that's correct, and very likely it should be added to PRIVATE CMake properties rather than PUBLIC, hence it would not affect your build at all (PRIVATE properties are not included in INTERFACE_* properties).
I don't know the long-term fix for this.I'll check if I can fix this.
In the short term, I'm going to attempt something likeget_target_property(templist fltk:fltk INTERFACE_LINK_LIBRARIES)
list(REMOVE_ITEM templist "-no-pie")
set_target_properties(fltk:fltk PROPERTIES INTERFACE_LINK_LIBRARIES ${templist})
Or something like that.
Might work but it's only a workaround.
That's probably due to some "old code" leaking into the "Modern CMake" approach. I didn't have the time yet to rewrite everything and I'm aware that there's still something to do.
I figured this would be the root cause.
In the short term, I'm going to attempt something likeget_target_property(templist fltk:fltk INTERFACE_LINK_LIBRARIES)
list(REMOVE_ITEM templist "-no-pie")
set_target_properties(fltk:fltk PROPERTIES INTERFACE_LINK_LIBRARIES ${templist})
Or something like that.
Might work but it's only a workaround.
Exactly.
767 if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" AND NOT FLTK_BUILD_SHARED_LIBS) 768 list(APPEND OPTIONAL_LIBS "-no-pie") 769 endif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" AND NOT FLTK_BUILD_SHARED_LIBS)I believe that we can remove that '-no-pie' entirely but I'm still investigating why it was introduced in the first place. The condition used for the assignment (... AND NOT FLTK_BUILD_SHARED_LIBS) is wrong anyway in this context.
775 target_link_libraries(fltk PUBLIC ${OPTIONAL_LIBS}) 831 target_link_libraries(fltk-shared PUBLIC ${OPTIONAL_LIBS})s/PUBLIC/PRIVATE/
Very likely, I see pretty much chaos and inconsistent code in this area. :-(
I started working on this but it will take some time - definitely not today.
For now I have a short request to test: can you please comment out (or delete) the 3 lines of code in src/CMakeLists.txt that set the '-no-pie' flag in the FLTK code and try again w/o the assignment?
767 if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" AND NOT FLTK_BUILD_SHARED_LIBS) 768 list(APPEND OPTIONAL_LIBS "-no-pie") 769 endif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" AND NOT FLTK_BUILD_SHARED_LIBS)
I believe that we can remove that '-no-pie' entirely but I'm still investigating why it was introduced in the first place. The condition used for the assignment (... AND NOT FLTK_BUILD_SHARED_LIBS) is wrong anyway in this context.
Alternatively (or additionally) you could try changing the two lines that assign OPTIONAL_LIBS as PUBLIC to PRIVATE:
775 target_link_libraries(fltk PUBLIC ${OPTIONAL_LIBS}) 831 target_link_libraries(fltk-shared PUBLIC ${OPTIONAL_LIBS}) s/PUBLIC/PRIVATE/
I'd appreciate if you could test and report back, but there's no need to hurry. I won't be able to work on it today, I need some sleep. If you could do it in your TZ's "today" so I could find it here tomorrow that would be great. TIA
PS: I'm also investigating an option like "DISABLE_GLU" to solve your other issue but I'll reply to the other thread tomorrow.
On Sunday, March 17, 2024 at 3:09:57 PM UTC-7 Albrecht-S wrote:
Very likely, I see pretty much chaos and inconsistent code in this area. :-(
I started working on this but it will take some time - definitely not today.
No worries. I have my workarounds and am happy to be patient to remove them once it gets settled. It looks like this may be the tip of a larger iceberg in certain ways.
For now I have a short request to test: can you please comment out (or delete) the 3 lines of code in src/CMakeLists.txt that set the '-no-pie' flag in the FLTK code and try again w/o the assignment?
767 if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" AND NOT FLTK_BUILD_SHARED_LIBS) 768 list(APPEND OPTIONAL_LIBS "-no-pie") 769 endif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" AND NOT FLTK_BUILD_SHARED_LIBS)
Removing these lines works exactly as you would expect. Everything else is the same, the '-no-pie' does not come through to my application, everything works.
Alternatively (or additionally) you could try changing the two lines that assign OPTIONAL_LIBS as PUBLIC to PRIVATE:
775 target_link_libraries(fltk PUBLIC ${OPTIONAL_LIBS}) 831 target_link_libraries(fltk-shared PUBLIC ${OPTIONAL_LIBS}) s/PUBLIC/PRIVATE/
I made this change as well, when I did so, the INTERFACE_LINK_LIBRARIES target property changed from:
/usr/lib64/libdl.a/usr/lib64/libX11.so/usr/lib64/libXext.so/usr/lib64/libXinerama.so/usr/lib64/libXfixes.so/usr/lib64/libXcursor.so/usr/lib64/libXrender.so/usr/lib64/libpango-1.0.so/usr/lib64/libpangocairo-1.0.so/usr/lib64/libcairo.so/usr/lib64/libgobject-2.0.so/usr/lib64/libpangoxft-1.0.so/usr/lib64/libXft.so/usr/lib64/libfontconfig.so-lwayland-egl -lEGL-L/usr/lib64-lgtk-3-lgdk-3-lpangocairo-1.0-lpango-1.0-lharfbuzz-latk-1.0-lcairo-gobject-lcairo-lgdk_pixbuf-2.0-lgio-2.0-lgobject-2.0-lglib-2.0-lwayland-cursor -lwayland-client -lxkbcommon -ldl-L/usr/lib64-ldbus-1-no-pie
To:
/usr/lib64/libdl.a/usr/lib64/libX11.so/usr/lib64/libXext.so/usr/lib64/libXinerama.so/usr/lib64/libXfixes.so/usr/lib64/libXcursor.so/usr/lib64/libXrender.so/usr/lib64/libpango-1.0.so/usr/lib64/libpangocairo-1.0.so/usr/lib64/libcairo.so/usr/lib64/libgobject-2.0.so/usr/lib64/libpangoxft-1.0.so/usr/lib64/libXft.so/usr/lib64/libfontconfig.so-lwayland-egl -lEGL-L/usr/lib64$<LINK_ONLY:-lgtk-3>$<LINK_ONLY:-lgdk-3>$<LINK_ONLY:-lpangocairo-1.0>$<LINK_ONLY:-lpango-1.0>$<LINK_ONLY:-lharfbuzz>$<LINK_ONLY:-latk-1.0>$<LINK_ONLY:-lcairo-gobject>$<LINK_ONLY:-lcairo>$<LINK_ONLY:-lgdk_pixbuf-2.0>$<LINK_ONLY:-lgio-2.0>$<LINK_ONLY:-lgobject-2.0>$<LINK_ONLY:-lglib-2.0>-lwayland-cursor -lwayland-client -lxkbcommon -ldl-L/usr/lib64$<LINK_ONLY:-ldbus-1>
Of course the '-no-pie' is gone from removing the first lines.
However, the change from PUBLIC to PRIVATE added the $<LINK_ONLY:foo> wrapper around a bunch of the list items. This still worked in the end, but I am not sure if this is what is expected / intended.
For fun, I restored the first three lines, but kept the change to PRIVATE. The result of this is as follows:
[...]
So, the change to PRIVATE does not keep the -no-pie from coming through.
The subsequent build failed. So, the PRIVATE marker is not having the effect I would have expected it to.
PS: I'm also investigating an option like "DISABLE_GLU" to solve your other issue but I'll reply to the other thread tomorrow.
Thanks for all the help,