Skip to content

debug/AssertFatal.cpp Not Included in yogacore Build with file(GLOB), Causes Linker Error When Building Yoga 3.2.1 as Shared Library (yoga/CMakeLists.txt Fix) #1806

@natalia-hultrix

Description

@natalia-hultrix

Description

Summary

When building the yogacore library with the default CMakeLists.txt in the yoga/ directory, the debug/AssertFatal.cpp file (which defines facebook::yoga::fatalWithMessage) is not included in the source list when using file(GLOB ...). This doesn’t affect the static build (libyogacore.a) in my current test suite, but it causes a linker error (undefined reference to facebook::yoga::fatalWithMessage) when building as a shared library (libyogacore.so).

Steps to Reproduce

  1. Modify yoga/CMakeLists.txt to support shared libraries:
    option(BUILD_SHARED_LIBS "Build yogacore as a shared library" OFF)
    if(BUILD_SHARED_LIBS)
        add_library(yogacore SHARED ${SOURCES})
    else()
        add_library(yogacore STATIC ${SOURCES})
    endif()
  2. Run CMake with shared library enabled:
    cmake -B build -S . -DBUILD_SHARED_LIBS=ON
    make -j$(nproc)
  3. Observe the linker error during the yogatests build:
    /usr/bin/ld: CMakeFiles/yogatests.dir/StyleTest.cpp.o: in function `facebook::yoga::Style::computeMargin(...)`:
    StyleTest.cpp:(.text...): undefined reference to `facebook::yoga::fatalWithMessage(char const*)`
    

Expected Behavior

  • The yogacore library (static or shared) should include all necessary source files, including debug/AssertFatal.cpp, so that fatalWithMessage is defined and the build completes successfully.

Actual Behavior

  • The original file(GLOB SOURCES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/**/*.cpp) does not include debug/AssertFatal.cpp.
  • Static builds succeed due to linker laziness (if fatalWithMessage isn’t called), but shared builds fail with an undefined reference error because the symbol is referenced in StyleTest.cpp (via Style.h).

Root Cause

  • The file(GLOB ...) pattern in yoga/CMakeLists.txt fails to recurse into the debug/ subdirectory, omitting debug/AssertFatal.cpp. This is unexpected since /**/*.cpp should include subdirectories, but it doesn’t work as intended in my environment (CMake 3.26, Fedora).

My Fix

I modified yoga/CMakeLists.txt to use file(GLOB_RECURSE ...) instead:

file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS
    ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)

This correctly includes debug/AssertFatal.cpp, and both static and shared builds succeed:

cmake -B build -S . -DBUILD_SHARED_LIBS=ON  # Works
cmake -B build -S . -DBUILD_SHARED_LIBS=OFF # Works
make -j$(nproc)

Suggested Action

  • Update yoga/CMakeLists.txt to use file(GLOB_RECURSE ...) or explicitly include debug/AssertFatal.cpp to ensure all necessary sources are built into yogacore.
  • Alternatively, clarify in the documentation if debug/AssertFatal.cpp is intentionally excluded and how users should handle shared library builds.

Environment

  • OS: Fedora 41
  • CMake Version: 3.26
  • Compiler: GCC
  • Yoga Version: 3.2.1

Additional Notes

  • The static build’s success seems to rely on the linker not needing fatalWithMessage in my test suite. If tests or consumers call it (e.g., via Style.h), the static build could fail too.
  • Full modified CMakeLists.txt:
    cmake_minimum_required(VERSION 3.13...3.26)
    project(yogacore)
    set(CMAKE_VERBOSE_MAKEFILE on)
    
    if(TARGET yogacore)
        return()
    endif()
    
    include(CheckIPOSupported)
    
    option(BUILD_SHARED_LIBS "Build yogacore as a shared library" OFF)
    
    set(YOGA_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/..)
    include(${YOGA_ROOT}/cmake/project-defaults.cmake)
    
    file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS
        ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
    
    if(BUILD_SHARED_LIBS)
        add_library(yogacore SHARED ${SOURCES})
    else()
        add_library(yogacore STATIC ${SOURCES})
    endif()
    
    if(ANDROID)
        target_link_libraries(yogacore log)
    endif()
    
    check_ipo_supported(RESULT result)
    if(result)
        set_target_properties(yogacore PROPERTIES
            CMAKE_INTERPROCEDURAL_OPTIMIZATION true)
    endif()
    
    target_include_directories(yogacore
        PUBLIC
        $<BUILD_INTERFACE:${YOGA_ROOT}>
        $<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include/yoga>)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions