GrammaTech / gtirb

Intermediate Representation for Binary analysis and transformation
https://grammatech.github.io/gtirb/
Other
305 stars 36 forks source link

Examples Fail #32

Closed jpc0016 closed 4 years ago

jpc0016 commented 4 years ago

Hi,

I completed the common build process but run into errors when attempting to import the gtirb libraries. The first error is <gtirb/gtirb.hpp> does not exist in my default include paths. I'm not sure if this is by design but using -I /path/to/GTIRB/include/ fixes that issue.

Next I receive what appears to be boost issues related to CFG.hpp:

$ clang++ -I ~/GTIRB/include/ populating_ir.cpp
In file included from populating_ir.cpp:12:
In file included from ~/GTIRB/include/gtirb/gtirb.hpp:25:
In file included from ~/GTIRB/include/gtirb/AuxData.hpp:19:
In file included from ~/GTIRB/include/gtirb/Block.hpp:19:
~/GTIRB/include/gtirb/CFG.hpp:71:5: error: no template named 'optional' in namespace 'std'; did you mean 'boost::optional'?
    std::optional<std::tuple<ConditionalEdge, DirectEdge, EdgeType>>;
    ^~~~~~~~~~~~~
    boost::optional
/usr/local/include/boost/optional/optional.hpp:845:7: note: 'boost::optional' declared here
class optional
      ^

This repeats four times. There appears to be a conflict between 'std' and 'boost' that is exclusive to Clang. I tried g++ and it returned "compilation terminated."

AaronBallman commented 4 years ago

I completed the common build process but run into errors when attempting to import the gtirb libraries. The first error is <gtirb/gtirb.hpp> does not exist in my default include paths. I'm not sure if this is by design but using -I /path/to/GTIRB/include/ fixes that issue.

It is relatively common for compilers to separate their header search paths for quoted and angle bracket includes, so I think this is not unexpected behavior even if it's not by design per se. Using -I is a good way to solve the issue.

Next I receive what appears to be boost issues related to CFG.hpp:

I think the issue is that Clang default to C++14 (in newer versions of Clang, anyway) but GTIRB requires C++17 support. Do you have the same issues if you pass -std=c++17 to Clang?

jpc0016 commented 4 years ago

All issues related to boost::optional are resolved when passing -std=c++17. Three out of four errors are resolved and I just have the proto/block error left. I suspect it's similar to the issue above in that some include path is broken. My populating_ir.cpp script only contains the same include libraries as the example script functions.cpp. My main function is blank.

$ clang++ -I ~/GTIRB/include/ -std=c++17 populating_ir.cpp 
In file included from populating_ir.cpp:12:
In file included from ~/GTIRB/include/gtirb/gtirb.hpp:25:
In file included from ~/GTIRB/include/gtirb/AuxData.hpp:19:
~/GTIRB/include/gtirb/Block.hpp:23:10: fatal error: 'proto/Block.pb.h' file not found
#include <proto/Block.pb.h>
         ^~~~~~~~~~~~~~~~~~
1 error generated.
AaronBallman commented 4 years ago

The Foo.pb.h files are generated by the protobuf compiler and wind up in the build artifacts when you build gtirb. You should be able to add -I $something/include where $something is whatever your gtirb build directory is.

I'm a bit surprised that -I ~/GTIRB/include/ doesn't find them because I'm assuming that's your base GTIRB build include directory. Do you see a folder named proto in there with header files in it?

jpc0016 commented 4 years ago

You are correct, ~/GTIRB/ is my base build directory. It's worth noting my .hpp files are actually in this path: ~/GTIRB/include/gtirb/.

I don't see a proto folder anywhere in my include directory so that's most likely the culprit. I have a proto folder in ~/GTIRB/src/ that contains all .proto extension files and a CMakeLists.txt file. It appears I should run make on it to build everything in /include/proto but now I'm wondering why that did not occur earlier.

AaronBallman commented 4 years ago

You are correct, ~/GTIRB/ is my base build directory. It's worth noting my .hpp files are actually in this path: ~/GTIRB/include/gtirb/.

Good, that's where we want them!

I don't see a proto folder anywhere in my include directory so that's most likely the culprit.

That's strange and does seem likely to be the issue.

I have a proto folder in ~/GTIRB/src/ that contains all .proto extension files and a CMakeLists.txt file.

That makes sense.

It appears I should run make on it to build everything in /include/proto but now I'm wondering why that did not occur earlier.

Me too! I would recommend doing a clean rebuild of gtirb where you clear the entire CMake build directory and delete CMake cache files, just in case there was an issue when CMake was configuring that is causing some bad behavior.

jpc0016 commented 4 years ago

OMG I'm a dummy. The correct include path is ~/GTIRB/build/include/ like so:

$ clang++ -I ~/GTIRB/build/include/ -std=c++17 populating_ir.cpp
$

My test program compiles; however, the include path is still required because headers still cannot be found. Any way to compile without invoking the path every time?

:~/GTIRB/build$ clang++ -std=c++17 populating_ir.cpp
populating_ir.cpp:12:10: fatal error: 'gtirb/gtirb.hpp' file not found
#include <gtirb/gtirb.hpp>
         ^~~~~~~~~~~~~~~~~
