Undefined references when compiling

I built OCC as static libraries, and now I want to build a static binary for portability.  My code is:

// STEP Read Methods
#include <STEPControl_Reader.hxx>
#include <TopoDS_Shape.hxx>
// STL Read & Write Methods
#include <StlAPI_Writer.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
// Bounding Box
#include <BRepBndLib.hxx> //bb
#include <Bnd_Box.hxx> //bb
// Volume
#include <BRepGProp.hxx> //vol
#include <GProp_GProps.hxx> //vol


#include <iostream>

int step2stl(char *in, char *out) {

  double Xmin, Ymin, Zmin, Xmax, Ymax, Zmax; //bb

  // Read from STEP
  STEPControl_Reader reader;
  IFSelect_ReturnStatus stat = reader.ReadFile(in);

  Standard_Integer NbRoots = reader.NbRootsForTransfer();
  Standard_Integer NbTrans = reader.TransferRoots();
  TopoDS_Shape Original_Solid = reader.OneShape();


  // get vol
  GProp_GProps gprops;
  BRepGProp::VolumeProperties(Original_Solid, gprops);
  double volume = gprops.Mass();

  // Get bounding box dimensions
  Bnd_Box B; //bb

  BRepBndLib::Add(Original_Solid, B); //bb
  B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax); //bb

  //bb print bounding box params
  // X
  std::cout << "Xmin: " << Xmin << "\n";
  std::cout << "Xmax: " << Xmax << "\n";
  std::cout << "Xsize: "<< Xmax-Xmin << "\n";
  // Y
  std::cout << "Ymin: " << Ymin << "\n";
  std::cout << "Ymax: " << Ymax << "\n";
  std::cout << "Ysize: "<< Ymax-Ymin << "\n";
  // Z
  std::cout << "Zmin: " << Zmin << "\n";
  std::cout << "Zmax: " << Zmax << "\n";
  std::cout << "Zsize: "<< Zmax-Zmin << "\n";
  // Volume
  std::cout << "Volume: "<< volume << "\n";
  // end marker for parsing
  std::cout <<"end\n";


  // Write to STL
  StlAPI_Writer stlWriter = StlAPI_Writer();
  //stlWriter.SetCoefficient(0.0001);
  stlWriter.ASCIIMode() = Standard_False;

  BRepMesh_IncrementalMesh Mesh( Original_Solid, 0.6 );

  Mesh.Perform();

  stlWriter.Write( Original_Solid, out);

  return 0;
}


Standard_Integer main (int argc, char *argv[]) {
  if (argc != 3) {
      std::cerr << "Usage: " << argv[0] << " file.step file.stl" << std::endl;
      return 1;
  }

  return step2stl(argv[1], argv[2]);
}

I'm using clang++ on Ubuntu to compile.

Before, I built the OCC dynamic library, and this code worked fine:

clang++ -std=c++11 -stdlib=libc++ -I/usr/local/include/oce -I/usr/include -ggdb3   -c -o main.o main.cpp

clang++ -std=c++11 -stdlib=libc++ -L/usr/local/lib -L/usr/lib -lTKBRep -lTKG2d -lTKG3d -lTKGeomBase -lTKMath -lTKMesh -lTKSTEP -lTKSTEP209 -lTKTopAlgo -lTKSTEPAttr -lTKSTEPBase -lTKSTL -lTKXSBase -lTKernel  -o step2stl main.o

Now, I want to compile from the static library, and I enter this:

clang++ -std=c++11 -stdlib=libc++ -I/usr/local/include/opencascade -I/usr/include -ggdb3   -c -o main.o main.cpp -static

clang++ -std=c++11 -stdlib=libc++ -L/usr/local/lib -L/usr/lib -L/usr/local/include/opencascade -lTKBRep -lTKG2d -lTKG3d -lTKGeomBase -lTKMath -lTKMesh -lTKSTEP -lTKSTEP209 -lTKTopAlgo -lTKSTEPAttr -lTKSTEPBase -lTKSTL -lTKXSBase -lTKernel  -o step2stl main.o -static

From here I get many errors:

