4.9 KiB
This document details how to compile a basic plugin in Visual Studio, MinGW, or GCC.
To find the functions and variables available for use in plugins, look for CC_API/CC_VAR in the .h files.
Source code of some actual plugins
Setup
You need to download and install either Visual Studio, MinGW, or GCC.
Note: MinGW/GCC are relatively small, while Visual Studio is gigabytes in size.
If you're just trying to compile a plugin on Windows you might want to use MinGW. See main readme.
I assume your directory is structured like this:
src/...
TestPlugin.c
Or in other words, in a directory somewhere, you have a file named TestPlugin.c, and then a sub-directory named src which contains the game's source code.
Basic plugin
#include "src/Chat.h"
#include "src/GameStructs.h"
static void TestPlugin_Init(void) {
cc_string msg = String_FromConst("Hello world!");
Chat_Add(&msg);
}
int Plugin_ApiVersion = 1;
struct IGameComponent Plugin_Component = { TestPlugin_Init };
Here's the idea for a basic plugin that shows "Hello world" in chat when the game starts. Alas, this won't compile...
Basic plugin boilerplate
#include "src/Chat.h"
#include "src/Game.h"
#ifdef CC_BUILD_WIN
#define CC_API __declspec(dllimport)
#define CC_VAR __declspec(dllimport)
#define EXPORT __declspec(dllexport)
#else
#define CC_API
#define CC_VAR
#define EXPORT __attribute__((visibility("default")))
#endif
static void TestPlugin_Init(void) {
cc_string msg = String_FromConst("Hello world!");
Chat_Add(&msg);
}
EXPORT int Plugin_ApiVersion = 1;
EXPORT struct IGameComponent Plugin_Component = { TestPlugin_Init };
With this boilerplate, we're ready to compile the plugin. All plugins require this boilerplate, so feel free to copy and paste it.
Writing plugins in C++
When including game headers, they must be surrounded with extern "C", i.e.
extern "C" {
#include "src/Chat.h"
#include "src/Game.h"
}
Otherwise you will get obscure Undefined reference errors when compiling.
Exported plugin functions must be surrounded with extern "C", i.e.
extern "C" {
EXPORT int Plugin_ApiVersion = 1;
EXPORT struct IGameComponent Plugin_Component = { TestPlugin_Init };
}
Otherwise your plugin will not load. (you'll see error getting plugin version in-game)
Linux
For Linux
Compiling
gcc TestPlugin.c -o TestPlugin.so -shared -fPIC
Then put TestPlugin.so into your game's plugins folder. Done.
Cross compile for Windows 32 bit
Prerequisites:
- Compile the game, see
Cross compiling for windowsin main readme - Rename compiled executable to ClassiCube.exe
- Install the
mingw-w64-toolspackage
TODO: this also works for mingw. clean this up.
TODO: also document alternate method of compiling the game using --out-implib
Compiling
First, generate list of exported symbols:
gendef src/ClassiCube.exe
Next create a linkable library:
i686-w64-mingw32-dlltool -d ClassiCube.def -l libClassiCube.a -D ClassiCube.exe
Finally compile the plugin:
i686-w64-mingw32-gcc TestPlugin.c -o TestPlugin.dll -s -shared -L . -lClassiCube
Then put TestPlugin.dll into your game's plugins folder. Done.
Ultra small dlls
If you ONLY use code from the game (no external libraries and no C standard library functions), add -nostartfiles -Wl,--entry=0 to the compile flags
This step isn't necessary, the dll works fine without it. But it does reduce the size of the dll from 11 to 4 kb.
Cross compile for Windows 64 bit
Repeat the steps of Cross compile for Windows 32 bit, but use x86_64-w64-mingw32 instead of i686-w64-mingw32
Windows
TODO when I have some more time...
Prerequisites:
- Compile the game, see
Cross compiling for windowsin main readme - Find the
ClassiCube.libthat was generated when compiling the game. Usually it is in eithersrc\x64\Debugorsrc\x86\Debug. - Add a new
Empty Projectto the ClassiCube solution, then add the plugin .c files to it
Note: If the plugin provides a .vcxproj file, you can skip step 2 and just open that project file instead.
Configuration
Right click the plugin project in the Solution Explorer pane, then click Properties
TODO: add screenshots here
TODO: may need to configure include directories
-
In
Configuration properties->General, make sureConfiguration typeis set toDynamic library (.DLL) -
In
Configuration properties->Linker->Input, click the dropdown button forAdditional Dependencies, then clickEdit. Add the full path toClassiCube.lib, then clickOK
Compiling
Build the project. There should be a line in the build output that tells you where you can find the .dll file like this:
Project1.vcxproj -> C:\classicube-dev\testplugin\src\x64\Debug\Project1.dll