{"id":16842568,"url":"https://github.com/rofl0r/rcb2","last_synced_at":"2025-04-11T05:52:15.230Z","repository":{"id":138311797,"uuid":"180214525","full_name":"rofl0r/rcb2","owner":"rofl0r","description":"intelligent and automatic build system for C","archived":false,"fork":false,"pushed_at":"2021-04-17T21:26:17.000Z","size":23,"stargazers_count":12,"open_issues_count":1,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-11T05:52:10.895Z","etag":null,"topics":["build-system","build-tool","c"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rofl0r.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-04-08T19:00:26.000Z","updated_at":"2024-09-10T17:38:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"f26e7db5-0956-4f9c-96b4-e2a53340b725","html_url":"https://github.com/rofl0r/rcb2","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rofl0r%2Frcb2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rofl0r%2Frcb2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rofl0r%2Frcb2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rofl0r%2Frcb2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rofl0r","download_url":"https://codeload.github.com/rofl0r/rcb2/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248351409,"owners_count":21089271,"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-system","build-tool","c"],"created_at":"2024-10-13T12:46:45.918Z","updated_at":"2025-04-11T05:52:15.217Z","avatar_url":"https://github.com/rofl0r.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"RcB2 - rofl0r's C builder 2nd generation\n========================================\n\n`rcb2` is the successor to [RcB](https://github.com/rofl0r/rcb).\nIt's a build system for C, where dependencies between files are documented with\nthe use of a special pragma inside the sourcefiles and headers.\nSo the code itself is the documentation how the program needs to be built.\n\nWhen you run `rcb2`, you simply pass it the name of the sourcefile containing\nthe `main()` function, and `rcb2` figures out which other files are needed.\n\nCross-compilation is as simple as using an appropriate `CC` environment\nvariable.\n\n`rcb2`, when started as `rcb2make`, writes a *GNU make* compatible Makefile\nwhich can be used for efficiency and to support parallel builds or to create\ntarballs for distribution which do not require `rcb2` itself.\n\n`rcb2` itself is parallel and very fast, it basically uses only the C\npreprocessor to figure out which files need to be built, then builds all\nrequired files in a single compiler call.\n\n## How it works, a small example:\n\nYou have a file `main.c` which, depending on some macros, shall use either\n`foo.h` and `foo.c`, or `bar.h` and `bar.c`.\n\nmain.c:\n```c\n#include \u003cstdio.h\u003e\n\n#ifdef FOO\n#include \"foo.h\"\n#define func foo\n#else\n#include \"bar.h\"\n#define func bar\n#endif\n\nint main() { printf(\"%s\\n\", func()); }\n\n```\n\nfoo.h:\n```c\nconst char *foo(void);\n#pragma RcB2 DEP \"foo.c\"\n```\n\nfoo.c:\n```c\nconst char *foo(void) { return \"foo\"; }\n```\n\nbar.h:\n```c\nconst char *bar(void);\n#pragma RcB2 DEP \"bar.c\"\n```\nbar.c:\n```c\nconst char *bar(void) { return \"bar\"; }\n```\n\nnow you can run `CFLAGS=-DFOO rcb2 main.c` and it will produce an executable\nnamed `main` which will print `foo` when run.\nif you execute `rcb2 main.c`, the build executable will print `bar`.\n\nyou can find the example in `tests/1`.\n\n## How to use\n\nIf a file (typically a header) requires some other files, you add a\n`#pragma RcB2 DEP \"../src/file1.c\" \"lib/file2.c\"`. Globs are supported too.\nAll path components need to be relative to the file containing the pragma.\n\nIf a .c file requires certain CFLAGS for compilation, e.g. `-std=c99`, you can\nadd `#pragma RcB2 CFLAGS \"-std=c99\"`. Note that this should be used really\nsparingly, since it will be applied to **all** files in the build, and it can\nunexpectedly break compilation for some files or on some systems:\nFor example on some BSDs, using `-std=c99` automatically enables a strict mode\nwhich deselects certain useful POSIX, XSI and GNU features, like *strdup()* etc.\n\nUse `#pragma RcB2 CPPFLAGS \"-DFOO\" \"-I..\"` if you need some macros or include\npaths to be enabled across compilation units.\nHere again, usage will be applied to **all** files, so adding e.g. `-I..` may\nhave unintended consequences if you use several libraries.\n\nLikewise, if a certain library is needed, e.g. `-lncurses` and `-lm`, you\ndeclare it like so: `#pragma RcB2 LINK \"-lncurses\" \"-lm\"`.\n\nnote that you could stuff both `-l` directives into the same set of double\nquotes, and it would work, but it is advised to specify each library separately.\nRcB2 drops duplicates to keep the compiler command line as short as possible.\nThe `LINK` directive should only be used for libraries, there's an `LDFLAGS`\ndirective that can be used for other necessary linker flags.\n\n`CPPFLAGS`, `CFLAGS`, `LINK (LIBS)` and `LDFLAGS` derived via RcB2 pragmas\nare considered essential for a working build and hardcoded into the resulting\nMakefile, unlike environment vars or presets used for compilation.\n\nThe pragmas can be put between preprocessor `#if`s and `#ifdef`s.\nOnly those that survive the preprocessor pass are being picked up.\n\nAfter all headers have the dependencies on the .c files they depend on properly\ndocumented, it's sufficient to simply include a header, and run `rcb2` on the\nfile, and it will pick up all files required instantly.\n\n`rcb2` has a `--pure` mode that throws all .c files onto the compiler in\na single pass.\nThis allows to use CFLAGS like `-fwhole-program` which can very efficiently\noptimize the binary.\n\n## Installation\n\ncopy `rcb2.py` into a directory in your *PATH* (e.g. /usr/bin) as `rcb2`.\nsymlink `rcb2` to `rcb2make` if you also want to use the makefile generator.\n\nyou can also simply copy/paste the following snippet into your shell:\n\n    export RCB2DEST=/usr/bin\n    cp rcb2.py \"$RCB2DEST\"/rcb2\n    ln -sf rcb2 \"$RCB2DEST\"/rcb2make\n\n## Implementation \u0026 Design\n\n`rcb2` simply runs the C preprocessor on the file passed on the command line,\nusing the supplied C/CPPFLAGS, and then parses the `#pragma RcB2` directives\nthat survived. All referenced files are then recursively processed in the exact\nsame manner, until the complete list is created. As a C preprocessor is a pretty\nsimple program, this is a very quick process.\n\nAfter the complete list of dependencies is known, they are passed to the\ncompiler. That's it.\n\nEven though the current version of `rcb2` is written in python2, it is really\nquick, and the concept is so simple that it could easily be rewritten in a more\nperformant/portable language such as C.\n\nAt this point, all command line parameters are experimental.\nRun `rcb2 --help` to get a full list of options.\n\n## History\n\nRcB, the previous version, used comments for the same purpose, which resulted in\na number of issues, especially in regard to conditional compilation.\nwhile experimenting with OMP, it occured to me that using a `#pragma`\ndirective would be the solution to those issues, as it survives a preprocessor\npass. therefore the existing conditional compilation the preprocessor offers can\nbe leveraged.\n\nRcB was also written in perl, a very ugly language, which is very hard to read\nonce a program has been written. Everytime a new cornercase required modifying\nthe code, it took a substantial amount of time to make sense of the almost\nrandom looking pile of dollar signs and curly braces.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frofl0r%2Frcb2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frofl0r%2Frcb2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frofl0r%2Frcb2/lists"}