{"id":20177831,"url":"https://github.com/tfc/nix_cmake_example","last_synced_at":"2025-07-19T05:07:02.558Z","repository":{"id":43039241,"uuid":"150246830","full_name":"tfc/nix_cmake_example","owner":"tfc","description":"An example with nix: How to automatically and reproducibly build and integration-test a database C++ app in 60 different build-configurations (library exchange/compiler exchange/static-nonstatic)","archived":false,"fork":false,"pushed_at":"2022-08-28T13:38:17.000Z","size":215,"stargazers_count":64,"open_issues_count":1,"forks_count":3,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-10T04:39:06.053Z","etag":null,"topics":["build-automation","build-configuration","c-plus-plus","dependency-injection","dependency-manager","docker","docker-image","integration-testing","nix","python","reproducible-builds","virtualization","workflow"],"latest_commit_sha":null,"homepage":"","language":"Nix","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tfc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-09-25T10:21:51.000Z","updated_at":"2025-01-27T17:55:54.000Z","dependencies_parsed_at":"2022-09-06T04:50:07.518Z","dependency_job_id":null,"html_url":"https://github.com/tfc/nix_cmake_example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tfc/nix_cmake_example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfc%2Fnix_cmake_example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfc%2Fnix_cmake_example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfc%2Fnix_cmake_example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfc%2Fnix_cmake_example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tfc","download_url":"https://codeload.github.com/tfc/nix_cmake_example/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfc%2Fnix_cmake_example/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265892098,"owners_count":23844966,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build-automation","build-configuration","c-plus-plus","dependency-injection","dependency-manager","docker","docker-image","integration-testing","nix","python","reproducible-builds","virtualization","workflow"],"created_at":"2024-11-14T02:17:36.549Z","updated_at":"2025-07-19T05:07:02.530Z","avatar_url":"https://github.com/tfc.png","language":"Nix","readme":"# An example nix project with C++ and Python\n\nThis project consists of 2 simple example applications that model a writer and\na reader to/from a postgres database:\n\nThe \"server\" application (C++) listens on TCP socket 1300 and writes into the\ndatabase whatever it receives.\nThe \"webserver\" application (Python) is either a script that just prints the\ndatabase content, or a webserver script (both included) that listens on port\n8000 and lists the latest 10 database \"messages\".\n\nBoth applications are relatively simple and stupid as they are mere\ndemonstration vehicles for showing:\n\n- how to setup a reproducible working environment with toolchain and library\n  dependencies etc. with a single command using `nix`\n- how to build the application(s) with different compilers, different library\n  versions, and select dynamic/static linking with a single parametrized\n  command using `nix`\n- how to make the build process reproducible so that it still works in a few\n  years on completely different linux environments, by pinning all versions of\n  the toolchain down using `nix`\n- how to automatically create minimal [`docker`](https://www.docker.com/) images\n  (so minimal that they contain no base distro image) using `nix`\n- how to run completely automated integration test scenarios in VMs using `nix`\n\n## Dependencies\n\nAt **compile time**, the applications need the following:\n\n- server\n  - C++ compiler toolchain ([GCC](https://gcc.gnu.org/) or\n    [clang](https://clang.llvm.org/))\n  - [`cmake`](https://cmake.org/) (meta) build system\n  - [`boost`](https://www.boost.org/) library\n  - [`libpqxx`](http://pqxx.org/development/libpqxx) library (C++ postgres\n    interface)\n  - [`gtest`](https://github.com/google/googletest) unit test framework\n- webserver\n  - [`python`](https://www.python.org/) version 3\n  - [`flask`](http://flask.pocoo.org/) library (webserver)\n  - [`psycopg2`](http://initd.org/psycopg/) library (postgres interface)\n\nThe applications can be compiled (the C++ app) and both be run without nix at\nall.\nBut in that case you have to install/configure all dependencies yourself -\nwith `nix`, everything will be handled automagically.\n\n## Build\n\nIn order to build the server app, do the following:\n\n```bash\n$ cd $project/server\n$ nix-build\n# You may now run ./result/bin/messagedb-server\n```\n\nIn order to package the python app into a wrapper script that can be called\nlike any binary, do the following:\n\n```bash\n$ cd $project/python_client\n$ nix-build\n# You may now run ./result/bin/mdb-webserver\n```\n\nThe python wrapper calls python with the dependencies in place, leaving no way\nto accidentally call it with the wrong python interpreter.\n(This way of packaging a python app is completely optional, `nix` does not force\nyou to do so)\n\n`nix` can be obtained [here](https://nixos.org/nix/download.html).\nThere is always the quick and unsafe `curl | sh` way to install, but there are\nalso instructions on the project website that include binary verification.\n\nPlease note that tab completion in the following examples works out of the\nbox on NixOS, while users of other distros have to install it manually.\nhttps://github.com/hedning/nix-bash-completions\n\n## Build in different configurations\n\nThe server app can be compiled in different configurations:\n\n- Compiler (can be easily extended/customized.)\n   - GCC 7.3.0 (That is the default choice in the current package list. Can be\n     easily parametrized, of course!)\n   - GCC 8.2.0\n   - clang 5.0.2\n   - clang 6.0.1\n   - clang 7.0.0\n- `boost` versions 1.6.3, 1.6.4, 1.6.5, 1.6.6, 1.6.7, 1.6.8\n- Binary linkage\n   - static (single-file with no further runtime dependencies)\n   - dynamic\n\nTo select one configuration, run:\n\n```bash\n$ cd $project\n$ nix-build release.nix -A \u003ctab-complete\u003e\nintegrationtest-mdb-server-clang7-boost166         integrationtest-mdb-server-static-clang8-boost169  mdb-server-gcc8-boost166\nintegrationtest-mdb-server-clang7-boost167         integrationtest-mdb-server-static-gcc7-boost166    mdb-server-gcc8-boost167\nintegrationtest-mdb-server-clang7-boost168         integrationtest-mdb-server-static-gcc7-boost167    mdb-server-gcc8-boost168\nintegrationtest-mdb-server-clang7-boost169         integrationtest-mdb-server-static-gcc7-boost168    mdb-server-gcc8-boost169\nintegrationtest-mdb-server-clang8-boost166         integrationtest-mdb-server-static-gcc7-boost169    mdb-server-static-clang7-boost166\nintegrationtest-mdb-server-clang8-boost167         integrationtest-mdb-server-static-gcc8-boost166    mdb-server-static-clang7-boost167\nintegrationtest-mdb-server-clang8-boost168         integrationtest-mdb-server-static-gcc8-boost167    mdb-server-static-clang7-boost168\nintegrationtest-mdb-server-clang8-boost169         integrationtest-mdb-server-static-gcc8-boost168    mdb-server-static-clang7-boost169\nintegrationtest-mdb-server-gcc7-boost166           integrationtest-mdb-server-static-gcc8-boost169    mdb-server-static-clang8-boost166\nintegrationtest-mdb-server-gcc7-boost167           mdb-server-clang7-boost166                         mdb-server-static-clang8-boost167\nintegrationtest-mdb-server-gcc7-boost168           mdb-server-clang7-boost167                         mdb-server-static-clang8-boost168\nintegrationtest-mdb-server-gcc7-boost169           mdb-server-clang7-boost168                         mdb-server-static-clang8-boost169\nintegrationtest-mdb-server-gcc8-boost166           mdb-server-clang7-boost169                         mdb-server-static-gcc7-boost166\nintegrationtest-mdb-server-gcc8-boost167           mdb-server-clang8-boost166                         mdb-server-static-gcc7-boost167\nintegrationtest-mdb-server-gcc8-boost168           mdb-server-clang8-boost167                         mdb-server-static-gcc7-boost168\nintegrationtest-mdb-server-gcc8-boost169           mdb-server-clang8-boost168                         mdb-server-static-gcc7-boost169\nintegrationtest-mdb-server-static-clang7-boost166  mdb-server-clang8-boost169                         mdb-server-static-gcc8-boost166\nintegrationtest-mdb-server-static-clang7-boost167  mdb-server-docker                                  mdb-server-static-gcc8-boost167\nintegrationtest-mdb-server-static-clang7-boost168  mdb-server-docker-static                           mdb-server-static-gcc8-boost168\nintegrationtest-mdb-server-static-clang7-boost169  mdb-server-gcc7-boost166                           mdb-server-static-gcc8-boost169\nintegrationtest-mdb-server-static-clang8-boost166  mdb-server-gcc7-boost167                           mdb-webservice\nintegrationtest-mdb-server-static-clang8-boost167  mdb-server-gcc7-boost168                           mdb-webservice-docker\nintegrationtest-mdb-server-static-clang8-boost168  mdb-server-gcc7-boost169\n\n$ nix-build release.nix -A mdb-server-gcc7-boost166\n# You may now run ./result/bin/messagedb-server\n```\n\n## Generate `docker` images for both apps\n\nCompiling and installing the docker images is simple.\nThe step of the docker image creation does not even require you to have `docker`\non your system.\n\nserver:\n\n```bash\n$ cd $project\n$ nix-build release.nix -A mdb-server-docker\n$ du -sh $(readlink -f result)\n46M     /nix/store/bnd9gzdgmrvdxd7cdrm7fxr39db8phfk-docker-image-mdb-server.tar.gz\n```\n\nThe docker image with the static version of the library is a bit smaller:\n\n```bash\n$ nix-build release.nix -A  mdb-server-docker-static\n$ du -sh $(readlink -f result)\n22M     /nix/store/58lpaf0yh6skjdxdd0qfc4vrw9nj1j76-docker-image-mdb-server.tar.gz\n```\n\nPlease note that this can of course be further reduced, but then the example\nwould go out of scope and we have a nice starting point already.\n\nThe webserver docker image:\n\n```bash\n$ nix-build release.nix -A mdb-webservice-docker\n$ du -sh $(readlink -f result)\n60M\t/nix/store/l4ipb3p325yaflsdna8h7nijla61vwrz-docker-image-mdb-webservice.tar.gz\n```\n\nWhat's particularly interesting about these docker images compared to\nconventionally created images is, that they only contain the run-time\ndependencies they need.\nThis means that for the statically linked binary, the corresponding docker\nimage, in addition to bash and its run-time dependencies, only contains the\nbinary itself. Likewise, for the dynamically linked binary, and the python\nwebserver, the docker images contain exactly the needed dependencies, e.g.\nPython 3.xyz for the webserver.\nIn contrast, building a Docker image traditionally, e.g., with a Docker file\nbuilt upon a Ubuntu/Debian/Fedora base image, would quickly result in an image\nsize around hundreds or MB.\n\n## Integration tests\n\nThere is only one integration test in this example.\nIt does the following\n\n- Create a complete Linux VM that contains at least:\n  - A preconfigured postgres DB (with role and DB for test user)\n  - both applications\n\nRunning the test does the following:\n  - Boot the VM\n  - wait for postgres to start\n  - then start the server app\n  - then start the webservice app\n  - feed some data into the VM via the server app\n  - check if the DB is in the right state\n  - check if the webserver's output is correct\n\nThis integration test scenario can easily be run with all different build\nconfigurations of the server app.\nThe NixOS distribution tests many of its packages with such integration tests.\nThese are however much more complex by running full herds of VMs in virtual\nnetworks, to some extent even with the X desktop activated and OCR etc. - out\nof scope for this example.\n\nTo run the integration tests, do:\n\n```bash\n$ nix-build release.nix -A integrationtest-mdb-server-\u003ctab-complete\u003e\nintegrationtest-mdb-server-clang7-boost166         integrationtest-mdb-server-gcc7-boost169           integrationtest-mdb-server-static-clang8-boost168\nintegrationtest-mdb-server-clang7-boost167         integrationtest-mdb-server-gcc8-boost166           integrationtest-mdb-server-static-clang8-boost169\nintegrationtest-mdb-server-clang7-boost168         integrationtest-mdb-server-gcc8-boost167           integrationtest-mdb-server-static-gcc7-boost166\nintegrationtest-mdb-server-clang7-boost169         integrationtest-mdb-server-gcc8-boost168           integrationtest-mdb-server-static-gcc7-boost167\nintegrationtest-mdb-server-clang8-boost166         integrationtest-mdb-server-gcc8-boost169           integrationtest-mdb-server-static-gcc7-boost168\nintegrationtest-mdb-server-clang8-boost167         integrationtest-mdb-server-static-clang7-boost166  integrationtest-mdb-server-static-gcc7-boost169\nintegrationtest-mdb-server-clang8-boost168         integrationtest-mdb-server-static-clang7-boost167  integrationtest-mdb-server-static-gcc8-boost166\nintegrationtest-mdb-server-clang8-boost169         integrationtest-mdb-server-static-clang7-boost168  integrationtest-mdb-server-static-gcc8-boost167\nintegrationtest-mdb-server-gcc7-boost166           integrationtest-mdb-server-static-clang7-boost169  integrationtest-mdb-server-static-gcc8-boost168\nintegrationtest-mdb-server-gcc7-boost167           integrationtest-mdb-server-static-clang8-boost166  integrationtest-mdb-server-static-gcc8-boost169\nintegrationtest-mdb-server-gcc7-boost168           integrationtest-mdb-server-static-clang8-boost167\n```\n\nThe result of such integration tests is a HTML/XML log document in the `result`\nfolder.\n\n## Nix CI\n\nNixOS comes with a service for continuous integration, called\n[`hydra`](https://github.com/NixOS/hydra).\nIt does not look as polished as other CIs and its integration is very github\ncentric (because `nix` and `NixOS` source code and package lists are hosted on\ngithub), but it is generally extensible with plugins.\n\nA screenshot of a private hydra instance building this project:\n\n![Running hydra instance on this project in action](doc/hydra_nix_example.png)\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftfc%2Fnix_cmake_example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftfc%2Fnix_cmake_example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftfc%2Fnix_cmake_example/lists"}