0

Okay so I have to separate projects one I will call engine and one I will call game. My goal is to build the engine project as a dynamic library (I use linux so .so) and then use this in my game project.

This is the structure of projects, the engine project has some libraries that are statically linked. Note I have removed some other vendors and file just to keep this simple as the problem still exists.

include
 |----- engine.h
src
 |------ engine.c
vendor
 |------ glfw (built statically)
          |--- build
          |      |--- src
          |            |--- libglfw3.a
          |--- include
                  |--- GLFW
                         |--- ...

I build this with the following cmake(most redacted but important stuff is there) into a build directory and also with another script to add a directory to my build folder with the include/GLFW and my own headers. Structure is as follows.

set(GLFW_PATH vendor/glfw)

add_library(${PROJECT_NAME} SHARED
        include/engine.h
        src/engine.c
        )

target_include_directories(${PROJECT_NAME} PUBLIC
        ${GLFW_PATH}/include
)

target_link_libraries(
        ${PROJECT_NAME}
        m
        ${CMAKE_SOURCE_DIR}/vendor/glfw/build/src/libglfw3.a
        OpenGL::GL
)
build
  |--- libengine.so
  |--- include
          |--- engine
          |      |--- engine.h
          |--- GLFW
                 |--- ...

Everything up until now works fine, using the include_directories in cmake when building the engine and setting it to the glfw/include in vendor allows me to use <GLFW/glfw3.> in the engine code and works fine.

Now for the core, I am currently building this with just make but the same issue happens when using cmake. I only have one source file main.c and this is the structure I both projects together, note I am including the engine header as <engine/engine.h>.

core
  |--- build
  |      |--- ... (.so is here and include)
  |--- CmakeLists.txt
game
 |--- main.c
 |--- Makefile

This is the make command I am using to use the core dynamic library and all of its header files.

CC = gcc

LIBS = -lengine
LIB_DIR = -L../core/build

INCLUDES = -I../core/build/include

build:
    $(CC) main.c $(LIB_DIR) $(INCLUDES) $(LIBS)

When running this command I get the following error (and some more).

/usr/bin/ld: main.c:(.text+0x36): undefined reference to `glfwCreateWindow'

What this is telling me at least is that using #include <enine/engine/h> in my game's source file worked but once that header tries to use #include <GLFW/glfw3.h> that is when does not work and any function called from there is now undefined.

Any tips on hot to fix this, thanks.

  • At first glance, it looks like you need to link in the `glfw` library (probably something like `-lglfw`, and possibly an additional `-L` argument to point at the necessary directory). – larsks May 23 '22 at 12:05
  • @larsks maybe you are correct but why would I need to link with glfw again after it already being statically link with the engine library. I though they will all be included in the .a file. – Jack Delahunt May 23 '22 at 12:10
  • 1
    Check (e.g. using `nm`) that `libglfw3.a` library actually has the symbol `glfwCreateWindow`. If it has, but your shared library doesn't have that symbol, then the whole object file from `libglfw3.a` was omitted because none symbol from it is used **by your library** itself. For avoid omitting object files, use `--whole-archive` parameter for linker: https://stackoverflow.com/questions/2649735/how-to-link-static-library-into-dynamic-library-in-gcc. About adding that parameter in CMake see [that question](https://stackoverflow.com/questions/53071878). – Tsyvarev May 23 '22 at 14:40
  • @Tsyvarev Thanks for the comment, I did what you said and got the following results. I used nm on the glfw static lib and found glfwCreateWindow with T, this just means its in the code. I did the same on my shared object and found the same but now with U meaning undefined. So somehow when building my library the symbol turns to undefined. nm letter meanings - https://linux.die.net/man/1/nm – Jack Delahunt May 23 '22 at 23:32
  • also adding whole archive gives me multiple definitions on a lot of libgcc functions. – Jack Delahunt May 23 '22 at 23:36
  • "adding whole archive gives me multiple definitions on a lot of libgcc functions." - Smells like you forgot `-no-whole-archive` after linking with `libglfw3.a`. – Tsyvarev May 23 '22 at 23:38
  • Okay update... just went through the whole process again and now it seems to be working not sure why. EDIT: it is now broke again after another build... – Jack Delahunt May 23 '22 at 23:46

0 Answers0