unresolved symbol errors for 'same project' code

53 views
Skip to first unread message

Elijah Emerson

unread,
Feb 22, 2016, 8:58:07 PM2/22/16
to Runtime-Compiled C++

Hi, first of all.. THANK YOU for putting this together as well as the "RCC++ for Rapid AI Development" article in GAME AI PRO. Ironically, I have an article in that book too =)


Also, I admit I'm new to all this and feel I'm missing something basic here. I'm hopeful you'll be able to figure out my issue quickly, apologies for the lengthy description.



Ok, I've added RCC++ into an existing game engine. I was able to get a new / simple test class to recompile correctly based on looking at ConsoleExample and SimpleTest. Man it's so awesome to see that working! However after setting up an existing 'code heavy' game object class, when it recompiles I get a lot of unresolved symbol errors with 'same project' math and game play code. 

here is an example error:
entity.obj : error LNK2019: unresolved external symbol "public: static float __cdecl Math::random(void)" (?random@Math@@SAMXZ) referenced in function ...

It's as if the existing 'same project' .obj files are not being used when recompiling the entity class. 


Here's a description of the work I've done:
Game Objects are constructed similar to SimpleTest. I made sure to derive from TInterface<IID_blah, IObject> and have RUNTIME_COMPILER_LINKLIBRARY and REGISTERCLASS(blah) in the .cpp as well as RUNTIME_MODIFIABLE_INCLUDE in the header (if its a registered class).

I made sure m_RuntimeLinkLibraryMap, m_RuntimeIncludeMap, m_RuntimeFileList look similar to SimpleTest. Of note m_RuntimeSourceDependencyMap is empty, just like SimpleTest. Should it not be?


In an attempt to fix this issue I tried manually calling PerModuleInterface::GetInstance()->AddRequiredSourceFiles("...\\src\\common\\util\\math.cpp"); and that fixes the unresolved symbol errors for the math functions. However I feel it's a hack and not something I should have to do because the examples don't do this and they work just fine. 

It feels like I'm missing something basic here, like pointing the code to the right place to find existing .obj files or something.


I assume the linker can use the existing math.obj already built for the .exe. 

RCC++ doesn't have to recompile existing 'same project' code that hasn't actually changed right? Obviously, I need to research RCC++ more, because i should know the answer to that question. =)


Ok, so does anyone have an idea what might be causing these unresolved symbol errors?


Thanks for your help... man oh man I can't wait to get this up and running!

Cheers,
Elijah

Doug Binks

unread,
Feb 23, 2016, 6:49:39 AM2/23/16
to Runtime-Compiled C++
Your article on Flow Field Tiles was very interesting, and I really enjoyed the Dungeon Siege and Supreme Commander series! 

Converting an existing class to be able to use RCC++ can be a little tricky.

Unfortunately there is no C++ standard for project structure, compilation and linking so to make RCC++ able to work on a variety of compilers it doesn't know about your project structure unless you tell it. You've started using two of the main approaches available (see [Interfacing to other code](https://github.com/RuntimeCompiledCPlusPlus/RuntimeCompiledCPlusPlus/wiki/Integrating-to-your-own-codebase) ), with the third being to create a system table which has a list of pointers to virtual interfaces.

It looks like you have the sorted out [using libraries with runtime modifiable classes](https://github.com/RuntimeCompiledCPlusPlus/RuntimeCompiledCPlusPlus/wiki/Using-libraries-from-runtime-modifiable-classes).

A math library is a good choice to use the [Runtime Source Dependency](https://github.com/RuntimeCompiledCPlusPlus/RuntimeCompiledCPlusPlus/wiki/Runtime-source-dependencies) approach for. You can do this more easily by adding RUNTIME_COMPILER_SOURCEDEPENDENCY define to the math.h header. See the link for more detail.

To speed up compilation, using virtual interfaces and the system table is a good approach if the functions are not being called too frequently (a few times per frame). This is the main approach the examples use, along with having inline functions in headers etc., mainly because the library and source dependency approach were added later - I should really make a new example when I get time.

In my own code I use entity component systems (aspects) with each system having a virtual interface and a pointer on the system table. They're all created at startup using REGISTERSINGLETON(class, true) and most of the communication is via a message stream, and the virtual interfaces mostly handle infrequent functionality or process many entities at once to reduce the virtual cost. My math and a few other things use the source dependency approach, most large external code is in a single dll lib.

The compiled code for RCC++ changes uses it's own intermediate directory, so the initial compile will recompile the source dependencies but afterwards should re-use the object files unless there has been a change (sorting out intermediate paths from compilers is none trivial, but might be possible to add a list of dirs to check to BuildTool.cpp using the CompilerOptions struct).

Let me know if there's anything I can help with, ping me on twitter with @dougbinks.

Note that (Will Wilson, one of the other authors of the article, ended up making a commercial offering for Visual Studio called [Recode](http://www.indefiant.com/) which you might want to check out. This has the upside of being pretty much plug and play, but the down side of only supporting changes in Visual Studio projects - less of a problem if that's your primary platform, since the code will still run as normal on other platforms just without runtime compilation.

Reply all
Reply to author
Forward
0 new messages