hwm2746 / brain-mesh-builder

Construct surface mesh models based on 3D image stacks of brains
GNU General Public License v3.0
3 stars 1 forks source link

Link error with GraphicsMagick-1.3.38 #1

Closed outpaddling closed 1 year ago

outpaddling commented 1 year ago

Good morning,

We're getting the following link error in our builds:

g++11 obj/bead.o obj/bead3d.o obj/brain3d.o obj/dodri_main.o obj/fnet.o obj/fnet3d.o obj/ftn_dodri.o obj/img.o obj/img3d.o obj/io_dodri.o obj/matvec.o obj/surface.o obj/io/bead3d_cmd.o obj/io/bead_cmd.o obj/io/brain3d_cmd.o obj/io/fnet3d_cmd.o obj/io/fnet_cmd.o obj/io/img3d_cmd.o obj/io/img_cmd.o obj/io/surface_cmd.o -O2 -pipe -fstack-protector-strong -Wl,-rpath=/usr/local/lib/gcc11 -Wl,-rpath=/usr/local/lib/gcc11 -Iinc -fno-strict-aliasing -pthread GraphicsMagick++-config --cppflags --ldflags --libs -o bindodri /usr/local/bin/ld: obj/bead.o: in function bead::writeImage(int, int, double*, double*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)': bead.cpp:(.text+0xac28): undefined reference toMagick::Image::draw(std::cxx11::list<Magick::Drawable, std::allocator > const&)' /usr/local/bin/ld: bead.cpp:(.text+0xac4c): undefined reference to `Magick::Image::write(std::cxx11::basic_string<char, std::char_traits, std::allocator > const&)' /usr/local/bin/ld: obj/fnet.o: in function fnet::writeImage(int, int, int, double*, double*, double*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)': fnet.cpp:(.text+0xf239): undefined reference toMagick::Image::draw(std::cxx11::list<Magick::Drawable, std::allocator > const&)' /usr/local/bin/ld: fnet.cpp:(.text+0xf248): undefined reference to `Magick::Image::draw(std::cxx11::list<Magick::Drawable, std::allocator > const&)' /usr/local/bin/ld: fnet.cpp:(.text+0xf2a2): undefined reference to Magick::Image::write(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)' /usr/local/bin/ld: obj/img.o: in functionimg::img(std::cxx11::basic_string<char, std::char_traits, std::allocator >, std::cxx11::basic_string<char, std::char_traits, std::allocator >)': img.cpp:(.text+0xabb3): undefined reference to Magick::Image::Image(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)' /usr/local/bin/ld: obj/img.o: in functionimg::writeImage(std::cxx11::basic_string<char, std::char_traits, std::allocator >, std::cxx11::basic_string<char, std::char_traits, std::allocator >, int, double, double)': img.cpp:(.text+0xbd26): undefined reference to `Magick::Image::write(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const&)' collect2: error: ld returned 1 exit status gmake[1]: [Makefile:29: bindodri] Error 1 gmake[1]: Leaving directory '/usr/ports/wip/brain-mesh-builder/work/brain-mesh-builder-v.1.0' Error code 1

The flags produced by GraphicsMagick++ look OK to me:

GraphicsMagick++-config --cppflags --ldflags --libs

-I/usr/local/include/GraphicsMagick -L/usr/local/lib -fstack-protector-strong -L/usr/local/lib -lGraphicsMagick++ -lGraphicsMagick -L/usr/local/lib -ljbig -lwebp -lwebpmux -llcms2 -ltiff -lfreetype -ljasper -ljpeg -ljxl -ljxl_threads -lpng16 -lwmflite -lXext -lSM -lICE -lX11 -llzma -lbz2 -lxml2 -lz -lm -lpthread -lomp

I'm wondering if this might be due to interface changes in the latest GraphicsMagick draw() and write() functions. Can you confirm that brain-mesh-builder work with GraphicsMagick 1.3.38?

If so, do you have any other ideas about what might cause this?

Thanks.

acchangg12 commented 1 year ago

Hello,

I verified that brain-mesh-builder works with the new GraphicsMagick 1.3.38.

I checked a couple things, and I think the issue is either from the path where GraphicsMagick++ is installed or with the GraphicsMagick++ installation itself.

Your errors suggest that your compiler can find Magick++.h, but maybe not find the necessary source files. The functions that have an "undefined reference" are in Image.h in GraphicsMagick/Magick++ of the installation. Can you find the folder (on my Linux system, this is in /usr/include) and check if the Image.h file is there? The source files where the functions are defined will be somewhere else.

There is a Magick++/demo folder in the download for GraphicsMagick, are you able to compile those stand-alone .cpp codes ok? I just used : g++ piddle.cpp -O3 -Wall -fno-strict-aliasing -pthread GraphicsMagick++-config --cppflags --ldflags --libs and it compiled.

