0

So I am building a tiny "game engine" in C++, using cmake to build it, and I am making it as a static library. In windows it works perfectly, but in linux I need to link X11.

Now this wouldn't be a problem, I can just add add_link_options(-lX11) in CMakeLists.txt, and mylib.a will build fine, but when I go and use my mylib.a, and link it into a C++ program, I also need to link X11 again using the add_link_options command.

I am trying to do something similar to what raylib does, and I also want to do linking and including the library how raylib does it (in raylib you only need to link libraylib.a, and everything else is taken care of), but in my case, every time I want to link mylib.a into a C++ project, I also need to link X11.

If I make mylib to be shared (mylib.so), it works without the need to link X11 in the second project as well, but I would like to have a static version of the library working as well.

Here's my CMakeLists.txt for my library:

cmake_minimum_required(VERSION 3.0.0)
project(ntt VERSION 0.1.0)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED TRUE)

add_link_options(-lX11)

# GLFW config (this one I copied from raylib directly)
set(BUILD_SHARED_LIBS OFF)
set(GLFW_BUILD_EXAMPLES OFF)
set(GLFW_BUILD_DOCS OFF)
set(GLFW_BUILD_TESTS OFF)
set(GLFW_INSTALL OFF)
add_subdirectory("${CMAKE_SOURCE_DIR}/src/glfw")
add_compile_definitions(_GLFW_X11)

# Generate source list
file(GLOB SOURCES "${CMAKE_SOURCE_DIR}/src/*.cpp")
list(APPEND SOURCES "${CMAKE_SOURCE_DIR}/src/glad/src/glad.c")
list(APPEND SOURCES $<TARGET_OBJECTS:glfw>)

# Create the library
add_library(ntt ${SOURCES})
set_target_properties(ntt PROPERTIES
    PUBLIC_HEADER "${CMAKE_SOURCE_DIR}/include/Engine.hpp"
)

# Add include directories
target_include_directories(
    ntt
        PUBLIC
            "${CMAKE_SOURCE_DIR}/include"
        PRIVATE
            "${CMAKE_SOURCE_DIR}/src/glad/include"
            "${CMAKE_SOURCE_DIR}/src/glfw/include"
)

And here's CMakeLists.txt for a project that uses my library, and doesn't work (unless I add the add_link_options(-lX11)):

cmake_minimum_required(VERSION 3.0.0)
project(TestCpp VERSION 0.1.0)

# I want to not need to have this line here
# add_link_options(-lX11)

add_executable(TestCpp main.cpp)

target_include_directories(TestCpp PUBLIC "${CMAKE_SOURCE_DIR}/include")
target_link_libraries(TestCpp PUBLIC "${CMAKE_SOURCE_DIR}/libntt.a")

When I try to build the second project I get a bunch of errors like this: /usr/bin/ld: /media/hdd/Development/C-C++/test/libntt.a(x11_monitor.c.o): in function `_glfwPollMonitorsX11': x11_monitor.c:(.text+0x3e8): undefined reference to `XFree' (they all come from places like x11_window, or x11_monitor, and all of them are abount missing references to different X11 functions used by glfw)

I know I must be missing something really easy, but I just don't know what. I am not new to C++, but this is the first time I've made an actual proper library, and I'm also pretty new to cmake (so pls excuse bad practices you might see in my CMakeLists).

I mostly relied on Microsoft's Visual Studio build system until recently, and the only reason I switched to cmake was to be able to port my code to more than one platform(windows) without jumping through the weird hoops that VS makes you jump through when configuring the project, and now I'm starting to like it, but every once in a while I bump into something like this.

So, in short: X11 links properly with -lX11, but I would like to only have the user link my library, and not have to bother with also linking X11 manually.

With raylib you only need to do target_link_libraries(mytarget PUBLIC raylib.a) and that links X11 and opengl and everything else needed, but in my case you also need to add_link_options(-lX11), and I want to not have to do that.

7
  • I dont think that it is possible to link a dynamic library (x11) to a static lib, I suppose it is because a static lib is simply an archive of your obj files. But you can link a dynamic lib to another dynamic lib Commented Nov 4, 2022 at 14:01
  • The thing is, raylib manages to do it somehow, and that's why I posted this question. If you want to link libraylib.a (the static version) it just works, and wutomatically links the shared lX11 along with itself. Commented Nov 4, 2022 at 14:03
  • I'm not sure, but it seems to be because raylib internaly use glfw. And as I see in its code glfw dynamically load x11 functions using dlopen: github.com/raysan5/raylib/blob/master/src/external/glfw/src/… Commented Nov 4, 2022 at 14:16
  • I also do that, I have the glfw source inside my code, and use cmake to link the two together, just like raylib handles glfw Commented Nov 4, 2022 at 14:20
  • maybe an include is missing somewhere. "x11_platform.h" has macros that could resolve your problem : #define XFree _glfw.x11.xlib.Free for example Commented Nov 4, 2022 at 14:33

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.