1 error generated.
AaronBallman commented 4 years ago

OMG I'm a dummy. The correct include path is ~/GTIRB/build/include/

Oh gosh, I didn't notice that you had mentioned ~/GTIRB/src earlier, sorry about that!

My test program compiles; however, the include path is still required because headers still cannot be found. Any way to compile without invoking the path every time?

In general, Clang has no way of knowing where to look for that information without using one of the command line switches to add an extra header search path. You could manually copy the build artifacts from building GTIRB (such as the contents of the include directory) next to your source file and use #include "gtirb/gtirb.hpp" (with quotes instead of angle brackets) and that should work because Clang's default quoted include search path includes the path to the source file being compiled.

jpc0016 commented 4 years ago

I guess I have to live with that for now. I still cannot run the /doc/examples or my example due to an invalid class reference. It appears there is no constructor in SymbolicExpression.cpp (line 35), just a class declaration. Context is declared in Context.hpp but I guess it's not properly referenced from SymbolicExpression.cpp.

$ clang++ -I ~/GTIRB/build/include/ -std=c++17 populating_ir.cpp 
/usr/bin/ld: /tmp/populating_ir-e48f6c.o: in function `main':
populating_ir.cpp:(.text+0x101): undefined reference to `gtirb::Context::Context()'
/usr/bin/ld: populating_ir.cpp:(.text+0x114): undefined reference to `gtirb::Context::~Context()'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
AaronBallman commented 4 years ago

The Context destructor is defined in Context.cpp (https://github.com/GrammaTech/gtirb/blob/master/src/Context.cpp#L32), so I'm not certain why you're seeing that link error.

If you run the following command (fixing up paths to find the file), do you get output:

nm lib/libgtirb.so | grep _ZN5gtirb7ContextD[0-9]Ev

For me, I get two different symbols:

000000000006f990 T _ZN5gtirb7ContextD1Ev
000000000006f990 T _ZN5gtirb7ContextD2Ev

When I demangle those, I get a destructor:

aaron@aaron-VirtualBox:~/sandboxes/gtirb_build$ c++filt _ZN5gtirb7ContextD1Ev
gtirb::Context::~Context()
aaron@aaron-VirtualBox:~/sandboxes/gtirb_build$ c++filt _ZN5gtirb7ContextD2Ev
gtirb::Context::~Context()
jpc0016 commented 4 years ago

Yes I got your exact same output when running that command from ~/GTIRB/build. Both destructors are there. I moved functions.cpp to the build folder but received the same linker error. I ran sudo apt-get update and sudo apt-get upgrade before re-running the compilation. Same result.

~/GTIRB/build$ clang++ -I ~/GTIRB/build/include/ -std=c++17 functions.cpp

/usr/bin/ld: /tmp/functions-bbc4e9.o: in function `main':
functions.cpp:(.text+0x101): undefined reference to `gtirb::Context::Context()'
/usr/bin/ld: functions.cpp:(.text+0x169): undefined reference to `gtirb::IR::load(gtirb::Context&, std::istream&)'
/usr/bin/ld: functions.cpp:(.text+0x204): undefined reference to `gtirb::blocks(boost::adjacency_list<boost::listS, boost::vecS, boost::bidirectionalS, gtirb::CfgNode*, std::optional<std::tuple<gtirb::ConditionalEdge, gtirb::DirectEdge, gtirb::EdgeType> >, std::unordered_map<gtirb::CfgNode const*, unsigned long, std::hash<gtirb::CfgNode const*>, std::equal_to<gtirb::CfgNode const*>, std::allocator<std::pair<gtirb::CfgNode const* const, unsigned long> > >, boost::listS>&)'
/usr/bin/ld: functions.cpp:(.text+0x31b): undefined reference to `gtirb::AuxDataContainer::getAuxData(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: functions.cpp:(.text+0x6ba): undefined reference to `gtirb::Context::~Context()'
/usr/bin/ld: functions.cpp:(.text+0x6de): undefined reference to `gtirb::Context::~Context()'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
tjohnson-gt commented 4 years ago

You do need to link against the gtirb library (and the proto library). So your clang++ command needs appropriate -L and -l options to tell clang++ where the gtirb library is. Something like:

~/GTIRB/build$ clang++ -I ~/GTIRB/build/include/ -std=c++17 functions.cpp -L ~/GTIRB/build/lib -lgtirb -lproto

I guess we need an action item to update the docs to spell out this kind of thing.

jpc0016 commented 4 years ago

It compiled! The output binary cannot find shared libraries though. This also happens when specifying the build/lib path:

~/GTIRB/build$ ./a.out ~/GTIRB/build/lib
./a.out: error while loading shared libraries: libgtirb.so: cannot open shared object file: No such file or directory
tjohnson-gt commented 4 years ago

You have to tell the OS where it can find the shared library. This can be done in several ways on Linux. One way is to set the LD_LIBRARY_PATH environment variable to include GTIRB's lib directory. Another way is to set your executable's rpath or runpath to include the directory.

The simplest thing for just experimenting in your immediate case may be to just run it as:

LD_LIBRARY_PATH=~/GTIRB/build/lib ./a.out

AaronBallman commented 4 years ago

I'm closing this issue as I believe it is resolved. Please open a new issue if this still persists with the master branch.