How to properly compile in stdlib without linking to external libraries?


#1

I don’t want to compile the stdlib externally (neither as shared or static library), but instead just compile chaiscript_stdlib.cpp and stl_extra.cpp along with my project, however I’m running into problems at the linking stage.

./extlibs/chaiscript_stdlib.cpp.o: In function `json::Object()':
/usr/include/c++/5/bits/shared_ptr_base.h:659: multiple definition of `json::Object()'
./src/Kit/ScriptedState.cpp.o:./extlibs/chaiscript/utility/json.hpp:435: first defined here

How could this possibly happen when the json.hpp file most certainly has header guards? (both #pragma once and #ifndef x #define x #endif)

Compiling using GCC version: gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010


#2

I should probably add I had this working when I prototyped with chaiscript. This issue seems to stem from storing a chaiscript::ChaiScript instance as a class member somehow. I wrap this class (ScriptedState) in a shared_ptr, and also create instances of this class only from a static class method (std::shared_ptr ScriptedState::Load() basically)


#3

This looks like an issue with the recently added JSON library. Can you provide a complete example so I can verify the issue?

Also, the layout of Spiced is the “officially recommended” way of compiling the stdlib in while reducing compile time issues.


#4

Thanks for the very quick response! And very awesome library you’ve created! :wink:

I will get a minimal reproducable example for you as soon as I can! Thank you, I will study Spiced’s implementation.


#5

EDIT2: Disregard. I have no idea what I’m doing. Awaiting your response.

EDIT: I fixed it by myself. I think I have misunderstood how the library should be compiled in, and had included the chaiscript stdlibrary and stl_extra cpp source files. Removing them solves the issue.

Old post here (my own fix commited)


Very minimal reproducable example: https://github.com/haikarainen/chaitest
If you’re on linux, just clone and run ./build.sh. Otherwise its as easy as cmake.

Note: This repo contains my own convenience-patched version of chaiscript (a few very tiny changes, like using std::cout for printing to flush buffers immediately). It should however be no different in this context.


#6

This turned out to be quite the circus. I managed to figure out the last thing that went wrong. Firstly, the problem was I had the .cpp files in my list of files to be compiled. This was the cause of the original error. When I then actually tried it in my project, it failed on runtime because it couldn’t find a .dll (This is linux, mind you, should’ve been so). I then circumvented this problem by changing how I initialized the chaiscript::ChaiScript instance. Previously I had initialized it with its empty constructor, and then added the std library to the instance afterwards; this caused it to somehow look for a dll instead. If I instead moved the initialization step so that it was initialized in the constructor like m_Script(Std_Lib::library()) it worked. I still dont know exactly why, would very much appreciate an explanation.


#7

You somehow managed to miss the example here for a compiled-in stdlib: http://chaiscript.com/examples.html#ChaiScript_Compiled_in_Stdlib_Example and just discovered on your own the proper way to do it.

The error you saw, that it couldn’t find a dll, is because it was looking for the stdlib, as you now know. .dll is only part of that error message, if you had looked closer you would have seen that it was attempting to find .dylib, .so, .dll, etc. I’ve worked with enough scripting engines for other languages to know that it is VERY frustrating when the scripting engine assumes a certain extension on a certain platform, so I don’t discriminate. ChaiScript will except any extension that it manages to load and execute for a binary module.


#8

Thanks for the response, again. Is there any way to store a ChaiScript instance on the stack (with default ctor, no initial assignment), while still having it use the compiled-in standard library (by just adding the module later)?


#9

No, that is not possible. It must find the standard library with ChaiScript is instantiated.

You could write a very simple wrapper that does what you want, however:

struct MyChaiWrapper
{
  MyChaiWrapper()
    : chai(chaiscript::Std_Lib::library())
  {
  }

  chaiscript::ChaiScript chai;
};

int main()
{
  MyChaiWrapper wrap;
  wrap.chai.eval("... something ");
}

Did that answer your question?


#10

I see. Yes it did, sorry for dragging this thread out for what feels like forever. And thank you again for being so dedicated to the project and supporting your users :blush: It is very appreciated