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 link problem with Xcode 15 #7670

Merged
merged 1 commit into from
Sep 25, 2023

Conversation

bjorng
Copy link
Contributor

@bjorng bjorng commented Sep 21, 2023

The dynamic libraries for the wx application would fail to build with the new linker in Xcode 15 for macOS. One workaround is to force the old linker to be used, but that will stop working when the the old linker is eventually retired.

It turns out that wx uses a very old way to create dynamic libraries. Essentially it asks the linker to accept that there are references to undefined symbols, trusting that they will be defined when the dynamic library is loaded. That is done using the following options:

-bundle -flat_namespace -undefined suppress

The option -undefined suppress is deprecated by the new linker and it will consider undefined symbols to be an error.

A more modern approaph to creating dynamic libraries is to use the the -bundle_loader option to point out an executable that can be used to satisfy references to undefined symbols:

 -bundle -bundle_loader $ERL_TOP/bin/aarch64-apple-darwin22.6.0/beam.smp

Care must be taken not to include the -bundler_loader option in configure tests that test linking, because the beam.smp executable has not been built at that time and the linker in older Xcode releases will complain if the executable does not exist. It seems that Xcode 15 will check that the executable exists only if there are references to undefined symbols.

While at it, update the ancient build instructions for wxWidgets.

@bjorng bjorng added team:VM Assigned to OTP team VM team:PS Assigned to OTP team PS fix testing currently being tested, tag is used by OTP internal CI labels Sep 21, 2023
@bjorng bjorng requested a review from dgud September 21, 2023 05:07
@bjorng bjorng self-assigned this Sep 21, 2023
@github-actions
Copy link
Contributor

github-actions bot commented Sep 21, 2023

CT Test Results

    2 files    17 suites   5m 29s ⏱️
155 tests 150 ✔️ 5 💤 0
171 runs  166 ✔️ 5 💤 0

Results for commit 94a8615.

♻️ This comment has been updated with latest results.

To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass.

See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally.

Artifacts

// Erlang/OTP Github Action Bot

HOWTO/INSTALL.md Outdated Show resolved Hide resolved
HOWTO/INSTALL.md Outdated Show resolved Hide resolved
@bjorng bjorng force-pushed the bjorn/wx/fix-xcode15-build/OTP-18768 branch from 5a2764d to cb16586 Compare September 21, 2023 10:30
@bjorng bjorng force-pushed the bjorn/wx/fix-xcode15-build/OTP-18768 branch from cb16586 to e3dfb18 Compare September 21, 2023 12:53
@jj1bdx
Copy link
Contributor

jj1bdx commented Sep 22, 2023

@bjorng

Summary

One more fix is needed for Xcode 15 to link the wx driver, to suppress undefined error messages during the configuration testing phase, by adding -undefined suppress to the linker flag.

My running environment

Mac mini 2013 M2 Pro, macOS 13.5.2, Xcode Command Line Tools 15.0, wxwidgets 3.2.2.1 from Homebrew

Synopsis

I've applied the patch in this PR to OTP-26.1, but this patch alone didn't solve the following error during running configure:

checking if we can link wxwidgets programs... no

This error prevents building wxe_driver although this error only generates following warning during configure:

configure: WARNING: Can not link wx program are all developer packages installed?

So this error does not stop the build but wxe_driver.so was not built.

The error is generated during executing the following test program:

otp/lib/wx/configure

Lines 7017 to 7082 in e3dfb18

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can link wxwidgets programs" >&5
printf %s "checking if we can link wxwidgets programs... " >&6; }
saved_LIBS=$LIBS
if test X"$WX_HAVE_STATIC_LIBS" = X"true" ; then
LIBS=$WX_LIBS_STATIC
fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include "wx/wx.h"
#include "wx/stc/stc.h"
class MyApp : public wxApp
{
virtual bool OnInit() {
// Test that we have a FromUTF8
// it isn't in too old wxWidgets versions
wxString test = wxString::FromUTF8((const char *)"foo");
wxStyledTextCtrl * foo = new wxStyledTextCtrl();
return foo;
};
};
IMPLEMENT_APP(MyApp)
_ACEOF
if ac_fn_cxx_try_link "$LINENO"
then :
CAN_LINK_WX=yes
else $as_nop
CAN_LINK_WX=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CXXFLAGS=$saved_CXXFLAGS
LIBS=$saved_LIBS
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CAN_LINK_WX" >&5
printf "%s\n" "$CAN_LINK_WX" >&6; }
if test X"$CAN_LINK_WX" != X"yes" ; then
echo "Can not link wx program are all developer packages installed?" >> ./CONF_INFO
WXERL_CAN_BUILD_DRIVER=false
if test X"$with_wx" = X"yes" ; then
as_fn_error $? "Can not link wx program are all developer packages installed?" "$LINENO" 5
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Can not link wx program are all developer packages installed?" >&5
printf "%s\n" "$as_me: WARNING: Can not link wx program are all developer packages installed?" >&2;}
fi
fi
fi

I've attached a related part of configure error log in lib/wx:

configure-error-log.txt

The error shows a massive number of undefined symbol errors as in the following excerpt:

