9

I am running ubuntu, and I can build ICU

I have included:

#include <unistr.h>
using namespace icu;

This is my build method for ICU:

CPPFLAGS="-DU_USING_ICU_NAMESPACE=0" 
CPPFLAGS="-DU_CHARSET_IS_UTF8=1"

export CFLAGS="-DU_CHARSET_IS_UTF8=1 -DU_GNUC_UTF16_STRING=1 -DU_STATIC_IMPLEMENTATION"
export CXXFLAGS="-DU_USING_ICU_NAMESPACE=0 -std=gnu++0x -DU_CHARSET_IS_UTF8=1 -DU_GNUC_UTF16_STRING=1 -DU_HAVE_CHAR16_T=1 -DUCHAR_TYPE=char16_t -Wall --std=c++0x -DU_STATIC_IMPLEMENTATION"
export CPPFLAGS="-DU_USING_ICU_NAMESPACE=0 -DU_CHARSET_IS_UTF8=1 -DU_STATIC_IMPLEMENTATION"
export LDFLAGS="-std=gnu++0x"

./runConfigureICU Linux --enable-static --disable-shared --disable-renaming

make check 
sudo make install

I then link to

/usr/local/lib/libicuuc.a

and try to compile

icu::UnicodeString s1=UNICODE_STRING("such characters are safe 123 %-.", 32);

but get the error

undefined reference to `icu_56::UnicodeString::UnicodeString(signed char, unsigned short const*, int)'

I found another post here on SO regarding the same problem, but when I follow the steps provided it does not fix my problem and may be a different version.

EDIT: This is the output from the IDE upon building the project

Cleaning Solution: myProject (Debug)

Cleaning: myProject (Debug)
Removing output files...
Clean complete

Building Solution: myProject (Debug)

Building: myProject (Debug)
Performing main compilation...

Precompiling headers

    Compiling source to object files
    g++  -MMD "/home/user/myProject/myProject/main.cpp" -g -O0 -std=c++11 -DDEBUG -I"/home/user/myProject/myProject/include" -I"/home/user/myProject/icu/unicode" -I"/home/user/myProject/myProject/.prec/Debug"  -c -o "/home/user/myProject/myProject/bin/Debug/main.o"

    Generating binary "myProject" from object files
    g++ -o "/home/user/myProject/myProject/bin/Debug/myProject" "/home/user/myProject/myProject/bin/Debug/main.o"
"/home/user/myProject/icu/libicuuc.a" 
    /home/user/myProject/myProject/bin/Debug/main.o: In function `icuTest':
    /home/user/myProject/myProject/icuTest.hpp:3: undefined reference to `icu_56::StringPiece::StringPiece(char const*)'
    /home/user/myProject/myProject/icuTest.hpp:3: undefined reference to `icu_56::UnicodeString::fromUTF8(icu_56::StringPiece const&)'
    /home/user/myProject/myProject/icuTest.hpp:3: undefined reference to `icu_56::UnicodeString::~UnicodeString()'
    /home/user/myProject/myProject/icuTest.hpp:3: undefined reference to `icu_56::UnicodeString::~UnicodeString()'
    collect2: error: ld returned 1 exit status
    Build complete -- 4 errors, 0 warnings

    ---------------------- Done ----------------------

    Build: 4 errors, 0 warnings
Chris
  • 2,340
  • 6
  • 40
  • 63
  • If you want to use .a file, May be you can try `/path/to/file.a` in you linker step – dlmeetei Feb 06 '16 at 21:42
  • Using `nm`, Will you have a look, which .a file have the `UnicodeString::~UnicodeString()` – dlmeetei Feb 06 '16 at 22:00
  • When I "nm libicuuc.a > dump" it does contain many references to UnicodeString but the rest is garbage so I don't know if I am looking at the deconstructor or not – Chris Feb 06 '16 at 22:28
  • Aah, I should mention to include `-C` to have demangle C++ symbols – dlmeetei Feb 06 '16 at 22:30
  • libicuuc.a does contain U icu::UnicodeString::~UnicodeString() – Chris Feb 06 '16 at 22:31
  • How are you linking? `/full/path/to/libicuuc.a` ? – dlmeetei Feb 06 '16 at 22:37
  • In my IDE under build>code generation>libraries .. where all my other .a files are linked. You can only choose .a files or .so files there so I'm certain it is the correct place to link it with the others working fine. – Chris Feb 06 '16 at 22:45
  • Yes it is using the full path /usr/local/lib/libicuuc.a – Chris Feb 06 '16 at 22:54
  • Ran out of options. Might be irrelevant now. ordering does matters in static linking. – dlmeetei Feb 06 '16 at 22:58
  • Your IDE should have an option to print the compiler command line when it's building. Activate that and post the result. – Sebastian Redl Feb 09 '16 at 07:53
  • Thankyou Sebastian, I have edited the question with my IDE's build output – Chris Feb 09 '16 at 12:28
  • if you can help me fix it I will accept your answer :) – Chris Feb 09 '16 at 13:38
  • @Chris: You say 'libicuuc.a does contain U icu::UnicodeString::~UnicodeString()' - but your question indicates that the linker is looking for 'icu_56::UnicodeString::~UnicodeString()'. Is the namespace mismatch the cause of your problem? – Jeremy Feb 17 '16 at 13:17
  • I tried using both the namespace icu and icu_56 but neither work – Chris Feb 17 '16 at 22:32
  • @Chris - Do you mean you tried configuring _the library_ both with --disable-renaming and without this switch? Or that you built _your main.cpp_ both with U_DISABLE_RENAMING set to 1 and without? Or all four combinations? Note that your question shows the library being configured with --disable-renaming (and hence using icu_56), but your main.cpp being compiled without U_DISABLE_RENAMING defined (and hence using icu). – Jeremy Feb 18 '16 at 13:45

