UNITY_BUILD: Undefined Reference
Using cmake version 3.19.2
under Windows and Linux:
I have a CMAKE project composed from a "backend" C++ static library, a "frontend" C++ static library using the backend one and a C shared library using the frontend that wraps the frontend API into a C API/ABI.
I'm pushing the frontend C++ static library to a Conan Repo and I have a test project to test my package with the conan test
.
Everything works fine, but if I set CMAKE_UNITY_BUILD=on
, it successfully builds everything. The Unit Tests of my backend, frontend and C works well, but when the conan test
command execute, I got a lot of "Undefined Reference" or LNK2019
under Windows.
The error pattern is :
lib.a (unity_9_cxx.cxx.o): In function FrontEndFunction:
FrontendFile.cpp: undefined reference to 'BackEndFunction'
Does anybody have an idea of what is wrong ?
Should I independently create an unity build for each library? If yes, what is the leading practices to do that ? Is that by using UNITY_GROUP
?
backend CMakeLists.txt:
set(SOURCE_FILES
"$afile.cpp"
)
set(HEADER_FILES
"${CPP_INCLUDE_DIR}/backend/afile.hpp"
"${CPP_INCLUDE_DIR}/backend/anotherfile.h"
)
add_library(backend STATIC
${HEADER_FILES}
${SOURCE_FILES}
)
add_library(mylib::backend ALIAS backend)
target_include_directories(backend
PUBLIC ${CPP_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries(backend
PUBLIC CONAN_PKG::date
PUBLIC CONAN_PKG::fmt
PUBLIC CONAN_PKG::ms-gsl
PUBLIC CONAN_PKG::yaml-cpp
)
target_compile_features(backend INTERFACE
cxx_defaulted_functions
)
SET_TARGET_PROPERTIES(backend PROPERTIES
POSITION_INDEPENDENT_CODE ON
DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}
CXX_STANDARD 17
)
install(FILES ${HEADER_FILES} DESTINATION include/mylib/backend)
frontend CMakeLists.txt
et(SOURCE_FILES
"$afrontendfile.cpp"
...
)
set(HEADER_FILES
"${CPP_INCLUDE_DIR}/afrontendfile.hpp"
"${CPP_INCLUDE_DIR}/anthoerfefile.h"
...
)
add_library(mylib STATIC
${SOURCE_FILES}
${HEADER_FILES}
)
add_subdirectory(backend)
target_include_directories(mylib PUBLIC ${CPP_INCLUDE_DIR})
target_link_libraries(mylib PUBLIC mylib::backend)
target_compile_features(mylib
INTERFACE
cxx_defaulted_functions
)
SET_TARGET_PROPERTIES(mylib
PROPERTIES
PUBLIC_HEADER "${HEADER_FILES}"
POSITION_INDEPENDENT_CODE ON
DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}
CXX_STANDARD 17
)
# 'make install' to the correct locations (provided by GNUInstallDirs).
install(
TARGETS mylib
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PUBLIC_HEADER DESTINATION include/mylib)
And the C wrapper CMakeLists.txt
add_library(CWrapper SHARED
${SOURCE_FILES}
${HEADER_FILES}
export.def
)
target_link_libraries(CWrapper PRIVATE mylib)
SET_TARGET_PROPERTIES(CWrapper
PROPERTIES
PUBLIC_HEADER "${HEADER_FILES}"
POSITION_INDEPENDENT_CODE ON
CXX_STANDARD 17
# PRIVATE_HEADER "${PRIVATE_HEADER_FILES}"
)
install(
TARGETS CWrapper
LIBRARY DESTINATION c/lib
ARCHIVE DESTINATION c/lib
RUNTIME DESTINATION c/bin
PUBLIC_HEADER DESTINATION c/include/myLib
)