configure:7046: g++ -o conftest  -g -Wall -fPIC -g -O2 -mmacosx-version-min=13 -Wno-deprecate
d-declarations -fno-strict-aliasing  -D_MACOSX -D_THREAD_SAFE -D_REENTRANT -I/opt/homebrew/li
b/wx/include/osx_cocoa-unicode-3.2 -I/opt/homebrew/include/wx-3.2 -D_FILE_OFFSET_BITS=64 -DWX
USINGDLL -D__WXMAC__ -D__WXOSX__ -D__WXOSX_COCOA__   -D_MACOSX -D_THREAD_SAFE -D_REENTRANT -m
macosx-version-min=13 -bundle -fPIC  conftest.cpp  >&5
In file included from conftest.cpp:31:
In file included from /opt/homebrew/include/wx-3.2/wx/wx.h:24:
In file included from /opt/homebrew/include/wx-3.2/wx/event.h:22:
In file included from /opt/homebrew/include/wx-3.2/wx/cursor.h:75:
/opt/homebrew/include/wx-3.2/wx/utils.h:749:35: warning: default member initializer for non-s
tatic data member is a C++11 extension [-Wc++11-extensions]
    wxEventLoop* m_modalEventLoop = NULL;
                                  ^
1 warning generated.
ld: Undefined symbols:
  wxEntry(int&, char**), referenced from:
      _main in conftest-610236.o
  wxTextAttr::Init(), referenced from:
      wxTextAttr::wxTextAttr() in conftest-610236.o
  wxStopWatch::Start(long), referenced from:
      wxStyledTextCtrl::wxStyledTextCtrl() in conftest-610236.o
  wxEvtHandler::QueueEvent(wxEvent*), referenced from:
      vtable for MyApp in conftest-610236.o

I suspect these undefined-symbol errors prevent building wxe_driver.so file.

Workaround

Adding -undefined suppress to the linker flag during the configuration testing phase will suppress the error, although this is not a fix of root cause.

See https://github.com/erlang/otp/compare/OTP-26.1...jj1bdx:otp:jj1bdx-otp-26.1-macOS-wx-fix?expand=1 for the diff with OTP-26.1. With this diff, the wx is successfully built and running with OTP-26.1 on macOS.

Thoughts

I am sure that this is not really a fix, and I don't know much about macOS linker issues. I hope Björn and OTP Team would deliver a much better fix than this.

@bjorng
Copy link
Contributor Author

bjorng commented Sep 22, 2023

Thanks! I have pushed a fixup commit.

It turns out that the linker test was broken when only dynamic wx libraries were available; no list of ws libraries would be given to the linker. The -undefined warning option that was used before this PR hid the bug by suppressing the errors for the undefined functions.

@jj1bdx
Copy link
Contributor

jj1bdx commented Sep 22, 2023

@bjorng bd01a1c worked fine here and wx was successfully invoked and running. Many thanks!

The dynamic libraries for the `wx` application would fail to build
with the new linker in Xcode 15 for macOS. One workaround is to force
the old linker to be used, but that will stop working when the the old
linker is eventually retired.

It turns out that `wx` uses a very old way to create dynamic
libraries. Essentially it asks the linker to accept that there are
references to undefined symbols, trusting that they will be defined
when the dynamic library is loaded. That is done using the following
options:

    -bundle -flat_namespace -undefined suppress

The option `-undefined suppress` is deprecated by the new linker and
it will consider undefined symbols to be an error.

A more modern approaph to creating dynamic libraries is to use the the
`-bundle_loader` option to point out an executable that can be used to
satisfy references to undefined symbols:

     -bundle -bundle_loader $ERL_TOP/bin/aarch64-apple-darwin22.6.0/beam.smp

Care must be taken not to include the `-bundler_loader` option in
`configure` tests that test linking, because the `beam.smp` executable
has not been built at that time and the linker in older Xcode releases
will complain if the executable does not exist. It seems that Xcode 15
will check that the executable exists only if there are references to
undefined symbols.

While at it, update the ancient build instructions for wxWidgets.
@bjorng bjorng force-pushed the bjorn/wx/fix-xcode15-build/OTP-18768 branch from bd01a1c to 94a8615 Compare September 22, 2023 06:16
@bjorng bjorng merged commit 0a03d20 into erlang:maint Sep 25, 2023
14 of 15 checks passed
@bjorng bjorng deleted the bjorn/wx/fix-xcode15-build/OTP-18768 branch September 25, 2023 06:34
@bjorng bjorng restored the bjorn/wx/fix-xcode15-build/OTP-18768 branch September 25, 2023 06:39
@bjorng bjorng deleted the bjorn/wx/fix-xcode15-build/OTP-18768 branch October 4, 2023 07:07
jj1bdx added a commit to jj1bdx/otp that referenced this pull request Oct 13, 2023
* This fix is a backport of the fix for OTP-18768 in OTP-26.1.1.
* Reference: erlang#7670
jj1bdx added a commit to jj1bdx/otp that referenced this pull request Oct 13, 2023
* This fix is a backport of the fix for OTP-18768 in OTP-26.1.1.
* Reference: erlang#7670
@yarisx yarisx mentioned this pull request Jan 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fix team:PS Assigned to OTP team PS team:VM Assigned to OTP team VM testing currently being tested, tag is used by OTP internal CI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants