feat(CTemplate): Move to CMake
This commit is contained in:
parent
595837a4ac
commit
7223f1b99b
10 changed files with 308 additions and 121 deletions
74
C_Tempate/.gitignore
vendored
Normal file
74
C_Tempate/.gitignore
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Linker output
|
||||
*.ilk
|
||||
*.map
|
||||
*.exp
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
*.idb
|
||||
*.pdb
|
||||
|
||||
# Kernel Module Compile Results
|
||||
*.mod*
|
||||
*.cmd
|
||||
.tmp_versions/
|
||||
modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
# Vscode
|
||||
.vscode/
|
||||
|
||||
# CMake
|
||||
CMakeLists.txt.user
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Testing
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
.cache/
|
||||
CTestTestfile.cmake
|
||||
_deps
|
||||
build/
|
||||
lib/
|
||||
bin/
|
||||
*.swp
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
{
|
||||
"configurations": {
|
||||
"Launch": {
|
||||
"adapter": "vscode-cpptools",
|
||||
"filetypes": [ "cpp", "c", "objc", "rust" ], // optional
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/output/main",
|
||||
//"args": [ "", "" ],
|
||||
"cwd": "${workspaceRoot}/output",
|
||||
//"environment": [ ... ],
|
||||
"externalConsole": true,
|
||||
"MIMode": "gdb"
|
||||
}
|
||||
},
|
||||
"Attach": {
|
||||
"adapter": "vscode-cpptools",
|
||||
"filetypes": [ "cpp", "c", "objc", "rust" ], // optional
|
||||
"configuration": {
|
||||
"request": "attach",
|
||||
"program": "${workspaceRoot}/output/main",
|
||||
"MIMode": "gdb"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
52
C_Tempate/CMakeLists.txt
Normal file
52
C_Tempate/CMakeLists.txt
Normal file
|
@ -0,0 +1,52 @@
|
|||
cmake_minimum_required(VERSION 3.14)
|
||||
# Generate compile_commands.json
|
||||
set(PROJECT_NAME cTemplate)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# Turn on testing by default
|
||||
option(BUILD_TESTING "Build tests" ON)
|
||||
# Turn off coverage by default
|
||||
option(ENABLE_COVERAGE "Enable test coverage" ON)
|
||||
|
||||
# Set C standard to C99
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
|
||||
|
||||
# Set the project name and version number. This allows for a user of your
|
||||
project(${PROJECT_NAME} VERSION 0.1)
|
||||
set(${PROJECT_NAME} 0.1)
|
||||
|
||||
# Function to prepend the subdirectory to source files in subdirectories
|
||||
FUNCTION(PREPEND var )
|
||||
SET(listVar "")
|
||||
FOREACH(f ${${var}})
|
||||
LIST(APPEND listVar "${CMAKE_CURRENT_SOURCE_DIR}/${f}")
|
||||
ENDFOREACH(f)
|
||||
SET(${var} "${listVar}" PARENT_SCOPE)
|
||||
ENDFUNCTION(PREPEND)
|
||||
|
||||
# After a normal build, we can specify the location of various outputs of the
|
||||
# build. We put executables and static libraries outside the build directory in
|
||||
# bin/ and lib/, respectively.
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib")
|
||||
|
||||
# Include source code and headers. This calls the CMakeLists.txt in each
|
||||
# subdirectory. These can define their own libraries, executables, etc. as targets,
|
||||
# but here we define all exportable targets in the root CMakeLists.txt.
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(include)
|
||||
|
||||
# enable unit testing via "make test" once the code has been compiled.
|
||||
# TODO: Google Test
|
||||
|
||||
if(BUILD_TESTING)
|
||||
message("Testing enabled")
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
target_include_directories(tests PRIVATE include)
|
||||
endif()
|
||||
|
||||
# Add PROJECT_NAME as an executable target.
|
||||
add_executable(${PROJECT_NAME} ${SRC} ${INC})
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE include)
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
#
|
||||
# 'make' build executable file 'main'
|
||||
# 'make clean' removes all .o and executable files
|
||||
#
|
||||
|
||||
# define the C compiler to use CC = gcc
|
||||
|
||||
# define any compile-time flags
|
||||
# CFLAGS := -std=c99 -Wall -Wextra -g -lm
|
||||
CFLAGS := -std=c99 -Wall -Wextra -g
|
||||
|
||||
# define library paths in addition to /usr/lib
|
||||
# if I wanted to include libraries not in /usr/lib I'd specify
|
||||
# their path using -Lpath, something like:
|
||||
LFLAGS =
|
||||
|
||||
# define output directory
|
||||
OUTPUT := output
|
||||
|
||||
# define source directory
|
||||
SRC := src
|
||||
|
||||
# define include directory
|
||||
INCLUDE := include
|
||||
|
||||
# define lib directory
|
||||
LIB := lib
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
MAIN := main.exe
|
||||
SOURCEDIRS := $(SRC)
|
||||
INCLUDEDIRS := $(INCLUDE)
|
||||
LIBDIRS := $(LIB)
|
||||
FIXPATH = $(subst /,\,$1)
|
||||
RM := del /q /f
|
||||
MD := mkdir
|
||||
else
|
||||
MAIN := main
|
||||
SOURCEDIRS := $(shell find $(SRC) -type d)
|
||||
INCLUDEDIRS := $(shell find $(INCLUDE) -type d)
|
||||
LIBDIRS := $(shell find $(LIB) -type d)
|
||||
FIXPATH = $1
|
||||
RM = rm -f
|
||||
MD := mkdir -p
|
||||
endif
|
||||
|
||||
# define any directories containing header files other than /usr/include
|
||||
INCLUDES := $(patsubst %,-I%, $(INCLUDEDIRS:%/=%))
|
||||
|
||||
# define the C libs
|
||||
LIBS := $(patsubst %,-L%, $(LIBDIRS:%/=%))
|
||||
|
||||
# define the C source files
|
||||
SOURCES := $(wildcard $(patsubst %,%/*.c, $(SOURCEDIRS)))
|
||||
|
||||
# define the C object files
|
||||
OBJECTS := $(SOURCES:.c=.o)
|
||||
|
||||
#
|
||||
# The following part of the makefile is generic; it can be used to
|
||||
# build any executable just by changing the definitions above and by
|
||||
# deleting dependencies appended to the file from 'make depend'
|
||||
#
|
||||
|
||||
OUTPUTMAIN := $(call FIXPATH,$(OUTPUT)/$(MAIN))
|
||||
|
||||
all: $(OUTPUT) $(MAIN)
|
||||
@echo Executing 'all' complete!
|
||||
|
||||
$(OUTPUT):
|
||||
$(MD) $(OUTPUT)
|
||||
|
||||
$(MAIN): $(OBJECTS)
|
||||
$(CC) $(INCLUDES) $(OBJECTS) $(LFLAGS) $(LIBS) -o $(OUTPUTMAIN) $(CFLAGS)
|
||||
|
||||
# this is a suffix replacement rule for building .o's from .c's
|
||||
# it uses automatic variables $<: the name of the prerequisite of
|
||||
# the rule(a .c file) and $@: the name of the target of the rule (a .o file)
|
||||
# (see the gnu make manual section about automatic variables)
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(OUTPUTMAIN)
|
||||
$(RM) $(call FIXPATH,$(OBJECTS))
|
||||
@echo Cleanup complete!
|
||||
|
||||
run: all
|
||||
./$(OUTPUTMAIN)
|
||||
@echo Executing 'run: all' complete!
|
16
C_Tempate/include/CMakeLists.txt
Normal file
16
C_Tempate/include/CMakeLists.txt
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
# Make an explicit list of all source files in IFJ23_INC. This is important
|
||||
# because CMake is not a build system: it is a build system generator. Suppose
|
||||
# you add a file foo.cpp to src/ after running cmake .. . If you set
|
||||
# IFJ23_INC with `file(GLOB ... )`, this is not passed to the makefile; it
|
||||
# doesn't know that foo.cpp exists and will not re-run cmake. Your
|
||||
# collaborator's builds will fail and it will be unclear why. Whether you use
|
||||
# file(GLOB ...) or not, you will need to re-run cmake, but with an explicit
|
||||
# file list, you know beforehand why your code isn't compiling.
|
||||
set(INC
|
||||
)
|
||||
|
||||
# Form the full path to the source files...
|
||||
PREPEND(INC)
|
||||
# ... and pass the variable to the parent scope.
|
||||
set(INC ${INC} PARENT_SCOPE)
|
17
C_Tempate/src/CMakeLists.txt
Normal file
17
C_Tempate/src/CMakeLists.txt
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
# Make an explicit list of all source files in `CMakeDemo_SRC`. This is important
|
||||
# because CMake is not a build system: it is a build system generator. Suppose
|
||||
# you add a file foo.cpp to src/ after running cmake .. . If you set
|
||||
# `CMakeDemo_SRC` with `file(GLOB ... )`, this is not passed to the makefile;
|
||||
# the makefile doesn't know that foo.cpp exists and will not re-run cmake. Your
|
||||
# collaborator's builds will fail and it will be unclear why. Whether you use
|
||||
# file(GLOB ...) or not, you will need to re-run cmake, but with an explicit
|
||||
# file list, you know beforehand why your code isn't compiling.
|
||||
set(SRC
|
||||
main.c
|
||||
)
|
||||
|
||||
# Form the full path to the source files...
|
||||
PREPEND(SRC)
|
||||
# ... and pass the variable to the parent scope.
|
||||
set(SRC ${SRC} PARENT_SCOPE)
|
|
@ -1,8 +1,25 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
/**
|
||||
* Copyright [2023] Jiří Štefka <jiriks74>
|
||||
* Project: AdventOfCode
|
||||
* @file main.c
|
||||
* @brief Main entry point
|
||||
* @author jiriks74
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* @brief Main entry point
|
||||
* @param argc Number of command-line arguments.
|
||||
* @param argv Array of command-line arguments.
|
||||
*/
|
||||
#ifndef TESTING
|
||||
int main(int argc, char *argv[])
|
||||
#endif
|
||||
#ifdef TESTING
|
||||
int main_test(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
printf("Hello world!\n");
|
||||
return 0;
|
||||
printf("Hello world!\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
80
C_Tempate/tests/CMakeLists.txt
Normal file
80
C_Tempate/tests/CMakeLists.txt
Normal file
|
@ -0,0 +1,80 @@
|
|||
set(PROJECT_NAME ${PROJECT_NAME} PARENT_SCOPE )
|
||||
# GoogleTest requires at least C++14
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Get GoogleTest
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
|
||||
)
|
||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
add_subdirectory(src)
|
||||
add_executable(tests ${TESTS})
|
||||
|
||||
# Link test executable against gtest & gtest_main
|
||||
target_link_libraries(
|
||||
tests
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
target_include_directories(tests PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
# Discover tests
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(tests)
|
||||
add_dependencies(tests ${PROJECT_NAME})
|
||||
|
||||
# The following section is inspired by https://github.com/cmake-modules/lcov
|
||||
if(ENABLE_COVERAGE)
|
||||
message("Test coverage enabled")
|
||||
# set(exclude_dir "*/tests/* */_deps/* /usr/include/c++/11/**/* /usr/include/c++/**/*")
|
||||
# set(exclude_dir "*/tests/* */_deps/* /usr/include/c++/11/tuple /usr/include/c++/11/**/*")
|
||||
|
||||
# Check for lcov, gcov and genhtml
|
||||
find_program(GCOV gcov)
|
||||
if (NOT GCOV)
|
||||
message(WARNING "gcov not found")
|
||||
endif()
|
||||
find_program(LCOV lcov)
|
||||
if (NOT LCOV)
|
||||
message(WARNING "lcov not found")
|
||||
endif()
|
||||
find_program(GENHTML genhtml)
|
||||
if (NOT GENHTML)
|
||||
message(WARNING "genhtml not found")
|
||||
endif()
|
||||
|
||||
if (GCOV AND LCOV AND GENHTML)
|
||||
# Set C compiler flags
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage -fprofile-arcs -ftest-coverage")
|
||||
# Set C++ compiler flags
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage -fprofile-arcs -ftest-coverage")
|
||||
|
||||
set(covname cov.info)
|
||||
add_custom_target(coverage DEPENDS ${covname})
|
||||
add_dependencies(coverage tests ${PROJECT_NAME})
|
||||
add_custom_command(
|
||||
OUTPUT ${covname}
|
||||
COMMAND ${LCOV} -c -o ${covname} -d ${CMAKE_BINARY_DIR}/tests/CMakeFiles/tests.dir/ -b . --gcov-tool ${GCOV}
|
||||
COMMAND ${LCOV} -r ${covname} -o ${covname} "*/tests/*" "*/_deps/**/*" "/usr/include/c++/**/*" "/usr/include/c++/11/**/*"
|
||||
COMMAND ${LCOV} -l ${covname}
|
||||
COMMAND ${GENHTML} ${covname} -output coverage
|
||||
COMMAND ${LCOV} -l ${covname} 2>/dev/null | grep Total | sed 's/|//g' | sed 's/Total://g' | awk '{print $1}' | sed s/%//g > coverage/total
|
||||
)
|
||||
set_directory_properties(PROPERTIES
|
||||
ADDITIONAL_CLEAN_FILES ${covname}
|
||||
)
|
||||
set_directory_properties(PROPERTIES
|
||||
ADDITIONAL_CLEAN_FILES coverage/
|
||||
)
|
||||
else()
|
||||
message(WARNING "Cannot enable coverage. Missing the required tools")
|
||||
endif()
|
||||
endif()
|
17
C_Tempate/tests/src/CMakeLists.txt
Normal file
17
C_Tempate/tests/src/CMakeLists.txt
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
# Make an explicit list of all source files in `IFJ23_TESTS`. This is important
|
||||
# because CMake is not a build system: it is a build system generator. Suppose
|
||||
# you add a file foo.cpp to src/ after running cmake .. . If you set
|
||||
# `IFJ23_TESTS` with `file(GLOB ... )`, this is not passed to the makefile;
|
||||
# the makefile doesn't know that foo.cpp exists and will not re-run cmake. Your
|
||||
# collaborator's builds will fail and it will be unclear why. Whether you use
|
||||
# file(GLOB ...) or not, you will need to re-run cmake, but with an explicit
|
||||
# file list, you know beforehand why your code isn't compiling.
|
||||
set(TESTS
|
||||
test.cpp
|
||||
)
|
||||
|
||||
# Form the full path to the source files...
|
||||
PREPEND(TESTS)
|
||||
# ... and pass the variable to the parent scope.
|
||||
set(TESTS ${TESTS} PARENT_SCOPE)
|
31
C_Tempate/tests/src/test.cpp
Normal file
31
C_Tempate/tests/src/test.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include <gtest/gtest.h>
|
||||
|
||||
#define TESTING
|
||||
|
||||
// Include the source file(s) to be tested.
|
||||
#include "main.c"
|
||||
|
||||
// Create a test fixture class template - this will be like a "conlection" of
|
||||
// tests. the : public ::testing::Test part is important! Add it to your fixture
|
||||
// class.
|
||||
class HelloTest : public ::testing::Test {
|
||||
HelloTest() {}
|
||||
|
||||
~HelloTest() {}
|
||||
|
||||
void SetUp() {}
|
||||
|
||||
void TearDown() {}
|
||||
};
|
||||
|
||||
// Add tests to the test fixture class.
|
||||
// @param fixture_class_name The name of the test fixture class.
|
||||
// @param test_name The name of the test.
|
||||
TEST(HelloTest, BasicAssertions) {
|
||||
// Execute the code to be tested.
|
||||
// Expect two strings not to be equal.
|
||||
EXPECT_STRNE("hello", "world");
|
||||
// Expect equality.
|
||||
EXPECT_EQ(7 * 6, 42);
|
||||
}
|
||||
|
Loading…
Reference in a new issue