1

I'm pretty new to CMake, and have just gotten into setting it up. I've gone ahead and implemented a simple opengl boilerplate, whose tree is like this

CMakeLists.txt
include
  glad
  KHR
src
  glad
    glad.c
    CMakeLists.txt
main.cpp
CMakeLists.txt
lib
.gitignore
.gitmodules
CMakePresets.json
README.md

My Root CMakeLists is this:

cmake_minimum_required (VERSION 3.8)
project ("GameBro")

set(APP_NAME "GameBro")

# Opengl stuff
find_package( OpenGL REQUIRED )
# GLFW stuff
set(BUILD_SHARED_LIBS OFF CACHE BOOL "")
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "")
set(GLFW_BUILD_TESTS OFF CACHE BOOL "")
set(GLFW_BUILD_DOCS OFF CACHE BOOL "")
set(GLFW_INSTALL OFF CACHE BOOL "")
# MSVC related stuff
if( MSVC )
    SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:mainCRTStartup" )
endif()
# Macro to add sources from subdirs
macro (add_sources)
    file (RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
    foreach (_src ${ARGN})
        if (_relPath)
            list (APPEND sources "${_relPath}/${_src}")
        else()
            list (APPEND sources "${_src}")
        endif()
    endforeach()
    if (_relPath)
        # propagate SRCS to parent directory
        set (sources ${sources} PARENT_SCOPE)
    endif()
endmacro()
# Library subdir
add_subdirectory( lib )
# Add sources
add_subdirectory( src )
# Add executable
include_directories( ${OPENGL_INCLUDE_DIRS} lib/glfw/include lib/glfw/deps include )
add_executable ( ${APP_NAME} ${sources} )
target_link_libraries (${APP_NAME} glfw ${GLFW_LIBRARIES})

My src CMakeLists is like this

add_sources( main.cpp )
#add_sources( glad/glad.c )
add_subdirectory (glad)

My src/glad CMakeLists is like this

add_sources( glad.c )

The problem is, when i try to compile - i get errors like undefined reference to glad_glCreateShader etc.... But, when i put glad.c in the same dir as main.cpp and modify CMakeLists accordingly, it works properly and compiles, and displays a rectangle. WHat am I doing wrong here?

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Moosa
  • 63
  • 5
  • 1
    Is there a specific reason to not just add the sources from `src/CMakeLists.txt`? `function(add_sources TARGET SUBDIR SRC1) foreach(SRC IN ITEMS ${SRC1} ${ARGN}) target_sources(${TARGET} PRIVATE ${SUBDIR}/${SRC}) endforeach() endfunction() add_sources(${APP_NAME} glad glad.c)` Or alternatively creating a library target in the subdir and linking it to your executable target? Using `add_subdirectory` to execute cmake logic that only communicates back information via variables the parent dir is highly unusual. – fabian Jul 16 '22 at 07:50
  • 1
    Have you tried printing out the value of `sources`? I suspect it's empty. `PARENT_SCOPE` in your function refers to the caller of the function not the parent file https://cmake.org/cmake/help/latest/command/set.html. A `set (sources ${sources} PARENT_SCOPE)` at the end of your cmake files might fix the problem but all seems very hacky and fragile – Alan Birtles Jul 16 '22 at 08:31
  • Why not just create a library target in each cmake file and link those libraries into your executable? – Alan Birtles Jul 16 '22 at 08:33
  • @fabian, I want to compartmentalise the build so that I can add and remove "modules" at will. – Moosa Jul 16 '22 at 08:51
  • @AlanBirtles: "`PARENT_SCOPE` in your function refers to the caller of the function not the parent file" - `add_sources` is not a function but a **macro**. A macro doesn't introduce a scope. But printing a value of `sources` is definitely good as the first step in the debugging. – Tsyvarev Jul 16 '22 at 17:57

1 Answers1

0

So, I seem to have finally fixed my problem. Here's how I did it.

SO, as @fabian pointed out, PARENT_SCOPE only refers to the immediately above scope. NOT the top-level scope. To fix this what I did was to add set (sources ${sources} PARENT_SCOPE) to each and every CMakeLists.txt file. Although this is a hacky workaround - it solves my purpose.

Moosa
  • 63
  • 5
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 18 '22 at 17:28