2

I'm trying to use NTL library, but I always get compiler errors about undefined symbols.

Example (taken from the NTL documentation):

#include <NTL/ZZ.h>

NTL_CLIENT

int main()
{
   ZZ a, b, c; 

   cin >> a; 
   cin >> b; 
   c = (a+1)*(b+1);
   cout << c << "\n";
}

Result:

$ g++ -lntl simple.cpp
/tmp/ccGwxURb.o: In function `main':
simple.cpp:(.text+0x3a): undefined reference to `NTL::operator>>(std::basic_istream<char, std::char_traits<char> >&, NTL::ZZ&)'
simple.cpp:(.text+0x4b): undefined reference to `NTL::operator>>(std::basic_istream<char, std::char_traits<char> >&, NTL::ZZ&)'
simple.cpp:(.text+0xda): undefined reference to `NTL::operator<<(std::basic_ostream<char, std::char_traits<char> >&, NTL::ZZ const&)'
/tmp/ccGwxURb.o: In function `NTL::ZZ::operator=(NTL::ZZ const&)':
simple.cpp:(.text._ZN3NTL2ZZaSERKS0_[NTL::ZZ::operator=(NTL::ZZ const&)]+0x22): undefined reference to `_ntl_gcopy'
/tmp/ccGwxURb.o: In function `NTL::ZZ::~ZZ()':
simple.cpp:(.text._ZN3NTL2ZZD2Ev[_ZN3NTL2ZZD5Ev]+0x14): undefined reference to `_ntl_gfree'
/tmp/ccGwxURb.o: In function `NTL::add(NTL::ZZ&, NTL::ZZ const&, long)':
simple.cpp:(.text._ZN3NTL3addERNS_2ZZERKS0_l[NTL::add(NTL::ZZ&, NTL::ZZ const&, long)]+0x2a): undefined reference to `_ntl_gsadd'
/tmp/ccGwxURb.o: In function `NTL::mul(NTL::ZZ&, NTL::ZZ const&, NTL::ZZ const&)':
simple.cpp:(.text._ZN3NTL3mulERNS_2ZZERKS0_S3_[NTL::mul(NTL::ZZ&, NTL::ZZ const&, NTL::ZZ const&)]+0x2d): undefined reference to `_ntl_gmul'
collect2: ld returned 1 exit status

The NTL headers are in /usr/include/NTL, so they should be included.

What's the problem? Am I compiling in the wrong way? If so, where can I find the right way, since it seems like there is not such a thing like "how to compile with ntl" in the documentation?

If I use using namespace NTL instead of NTL_CLIENT nothing changes:

$ ls /usr/lib | grep libntl
libntl-5.4.2.so
libntl.a
libntl.so
$ ls /usr/include | grep NTL
NTL
$ g++ -L/usr/lib -lntl -lgmp -lm simple.cpp
/tmp/ccwdQkr4.o: In function `main':
simple.cpp:(.text+0x3a): undefined reference to `NTL::operator>>(std::basic_istream<char, std::char_traits<char> >&, NTL::ZZ&)'
simple.cpp:(.text+0x4b): undefined reference to `NTL::operator>>(std::basic_istream<char, std::char_traits<char> >&, NTL::ZZ&)'
simple.cpp:(.text+0xda): undefined reference to `NTL::operator<<(std::basic_ostream<char, std::char_traits<char> >&, NTL::ZZ const&)'
/tmp/ccwdQkr4.o: In function `NTL::ZZ::operator=(NTL::ZZ const&)':
simple.cpp:(.text._ZN3NTL2ZZaSERKS0_[NTL::ZZ::operator=(NTL::ZZ const&)]+0x22): undefined reference to `_ntl_gcopy'
/tmp/ccwdQkr4.o: In function `NTL::ZZ::~ZZ()':
simple.cpp:(.text._ZN3NTL2ZZD2Ev[_ZN3NTL2ZZD5Ev]+0x14): undefined reference to `_ntl_gfree'
/tmp/ccwdQkr4.o: In function `NTL::add(NTL::ZZ&, NTL::ZZ const&, long)':
simple.cpp:(.text._ZN3NTL3addERNS_2ZZERKS0_l[NTL::add(NTL::ZZ&, NTL::ZZ const&, long)]+0x2a): undefined reference to `_ntl_gsadd'
/tmp/ccwdQkr4.o: In function `NTL::mul(NTL::ZZ&, NTL::ZZ const&, NTL::ZZ const&)':
simple.cpp:(.text._ZN3NTL3mulERNS_2ZZERKS0_S3_[NTL::mul(NTL::ZZ&, NTL::ZZ const&, NTL::ZZ const&)]+0x2d): undefined reference to `_ntl_gmul'
collect2: ld returned 1 exit status
$ cat simple.cpp
#include <NTL/ZZ.h>

