В настоящее время я изучаю CMake :) Проект прост: модульные тесты для моей собственной версии очереди в C. У меня есть следующая структура проекта:
Queue/
|--build/
|--lib/
| |--CMakeLists.txt
|--src/
| |--queue.h
| |--queue.c
|--tst/
| |--CMakeLists.txt
| |--main.cpp
| |--constructor_tests.cpp
| |--destructor_tests.cpp
|--CMakeLists.txt
lib / CMakeLists.txt:
cmake_minimum_required (VERSION 3.1)
# Download and install GTest
include(ExternalProject)
ExternalProject_Add(gtest
URL https://github.com/google/googletest/archive/release-1.8.0.zip
PREFIX ${PROJECT_SOURCE_DIR}/lib/gtest
INSTALL_COMMAND ""
)
tst / CMakeLists.txt:
cmake_minimum_required (VERSION 3.1)
# Include src directory
include_directories(${PROJECT_SOURCE_DIR}/src)
set(TESTS main.cpp
constructor_tests.cpp
destructor_tests.cpp
${PROJECT_SOURCE_DIR}/src/queue.c)
# Set paths for GTest include dir and GTest libs
set(GTEST_INCLUDE_DIR
${PROJECT_SOURCE_DIR}/lib/gtest/src/gtest/googletest/include)
set(GTEST_LIB_DIR
${PROJECT_SOURCE_DIR}/lib/gtest/src/gtest-build/googlemock/gtest)
add_executable(QueueTests ${TESTS})
add_dependencies(QueueTests gtest)
include_directories(${GTEST_INCLUDE_DIR})
target_link_libraries(QueueTests ${GTEST_LIB_DIR}/libgtest.a)
target_link_libraries(QueueTests ${GTEST_LIB_DIR}/libgtest_main.a)
enable_testing()
add_test(NAME QueueTests
COMMAND QueueTests)
root CMakeLists .txt:
cmake_minimum_required(VERSION 3.10)
project(Tests)
# Set language standards
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_STANDARD 11)
# Add lib dir and go to /lib/CMakeLists.txt
add_subdirectory(lib)
# Add tst dir and go to /tst/CMakeLists.txt
add_subdirectory(tst)
Однако на последнем этапе компиляции (связывание) у меня есть неопределенная ошибка символов:
Undefined symbols for architecture x86_64:
"init(Queue_T*, int)", referenced from:
Queue_Tests_Values_after_init_Test::TestBody() in constructor_tests.cpp.o
ld: symbol(s) not found for architecture x86_64
Исходный код выглядит следующим образом:
src / queue.h:
#ifndef QUEUE_H
#define QUEUE_H
//==========================================================//
// INCLUDES SECTION START //
//==========================================================//
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
//==========================================================//
// INCLUDES SECTION END //
//==========================================================//
//==========================================================//
// TYPES SECTION START //
//==========================================================//
typedef uint8_t Check_Val;
typedef signed int Position;
typedef const int* Element;
#define E_NOT_OK ((Check_Val) 0u)
#define E_OK ((Check_Val) 1u)
#define EMPTY ((bool) 0u)
#define NOT_EMPTY ((bool) 1u)
#define INIT_FRONT ((Position) 0)
#define INIT_BACK ((Position) 0)
#define INVALID_FRONT ((Position) -1)
#define INVALID_BACK ((Position) -1)
#define INVALID_SIZE ((signed int) -1)
typedef struct {
int* data;
Position front;
Position back;
int size;
} Queue_T;
//==========================================================//
// TYPES SECTION END //
//==========================================================//
//==========================================================//
// FUNCTION PROTOTYPES SECTION START //
//==========================================================//
Check_Val init(Queue_T* queue, const int size);
Check_Val deinit(Queue_T* queue);
Check_Val push(Queue_T* queue, const int* val);
Check_Val pop(Queue_T* queue);
Element front(const Queue_T* queue);
Element back(const Queue_T* queue);
bool empty(const Queue_T* queue);
//==========================================================//
// FUNCTION PROTOTYPES SECTION END //
//==========================================================//
#endif
src / queue. c:
#include <stdlib.h>
#include "queue.h"
//==========================================================//
Check_Val init(Queue_T* queue, const int size) {
queue->data = (int*)malloc(sizeof(int) * size);
if(queue->data == NULL) {
puts("Malloc failed in init\n");
return E_NOT_OK;
}
queue->front = INIT_FRONT;
queue->back = INIT_BACK;
queue->size = size;
return E_OK;
}
Проверка также очень проста, поэтому она не является ошибкой. tst / constructor_tests. cpp:
#include "gtest/gtest.h"
#include "queue.h"
TEST(Queue_Constructor_Tests, structAfterInit) {
const size_t WANTED_SIZE = 10u;
Check_Val init_retVal = E_NOT_OK;
Queue_T queue;
init_retVal = init(&queue, WANTED_SIZE);
EXPECT_TRUE(queue.data != NULL);
EXPECT_EQ(queue.front, INIT_FRONT);
EXPECT_EQ(queue.back, INIT_BACK);
EXPECT_EQ(queue.size, WANTED_SIZE);
EXPECT_EQ(init_retVal, E_OK);
}
Видимо, компилятор видит объявления функции, но не может связать ее реализацию. Думал, что добавление sr c решит проблему:
set(TESTS main.cpp
constructor_tests.cpp
destructor_tests.cpp
${PROJECT_SOURCE_DIR}/src/queue.c)
, но это не так. Любая помощь, как правильно связать это?