/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/libc++.a(iostream.cpp.o):(.data.rel.ro._ZTINSt3__110__stdinbufIcEE[_ZTINSt3__110__stdinbufIcEE]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info'
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/libc++.a(iostream.cpp.o):(.data.rel.ro._ZTINSt3__110__stdinbufIwEE[_ZTINSt3__110__stdinbufIwEE]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info'
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/libc++.a(iostream.cpp.o):(.data.rel.ro._ZTINSt3__111__stdoutbufIcEE[_ZTINSt3__111__stdoutbufIcEE]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info'
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/libc++.a(iostream.cpp.o):(.data.rel.ro._ZTINSt3__111__stdoutbufIwEE[_ZTINSt3__111__stdoutbufIwEE]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info'
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/libc++.a(locale.cpp.o): In function `std::__1::__cloc()':
(.text+0x2c): undefined reference to `__cxa_guard_acquire'
(.text+0x56): undefined reference to `__cxa_guard_release'
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/libc++.a(locale.cpp.o): In function `std::__1::__time_put::~__time_put()':
(.text+0x1a04): undefined reference to `__cxa_guard_acquire'
(.text+0x1a2e): undefined reference to `__cxa_guard_release'
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/libc++.a(locale.cpp.o): In function `std::__1::__throw_runtime_error(char const*)':
(.text+0x3dcd): undefined reference to `__cxa_allocate_exception'
(.text+0x3de2): undefined reference to `typeinfo for std::runtime_error'
(.text+0x3de9): undefined reference to `std::runtime_error::~runtime_error()'
(.text+0x3df1): undefined reference to `__cxa_throw'
(.text+0x3dfc): undefined reference to `__cxa_free_exception'
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/libc++.a(locale.cpp.o): In function `std::__1::locale::__imp::__imp(unsigned long)':
(.text+0x5b7e): undefined reference to `__cxa_guard_acquire'
(.text+0x5bac): undefined reference to `__cxa_guard_release'
(.text+0x5bbd): undefined reference to `__cxa_guard_acquire'
(.text+0x5beb): undefined reference to `__cxa_guard_release'
(.text+0x5bfc): undefined reference to `__cxa_guard_acquire'
(.text+0x5c2a): undefined reference to `__cxa_guard_release'
(.text+0x5c3b): undefined reference to `__cxa_guard_acquire'
(.text+0x5c69): undefined reference to `__cxa_guard_release'
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/libc++.a(locale.cpp.o): In function `std::__1::locale::__imp::__imp(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long)':
(.text+0x696b): undefined reference to `__cxa_guard_acquire'
(.text+0x69a8): undefined reference to `__cxa_guard_release'
(.text+0x6a1b): undefined reference to `__cxa_guard_abort'
(.text+0x6b68): undefined reference to `__cxa_begin_catch'
(.text+0x6bbb): undefined reference to `__cxa_rethrow'
(.text+0x6bc3): undefined reference to `__cxa_end_catch'
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/libc++.a(locale.cpp.o): In function `std::__1::locale::classic()':
(.text+0x6c0c): undefined reference to `__cxa_guard_acquire'
(.text+0x6c45): undefined reference to `__cxa_guard_release'
(.text+0x6c56): undefined reference to `__cxa_guard_abort'
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/libc++.a(locale.cpp.o): In function `std::__1::locale::__imp::__imp(std::__1::locale::__imp const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int)':
(.text+0x7786): undefined reference to `__cxa_begin_catch'
(.text+0x77d9): undefined reference to `__cxa_rethrow'
(.text+0x77e1): undefined reference to `__cxa_end_catch'
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/libc++.a(locale.cpp.o): In function `std::__1::locale::__imp::__imp(std::__1::locale::__imp const&, std::__1::locale::__imp const&, int)':
(.text+0x7b01): undefined reference to `__cxa_begin_catch'
.
.
.
.
.
.
#many lines later...
(.text+0x1d21): undefined reference to `pthread_mutex_unlock'
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/libgcc_eh.a(unwind-dw2-fde-dip.o): In function `__register_frame_info_bases.part.6':
(.text+0x1834): undefined reference to `pthread_mutex_unlock'
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/libgcc_eh.a(unwind-dw2-fde-dip.o): In function `__register_frame_info_table_bases':
(.text+0x1944): undefined reference to `pthread_mutex_unlock'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Please help.  My end goal is to create a static portable binary.

 

Thanks

Kevin Carpenter's picture

If I change to libstdc++, I get a different set of errors:

clang++ -std=c++11 -stdlib=libstdc++ -I/usr/local/include/opencascade -I/usr/include -ggdb3   -c -o main.o main.cpp -static

clang++ -std=c++11 -stdlib=libstdc++ -L/usr/local/lib -L/usr/lib -L/usr/local/include/opencascade -lTKBRep -lTKG2d -lTKG3d -lTKGeomBase -lTKMath -lTKMesh -lTKSTEP -lTKSTEP209 -lTKTopAlgo -lTKSTEPAttr -lTKSTEPBase -lTKSTL -lTKXSBase -lTKernel  -o step2stl main.o -static

gives:

main.o: In function `step2stl(char*, char*)':
/mnt/c/converters/step2stl/test/main.cpp:24: undefined reference to `STEPControl_Reader::STEPControl_Reader()'
/mnt/c/converters/step2stl/test/main.cpp:25: undefined reference to `XSControl_Reader::ReadFile(char const*)'
/mnt/c/converters/step2stl/test/main.cpp:27: undefined reference to `STEPControl_Reader::NbRootsForTransfer()'
/mnt/c/converters/step2stl/test/main.cpp:28: undefined reference to `XSControl_Reader::TransferRoots()'
/mnt/c/converters/step2stl/test/main.cpp:29: undefined reference to `XSControl_Reader::OneShape() const'
/mnt/c/converters/step2stl/test/main.cpp:38: undefined reference to `GProp_GProps::GProp_GProps()'
/mnt/c/converters/step2stl/test/main.cpp:39: undefined reference to `BRepGProp::VolumeProperties(TopoDS_Shape const&, GProp_GProps&, bool, bool, bool)'
/mnt/c/converters/step2stl/test/main.cpp:40: undefined reference to `GProp_GProps::Mass() const'
/mnt/c/converters/step2stl/test/main.cpp:43: undefined reference to `Bnd_Box::Bnd_Box()'
/mnt/c/converters/step2stl/test/main.cpp:45: undefined reference to `BRepBndLib::Add(TopoDS_Shape const&, Bnd_Box&, bool)'
/mnt/c/converters/step2stl/test/main.cpp:46: undefined reference to `Bnd_Box::Get(double&, double&, double&, double&, double&, double&) const'
/mnt/c/converters/step2stl/test/main.cpp:68: undefined reference to `StlAPI_Writer::StlAPI_Writer()'
/mnt/c/converters/step2stl/test/main.cpp:72: undefined reference to `BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh(TopoDS_Shape const&, double, bool, double, bool)'
/mnt/c/converters/step2stl/test/main.cpp:74: undefined reference to `BRepMesh_IncrementalMesh::Perform()'
/mnt/c/converters/step2stl/test/main.cpp:76: undefined reference to `StlAPI_Writer::Write(TopoDS_Shape const&, char const*)'
/mnt/c/converters/step2stl/test/main.cpp:79: undefined reference to `BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh()'
/mnt/c/converters/step2stl/test/main.cpp:79: undefined reference to `BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh()'
main.o: In function `opencascade::handle<TopLoc_SListNodeOfItemLocation>::EndScope()':
/usr/local/include/opencascade/Standard_Handle.hxx:393: undefined reference to `Standard_Transient::DecrementRefCounter() const'
main.o: In function `opencascade::handle<TopoDS_TShape>::EndScope()':
/usr/local/include/opencascade/Standard_Handle.hxx:393: undefined reference to `Standard_Transient::DecrementRefCounter() const'
main.o: In function `~XSControl_Reader':
/usr/local/include/opencascade/XSControl_Reader.hxx:91: undefined reference to `vtable for XSControl_Reader'
main.o: In function `NCollection_Sequence<TopoDS_Shape>::Clear(opencascade::handle<NCollection_BaseAllocator> const&)':
/usr/local/include/opencascade/NCollection_Sequence.hxx:170: undefined reference to `NCollection_BaseSequence::ClearSeq(void (*)(NCollection_SeqNode*, opencascade::handle<NCollection_BaseAllocator>&))'
main.o: In function `opencascade::handle<NCollection_BaseAllocator>::EndScope()':
/usr/local/include/opencascade/Standard_Handle.hxx:393: undefined reference to `Standard_Transient::DecrementRefCounter() const'
main.o: In function `opencascade::handle<NCollection_BaseAllocator>::BeginScope()':
/usr/local/include/opencascade/Standard_Handle.hxx:387: undefined reference to `Standard_Transient::IncrementRefCounter() const'
main.o: In function `NCollection_BaseSequence::operator delete(void*)':
/usr/local/include/opencascade/NCollection_BaseSequence.hxx:53: undefined reference to `Standard::Free(void*)'
main.o: In function `opencascade::handle<XSControl_WorkSession>::EndScope()':
/usr/local/include/opencascade/Standard_Handle.hxx:393: undefined reference to `Standard_Transient::DecrementRefCounter() const'
main.o: In function `NCollection_Sequence<opencascade::handle<Standard_Transient> >::Clear(opencascade::handle<NCollection_BaseAllocator> const&)':
/usr/local/include/opencascade/NCollection_Sequence.hxx:170: undefined reference to `NCollection_BaseSequence::ClearSeq(void (*)(NCollection_SeqNode*, opencascade::handle<NCollection_BaseAllocator>&))'
main.o: In function `opencascade::handle<Standard_Transient>::EndScope()':
/usr/local/include/opencascade/Standard_Handle.hxx:393: undefined reference to `Standard_Transient::DecrementRefCounter() const'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Now it seems to have a linking issue with the occ libs or header files??

Kirill Gavrilov's picture

The order is critical when passing arguments to compiler. The order include NOT just OCCT libraries, but also your own libraries (main.o - consider renaming you static library to mylib.a to avoid confusion), system libraries (-dl, -lpthread), C/C++ runtime and libraries (-lstdc++).
Follow compiler logic literally:

  • -lTKMesh
    OK, no symbols to resolve, just ignore it
  • main.o
    OK, link symbols from main.o to executable.
    At this moment your executable is probably extened by new object code calling OCCT libraries, but they are not linked.
  • -static
    This is not an opposite to -shared, make sure that you really need this flag for making your executable.

See unresolved symbols from TKMesh like BRepMesh_IncrementalMesh - try moving -lTKMesh after the object code using TKMesh.
See unresolved symbols from pthreads like pthread_mutex_unlock - try adding -lpthread at the end of the list.
 

Oliver R's picture

I do not have the static libs build but here is a shot in the dark: try with a different link order:

-lTKBin -lTKBinL -lTKBinTObj -lTKBinXCAF -lTKBO -lTKBool -lTKBRep -lTKCAF -lTKCDF -lTKDCAF -lTKDraw -lTKernel -lTKFeat -lTKFillet -lTKG2d -lTKG3d -lTKGeomAlgo -lTKGeomBase -lTKHLR -lTKIGES -lTKLCAF -lTKMath -lTKMesh -lTKMeshVS -lTKOffset -lTKOpenGl -lTKPrim -lTKQADraw -lTKRWMesh -lTKService -lTKShHealing -lTKStd -lTKStdL -lTKSTEP209 -lTKSTEP -lTKSTEPAttr -lTKSTEPBase -lTKSTL -lTKTObj -lTKTObjDRAW -lTKTopAlgo -lTKTopTest -lTKV3d -lTKVCAF -lTKViewerTest -lTKVRML -lTKXCAF -lTKXDEDRAW -lTKXDEIGES -lTKXDESTEP -lTKXMesh -lTKXml -lTKXmlL -lTKXmlTObj -lTKXmlXCAF -lTKXSBase -lTKXSDRAW

Kevin Carpenter's picture

That did not seem to have an effect.  It gave me the same errors as my second post...

g b's picture

I think I have a very similar problem. I also get the unknown reference error for BRepMesh_IncrementalMesh constructor.

Here is m CMake file

cmake_minimum_required(VERSION 3.5)

project(testOCCT LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include_directories(/home/user/opencascade/build_d/include/opencascade/)

find_package(Qt5Core)

add_executable(testOCCT
  main.cpp
)

target_link_libraries(testOCCT Qt5::Core)

set(OCCT_LIBS TKMesh; TKSTEP; TKSTL; TKXSBase; TKernel)
target_link_libraries(testOCCT ${OCCT_LIBS})

and this is the code

// STEP Read Methods
#include <STEPControl_Reader.hxx>
#include <TopoDS_Shape.hxx>
// STL Read & Write Methods
#include <StlAPI_Writer.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRep_Builder.hxx>

#include <iostream>

int step2stl(char *in, char *out) {

    // Read from STEP
    STEPControl_Reader reader;
    IFSelect_ReturnStatus stat = reader.ReadFile(in);

    Standard_Integer NbRoots = reader.NbRootsForTransfer();
    Standard_Integer NbTrans = reader.TransferRoots();
    TopoDS_Shape Original_Solid = reader.OneShape();

    // Write to STL
    StlAPI_Writer stlWriter = StlAPI_Writer();
    stlWriter.ASCIIMode() = Standard_False;

    BRepMesh_IncrementalMesh Mesh(Original_Solid, 0.1);

    Mesh.Perform();
    stlWriter.Write( Original_Solid, out);

    return 0;
}


Standard_Integer main (int argc, char *argv[])
{
  char infile[] = "/home/user/test/screw.step";
  char ofile[] = "/home/user/test/out.stl";
  return step2stl(infile, ofile);
}

This will result in the error:

main.cpp:30: error: undefined reference to `BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh(TopoDS_Shape const&, double, bool, double, bool)'

EDIT:

I found the solution to my problem at least. I forgot to add

link_directories(/home/user/opencascade/build_r/lin64/gcc/lib/)

and since I had compiled occ by myself, but also had installed some dev libs over the packet management it could find the libraries from the packet management and did  not complain, however the version was different and they did not work.
So maybe something similar could also be the case for your problem?