commit 6e7ebd4027d6a835899649410182f8ee9121458f Author: Vladislav Ostapov Date: Tue Dec 10 17:38:20 2024 +0300 релиз diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f11b75 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ diff --git a/lib-generator.iml b/lib-generator.iml new file mode 100644 index 0000000..7372f94 --- /dev/null +++ b/lib-generator.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..96522a5 --- /dev/null +++ b/main.py @@ -0,0 +1,67 @@ +import os +import sys + +from jinja2 import Environment, FileSystemLoader + + +def generate_context(libname): + return { + 'project_name': libname, + 'project_name_code': libname.replace(' ', '_').lower(), + 'project_name_cmake': libname.replace(' ', '-').lower(), + 'include_dir': libname.replace(' ', '-').lower(), + 'include_header': f"{libname.replace(' ', '-').lower()}/{libname.split(' ')[-1].lower()}.h", + 'namespace': libname.split(' ')[-1].lower() + } + + +def render_template(filename, context): + file_loader = FileSystemLoader('templates') + env = Environment(loader=file_loader) + template = env.get_template(f'{filename}.jinja') + return template.render(context) + + +def write_file(filename, content): + with open(filename, 'w') as f: + f.write(content) + + +def create_all(libname, libpath, examples): + os.mkdir(libpath) + os.mkdir(f"{libpath}/include") + os.mkdir(f"{libpath}/include/{libname.replace(' ', '-').lower()}") + os.mkdir(f"{libpath}/src") + os.mkdir(f"{libpath}/tests") + + context = generate_context(libname) + + context['examples_names'] = examples + + write_file(f"{libpath}/CMakeLists.txt", render_template("CMakeLists.txt", context)) + write_file(f"{libpath}/include/{context['include_header']}", render_template("include/lib/lib.h", context)) + write_file(f"{libpath}/src/{context['namespace']}.cpp", render_template("src/lib.cpp", context)) + write_file(f"{libpath}/tests/CMakeLists.txt", render_template("tests/CMakeLists.txt", context)) + write_file(f"{libpath}/tests/main.cpp", render_template("tests/main.cpp", context)) + write_file(f"{libpath}/tests/test-{context['namespace']}.cpp", render_template("tests/test-lib.cpp", context)) + + if len(examples) > 0: + os.mkdir(f"{libpath}/examples") + for example in examples: + context = generate_context(libname) + context['example_name'] = example + context['example_name_code'] = example.replace(' ', '_').lower() + context['example_name_cmake'] = example.replace(' ', '-').lower() + + example_dir = f"{libpath}/examples/{context['example_name_cmake']}" + os.mkdir(example_dir) + write_file(f"{example_dir}/CMakeLists.txt", render_template("examples/CMakeLists.txt", context)) + write_file(f"{example_dir}/main.cpp", render_template("examples/main.cpp", context)) + + +if __name__ == "__main__": + if len(sys.argv) < 3: + print(f"Usage: {sys.argv[0]} libname /path/to/project ...") + exit(1) + create_all(sys.argv[1], sys.argv[2], sys.argv[3:]) + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8ce973e --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +Jinja2 diff --git a/templates/CMakeLists.txt.jinja b/templates/CMakeLists.txt.jinja new file mode 100644 index 0000000..2b8671a --- /dev/null +++ b/templates/CMakeLists.txt.jinja @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 3.20) +project({{ project_name_cmake }}) + +option({{ project_name | replace(" ", "_") | upper }}_BUILD_TESTS "Build {{ project_name }} tests" OFF) +option({{ project_name | replace(" ", "_") | upper }}_BUILD_EXAMPLES "Build {{ project_name }} examples" OFF) + +set(CMAKE_CXX_STANDARD 20) + +set(default_build_type "Release") +set(CMAKE_CXX_FLAGS "-Wall ${CMAKE_CXX_FLAGS}") + +if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release") + message(STATUS "Build type is release. Optimization for speed, without debug info.") + add_compile_options(-Ofast -s) +elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") + message(STATUS "Minimal optimization, debug info included") + add_compile_options(-g) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0") + add_definitions(-DUSE_DEBUG) +else() + message(FATAL_ERROR "You must set build type \"Debug\" or \"Release\". Another build types not supported!") +endif() + +message("{{ project_name }} CXX Flags: " ${CMAKE_CXX_FLAGS}) +message("{{ project_name }} CMAKE_BUILD_TYPE: " ${CMAKE_BUILD_TYPE}) + +add_library(${PROJECT_NAME} STATIC + include/{{ include_header }} + src/{{ namespace }}.cpp +) + +target_include_directories(${PROJECT_NAME} PUBLIC include/) + +if ({{ project_name | replace(" ", "_") | upper }}_BUILD_EXAMPLES) + message("Build examples enabled") +{% for ex in examples_names %} add_subdirectory(examples/{{ ex | replace(" ", "-") | lower }}) +{% endfor %}endif() + +if ({{ project_name | replace(" ", "_") | upper }}_BUILD_TESTS) + message("Build tests enabled") + add_subdirectory(tests) +endif() \ No newline at end of file diff --git a/templates/examples/CMakeLists.txt.jinja b/templates/examples/CMakeLists.txt.jinja new file mode 100644 index 0000000..730b206 --- /dev/null +++ b/templates/examples/CMakeLists.txt.jinja @@ -0,0 +1,12 @@ +set(EXECUTABLE {{ example_name_cmake }}) + +set(CMAKE_CXX_STANDARD 20) + +include_directories(./) +set(SOURCES + main.cpp +) + +add_executable(${EXECUTABLE} ${SOURCES}) +target_link_libraries(${EXECUTABLE} PRIVATE {{ project_name_cmake }}) + diff --git a/templates/examples/main.cpp.jinja b/templates/examples/main.cpp.jinja new file mode 100644 index 0000000..96ed235 --- /dev/null +++ b/templates/examples/main.cpp.jinja @@ -0,0 +1,8 @@ +#include <{{ include_header }}> +#include + +int main() { + {{ namespace }}::func(); + std::cout << "Hello from example {{ example_name }}!" << std::endl; + return 0; +} diff --git a/templates/include/lib/lib.h.jinja b/templates/include/lib/lib.h.jinja new file mode 100644 index 0000000..31bb649 --- /dev/null +++ b/templates/include/lib/lib.h.jinja @@ -0,0 +1,8 @@ +#ifndef {{ project_name | replace(" ", "_") | upper }}_H +#define {{ project_name | replace(" ", "_") | upper }}_H + +namespace {{ namespace }} { + void func(); +} + +#endif //{{ project_name | replace(" ", "_") | upper }}_H \ No newline at end of file diff --git a/templates/src/lib.cpp.jinja b/templates/src/lib.cpp.jinja new file mode 100644 index 0000000..b13522d --- /dev/null +++ b/templates/src/lib.cpp.jinja @@ -0,0 +1,4 @@ +#include <{{ include_header }}> + +void {{ namespace }}::func() { +} diff --git a/templates/tests/CMakeLists.txt.jinja b/templates/tests/CMakeLists.txt.jinja new file mode 100644 index 0000000..8f5d4a9 --- /dev/null +++ b/templates/tests/CMakeLists.txt.jinja @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.20) +project({{ project_name_cmake }}-tests) + +set(CMAKE_CXX_STANDARD 20) + +find_package(GTest REQUIRED) + +set(default_build_type "Release") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") +set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0") # -fprofile-arcs -ftest-coverage +set(CMAKE_CXX_FLAGS_RELEASE "-O2 -s") + +message(${CMAKE_CXX_FLAGS}) + +include_directories(../include) + +add_executable(${PROJECT_NAME} + main.cpp + test-{{ namespace }}.cpp + ../include/{{ include_header }} + ../src/{{ namespace }}.cpp +) + +target_link_libraries(${PROJECT_NAME} GTest::gtest) diff --git a/templates/tests/main.cpp.jinja b/templates/tests/main.cpp.jinja new file mode 100644 index 0000000..01b60c7 --- /dev/null +++ b/templates/tests/main.cpp.jinja @@ -0,0 +1,6 @@ +#include "gtest/gtest.h" + +int main(int argc, char ** argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/templates/tests/test-lib.cpp.jinja b/templates/tests/test-lib.cpp.jinja new file mode 100644 index 0000000..769c7c9 --- /dev/null +++ b/templates/tests/test-lib.cpp.jinja @@ -0,0 +1,7 @@ +#include <{{ include_header }}> +#include + +TEST({{ project_name_code }}, {{ namespace }}_example) { + {{ namespace }}::func(); + SUCCEED(); +}