From ac34883ef64d41ee55652fc6a64079399fe1eaf4 Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Wed, 18 Feb 2026 19:13:24 +0500 Subject: [PATCH 01/18] chore(build): #44: add conan receipts of libodb and libodb-pgsql --- deps/libodb-pgsql/conanfile.py | 81 ++++++++++++++++++++++++++++++++++ deps/libodb/conanfile.py | 75 +++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 deps/libodb-pgsql/conanfile.py create mode 100644 deps/libodb/conanfile.py diff --git a/deps/libodb-pgsql/conanfile.py b/deps/libodb-pgsql/conanfile.py new file mode 100644 index 0000000..eac86a3 --- /dev/null +++ b/deps/libodb-pgsql/conanfile.py @@ -0,0 +1,81 @@ +from conan import ConanFile +from conan.tools.gnu import Autotools, AutotoolsToolchain, AutotoolsDeps +from conan.tools.files import get, copy, rmdir +from conan.tools.layout import basic_layout +import os + +required_conan_version = ">=2.0" + +class LibODBPgsqlConan(ConanFile): + name = "libodb-pgsql" + version = "2.5.0" + + license = "GPL-2.0-only OR proprietary" + url = "https://github.com/your-username/conan-libodb-pgsql" + homepage = "https://www.codesynthesis.com/products/odb/" + description = "PostgreSQL database support for ODB ORM" + topics = ("orm", "database", "postgresql", "c++", "persistence") + + package_type = "library" + settings = "os", "arch", "compiler", "build_type" + + options = { + "shared": [True, False], + "fPIC": [True, False], + } + + default_options = { + "shared": False, + "fPIC": True, + } + + def config_options(self): + if self.settings.os == "Windows": + del self.options.fPIC + + def configure(self): + if self.options.shared: + self.options.rm_safe("fPIC") + + def requirements(self): + self.requires("libodb/2.4.0") + self.requires("libpq/16.8") + + def layout(self): + basic_layout(self, src_folder="src") + + def source(self): + get(self, + f"https://www.codesynthesis.com/download/odb/{self.version}/libodb-pgsql-{self.version}.tar.gz", + strip_root=True) + + def generate(self): + tc = AutotoolsToolchain(self) + tc.generate() + + deps = AutotoolsDeps(self) + deps.generate() + + def build(self): + autotools = Autotools(self) + autotools.configure() + autotools.make() + + def package(self): + autotools = Autotools(self) + autotools.install() + + copy(self, "LICENSE", + src=self.source_folder, + dst=os.path.join(self.package_folder, "licenses")) + + rmdir(self, os.path.join(self.package_folder, "share")) + rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig")) + + def package_info(self): + self.cpp_info.libs = ["odb-pgsql"] + + self.cpp_info.requires = ["libodb::libodb", "libpq::pq"] + + if self.settings.os in ["Linux", "FreeBSD"]: + self.cpp_info.system_libs.append("pthread") \ No newline at end of file diff --git a/deps/libodb/conanfile.py b/deps/libodb/conanfile.py new file mode 100644 index 0000000..993ca31 --- /dev/null +++ b/deps/libodb/conanfile.py @@ -0,0 +1,75 @@ +from conan import ConanFile +from conan.tools.gnu import Autotools, AutotoolsToolchain, AutotoolsDeps +from conan.tools.files import get, copy, rmdir +from conan.tools.layout import basic_layout +import os + +required_conan_version = ">=2.0" + +class LibODBConan(ConanFile): + name = "libodb" + version = "2.5.0" + + license = "GPL-2.0-only" + url = "https://github.com/aasheptunov" + homepage = "https://www.codesynthesis.com/products/odb/" + description = "ODB is an object-relational mapping (ORM) system for C++" + topics = ("orm", "database", "sql", "c++", "persistence") + + package_type = "library" + settings = "os", "arch", "compiler", "build_type" + + options = { + "shared": [True, False], + "fPIC": [True, False], + } + + default_options = { + "shared": False, + "fPIC": True, + } + + def config_options(self): + if self.settings.os == "Windows": + del self.options.fPIC + + def configure(self): + if self.options.shared: + self.options.rm_safe("fPIC") + + def layout(self): + basic_layout(self, src_folder="odb") + + def source(self): + get(self, + f"https://www.codesynthesis.com/download/odb/{self.version}/libodb-{self.version}.tar.gz", + strip_root=True) + + def generate(self): + tc = AutotoolsToolchain(self) + tc.generate() + + deps = AutotoolsDeps(self) + deps.generate() + + def build(self): + autotools = Autotools(self) + autotools.configure() + autotools.make() + + def package(self): + autotools = Autotools(self) + autotools.install() + + copy(self, "LICENSE", + src=self.source_folder, + dst=os.path.join(self.package_folder, "licenses")) + + rmdir(self, os.path.join(self.package_folder, "share")) + rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig")) + + def package_info(self): + self.cpp_info.libs = ["odb"] + + if self.settings.os in ["Linux", "FreeBSD"]: + self.cpp_info.system_libs.append("pthread") \ No newline at end of file From 9d1741619df87010fbaab98caca8df8c7be6e91f Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Wed, 18 Feb 2026 19:14:05 +0500 Subject: [PATCH 02/18] chore(build): #44: add to deps libodb and libodb-pgsql --- conanfile.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/conanfile.py b/conanfile.py index 0307e98..dcb1265 100644 --- a/conanfile.py +++ b/conanfile.py @@ -45,3 +45,5 @@ def package(self): def requirements(self): self.requires("drogon/1.9.10") self.requires("gtest/1.14.0") + self.requires("libodb/2.5.0@cppget/stable") + self.requires("libodb-pgsql/2.5.0@cppget/stable") From e8f8fac17ffcbe1e33a9dc1ee41388fc2787b399 Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Tue, 17 Feb 2026 18:01:33 +0500 Subject: [PATCH 03/18] chore(build): #44: update drogon version drogon with 1.9.10 doesent build even for x86-64 --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index dcb1265..a42ae0d 100644 --- a/conanfile.py +++ b/conanfile.py @@ -43,7 +43,7 @@ def package(self): cmake.install() def requirements(self): - self.requires("drogon/1.9.10") + self.requires("drogon/1.9.12") self.requires("gtest/1.14.0") self.requires("libodb/2.5.0@cppget/stable") self.requires("libodb-pgsql/2.5.0@cppget/stable") From 67a0e58162e065e209a95d92ff23f763a6731f2b Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Fri, 20 Feb 2026 19:43:07 +0500 Subject: [PATCH 04/18] chore(build): #44: delete prebuilded packages installing --- .devcontainer/Dockerfile | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index bfd74d8..d0cf18c 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -2,27 +2,14 @@ FROM mcr.microsoft.com/devcontainers/base:ubuntu-22.04 AS base RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ && apt-get -y install --no-install-recommends \ - build-essential clang lld make gdb cmake ninja-build \ - git curl wget unzip sudo \ - pip \ - clang-format clang-tidy \ - libpq-dev \ + build-essential clang lld make gdb cmake ninja-build \ + git curl wget unzip sudo \ + pip \ + clang-format clang-tidy \ && apt-get autoremove -y \ && apt-get clean -y \ && rm -rf /var/lib/apt/lists/* RUN pip install conan -ARG ODB_VERSION=2.5.0 - -RUN mkdir -p /opt/odb && \ - wget -q -nc -P /opt/odb \ - https://www.codesynthesis.com/download/odb/${ODB_VERSION}/ubuntu/ubuntu22.04/x86_64/libodb_${ODB_VERSION}-0~ubuntu22.04_amd64.deb \ - https://www.codesynthesis.com/download/odb/${ODB_VERSION}/ubuntu/ubuntu22.04/x86_64/libodb-dev_${ODB_VERSION}-0~ubuntu22.04_amd64.deb \ - https://www.codesynthesis.com/download/odb/${ODB_VERSION}/ubuntu/ubuntu22.04/x86_64/libodb-pgsql_${ODB_VERSION}-0~ubuntu22.04_amd64.deb \ - https://www.codesynthesis.com/download/odb/${ODB_VERSION}/ubuntu/ubuntu22.04/x86_64/libodb-pgsql-dev_${ODB_VERSION}-0~ubuntu22.04_amd64.deb \ - https://www.codesynthesis.com/download/odb/${ODB_VERSION}/ubuntu/ubuntu22.04/x86_64/odb_${ODB_VERSION}-0~ubuntu22.04_amd64.deb - -RUN dpkg -i /opt/odb/*.deb && rm -rf /opt/odb - COPY to-dos-conan-profile.conf /root/.conan2/profiles/default \ No newline at end of file From 4a439bc8464b2476a84cf5df1ed4375eee989f6e Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Fri, 20 Feb 2026 19:45:21 +0500 Subject: [PATCH 05/18] chore(build): #44: WIP added env for local conan index store also prepare conan recipe for libodb-pgsql --- deps/libodb-pgsql/conanfile.py | 81 ---------------- deps/libodb/conanfile.py | 75 --------------- deps/recipes/libodb-pgsql/all/conanfile.py | 72 ++++++++++++++ deps/recipes/libodb-pgsql/config.yml | 3 + deps/recipes/libodb/all/conanfile.py | 103 +++++++++++++++++++++ deps/recipes/libodb/config.yml | 3 + 6 files changed, 181 insertions(+), 156 deletions(-) delete mode 100644 deps/libodb-pgsql/conanfile.py delete mode 100644 deps/libodb/conanfile.py create mode 100644 deps/recipes/libodb-pgsql/all/conanfile.py create mode 100644 deps/recipes/libodb-pgsql/config.yml create mode 100644 deps/recipes/libodb/all/conanfile.py create mode 100644 deps/recipes/libodb/config.yml diff --git a/deps/libodb-pgsql/conanfile.py b/deps/libodb-pgsql/conanfile.py deleted file mode 100644 index eac86a3..0000000 --- a/deps/libodb-pgsql/conanfile.py +++ /dev/null @@ -1,81 +0,0 @@ -from conan import ConanFile -from conan.tools.gnu import Autotools, AutotoolsToolchain, AutotoolsDeps -from conan.tools.files import get, copy, rmdir -from conan.tools.layout import basic_layout -import os - -required_conan_version = ">=2.0" - -class LibODBPgsqlConan(ConanFile): - name = "libodb-pgsql" - version = "2.5.0" - - license = "GPL-2.0-only OR proprietary" - url = "https://github.com/your-username/conan-libodb-pgsql" - homepage = "https://www.codesynthesis.com/products/odb/" - description = "PostgreSQL database support for ODB ORM" - topics = ("orm", "database", "postgresql", "c++", "persistence") - - package_type = "library" - settings = "os", "arch", "compiler", "build_type" - - options = { - "shared": [True, False], - "fPIC": [True, False], - } - - default_options = { - "shared": False, - "fPIC": True, - } - - def config_options(self): - if self.settings.os == "Windows": - del self.options.fPIC - - def configure(self): - if self.options.shared: - self.options.rm_safe("fPIC") - - def requirements(self): - self.requires("libodb/2.4.0") - self.requires("libpq/16.8") - - def layout(self): - basic_layout(self, src_folder="src") - - def source(self): - get(self, - f"https://www.codesynthesis.com/download/odb/{self.version}/libodb-pgsql-{self.version}.tar.gz", - strip_root=True) - - def generate(self): - tc = AutotoolsToolchain(self) - tc.generate() - - deps = AutotoolsDeps(self) - deps.generate() - - def build(self): - autotools = Autotools(self) - autotools.configure() - autotools.make() - - def package(self): - autotools = Autotools(self) - autotools.install() - - copy(self, "LICENSE", - src=self.source_folder, - dst=os.path.join(self.package_folder, "licenses")) - - rmdir(self, os.path.join(self.package_folder, "share")) - rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig")) - - def package_info(self): - self.cpp_info.libs = ["odb-pgsql"] - - self.cpp_info.requires = ["libodb::libodb", "libpq::pq"] - - if self.settings.os in ["Linux", "FreeBSD"]: - self.cpp_info.system_libs.append("pthread") \ No newline at end of file diff --git a/deps/libodb/conanfile.py b/deps/libodb/conanfile.py deleted file mode 100644 index 993ca31..0000000 --- a/deps/libodb/conanfile.py +++ /dev/null @@ -1,75 +0,0 @@ -from conan import ConanFile -from conan.tools.gnu import Autotools, AutotoolsToolchain, AutotoolsDeps -from conan.tools.files import get, copy, rmdir -from conan.tools.layout import basic_layout -import os - -required_conan_version = ">=2.0" - -class LibODBConan(ConanFile): - name = "libodb" - version = "2.5.0" - - license = "GPL-2.0-only" - url = "https://github.com/aasheptunov" - homepage = "https://www.codesynthesis.com/products/odb/" - description = "ODB is an object-relational mapping (ORM) system for C++" - topics = ("orm", "database", "sql", "c++", "persistence") - - package_type = "library" - settings = "os", "arch", "compiler", "build_type" - - options = { - "shared": [True, False], - "fPIC": [True, False], - } - - default_options = { - "shared": False, - "fPIC": True, - } - - def config_options(self): - if self.settings.os == "Windows": - del self.options.fPIC - - def configure(self): - if self.options.shared: - self.options.rm_safe("fPIC") - - def layout(self): - basic_layout(self, src_folder="odb") - - def source(self): - get(self, - f"https://www.codesynthesis.com/download/odb/{self.version}/libodb-{self.version}.tar.gz", - strip_root=True) - - def generate(self): - tc = AutotoolsToolchain(self) - tc.generate() - - deps = AutotoolsDeps(self) - deps.generate() - - def build(self): - autotools = Autotools(self) - autotools.configure() - autotools.make() - - def package(self): - autotools = Autotools(self) - autotools.install() - - copy(self, "LICENSE", - src=self.source_folder, - dst=os.path.join(self.package_folder, "licenses")) - - rmdir(self, os.path.join(self.package_folder, "share")) - rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig")) - - def package_info(self): - self.cpp_info.libs = ["odb"] - - if self.settings.os in ["Linux", "FreeBSD"]: - self.cpp_info.system_libs.append("pthread") \ No newline at end of file diff --git a/deps/recipes/libodb-pgsql/all/conanfile.py b/deps/recipes/libodb-pgsql/all/conanfile.py new file mode 100644 index 0000000..c2bfbef --- /dev/null +++ b/deps/recipes/libodb-pgsql/all/conanfile.py @@ -0,0 +1,72 @@ +from conan import ConanFile +from conan.tools.cmake import CMake, cmake_layout +from conan.tools.files import get, save, copy +import os +import textwrap + +class LibodbPgsqlConan(ConanFile): + name = "libodb-pgsql" + version = "2.5.0" + settings = "os", "compiler", "build_type", "arch" + requires = ("libodb/2.5.0", "libpq/17.7") + generators = "CMakeToolchain" + + def layout(self): + cmake_layout(self) + + def source(self): + get(self, + f"https://www.codesynthesis.com/download/odb/{self.version}/libodb-pgsql-{self.version}.tar.gz", + sha256="f6e63db4a2f77604f48115f64c74a5854ca20f03f208568966693e95712a3e17", + strip_root=True) + + def build(self): + libodb_inc = self.dependencies["libodb"].package_folder + "/include" + libpq_inc = self.dependencies["libpq"].package_folder + "/include" + + self.run(f"cp -r {libodb_inc}/odb {self.source_folder}/") + + cmake_content = textwrap.dedent(f"""\ + cmake_minimum_required(VERSION 3.15) + project(libodb-pgsql VERSION {self.version} LANGUAGES CXX) + + file(GLOB_RECURSE SOURCES "odb/pgsql/*.cxx") + + add_library(libodb-pgsql ${{SOURCES}}) + + target_include_directories(libodb-pgsql PRIVATE + ${{CMAKE_CURRENT_SOURCE_DIR}} + ${{CMAKE_CURRENT_SOURCE_DIR}}/odb/pgsql/details/pregenerated + {libpq_inc} + ) + + target_link_libraries(libodb-pgsql PUBLIC odb PRIVATE pq) + target_compile_definitions(libodb-pgsql PUBLIC ODB_THREADS_POSIX) + target_compile_features(libodb-pgsql PUBLIC cxx_std_11) + """) + + save(self, os.path.join(self.source_folder, "CMakeLists.txt"), cmake_content) + + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + copy(self, "LICENSE", src=self.source_folder, + dst=os.path.join(self.package_folder, "licenses")) + copy(self, "*.h", src=self.source_folder, + dst=os.path.join(self.package_folder, "include"), keep_path=True) + copy(self, "*.hxx", src=self.source_folder, + dst=os.path.join(self.package_folder, "include"), keep_path=True) + copy(self, "*.ixx", src=self.source_folder, + dst=os.path.join(self.package_folder, "include"), keep_path=True) + copy(self, "*.txx", src=self.source_folder, + dst=os.path.join(self.package_folder, "include"), keep_path=True) + copy(self, "*.a", src=self.build_folder, + dst=os.path.join(self.package_folder, "lib"), keep_path=False) + +def package_info(self): + self.cpp_info.libs = ["libodb-pgsql"] + self.cpp_info.requires = ["libodb::libodb", "libpq::pq"] + self.cpp_info.system_libs = [] + diff --git a/deps/recipes/libodb-pgsql/config.yml b/deps/recipes/libodb-pgsql/config.yml new file mode 100644 index 0000000..fca5391 --- /dev/null +++ b/deps/recipes/libodb-pgsql/config.yml @@ -0,0 +1,3 @@ +versions: + "2.5.0": + folder: all \ No newline at end of file diff --git a/deps/recipes/libodb/all/conanfile.py b/deps/recipes/libodb/all/conanfile.py new file mode 100644 index 0000000..7ece3cb --- /dev/null +++ b/deps/recipes/libodb/all/conanfile.py @@ -0,0 +1,103 @@ +import os +import textwrap +from conan import ConanFile +from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout +from conan.tools.files import get, save, rmdir + + +class LibOdbConan(ConanFile): + name = "libodb" + version = "2.5.0" + description = "ODB C++ ORM — core runtime library" + license = "GPL-2.0-only" + homepage = "https://www.codesynthesis.com/products/odb/" + topics = ("odb", "orm", "database", "c++") + + settings = "os", "compiler", "build_type", "arch" + options = {"shared": [True, False], "fPIC": [True, False]} + default_options = {"shared": False, "fPIC": True} + + def layout(self): + cmake_layout(self, src_folder="src") + + def validate(self): + if self.settings.os != "Linux": + raise ConanInvalidConfiguration( + f"{self.ref} supporting only in devcontainers/base:ubuntu-22.04" + ) + + def source(self): + get( + self, + url=f"https://www.codesynthesis.com/download/odb/{self.version}/libodb-{self.version}.tar.gz", + sha256="700038a73c6cbead011129b15030b7cdd3f73510b687f2c4504808df4230441b", # replace hash if you changing sources + strip_root=True, + ) + self._inject_cmake() + + def _inject_cmake(self): + major = self.version.split(".")[0] + cmake = textwrap.dedent(f"""\ + cmake_minimum_required(VERSION 3.15) + project(libodb VERSION {self.version} LANGUAGES CXX) + + file(GLOB ODB_SOURCES "odb/*.cxx") + file(GLOB ODB_DETAILS_SOURCES "odb/details/*.cxx") + + add_library(odb + ${{ODB_SOURCES}} + ${{ODB_DETAILS_SOURCES}} + ) + + target_include_directories(odb PUBLIC + $ + $ + ) + + target_compile_features(odb PUBLIC cxx_std_11) + + find_package(Threads REQUIRED) + target_compile_definitions(odb PUBLIC ODB_THREADS_POSIX) + target_link_libraries(odb PUBLIC Threads::Threads) + + set_target_properties(odb PROPERTIES + VERSION {self.version} + SOVERSION {major} + ) + + install(TARGETS odb + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin + ) + install(DIRECTORY odb/ + DESTINATION include/odb + FILES_MATCHING + PATTERN "*.hxx" + PATTERN "*.ixx" + PATTERN "*.txx" + PATTERN "*.h" + ) + """) + save(self, os.path.join(self.source_folder, "CMakeLists.txt"), cmake) + + def generate(self): + tc = CMakeToolchain(self) + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + cmake = CMake(self) + cmake.install() + rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig")) + rmdir(self, os.path.join(self.package_folder, "share")) + + def package_info(self): + self.cpp_info.libs = ["odb"] + self.cpp_info.system_libs = ["pthread"] + self.cpp_info.set_property("cmake_target_name", "libodb::libodb") + self.cpp_info.set_property("pkg_config_name", "libodb") diff --git a/deps/recipes/libodb/config.yml b/deps/recipes/libodb/config.yml new file mode 100644 index 0000000..fca5391 --- /dev/null +++ b/deps/recipes/libodb/config.yml @@ -0,0 +1,3 @@ +versions: + "2.5.0": + folder: all \ No newline at end of file From d6c9cb173dd9b3df12d8e4b91b54fa728a00f0db Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Fri, 20 Feb 2026 19:45:45 +0500 Subject: [PATCH 06/18] chore(build): #44: delete conan index store --- conanfile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conanfile.py b/conanfile.py index a42ae0d..094274a 100644 --- a/conanfile.py +++ b/conanfile.py @@ -45,5 +45,5 @@ def package(self): def requirements(self): self.requires("drogon/1.9.12") self.requires("gtest/1.14.0") - self.requires("libodb/2.5.0@cppget/stable") - self.requires("libodb-pgsql/2.5.0@cppget/stable") + self.requires("libodb/2.5.0") + self.requires("libodb-pgsql/2.5.0") From ebe9f7a289beeac0c97326bd80baf958fc805ddb Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Fri, 20 Feb 2026 19:46:11 +0500 Subject: [PATCH 07/18] chore(build): #44: add finding libodb from builded by conan packages --- CMakeLists.txt | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f61829c..3bbc9eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.15) set(PROJECT_NAME "to-dos-api") project(${PROJECT_NAME} CXX) + file(GLOB_RECURSE sources CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/src/*/*.cpp ${CMAKE_SOURCE_DIR}/src/data/models/odb-gen/*.cxx @@ -11,21 +12,40 @@ set(PROJECT_OBJECTS ${PROJECT_NAME}_lib) add_library(${PROJECT_OBJECTS} OBJECT ${sources}) +find_package(Drogon REQUIRED) +find_package(jsoncpp REQUIRED) +find_package(libodb REQUIRED) + +find_library(ODB_PGSQL_LIB + NAMES odb-pgsql libodb-pgsql + REQUIRED +) +find_path(ODB_PGSQL_INCLUDE + NAMES odb/pgsql/database.hxx + REQUIRED +) + +find_library(LIBPQ NAMES pq REQUIRED) +find_library(LIBPGCOMMON NAMES pgcommon REQUIRED) +find_library(LIBPGPORT NAMES pgport REQUIRED) + target_include_directories(${PROJECT_OBJECTS} PUBLIC ${CMAKE_SOURCE_DIR}/src - /usr/include - src/data/models/ + ${CMAKE_SOURCE_DIR}/src/data/models + ${ODB_PGSQL_INCLUDE} ) -find_package(Drogon REQUIRED) -find_package(jsoncpp REQUIRED) - -target_link_libraries(${PROJECT_OBJECTS} PUBLIC +target_link_libraries(${PROJECT_OBJECTS} PUBLIC Drogon::Drogon JsonCpp::JsonCpp - odb odb-pgsql + ${ODB_PGSQL_LIB} + libodb::libodb + ${LIBPQ} + ${LIBPGCOMMON} + ${LIBPGPORT} ) + add_executable(${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/src/main.cpp $ From 3418d003bcc5af898edfab6a9df7f4542bab06d2 Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Tue, 24 Feb 2026 18:04:11 +0500 Subject: [PATCH 08/18] chore(build): #44: fix collecting of ODB_DETAILS_SOURCES libodb --- deps/recipes/libodb/all/conanfile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deps/recipes/libodb/all/conanfile.py b/deps/recipes/libodb/all/conanfile.py index 7ece3cb..69d5d8c 100644 --- a/deps/recipes/libodb/all/conanfile.py +++ b/deps/recipes/libodb/all/conanfile.py @@ -41,8 +41,8 @@ def _inject_cmake(self): cmake_minimum_required(VERSION 3.15) project(libodb VERSION {self.version} LANGUAGES CXX) - file(GLOB ODB_SOURCES "odb/*.cxx") - file(GLOB ODB_DETAILS_SOURCES "odb/details/*.cxx") + file(GLOB ODB_SOURCES "odb/*.cxx") + file(GLOB_RECURSE ODB_DETAILS_SOURCES "odb/details/*.cxx") add_library(odb ${{ODB_SOURCES}} From c4e4807251561523de6322943d2fdc8851bec1e7 Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Tue, 24 Feb 2026 18:07:47 +0500 Subject: [PATCH 09/18] chore(devcontainer): #44: add postbuild command adding a local recipes store --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index fd58d96..aaf2351 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -10,7 +10,7 @@ // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [], // Use 'postCreateCommand' to run commands after the container is created. - // "postCreateCommand": "conan profile detect --force", + "postCreateCommand": "conan remote add local-recipes ./deps --type=local-recipes-index", // Add a local recipes store for odb libraries // Configure tool-specific properties. // "customizations": {}, // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. From 03a2ad0a8f2e0e424682a01f6eece13a1056c3e7 Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Tue, 24 Feb 2026 18:08:23 +0500 Subject: [PATCH 10/18] chore(cmake): #44: add finding libodb packages and searching all models directories --- CMakeLists.txt | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bbc9eb..01d3a98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 3.15) set(PROJECT_NAME "to-dos-api") project(${PROJECT_NAME} CXX) - file(GLOB_RECURSE sources CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/src/*/*.cpp ${CMAKE_SOURCE_DIR}/src/data/models/odb-gen/*.cxx @@ -12,40 +11,35 @@ set(PROJECT_OBJECTS ${PROJECT_NAME}_lib) add_library(${PROJECT_OBJECTS} OBJECT ${sources}) -find_package(Drogon REQUIRED) -find_package(jsoncpp REQUIRED) -find_package(libodb REQUIRED) - -find_library(ODB_PGSQL_LIB - NAMES odb-pgsql libodb-pgsql - REQUIRED -) -find_path(ODB_PGSQL_INCLUDE - NAMES odb/pgsql/database.hxx - REQUIRED +file(GLOB_RECURSE database_models + ${CMAKE_CURRENT_SOURCE_DIR}/src/data/models/*.h ) -find_library(LIBPQ NAMES pq REQUIRED) -find_library(LIBPGCOMMON NAMES pgcommon REQUIRED) -find_library(LIBPGPORT NAMES pgport REQUIRED) +set(database_model_dirs "") +foreach(header ${database_models}) + get_filename_component(dir ${header} DIRECTORY) + list(APPEND database_model_dirs ${dir}) +endforeach() +list(REMOVE_DUPLICATES database_model_dirs) target_include_directories(${PROJECT_OBJECTS} PUBLIC ${CMAKE_SOURCE_DIR}/src - ${CMAKE_SOURCE_DIR}/src/data/models - ${ODB_PGSQL_INCLUDE} + /usr/include + ${database_model_dirs} ) -target_link_libraries(${PROJECT_OBJECTS} PUBLIC +find_package(Drogon REQUIRED) +find_package(jsoncpp REQUIRED) +find_package(libodb REQUIRED) +find_package(libodb-pgsql REQUIRED) + +target_link_libraries(${PROJECT_OBJECTS} PUBLIC Drogon::Drogon JsonCpp::JsonCpp - ${ODB_PGSQL_LIB} libodb::libodb - ${LIBPQ} - ${LIBPGCOMMON} - ${LIBPGPORT} + libodb-pgsql::libodb-pgsql ) - add_executable(${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/src/main.cpp $ From f7eb751648be4faba04f9d585130a51f1f31d5ab Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Tue, 24 Feb 2026 18:08:53 +0500 Subject: [PATCH 11/18] chore(models): #44: add script for generating odb files for model --- scripts/generate_odb_files.sh | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 scripts/generate_odb_files.sh diff --git a/scripts/generate_odb_files.sh b/scripts/generate_odb_files.sh new file mode 100644 index 0000000..0ea162e --- /dev/null +++ b/scripts/generate_odb_files.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +set -euo pipefail + +ODB_DEB_URL="https://www.codesynthesis.com/download/odb/2.5.0/ubuntu/ubuntu22.04/x86_64/odb_2.5.0-0~ubuntu22.04_amd64.deb" +ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)" +MODELS_DIR="$ROOT_DIR/src/data/models" +ODB_OUT_DIR="$MODELS_DIR/odb-gen" + +# ── Resolve Conan include paths ─────────────────────────────── +echo "[0/3] Resolving Conan include paths..." +ODB_INCLUDE="$(conan cache path libodb/2.5.0)/../s/src" +PGSQL_INCLUDE="$(conan cache path libodb-pgsql/2.5.0)/../s/src" +echo " libodb → $ODB_INCLUDE" +echo " libodb-pg → $PGSQL_INCLUDE" + +# ── Install ─────────────────────────────────────────────────── +echo "[1/3] Installing ODB..." +tmp=$(mktemp -d) +curl -fsSL -o "$tmp/odb.deb" "$ODB_DEB_URL" +sudo apt-get install -y "$tmp/odb.deb" +rm -rf "$tmp" + +# ── Generate ────────────────────────────────────────────────── +echo "[2/3] Generating ODB files..." +mkdir -p "$ODB_OUT_DIR" + +find "$MODELS_DIR" -type f \( -name "*.hxx" -o -name "*.h" \) \ + -not -path "$ODB_OUT_DIR/*" -print0 | \ +while IFS= read -r -d '' header; do + echo " → $(basename "$header")" + odb --std c++20 -d pgsql --generate-query \ + -o "$ODB_OUT_DIR" \ + -I "$ODB_INCLUDE" \ + -I "$PGSQL_INCLUDE" \ + -I "$ROOT_DIR" \ + "$header" +done + +# ── Cleanup ─────────────────────────────────────────────────── +echo "[3/3] Removing ODB..." +sudo apt-get remove -y odb + +echo "Done. Output: $ODB_OUT_DIR" From 79bbbd3efc037439ac4c0cf77ca4be55c397c7b9 Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Tue, 24 Feb 2026 18:03:24 +0500 Subject: [PATCH 12/18] chore(build): #44: fully rewrite conanfile for libodb-pgsql --- deps/recipes/libodb-pgsql/all/conanfile.py | 157 +++++++++++++++------ 1 file changed, 112 insertions(+), 45 deletions(-) diff --git a/deps/recipes/libodb-pgsql/all/conanfile.py b/deps/recipes/libodb-pgsql/all/conanfile.py index c2bfbef..4eb23f7 100644 --- a/deps/recipes/libodb-pgsql/all/conanfile.py +++ b/deps/recipes/libodb-pgsql/all/conanfile.py @@ -1,72 +1,139 @@ -from conan import ConanFile -from conan.tools.cmake import CMake, cmake_layout -from conan.tools.files import get, save, copy import os import textwrap +from conan import ConanFile +from conan.errors import ConanInvalidConfiguration +from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps, cmake_layout +from conan.tools.files import get, save, rmdir -class LibodbPgsqlConan(ConanFile): + +class LibOdbPgsqlConan(ConanFile): name = "libodb-pgsql" version = "2.5.0" + license = "GPL-2.0-only" + homepage = "https://www.codesynthesis.com/products/odb/" + topics = ("odb", "orm", "database", "c++") + settings = "os", "compiler", "build_type", "arch" - requires = ("libodb/2.5.0", "libpq/17.7") - generators = "CMakeToolchain" + options = {"shared": [True, False], "fPIC": [True, False]} + default_options = {"shared": False, "fPIC": True} + + def config_options(self): + if self.settings.os == "Windows": + del self.options.fPIC + + def configure(self): + if self.options.shared: + self.options.rm_safe("fPIC") def layout(self): - cmake_layout(self) + cmake_layout(self, src_folder="src") - def source(self): - get(self, - f"https://www.codesynthesis.com/download/odb/{self.version}/libodb-pgsql-{self.version}.tar.gz", - sha256="f6e63db4a2f77604f48115f64c74a5854ca20f03f208568966693e95712a3e17", - strip_root=True) + def validate(self): + if self.settings.os != "Linux": + raise ConanInvalidConfiguration( + f"{self.ref} supported only on devcontainers/base:ubuntu-22.04" + ) - def build(self): - libodb_inc = self.dependencies["libodb"].package_folder + "/include" - libpq_inc = self.dependencies["libpq"].package_folder + "/include" + def requirements(self): + self.requires("libodb/2.5.0") + self.requires("libpq/17.7") - self.run(f"cp -r {libodb_inc}/odb {self.source_folder}/") + def source(self): + get( + self, + url=f"https://www.codesynthesis.com/download/odb/{self.version}/libodb-pgsql-{self.version}.tar.gz", + sha256="f6e63db4a2f77604f48115f64c74a5854ca20f03f208568966693e95712a3e17", # replace hash if you changing sources + strip_root=True, + ) + self._inject_cmake() - cmake_content = textwrap.dedent(f"""\ + def _inject_cmake(self): + major = self.version.split(".")[0] + cmake = textwrap.dedent(f"""\ cmake_minimum_required(VERSION 3.15) - project(libodb-pgsql VERSION {self.version} LANGUAGES CXX) + project(odb-pgsql VERSION {self.version} LANGUAGES CXX) + + find_package(libodb REQUIRED CONFIG) + find_package(PostgreSQL REQUIRED CONFIG) - file(GLOB_RECURSE SOURCES "odb/pgsql/*.cxx") + file(GLOB ODB_SOURCES "odb/pgsql/*.cxx") - add_library(libodb-pgsql ${{SOURCES}}) + file(GLOB ODB_PREGENERATED_SOURCES + "odb/pgsql/details/pregenerated/odb/pgsql/details/*.cxx" + ) + + add_library(odb-pgsql + ${{ODB_SOURCES}} + ${{ODB_PREGENERATED_SOURCES}} + ) - target_include_directories(libodb-pgsql PRIVATE - ${{CMAKE_CURRENT_SOURCE_DIR}} - ${{CMAKE_CURRENT_SOURCE_DIR}}/odb/pgsql/details/pregenerated - {libpq_inc} + target_include_directories(odb-pgsql PUBLIC + $ + $ + $ ) - target_link_libraries(libodb-pgsql PUBLIC odb PRIVATE pq) - target_compile_definitions(libodb-pgsql PUBLIC ODB_THREADS_POSIX) - target_compile_features(libodb-pgsql PUBLIC cxx_std_11) + target_compile_features(odb-pgsql PUBLIC cxx_std_11) + + target_link_libraries(odb-pgsql PUBLIC + libodb::libodb + PostgreSQL::PostgreSQL + ) + + set_target_properties(odb-pgsql PROPERTIES + VERSION {self.version} + SOVERSION {major} + POSITION_INDEPENDENT_CODE ON + ) + + install(TARGETS odb-pgsql + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin + ) + + install(DIRECTORY odb/pgsql + DESTINATION include/odb + FILES_MATCHING + PATTERN "*.hxx" + PATTERN "*.ixx" + PATTERN "*.txx" + PATTERN "*.h" + PATTERN "pregenerated" EXCLUDE + ) + + install(DIRECTORY odb/pgsql/details/pregenerated/odb/pgsql/details + DESTINATION include/odb/pgsql + FILES_MATCHING + PATTERN "*.hxx" + PATTERN "*.ixx" + ) """) + save(self, os.path.join(self.source_folder, "CMakeLists.txt"), cmake) - save(self, os.path.join(self.source_folder, "CMakeLists.txt"), cmake_content) + def generate(self): + tc = CMakeToolchain(self) + tc.generate() + deps = CMakeDeps(self) + deps.generate() + + def build(self): cmake = CMake(self) cmake.configure() cmake.build() def package(self): - copy(self, "LICENSE", src=self.source_folder, - dst=os.path.join(self.package_folder, "licenses")) - copy(self, "*.h", src=self.source_folder, - dst=os.path.join(self.package_folder, "include"), keep_path=True) - copy(self, "*.hxx", src=self.source_folder, - dst=os.path.join(self.package_folder, "include"), keep_path=True) - copy(self, "*.ixx", src=self.source_folder, - dst=os.path.join(self.package_folder, "include"), keep_path=True) - copy(self, "*.txx", src=self.source_folder, - dst=os.path.join(self.package_folder, "include"), keep_path=True) - copy(self, "*.a", src=self.build_folder, - dst=os.path.join(self.package_folder, "lib"), keep_path=False) - -def package_info(self): - self.cpp_info.libs = ["libodb-pgsql"] - self.cpp_info.requires = ["libodb::libodb", "libpq::pq"] - self.cpp_info.system_libs = [] + cmake = CMake(self) + cmake.install() + rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig")) + rmdir(self, os.path.join(self.package_folder, "share")) + def package_info(self): + self.cpp_info.libs = ["odb-pgsql"] + self.cpp_info.requires = [ + "libodb::libodb", + "libpq::pq", + ] + self.cpp_info.set_property("cmake_target_name", "libodb-pgsql::libodb-pgsql") + self.cpp_info.set_property("pkg_config_name", "libodb-pgsql") From c1541786c5c7a2c1b1d3662b32fc76f3cc61cfd4 Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Tue, 24 Feb 2026 18:15:46 +0500 Subject: [PATCH 13/18] chore(cmake): #44: add .hxx to database_models --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 01d3a98..6f56a1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ add_library(${PROJECT_OBJECTS} OBJECT ${sources}) file(GLOB_RECURSE database_models ${CMAKE_CURRENT_SOURCE_DIR}/src/data/models/*.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/data/models/*.hxx ) set(database_model_dirs "") From b84c569eb1570be5bdf2b0913fd6e59064d31a3a Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Tue, 24 Feb 2026 18:16:30 +0500 Subject: [PATCH 14/18] docs(orm): #44: update readme regard new build instructions --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 09b1886..c529a7a 100644 --- a/README.md +++ b/README.md @@ -75,9 +75,10 @@ Alternatively, use the CMake Tools Extension in VS Code. To do this, open the CM ### ORM: -After creating the database or model, it is necessary to generate the auxiliary ODB files with the command `odb --std c++20 -d pgsql --generate-query -o odb-gen ` from the folder `src/data/models`. +After creating the database or model, it is necessary to generate the auxiliary ODB files. +For generating these files use script `./scripts/generate_odb_files.sh` -After executing the command, files will be created or updated in the folder `src/data/models/odb-gen'. Please do not modify or transfer these files for the correct operation of the application. +After executing the script, files will be created or updated in the folder `src/data/models/odb-gen'. Please do not modify or transfer these files for the correct operation of the application. ### Migrations: From 7dea31b93a3133ce2d0a4f370aa8be16a9e0cf4b Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Tue, 24 Feb 2026 18:28:34 +0500 Subject: [PATCH 15/18] chore(build): #44: increase speed building --- .devcontainer/to-dos-conan-profile.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/.devcontainer/to-dos-conan-profile.conf b/.devcontainer/to-dos-conan-profile.conf index 71729b1..2c7b3fd 100644 --- a/.devcontainer/to-dos-conan-profile.conf +++ b/.devcontainer/to-dos-conan-profile.conf @@ -9,4 +9,5 @@ compiler.cppstd=gnu20 [conf] tools.build:compiler_executables={"c":"clang","cpp":"clang++"} +tools.build:jobs={{os.cpu_count()}} tools.system.package_manager:mode=install \ No newline at end of file From fa88116a14a6ed98a45ffb82a9726b89058bb19e Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Tue, 24 Feb 2026 18:51:32 +0500 Subject: [PATCH 16/18] ci: #44: add local recipes store --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a4f159d..571c090 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,6 +33,7 @@ jobs: cp .devcontainer/to-dos-conan-profile.conf .conan2/profiles/default export CONAN_HOME="$(pwd)/.conan2" + conan remote add local-recipes ./deps --type=local-recipes-index conan install . --build=missing # we don't need to push docker image that was built using our Dev Container push: never From e2e8e2c27e252a14905e9c4e16a28b3aa168dcd3 Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Wed, 25 Feb 2026 12:38:02 +0500 Subject: [PATCH 17/18] chore(build): #44: delete unnecessary windows checking --- deps/recipes/libodb-pgsql/all/conanfile.py | 23 ++++++++++++++++++---- deps/recipes/libodb/all/conanfile.py | 19 +++++++++++++++++- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/deps/recipes/libodb-pgsql/all/conanfile.py b/deps/recipes/libodb-pgsql/all/conanfile.py index 4eb23f7..ae3aca8 100644 --- a/deps/recipes/libodb-pgsql/all/conanfile.py +++ b/deps/recipes/libodb-pgsql/all/conanfile.py @@ -5,7 +5,6 @@ from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps, cmake_layout from conan.tools.files import get, save, rmdir - class LibOdbPgsqlConan(ConanFile): name = "libodb-pgsql" version = "2.5.0" @@ -18,8 +17,7 @@ class LibOdbPgsqlConan(ConanFile): default_options = {"shared": False, "fPIC": True} def config_options(self): - if self.settings.os == "Windows": - del self.options.fPIC + pass def configure(self): if self.options.shared: @@ -31,7 +29,24 @@ def layout(self): def validate(self): if self.settings.os != "Linux": raise ConanInvalidConfiguration( - f"{self.ref} supported only on devcontainers/base:ubuntu-22.04" + f"{self.ref} is supported only on Linux" + ) + try: + with open("/etc/os-release") as f: + info = dict( + line.strip().split("=", 1) + for line in f if "=" in line + ) + distro = info.get("ID", "").strip('"') + version = info.get("VERSION_ID", "").strip('"') + if distro != "ubuntu" or version != "22.04": + raise ConanInvalidConfiguration( + f"{self.ref} is supported only on Ubuntu 22.04 " + f"(detected: {distro} {version})" + ) + except FileNotFoundError: + raise ConanInvalidConfiguration( + f"{self.ref} requires Ubuntu 22.04 (/etc/os-release not found)" ) def requirements(self): diff --git a/deps/recipes/libodb/all/conanfile.py b/deps/recipes/libodb/all/conanfile.py index 69d5d8c..37af06b 100644 --- a/deps/recipes/libodb/all/conanfile.py +++ b/deps/recipes/libodb/all/conanfile.py @@ -23,7 +23,24 @@ def layout(self): def validate(self): if self.settings.os != "Linux": raise ConanInvalidConfiguration( - f"{self.ref} supporting only in devcontainers/base:ubuntu-22.04" + f"{self.ref} is supported only on Linux" + ) + try: + with open("/etc/os-release") as f: + info = dict( + line.strip().split("=", 1) + for line in f if "=" in line + ) + distro = info.get("ID", "").strip('"') + version = info.get("VERSION_ID", "").strip('"') + if distro != "ubuntu" or version != "22.04": + raise ConanInvalidConfiguration( + f"{self.ref} is supported only on Ubuntu 22.04 " + f"(detected: {distro} {version})" + ) + except FileNotFoundError: + raise ConanInvalidConfiguration( + f"{self.ref} requires Ubuntu 22.04 (/etc/os-release not found)" ) def source(self): From eaaf4767da69289c10e49782f2b785f4068fcced Mon Sep 17 00:00:00 2001 From: Oleg Kl Date: Wed, 25 Feb 2026 12:44:58 +0500 Subject: [PATCH 18/18] chore(build): #44: add options switcher for shared configuration --- deps/recipes/libodb/all/conanfile.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deps/recipes/libodb/all/conanfile.py b/deps/recipes/libodb/all/conanfile.py index 37af06b..317ec35 100644 --- a/deps/recipes/libodb/all/conanfile.py +++ b/deps/recipes/libodb/all/conanfile.py @@ -17,6 +17,10 @@ class LibOdbConan(ConanFile): options = {"shared": [True, False], "fPIC": [True, False]} default_options = {"shared": False, "fPIC": True} + def configure(self): + if self.options.shared: + self.options.rm_safe("fPIC") + def layout(self): cmake_layout(self, src_folder="src")