using namespace NTL;

int main()
{
   ZZ a, b, c; 

   std::cin >> a; 
   std::cin >> b; 
   c = (a+1)*(b+1);
   std::cout << c << "\n";
}
Bakuriu
  • 98,325
  • 22
  • 197
  • 231

5 Answers5

3

These are not compiler errors. These are linker errors. It isn't sufficient to include the header during compilation. You also need to specify the libraries being used during linking.

I don't know about NTL so I don't know which library needs to be included but I would expect that it is mentioned somewhere in whatever documentation is available. A quick search with Google seems to indicate that you need to use -lntl (assuming the library is installed in a standard directory).

Note that traditionally C compilers process the command line from left to right, so you should add -lntl before the source file that uses the NTL library.

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • This answer misses the point: 1) If you read my question you can see I *do* use `-lntl`, and I also mentioned the fact that the NTL are installed correctly[yes, I've just said the headers were in the correct place, but I double checked and there is a libntl.so in /usr/lib]. 2) There is no such a thing as "documentation" for NTL. I've found a brief explanation on compilation, but it does not solve the problem. – Bakuriu Aug 27 '12 at 10:53
  • 1
    Well, you don't use `-lntl` to resolve symbols. It is correct that I didn't see it but mentioning it first is not where I was looking: object files, including libraries, are processed left to right. Mention the libraries after your source if you want to get the symbols resolved. – Dietmar Kühl Aug 27 '12 at 11:03
  • Okay, putting the "-lX" after the argument works. But I don't understand why this should happen. Why does order matter? And also, I've always thought the "correct" way to call a program is `$ name [options] arguments...`, so why `g++` wants arguments before options? – Bakuriu Aug 27 '12 at 11:30
  • Linking traditionally just processes objects left to right. For source or object files the respective unit is always included and symbols added as resolved/unresolved as in the objects. The "-lX" options aren't really options but a shortcut for `/lubX.a‘. The archives are searched for currently unresolved symbols and object pulled in as needed. I think this this just used to avoid the potential to rescan libraries on low-resource systems. – Dietmar Kühl Aug 27 '12 at 11:50
  • I was having this problem, then -lntl fixed it all. Thanks @DietmarKühl – CtheGood May 27 '15 at 17:17
2

I had the same issue and after reading the NTL docs, I used the following:

g++ -g -O2 -std=c++11 -pthread -march=native foo.cpp -o foo -lntl -lgmp -lm

I think the gmp library is also required alongside with ntl.

Mairon
  • 621
  • 8
  • 21
0

I had somewhat of the same problem when I first started using the library. After having compiled the library, every time you use the library for a project, you have to go to Project > Add Existing Item (shortcut key: Ctrl+Shift+A) and select the .lib file you produced when compiling the library.

If this doesn't work, feel free to Inbox me and I can send you detailed instructions I have documented on how to Compile the library and utilize it.

Patrick M
  • 10,547
  • 9
  • 68
  • 101
SS-Mag
  • 38
  • 5
  • 1
    Welcome to StackOverflow. Your answer seems to be framed on using an IDE (perhaps Visual Studio), but it is not clear that the asker is using or not. To make your answer more valuable to others, it is better to include all the information you have on the topic. Please consider adding at least an overview of your compilation steps. – Patrick M Jul 09 '14 at 20:32
  • 1
    @user3727590: I do not think it is proper on StackOverflow to invite somebody to have a private mail exchange about the solution of a problem... instead please help the community posting a full answer clarifying all the details you want to write by mail :) – Morix Dev Jul 09 '14 at 20:32
0

Hi to solve this problem you should run program by terminal for example

 g++ simple.cpp -o simple -lntl

then to show result write

./simple
thor
  • 21,418
  • 31
  • 87
  • 173
M.esmail
  • 11
  • 1
0

I had a similar issue. I was using Codelite IDE on ubuntu. I solved the issue by changing the order in Setting --> Linker --> Libraries as follows:

ntl gmp

When the order is different (gmp;ntl) then I was getting the error.

So please check the order and move ntl first before gmp

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 05 '21 at 12:30