4 Answers4

4

When you ran:

./runConfigureICU Linux --enable-static --disable-shared --disable-renaming

did you heed the warning?:

*** WARNING: You must set the following flags before code compiled against this ICU will function properly:

    -DU_DISABLE_RENAMING=1

The recommended way to do this is to prepend the following lines to source/common/unicode/uconfig.h or #include them near the top of that file.

 /* -DU_DISABLE_RENAMING=1 */
#define U_DISABLE_RENAMING 1

If not, then do so now.

Next, modify your test program to #include <unicode/uconfig.h> before anything else, e.g.

main.cpp

#include <unicode/uconfig.h>
#include <unicode/platform.h>
#include <unicode/unistr.h>

int main()
{
    icu::UnicodeString s1=UNICODE_STRING("such characters are safe 123 %-.", 32);
    (void)s1;
    return 0;
}

The it will compile and link against libicuuc.a.

You can if you wish ensure that boilerplate headers like unicode/uconfig.h and unicode/platform.h are automatically included by the the compiler before anything else by making use of a pre-include header, e.g.

icu_preinc.h

// pre-include header for icu
#include <unicode/uconfig.h>
#include <unicode/platform.h>

which you pass to GCC or clang with the option:

-include /path/to/icu_preinc.h

You can put this option in your CPPFLAGS if you use a make-based build system.

In the case of the toy program above it is enough just to define U_DISABLE_RENAMING=1 on the commandline, without including <unicode/uconfig.h>

g++ -DU_DISABLE_RENAMING=1 -o prog main.cpp -L/your/libicuuc/search/path -licuuc
Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
3

I notice that your g++ line is not pointing to /usr/local/lib/libicuuc.a where you say you installed icu. It obviously is compiling against the headers OK, but does the static library exist in the path you are using ("/home/user/myProject/icu/libicuuc.a")?

  • I should have pointed out I took it from the same place, and I have just checked the file hash which is the same, just to prove to myself. Thankyou anyway. – Chris Feb 09 '16 at 22:29
1

I think the problem is in the g++ syntax:

g++ -o "/home/user/myProject/myProject/bin/Debug/myProject" "/home/user/myProject/myProject/bin/Debug/main.o" "/home/user/myProject/icu/libicuuc.a" 

You are saying to build myProject using object file main.o and object file libicuuc.a. However, the latter is not an object file, it is a static library. I think you should modify the g++ line to:

g++ /home/user/myProject/myProject/bin/Debug/main.o -L/home/user/myProject/icu/ -licuuc -o /home/user/myProject/myProject/bin/Debug/myProject

-L/home/user/myProject/icu/ tell the linker to look for libraries in /home/user/myProject/icu/ folder and -licuuc tells it o link a library named libicuuc.a or libicuuc.so

Jakub Zaverka
  • 8,816
  • 3
  • 32
  • 48
  • I am wondering if I built ICU properly because I have done exactly as you have advised and I still get undefined reference to `icu_56::StringPiece::StringPiece(char const*)' undefined reference to `icu_56::UnicodeString::fromUTF8(icu_56::StringPiece const&)' undefined reference to `icu_56::UnicodeString::~UnicodeString()' – Chris Feb 17 '16 at 19:16
  • Then I would follow up on Jeremy's comment. The namespace you are claiming to be using is icu, but it really is icu_56 in the header files and that is what the linker complains about. You have headers with icu_56, but library with icu namespaces. So, perhaps, you really rebuilt the ICU incorrecly. – Jakub Zaverka Feb 17 '16 at 21:36
  • I tried using both the namespace icu and icu_56 but neither work, same error – Chris Feb 17 '16 at 22:32
  • It cant even get it to work with the non static .so library – Chris Feb 17 '16 at 23:34
  • What does "UNICODE_STRING" expand to? It looks like a macro. – Jakub Zaverka Feb 18 '16 at 10:11
1

note: for ICU 67 it should be using namespace icu_67.

krak'175
  • 11
  • 2