wxWidgets / wxWidgets

Cross-Platform C++ GUI Library
https://www.wxwidgets.org/
5.93k stars 1.73k forks source link

A linking error when wxRegEx is used in some autotools/libtool project #18701

Open wxtrac opened 4 years ago

wxtrac commented 4 years ago

Issue migrated from trac ticket # 18701

component: build | priority: normal | keywords: wxRegEx libtool

2020-03-18 13:08:42: anhsoft created the issue


To reproduce it, I am prepare a minimal source tree:

./
  configure.ac
  Makefile.am
  main.cpp
  a/
    a.cpp
    Makefile.am

-*/configure.ac:**

AC_PREREQ([2.69])
AC_INIT([test], [1.0])
AC_LANG([C++])
AM_INIT_AUTOMAKE([foreign no-define subdir-objects])
AM_PROG_AR
LT_PREREQ([2.4.2])
LT_INIT
AC_CONFIG_MACRO_DIRS([m4])
AC_CONFIG_SRCDIR([main.cpp])
AC_CONFIG_FILES([Makefile a/Makefile])
AC_PROG_CXX
AC_PROG_CXXCPP
AC_PROG_LIBTOOL
AC_OUTPUT

-*/Makefile.am** (PROGRAM makefile):

ACLOCAL_AMFLAGS = -I m4
SUBDIRS = a
bin_PROGRAMS = test
test_SOURCES = main.cpp
test_LDADD = a/liba.la
test_DEPENDENCIES = $(test_LDADD)

-*/main.cpp** (PROGRAM):

void foo(); // an external declaration of foo() that we call in main.cpp. foo() is an 'a' library internals, see below.

int main(int argc, char *argv[]) {
   foo(); // call 'a' library internals
   return 0;
}

-*/a/a.cpp** ('a' LTLIBRARY):

#include <wx/string.h>
#include <wx/regex.h>

void foo() {
   // Any code containing the wxRegEx class, e.g. -->

   wxRegEx RE(wxT("xyz"));
   if(RE.IsValid())
      RE.Matches(wxT("xyz"));
}

-*/a/Makefile.am** ('a' LTLIBRARY makefile):

noinst_LTLIBRARIES = liba.la
liba_la_SOURCES = a.cpp

-*Commands to prepare and configure (clarification: statically compiled wxWidgets is assumed in '/mnt/sda4/projects/linux/luna/build_wx_debug')**

libtoolize --copy
aclocal -I m4
automake --foreign --add-missing --copy
autoconf
./configure CPPFLAGS="$(/mnt/sda4/projects/linux/luna/build_wx_debug/bin/wx-config --static=yes --cppflags)" LDFLAGS="$(/mnt/sda4/projects/linux/luna/build_wx_debug/bin/wx-config --static=yes --libs)"
make

Here are the wxWidgets configs separately. Output of 'wx-config --static=yes --cppflags':

-I/mnt/sda4/projects/linux/luna/build_wx_debug/lib/wx/include/gtk3-unicode-static-3.1 -I/mnt/sda4/projects/linux/luna/build_wx_debug/include/wx-3.1 -D_FILE_OFFSET_BITS=64 -D__WXGTK__

Output of 'wx-config -static=yes --libs':

-L/mnt/sda4/projects/linux/luna/build_wx_debug/lib -pthread   /mnt/sda4/projects/linux/luna/build_wx_debug/lib/libwx_gtk3u-3.1.a -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 -pthread -lgthread-2.0 -lglib-2.0 -lX11 -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 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 -lglib-2.0 -lharfbuzz -lfontconfig -lfreetype -lwxtiff-3.1 -lwxjpeg-3.1 -lwxpng-3.1 -lwxregexu-3.1 -lwxscintilla-3.1 -lwxexpat-3.1 -lz -lz -ldl -lm 

And on make the aforementioned link error occur:

libtool: link: g++ -g -O2 -pthread -pthread -o test main.o  -L/mnt/sda4/projects/linux/luna/build_wx_debug/lib /mnt/sda4/projects/linux/luna/build_wx_debug/lib/libwx_gtk3u-3.1.a -lm a/.libs/liba.a -lgthread-2.0 -lX11 -lgtk-3 -lgdk-3 -lpangocairo-1.0 -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 -lglib-2.0 -lharfbuzz -lfontconfig -lfreetype -lwxtiff-3.1 -lwxjpeg-3.1 -lwxpng-3.1 -lwxregexu-3.1 -lwxscintilla-3.1 -lwxexpat-3.1 -lz -ldl -pthread
/usr/bin/ld.default: a/.libs/liba.a(a.o): in function `foo()':
/mnt/sda4/projects/linux/luna/build_wx_debug/include/wx-3.1/wx/regex.h:81: undefined reference to `wxRegEx::Init()'
/usr/bin/ld.default: /mnt/sda4/projects/linux/luna/build_wx_debug/include/wx-3.1/wx/regex.h:82: undefined reference to `wxRegEx::Compile(wxString const&, int)'
/usr/bin/ld.default: a/.libs/liba.a(a.o): in function `foo()':
/mnt/sda4/projects/linux/luna/regex_test/a/a.cpp:11: undefined reference to `wxRegEx::Matches(wxString const&, int) const'
/usr/bin/ld.default: /mnt/sda4/projects/linux/luna/regex_test/a/a.cpp:7: undefined reference to `wxRegEx::~wxRegEx()'
/usr/bin/ld.default: /mnt/sda4/projects/linux/luna/regex_test/a/a.cpp:7: undefined reference to `wxRegEx::~wxRegEx()'
collect2: error: ld returned 1 exit status
make[1]: *** [Makefile:452: test] Error 1

However, if I simply include the code containing the wxRegEx class from /a/a.cpp to /main.cpp then a linking process ends successfully.

The new /main.cpp (PROGRAM) that doesn't cause an error:

// Copyed from /a/a.cpp
#include <wx/string.h>
#include <wx/regex.h>

// Simply declare bar(), it's fully equivalent to foo()
void bar() {
   // Any code containing wxRegEx, e.g.

   wxRegEx RE(wxT("xxx"));
   wxString str = wxT("xxx");

   if(RE.IsValid())
      RE.Matches(str);
}

// The rest with no changes
void foo();

int main(int argc, char *argv[]) {
   foo();
   return 0;
}

-*make** output at last case:

libtool: link: g++ -g -O2 -pthread -pthread -o test main.o  -L/mnt/sda4/projects/linux/luna/build_wx_debug/lib /mnt/sda4/projects/linux/luna/build_wx_debug/lib/libwx_gtk3u-3.1.a -lm a/.libs/liba.a -lgthread-2.0 -lX11 -lgtk-3 -lgdk-3 -lpangocairo-1.0 -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 -lglib-2.0 -lharfbuzz -lfontconfig -lfreetype -lwxtiff-3.1 -lwxjpeg-3.1 -lwxpng-3.1 -lwxregexu-3.1 -lwxscintilla-3.1 -lwxexpat-3.1 -lz -ldl -pthread
wxtrac commented 4 years ago

2020-03-18 13:25:49: @vadz commented


Check libtool verbose output, something strange is going on here because libtool link line shows that liba.a comes before -lwwxregexu-3.1 but this error should only happen if it comes afterwards (because when using static libraries link order matters).

Also, you're mixing up CPP (C preprocessor) and CXX flags, you really should be using CXXFLAGS and --cxxflags instead.

In any case, I really don't think this is a problem with wxWidgets, but rather with your build system (even if I don't see what it is, immediately).

wxtrac commented 4 years ago

2020-03-18 14:47:30: anhsoft commented


It's something strange for me too. I tested the code on both Xubuntu-19.10 and SimplyLinux-rc-8.990 with same result. The --cxxflags option is really necessary for this, but as far as I know, CXXFLAGS sends an option to the compiler, not the preprocessor.