I'm exploring using IBM's ICU to work with Unicode strings, by writing sample code.
Following the steps from ICU's page, I unpacked the contents of icu4c-57_1-RHEL6-x64.tgz onto /usr/local/include and /usr/local/bin, on my Linux box. Would this suffice for one to start using the ICU library?
Sample code:
#include <iostream>
#include <string.h>
#include <locale.h>
#include "unicode/coll.h"
#include "unicode/utypes.h"
using namespace icu;
using namespace std;
int main()
{
UErrorCode success = U_ZERO_ERROR;
Collator *collator = Collator::createInstance(success);
collator->setStrength(Collator::PRIMARY);
if (collator->compare("débárquér", "debarquer") == 0) {
cout << "Strings are equal" << endl;
} else {
cout << "Strings are unequal" << endl;
}
return 0;
}
Compilation of this code fails:
$ g++ unicode.cc
/tmp/ccUknunM.o: In function `main':
unicode.cc:(.text+0x20): undefined reference to `icu_4_2::Collator::createInstance(UErrorCode&)'
unicode.cc:(.text+0x61): undefined reference to `icu_4_2::UnicodeString::UnicodeString(char const*)'
unicode.cc:(.text+0x72): undefined reference to `icu_4_2::UnicodeString::UnicodeString(char const*)'
unicode.cc:(.text+0x97): undefined reference to `icu_4_2::UnicodeString::~UnicodeString()'
unicode.cc:(.text+0xaa): undefined reference to `icu_4_2::UnicodeString::~UnicodeString()'
unicode.cc:(.text+0xc3): undefined reference to `icu_4_2::UnicodeString::~UnicodeString()'
unicode.cc:(.text+0xdd): undefined reference to `icu_4_2::UnicodeString::~UnicodeString()'
collect2: ld returned 1 exit status
From the output, it appears that ICU installation is either incorrect or incomplete. What am I missing?
Thanks!
Edit:
When I search for the file coll.h, this is what I see:
$ find /usr/local/ -name coll.h
/usr/local/bin/usr/local/include/unicode/coll.h
/usr/local/include/usr/local/include/unicode/coll.h
Does this look alright?
The "steps from the ICU page" state that...
...the .tgz file unpacks to a "/usr/local" type hierarchy.
Looking at the archive contents...
$ tar tzf icu4c-57_1-RHEL6-x64.tgz
readme.txt
usr/
usr/local/
usr/local/lib/
usr/local/lib/libicudata.so.57.1
usr/local/lib/libicudata.so
usr/local/lib/libicudata.so.57
...
...you are supposed to extract that archive to root (/), not once to /usr/local/bin and once to /usr/local/include as you did. (The path repetition in your find results should have been a hint. No, it does not look alright at all.)
That being said, what you really should have done is checking your distribution's package manager for the ICU packages (libicu, libicu-dev, ...). Installing via your package manager has several advantages:
It avoids problems like the one you just encountered.
It ensures that the version of ICU you are using for your programs is the same as used by other package's programs; ending up with a binary that links two different versions of the ICU libraries is just asking for trouble.
It keeps the package updated automatically.
Depending on your distribution, you might not get the absolute latest release, but that does usually not matter much.
Once you have a functioning installtion, third-party frameworks commonly require you to explicitly state an include/ subdirectory, either in the source or the build file, to make it clear which framework(s) you are actually using. For ICU, the prefix is (somewhat unintuitively) unicode... and they don't make this explicit in their documentation, where it reads...
#include <unistr.h>
So, if you instead write...
#include "unicode/coll.h"
...it should work.
Related
I am trying to switch to Windows environment from Linux, but find it a very hard path.
This time I wanted to test if I can work with boost library.
I had problems with compiling boost on windows, so I downloaded precompiled version. I unpacked everything and tested positively that I can compile the header-only librariers.
Then I copied some simple boost::asio example. I set up everything in Eclipse. Compilation went fine, but during linking I got 'undefined reference' problem to 'boost::system' internal stuff.
C:/Users/jacek/cpp/boost_1_62_0/boost/system/error_code.hpp:221: undefined reference to `boost::system::generic_category()'
C:/Users/jacek/cpp/boost_1_62_0/boost/system/error_code.hpp:222: undefined reference to `boost::system::generic_category()'
C:/Users/jacek/cpp/boost_1_62_0/boost/system/error_code.hpp:223: undefined reference to `boost::system::system_category()'
So I added '-lboost_system', as well as the path to the libraries directory, to my linking options. But this did not help.
g++ "-LC:\\Users\\jacek\\cpp\\boost_1_62_0\\lib64-msvc-14.0" -o TestAsio.exe "src\\Main.o" -lboost_system
I checked the libraries directory and found there is a bunch of files containing 'boost_system' in the name. They are:
libboost_system-vc140-mt-1_62.lib
libboost_system-vc140-mt-gd-1_62.lib
libboost_system-vc140-mt-s-1_62.lib
libboost_system-vc140-mt-sgd-1_62.lib
libboost_system-vc140-s-1_62.lib
libboost_system-vc140-sgd-1_62.lib
I did not know which I should use. I tried adding 'libboost_system-vc140-mt-1_62' to the linking options, I tried all other files, I tried renaming the files to the linux pattern 'libboost_system.a', but nothing worked.
g++ "-LC:\\Users\\jacek\\cpp\\boost_1_62_0\\lib64-msvc-14.0" -o TestAsio.exe "src\\Main.o" -llibboost_system-vc140-mt-1_62 -llibboost_system-vc140-mt-gd-1_62 -llibboost_system-vc140-mt-s-1_62 -llibboost_system-vc140-mt-sgd-1_62 -llibboost_system-vc140-s-1_62 -llibboost_system-vc140-sgd-1_62
What am I doing wrong here?
Please help...
YotKay
I solved it myself with the help of a comment from this post: boost asio example compilation error
It looks like the precompiled version of Boost is created with Visual Studion and is NOT COMPATIBLE with G++. I if I decided to install MinGW then I cannot use the precompiled version of boost, but must compile it myself using g++.
I did that.
Now I have libraries compiled with G++.
I specify the path to the boost system library like that:
c:\Users\jacek\cpp\boost_1_62_0\libraries\boost\bin.v2\libs\system\build\gcc-mingw-6.2.0\debug\link-static\
and add this option:
-lboost_system-mgw62-d-1_62
Now the problem with boost::system disappears. However, another one pops up with boost asio, but luckily the answer is here: MinGW linker error: winsock
The example works fine now on my Windows 10 laptop.
#include <boost/asio/io_service.hpp>
#include <boost/asio/steady_timer.hpp>
#include <chrono>
#include <iostream>
using namespace boost::asio;
int main()
{
io_service ioservice;
steady_timer timer{ioservice, std::chrono::seconds{3}};
timer.async_wait([](const boost::system::error_code &ec)
{ std::cout << "3 sec\n"; });
ioservice.run();
}
This was asked several times however I don't know what I'm doing wrong. I'm trying to get the current date subtracted by 7. Here's the Main:
#include <iostream>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/date_formatting.hpp>
#include <boost/date_time/gregorian/greg_month.hpp>
using namespace std;
using namespace boost::gregorian;
int main(int argc, char **argv) {
time_t rawtime;
struct tm *timeinfo;
time (&rawtime);
timeinfo = localtime (&rawtime);
date cdate(timeinfo->tm_year+1900, timeinfo->tm_mon+1, timeinfo->tm_mday);
cdate += date_duration(-7);
string date = to_iso_string(cdate);
cout << date << endl;
return 0;
}
When I try to compile it I get the following error.
E:/include/boost/date_time/date_formatting.hpp:44: undefined reference to `boost::gregorian::greg_month::as_short_string() const'
E:/include/boost/date_time/date_formatting.hpp:49: undefined reference to `boost::gregorian::greg_month::as_long_string() const'
Can anyone help? I thought I included the neccessary files..
Boost date_time is not a header-only library. Please build the library and then add it. Simple in gcc:
gcc myapp.cpp -omyapp -lboost_date_time
(Be careful! This library sneakily appears to work as a header-only library at optimization levels -O2 and higher, due to inlining; but it will fail to link when you use lower optimization levels where the compiler's inliner isn't as aggressive.)
I think the compiler is complaining about the inclusion of boost lib.
In order to use boost::gregorian(boost::date_time), you need to use
bjam to build boost library and then link it against the FileSystem lib.
The reference of boost see click here.
EDIT: According to what you got above, the problem is that the library can't be found, mingw seems like don't know where it is. A re-installation of mingw maybe required or you can try to specify the specific path of the library.
Good luck!
you should add the link lib named
libboost_date_time-mgw46-d-1_54.dll.a
(my path D:\My Documents\Downloads\boost_1_54_0\bin.v2\libs\date_time\build\gcc-mingw-4.6.2\debug\libboost_date_time-mgw46-d-1_54.dll.a) to the compiler's path
Good luck
The reason of the linking issue is the class grep_month part of implementation is at other cpp file located in file boost_xxx_xx_x\libs\date_time\src\gregorian\greg_month.cpp. So this should be built into a static library or directly built into your target.
The other reason of why the "Release" mode with option "O2" building could pass ok, it should be caused by the final codes has not called the gregorian::greg_month related codes, and the complier ignore linking the unused function into the target, so the building is sneakily passed.
So the CyberGuy's comments in the stackoverflow website about the argument of inlining should just be a guess.
I know it's a stupid question, but still.
I want to use the QJson library in my project. I've downloaded the tarball from the official site (probably need to mention that I'm under 64-bit Ubuntu 12.04). The INSTALL file has the following instructions
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=_preferred_path_ ..
make
make install
/sbin/ldconfig, if necessary
which I followed precisely. I've got the /include, /lib and share folders of QJson added to my /usr/local.
After that, I open my IDE (which is QtCreator), and make a test project with the following simple code:
#include <QVariant>
#include <qjson/serializer.h>
int main(int argc, char *argv[])
{
QJson::Serializer s;
QVariantMap map;
map["hello"] = QVariantList() <<"t1"<<"t2";
QByteArray json = s.serialize(map);
}
The #include is handled fine, all the types are recognized, the auto-complete for the QJson classes works fine. However, when trying to compile, I'm getting this (full path removed for readability):
<...>/QJsonTest/main.cpp:15: undefined reference to `QJson::Serializer::Serializer()'
<...>/QJsonTest/main.cpp:18: undefined reference to `QJson::Serializer::serialize(QVariant const&)'
<...>/QJsonTest/main.cpp:18: undefined reference to `QJson::Serializer::~Serializer()'
<...>/QJsonTest/main.cpp:18: undefined reference to `QJson::Serializer::~Serializer()'
collect2: ld returned 1 exit status
What's the reason, and how do I make it work?
You are hitting linker (not compiler) errors. You need to add the path to your QJson library files with a -L option
I am new to using libraries and I am having some trouble with lapack++ and getting it to work. I will explain what I have done and tried so far.
First I installed BLAS and LAPACK and that went fine. I now have installed LAPACK++ version 2.5.2 (http://lapackpp.sourceforge.net/) so I can call various linear algebra routines in C/C++. After I configure, make and then make install it places all the C/C++ header files in /usr/local/include/lapackpp/ some of which are..
arch.h
bmd.h
gmf.h
lapackc.h
lautil.h
spdmd.h
ultgmd.h
bfd.h
...
and also the following files in /usr/local/lib
liblapackpp.la
liblapackpp.so
liblapackpp.so.14
liblapackpp.so.14.2.0
Now if I try to compile using g++ the simple code of
#include <lapackpp/lapackpp.h>
using namespace std;
int main(int argc, char** argv) {
return 0;
}
I get the following output...
In file included from /usr/local/include/lapackpp/lapackc.h:14,
from /usr/local/include/lapackpp/lapack.h:10,
from /usr/local/include/lapackpp/lapackpp.h:16,
from test.cpp:1:
/usr/local/include/lapackpp/lacomplex.h:45:23: error: laversion.h: No such file or directory
/usr/local/include/lapackpp/lacomplex.h:48:17: error: f2c.h: No such file or directory
In file included from /usr/local/include/lapackpp/lapackpp.h:47,
from test.cpp:1:
/usr/local/include/lapackpp/latmpl.h:36:22: error: lafnames.h: No such file or directory
I solved this problem by writing the location of the header file explicitly in the header file that was causing trouble.
Eg. I replaced
#include
with
#include
After doing this my code compiles fine.
Now if I try to compile the code
#include <cstdlib>
#include <iostream>
#include <lapackpp/lapackpp.h>
using namespace std;
int main(int argc, char** argv) {
LaGenMatDouble A(5,5);
cout << "This is a test." << endl;
return 0;
}
by typing
g++ test.cpp -o test -I usr/local/include/lapackpp
I get the following errors
/tmp/ccAq6nkP.o: In function `main':
test.cpp:(.text+0x22): undefined reference to `LaGenMatDouble::LaGenMatDouble(int, int)'
test.cpp:(.text+0x4f): undefined reference to `LaGenMatDouble::~LaGenMatDouble()'
test.cpp:(.text+0x67): undefined reference to `LaGenMatDouble::~LaGenMatDouble()'
collect2: ld returned 1 exit status
(Info on LaGenMatDouble is here )
which suggests I may be linking to the library wrong?
After some googling I realised that I needed to link to the header files using -I and the shared library by -L and the library itself by -llapackpp, so then I typed
g++ test.cpp -o test -I usr/local/include/lapackpp -L usr/local/lib -llapackpp
which compiled the code, now when I ran the program by typing ./test I go the error
./test: error while loading shared libraries: liblapackpp.so.14: cannot open shared object file: No such file or directory
and now I am confused.
I am unsure if this has anything to do with the problem but when I type
pkg-config lapackpp --libs
I get
Package lapackpp was not found in the pkg-config search path.
Perhaps you should add the directory containing `lapackpp.pc'
to the PKG_CONFIG_PATH environment variable
No package 'lapackpp' found
The same happens for lapack and blas too.
I am unsure what to do. Any help would be very much appreciated, thanks!
Linking goes fine because you tell to the linker where the library is, but execution failed because the loader doesn't know anything about the location of your libraries (you can check that performing ldd yourapp, which shows the library needed by your application).
Usually, you can solve that by telling to the loader where the library is through the variable LD_LIBRARY_PATH, but it is a crude tool. A different solution is to encode that instruction directly in the executable, as described here, or simply to link statically your application using the switch -static
If you're after a C++ library that wraps LAPACK (and/or BLAS), you might be better off using a more modern library such as Armadillo. Besides using LAPACK as a backend for solvers and matrix factorizations, it uses expression templates to speed up operations.
After looking around for various sound API libraries, I have decided to use FMOD for the time being.
Problem is that whenever I try to compile one of the code examples, I get the following errors:
obj\Release\main.o:main.cpp|| undefined reference to `FMOD::System::getVersion(unsigned int*)#8'|
obj\Release\main.o:main.cpp|| undefined reference to `FMOD::System::init(int, unsigned int, void*)#16'|
obj\Release\main.o:main.cpp|| undefined reference to `FMOD::System::createSound(char const*, unsigned int, FMOD_CREATESOUNDEXINFO*, FMOD::Sound**)#20'|
obj\Release\main.o:main.cpp|| undefined reference to `FMOD::Sound::setMode(unsigned int)#8'|
The code example that I am using being this:
#include <D:\Games\FMOD Programmers API Win32\api\inc\fmod.hpp>
#include <D:\Games\FMOD Programmers API Win32\api\inc\fmod_errors.h>
#include <sstream>
#include <windows.h> // for PlaySound()
#include <time.h>
#include <mmsystem.h>
using namespace std;
int main(int argc, char* argv[])
{
FMOD::System *system;
FMOD::Sound *sound1, *sound2, *sound3;
FMOD::Channel *channel = 0;
FMOD_RESULT result;
int key;
unsigned int version;
/*
Create a System object and initialize.
*/
result = FMOD::System_Create(&system);
result = system->getVersion(&version);
result = system->init(32, FMOD_INIT_NORMAL, 0);
result = system->createSound("../media/drumloop.wav", FMOD_HARDWARE, 0, &sound1);
result = sound1->setMode(FMOD_LOOP_OFF); /* drumloop.wav has embedded loop points which automatically makes looping turn on, */
/* so turn it off here. We could have also just put FMOD_LOOP_OFF in the above CreateSound call. */
// Code continues into other bits that work...
I am using the latest version of FMOD and am using the Code::Blocks IDE (ver 10.05), with the GNU GCC compiler. The project is of type "Console application". The fmodex.dll file is in the folder of my project. I am using windows XP 32 bit SP3.
I have linked to the libfmodex.a library and have tried linking to the other libraries it has there as well, but this does not solve the problem.
My question is, therefore, what do I need to do to stop these errors occurring? As when I encountered similar "Undefined reference to x" errors before using other libraries. I had just forgotten to link to them in Code::Blocks and as soon as I did, they would work.
Do say if you need more information regarding the code etc.
When using FMOD with Code::Blocks you need to use the C API, not the C++ API. FMOD is built with Visual Studio, therefore the C++ symbols use the VC mangling scheme. There is a note in the "Getting Started with FMOD for Windows" document that mentions this.
http://en.wikipedia.org/wiki/Name_mangling#How_different_compilers_mangle_the_same_functions
I do not have a Windows box ready to verify this on, but try replacing those backslashes with forward slashes in the include paths, or escape the backslashes.
#include <D:/Games/FMOD Programmers API Win32/api/inc/fmod.hpp>
#include <D:/Games/FMOD Programmers API Win32/api/inc/fmod_errors.h>
or
#include <D:\\Games\\FMOD Programmers API Win32\\api\\inc\\fmod.hpp>
#include <D:\\Games\\FMOD Programmers API Win32\\api\\inc\\fmod_errors.h>
(Or, better, just add D:\Games\FMOD Programmers API Win32\api\inc\ to your list of include paths, and include the files by filename instead of full path; then your code might actually compile somewhere other than your specific computer!)
Those undefined reference errors mean that the compiler, or rather the linker part of the compiler, cannot find the library.
I don't use Code::Blocks so I don't know where the setting is, but you need to tell your project to use the library and where to find it.
Just putting the DLL in the directory is enough for running the program, but for linking it you need a .lib file.