Also, what operating system are you using? Installation may require setting some path variables (there's some description in the GraphicsMagick++ website) such that the compiler can find the necessary files.

Please don't hesitate to reach out with further questions.

outpaddling commented 1 year ago

Thanks for the quick feedback. Image.h is present:

find /usr/local/include/GraphicsMagick/ -name Image.h /usr/local/include/GraphicsMagick/Magick++/Image.h

It contains two prototypes with different interfaces for draw(), but no definitions. I would think the defs would be in libGraphicsMagic++.so, which is used by the link command.

// Draw on image using a single drawable
void            draw ( const Drawable &drawable_ );

// Draw on image using a drawable list
void            draw ( const std::list<Magick::Drawable> &drawable_ );

This is on FreeBSD using the GraphicsMagick port, which is well-tested and used by many other ports. I'm developing a brain-mesh-builder port, so that FreeBSD users can just type "pkg install brain-mesh-builder".

https://github.com/outpaddling/freebsd-ports-wip/tree/master/brain-mesh-builder

I'm not seeing any issues with the compile or link commands, hence the thought about the draw() interface. Maybe the prototypes in Image.h don't quite match the call in the eyes of my gcc.

acchangg12 commented 1 year ago

I have the same function definitions.

I think you are right in that the prototypes don't match with your gcc compiler version (g++11). In your output, the lines that contain "std::__cxx11::" would be different from the "std::" of the gcc compiler we used.

In the demo files from GraphicsMagick, there is a file, piddle.cpp, with the line: piddle.cpp: std::list drawList; For our variables, we did not specify "std::" since in globals.h, we declare "using namespace std".

Thus when you compile, the input variables are std::__cxx11, and not the std:: that the function call expects: void draw ( const std::list &drawable );_

I wonder if you can either use the g++ compiler (doing g++ -std=c++11 works as well), or you can try adding std:: to the list drawBead; line in ./src/bead.cpp (line 1249 of code) to hard-set the definition. If the error for that particular function (bead::writeImage(..)) is gone after this, then it is the difference in compilers. We may need to place std:: anywhere list is called, and potentially other related functions.

I saw online too that some people have issues with the std::__cxx11::string versus std::string. So if setting std:: as suggested above gets rid of the GraphicsMagick related issues, other errors may still pop up.

outpaddling commented 1 year ago

Doesn't seem to be a std vs std::__cxx11 issue. I tried adding std:: to the drawBead def and also tried casing the argument to draw(). Neither had any effect. I then tried adding -D_GLIBCXX_USE_CXX11_ABI=0, and interestingly I get basically the same error, but without the ::_cxx11. Maybe something to do with the std:allocator that's being added?

/usr/local/bin/ld: obj/bead.o: in function bead::writeImage(int, int, double*, double*, std::string, std::string)': bead.cpp:(.text+0xdc9a): undefined reference toMagick::Image::draw(std::list<Magick::Drawable, std::allocator > const&)' /usr/local/bin/ld: bead.cpp:(.text+0xdcba): undefined reference to Magick::Image::write(std::string const&)' /usr/local/bin/ld: obj/fnet.o: in functionfnet::writeImage(int, int, int, double, double, double, std::string, std::string)': fnet.cpp:(.text+0xf91f): undefined reference to Magick::Image::draw(std::list<Magick::Drawable, std::allocator<Magick::Drawable> > const&)' /usr/local/bin/ld: fnet.cpp:(.text+0xf92e): undefined reference toMagick::Image::draw(std::list<Magick::Drawable, std::allocator > const&)' /usr/local/bin/ld: fnet.cpp:(.text+0xf97f): undefined reference to Magick::Image::write(std::string const&)' /usr/local/bin/ld: obj/img.o: in functionimg::img(std::string, std::string)': img.cpp:(.text+0xd895): undefined reference to Magick::Image::Image(std::string const&)' /usr/local/bin/ld: obj/img.o: in functionimg::writeImage(std::string, std::string, int, double, double*)': img.cpp:(.text+0xea85): undefined reference to `Magick::Image::write(std::string const&)' collect2: error: ld returned 1 exit status gmake[1]: *** [Makefile:30: bindodri] Error 1 gmake[1]: Leaving directory '/usr/ports/wip/brain-mesh-builder/work/brain-mesh-builder-v.1.0'

acchangg12 commented 1 year ago

That's unfortunate. For sanity check, can you verify that you have the correct package installed? In a unix-like system, you can do: sudo apt install -y libgraphicsmagick++1-dev

There may be a difference in the *-dev version than the downloadable one. Just in case, here is the link to the package: https://packages.ubuntu.com/bionic/libgraphicsmagick++1-dev

outpaddling commented 1 year ago

That's exactly how I queried the GraphicsMagick version before opening the issue:

FreeBSD moray.acadix bacon ~ 999: pkg info|grep GraphicsMagick GraphicsMagick-1.3.38_4,1 Fast image processing tools based on ImageMagick

We can keep mulling over this, but #2 is a better approach for developing the FreeBSD port. Let me know if you have any insights about using clang, otherwise I'll just keep poking at it until I win.

outpaddling commented 1 year ago

I think this is not worth pursuing, since it's mostly working with clang now. Using GCC was only meant as a stop-gap until I figured out the clang issues.