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 issue #3795 - Fix LDC linked dynamically with Phobos and DRuntime when built with GDMD. #3810

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 52 additions & 2 deletions cmake/Modules/ExtractDMDSystemLinker.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,63 @@ list(GET linker_line 0 D_LINKER_COMMAND)
list(REMOVE_AT linker_line 0)

if("${D_COMPILER_ID}" STREQUAL "GDMD")
# Filter linker arguments for those we know can be safely reused
# Filter linker arguments for those we know can be safely reused.
# Prepend arguments starting with "-B" in D_LINKER_ARGS with "-Wl," when
# using GDMD. The latter is needed because the arguments reported by GDMD
# are what is passed to COLLECT2 while D_LINKER_ARGS are later passed to
# CXX. The problem with that is that without "-Wl," prefix the -Bstatic
# and -Bdynamic arguments before and after -lgphobos and -lgdruntime are
# dropped. And that is a problem because without these the produced LDC is
# linked dynamically to libgphobos and libgdruntime so these have to be
# available whereever LDC is used.
Comment on lines +72 to +76
Copy link
Contributor

@ibuclaw ibuclaw Aug 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what you are describing is something specific to Debian and all its derivatives (Ubuntu, etc...)

https://salsa.debian.org/toolchain-team/gcc/-/blob/gcc-9-debian/debian/patches/gdc-dynamic-link-phobos.diff

There exists the driver option -static-libphobos which covers what looks to be your intent for messing around with -Bdynamic and -Bstatic.

So you can simplify this as just -static-libphobos -Wl,--allow-multiple-definition.

Copy link
Contributor Author

@dbankov-vmware dbankov-vmware Aug 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ibuclaw I'm building GDC from the source in GCC 9.3 and if used directly my GDC version links both Phobos and DRuntime statically by default.

The problem occurs only when building LDC because when -DLDC_LINK_MANUALLY=ON (which is the default for GDMD) instead of calling GDMD for linking LDC build script calls CXX for linking. Now to make sure that the correct libraries (phobos and druntime) are linked by CXX, LDC build script extracts the link line from a call to GDMD with -v and then copies all arguments which start with -L, -l and -B in a list which is later passed to CXX. The problem here is that for GDMD the link line reported by -v is what is passed to COLLECT2 (which are practically parameters passed to LD) and then when LDC build script passes these directly to CXX only parameters starting with -L and -l are honoured while these starting with -B are simply dropped. The result is that although the link line reported by GDMD contains -Bstatic before -lgphobos and -lgdruntime and -Bdynamic after these when CXX is linking LDC it drops the parameters starting -B and LDC ends up being linked dynamically with Phobos and DRuntime. What was needed was for parameters starting with -B from the link line reported by GDMD to be prepended with -Wl, in LDC build script so when these are passed to CXX it to correctly redirect them to LD.


# Once libgphobos and libgdruntime are linked statically symbol conflicts
# for _d_allocmemory, _d_newclass, _d_newitemiT and _d_newitemT symbols
# were revealed which are fixed by checking if these symbols are marked as
# weak in libgdruntime.a and if not "-Wl,-allow-multiple-definition" link
# option is added to avoid link failure.
set(D_LINKER_ARGS)
set(BSTATIC OFF)
set(STATIC_GPHOBOS OFF)
foreach(arg ${linker_line})
if("${arg}" MATCHES ^-L.*|^-l.*|^-B.*)
if("${arg}" MATCHES ^-L.*|^-l.*)
list(APPEND D_LINKER_ARGS "${arg}")
if(BSTATIC)
if("${arg}" STREQUAL -lgphobos)
set(STATIC_GPHOBOS ON)
endif()
endif()
elseif("${arg}" MATCHES ^-B.*)
list(APPEND D_LINKER_ARGS "-Wl,${arg}")
if("${arg}" STREQUAL -Bstatic)
set(BSTATIC ON)
elseif("${arg}" STREQUAL -Bdynamic)
set(BSTATIC OFF)
endif()
endif()
endforeach()
if(STATIC_GPHOBOS)
execute_process(
COMMAND "${D_COMPILER}" -q,-print-file-name=libgdruntime.a
COMMAND "head" -n1
COMMAND "xargs" nm -gC
COMMAND "grep"
-e \\<_d_allocmemory\\>
-e \\<_d_newclass\\>
-e \\<_d_newitemiT\\>
-e \\<_d_newitemT\\>
COMMAND "cut" -d " " -f 2
COMMAND "sort"
COMMAND "uniq"
OUTPUT_VARIABLE LIB_GDRUNTIME_LIFETIME_SYMBOL_TYPES
ERROR_QUIET)
string(STRIP
${LIB_GDRUNTIME_LIFETIME_SYMBOL_TYPES}
LIB_GDRUNTIME_LIFETIME_SYMBOL_TYPES)
if(NOT LIB_GDRUNTIME_LIFETIME_SYMBOL_TYPES STREQUAL W)
list(APPEND D_LINKER_ARGS "-Wl,--allow-multiple-definition")
endif()
endif()
else()
set(D_LINKER_ARGS ${linker_line})
endif()