servo / pathfinder

A fast, practical GPU rasterizer for fonts and vector graphics
Apache License 2.0
3.6k stars 201 forks source link

Add build instructions for C examples #374

Open lambdadog opened 4 years ago

lambdadog commented 4 years ago

I'm trying to get the C examples to build currently and am running into a number of issues.

It seems like some specific flags likely need to be passed to cargo cbuild and cargo cinstall to prep the environment for building the c_canvas_* examples, and the closest I got* still had errors when attempting to import the generated header file

*To get as close as I did, I ran cargo cbuild --destdir=./build --prefix=, cargo cinstall --destdir=./build --prefix=, then edited c_canvas_minimal.c to import pathfinder_c/pathfinder_c.h instead of pathfinder/pathfinder.h, and even then I ran into the error you see below:

$ make
mkdir -p build && gcc -c -Wall -g -I../../c/build/include -O2 `sdl2-config --cflags` -o build/c_canvas_minimal.o c_canvas_minimal.c
In file included from c_canvas_minimal.c:13:
../../c/build/include/pathfinder_c/pathfinder_c.h:246:9: error: unknown type name ‘SVGScene’
  246 | typedef SVGScene SVGScene;
      |         ^~~~~~~~
make: *** [Makefile:41: build/c_canvas_minimal.o] Error 1
lambdadog commented 4 years ago

I tried modifying pathfinder_c.h, adding typedef struct SVGScene SVGScene; on a guess (I'm not a C programmer at all, and I know editing generated files isn't the solution most likely, but I just wanted to see if I could get to the next error) and then everything compiled but I ran into linktime errors about a number of undefined references:

/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:56: undefined reference to `PFGLLoadWith'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:58: undefined reference to `PFGLDestFramebufferCreateFullWindow'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:59: undefined reference to `PFFilesystemResourceLoaderLocate'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:59: undefined reference to `PFGLDeviceCreate'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:59: undefined reference to `PFGLRendererCreate'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:69: undefined reference to `PFCanvasFontContextCreateWithSystemSource'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:69: undefined reference to `PFCanvasCreate'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:73: undefined reference to `PFCanvasSetLineWidth'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:76: undefined reference to `PFCanvasStrokeRect'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:79: undefined reference to `PFCanvasFillRect'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:82: undefined reference to `PFPathCreate'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:83: undefined reference to `PFPathMoveTo'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:84: undefined reference to `PFPathLineTo'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:85: undefined reference to `PFPathLineTo'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:86: undefined reference to `PFPathClosePath'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:87: undefined reference to `PFCanvasStrokePath'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:90: undefined reference to `PFCanvasCreateScene'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:92: undefined reference to `PFSceneProxyCreateFromSceneAndRayonExecutor'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:93: undefined reference to `PFBuildOptionsCreate'
/home/lambdadog/devel/pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c:93: undefined reference to `PFSceneProxyBuildAndRenderGL'
leroycep commented 4 years ago

I was able to get the example running by manually compiling directly with gcc instead of using the Makefile.

$ gcc c_canvas_minimal.c  `pkg-config --cflags --libs pathfinder_c` `sdl2-config --cflags --libs`

The important part here is including the --libs flag for pkg-config; without it I get same linktime errors @lambdadog was getting.

I installed it in a non-standard path, so I also had to set PKG_CONFIG_PATH and LD_LIBRARY_PATH:

$ cargo cinstall --prefix /home/leroycep/.local
$ export PKG_CONFIG_PATH=/home/leroycep/.local/lib/pkgconfig
$ export LD_LIBRARY_PATH=/home/leroycep/.local/lib
lambdadog commented 4 years ago

@leroycep By following these instructions (and a couple of additional steps*) I was able to get it building.... but it freezes up and doesn't render anything.

*The extra steps being:

  1. Modify the #include statement in c_canvas_minimal.c to read #include <pathfinder_c.h>
  2. Make the same modifications to pathfinder_c.h that I mentioned above (adding typedef struct SVGScene SVGScene)
lambdadog commented 4 years ago

I definitely feel like I shouldn't be modifying pathfinder_c.h but I can't seem to find what I would be missing with getting it to compile without the modification...

EDIT: Looking, SVGScene is in pathfinder_svg and is included in the C interface by this line... I'm not sure why cargo-c is generating a C header that won't compile on my system....

lambdadog commented 4 years ago

Okay, now it's suddenly working.... not sure what's up with that, I don't believe I've changed anything. I just tried compiling it and running it again in the exact same environment. This was after building another (rust) example though, so that may have something to do with it, actually.

I still need to add typedef struct SVGScene SVGScene; into pathfinder_c.h though.

leroycep commented 4 years ago

I noticed something similar to the freezing. I was still able to exit the program with the escape key, so I think it has to do with how the program renders. It only renders once, and then waits for user input. Rendering inside the loop instead might fix it.

leroycep commented 4 years ago

It looks like the SVGScene issue was fixed in 42289eec6ea9e8a50cb76babf4027ed4d318c48c:

diff --git a/c/cbindgen.toml b/c/cbindgen.toml
index f8af9071..902ee9b5 100644
--- a/c/cbindgen.toml
+++ b/c/cbindgen.toml
@@ -54,3 +57,4 @@ include = [
 "ResourceLoaderWrapper" = "PFResourceLoaderWrapperPrivate"
 "Scene" = "PFScenePrivate"
 "SceneProxy" = "PFSceneProxyPrivate"
+"SVGScene" = "PFSVGScenePrivate"

SVGScene just needed to have it's export renamed, apparently.

However, now the build fails because NSObject is unknown. I think in this case the offending code needs to be hidden behind a flag, as the Metal api (where NSObject is used) is only for Apple device. cbindgen.toml just needs to have a [defines] section added:

[defines]
"target_os" = "macos" = "DEFINE_MACOS"
"feature" = "pf-gl" = "DEFINE_FEATURE_PF_GL"

Not sure what the flags should be called.

pcwalton commented 4 years ago

Does this work better as of https://github.com/servo/pathfinder/commit/c6151da25470124df1c38e650792ded2e2caf6f5?