README
ΒΆ
βοΈ craftC
A fast, minimal C build tool inspired by Taskfile & Make. Designed for speed, clarity, and cross-platform simplicity.
π Features
- β‘ Lightning-fast incremental builds with dependancy tracking
- π§ Smart recompilation detection with reasoning
- π¨ C compiler integration with support for custom flags
- π¦ Static library archiving
- π Application linking
- β Clear verbose output option
- π§© Simple CLI
- π§° Cross-platform: Linux, (macOS, Windows not tested yet)
π¦ Installation
Install with Go:
go install github.com/ameershira/craftc@latest
Or clone and build manually:
git clone https://github.com/ameershira/craftc
cd craftc
go build .
π§© Usage Examples
The examples below use the verbose flag to print output to the console.
1. Build an object file
Use the obj command:
craftc obj -cc cc -cfile ./libsrc1.c -cflags "-Wall -O2" -objdir ./build/obj -v
Output:
[build] π§ build/obj/libsrc1.c.o: object file does not exist.
[compile] π¨ /usr/bin/cc -Wall -O2 -MMD -MF build/obj/libsrc.libsrc1.c.d -c ./libsrc1.c -o build/obj/libsrc1.c.o
Re-run:
β
build/obj/libsrc1.c.o is up to date.
2. Build multiple object files concurrently
Use the objs command:
craftc objs -cc cc -cfiles "./libsrc1.c ./libsrc2.c" -cflags "-Wall" -objdir ./build/obj -v
Output:
[build] π§ build/obj/libsrc2.c.o: object file does not exist.
[build] π§ build/obj/libsrc1.c.o: object file does not exist.
[compile] π¨ /usr/bin/cc -Wall -MMD -MF build/obj/libsrc2.c.d -c ./libsrc2.c -o build/obj/libsrc2.c.o
[compile] π¨ /usr/bin/cc -Wall -MMD -MF build/obj/libsrc1.c.d -c ./libsrc1.c -o build/obj/libsrc1.c.o
3. Build a static library
Use the static-lib command:
craftc static-lib -cc cc -cfiles "./libsrc1.c ./libsrc2.c" -cflags "-Wall -O2" -lib-path "./build/lib.a" -objdir ./build/obj -v
Output:
[build] π§ build/obj/libsrc2.c.o: object file does not exist.
[build] π§ build/obj/libsrc1.c.o: object file does not exist.
[compile] π¨ /usr/bin/cc -Wall -O2 -MMD -MF build/obj/libsrc2.c.d -c ./libsrc2.c -o build/obj/libsrc2.c.o
[compile] π¨ /usr/bin/cc -Wall -O2 -MMD -MF build/obj/libsrc1.c.d -c ./libsrc1.c -o build/obj/libsrc1.c.o
[archive] π¦ /usr/bin/ar rcs ./build/lib.a build/obj/libsrc1.c.o build/obj/libsrc2.c.o
Re-run:
β
build/obj/libsrc2.c.o is up to date.
β
build/obj/libsrc1.c.o is up to date.
β
π¦ ./build/lib.a is up to date.
4. Build an executable
We also statically link against a library.
Use the exe command:
craftc exe -cc cc -cfiles "main.c" -objdir ./build/obj -cflags "-Wall -O2 -I ./libsrc" -lib-paths "./build/lib.a" -exe-path ./app
Output:
[build] π§ build/obj/main.c.o: object file does not exist.
[compile] π¨ /usr/bin/cc -Wall -O2 -I ./libsrc -MMD -MF build/obj/main.c.d -c ./main.c -o build/obj/main.c.o
[linking] π /usr/bin/cc build/obj/main.c.o ./build/lib.a -o ./build/app
Re-run:
β
build/obj/main.c.o is up to date.
β
π ./build/app is up to date.
5. Task integration
Craftc's commands are designed to be composable. This makes it simple and easy to understand and integrate into other tools such as Task.
The example below utlises Task to build an executable, and also build the dependancy library is required.
Example:
version: '3'
tasks:
lib:
desc: Build a static library with a few source files
vars:
BUILD_DIR: ./build/{{.TASK}}
OBJ_DIR: '{{.BUILD_DIR}}/obj'
SRC: ./libsrc/libsrc1.c ./libsrc/libsrc2.c
STATIC_LIB: '{{.BUILD_DIR}}/{{.TASK}}.a'
CFLAGS: -Wall -O2
cmds:
- ./craftc static-lib -cc cc -cfiles "{{.SRC}}" -objdir {{.OBJ_DIR}} -cflags "{{.CFLAGS}}" -lib-path "{{.STATIC_LIB}}" -i {{.CLI_ARGS}}
exe:
desc: Build an exe cmd with a few source files
vars:
BUILD_DIR: ./build/{{.TASK}}
OBJ_DIR: '{{.BUILD_DIR}}/obj'
SRC: ./appsrc/main.c
STATIC_LIB: ./build/lib/lib.a
CFLAGS: -Wall -O2 -I ./libsrc
# LDFLAGS: -Wl,--trace
APP_PATH: '{{.BUILD_DIR}}/{{.TASK}}-app'
deps:
- task: lib
cmds:
- >
./craftc exe
-cc cc
-cfiles "{{.SRC}}"
-objdir {{.OBJ_DIR}}
-cflags "{{.CFLAGS}}"
-ldflags "{{.LDFLAGS}}"
-exe-path {{.APP_PATH}}
-lib-paths "{{.STATIC_LIB}}"
-i {{.CLI_ARGS}}
Output:
[build] π§ build/lib/obj/libsrc.libsrc2.c.o: object file does not exist.
[build] π§ build/lib/obj/libsrc.libsrc1.c.o: object file does not exist.
[compile] π¨ /usr/bin/cc -Wall -O2 -MMD -MF build/lib/obj/libsrc.libsrc1.c.d -c ./libsrc/libsrc1.c -o build/lib/obj/libsrc.libsrc1.c.o
[compile] π¨ /usr/bin/cc -Wall -O2 -MMD -MF build/test4/obj/libsrc.libsrc2.c.d -c ./libsrc/libsrc2.c -o build/lib/obj/libsrc.libsrc2.c.o
[archive] π¦ /usr/bin/ar rcs ./build/lib/lib.a build/lib/obj/libsrc.libsrc1.c.o build/lib/obj/libsrc.libsrc2.c.o
[build] π§ build/exe/obj/appsrc.main.c.o: object file does not exist.
[compile] π¨ /usr/bin/cc -Wall -O2 -I ./libsrc -MMD -MF build/exe/obj/appsrc.main.c.d -c ./appsrc/main.c -o build/exe/obj/appsrc.main.c.o
[linking] π /usr/bin/cc build/exe/obj/appsrc.main.c.o ./build/lib/lib.a -o ./build/exe/app
Re-run:
β
build/lib/obj/libsrc.libsrc2.c.o is up to date.
β
build/lib/obj/libsrc.libsrc1.c.o is up to date.
β
π¦ ./build/lib/lib.a is up to date.
β
build/exe/obj/appsrc.main.c.o is up to date.
β
π ./build/exe/app is up to date.
Documentation
ΒΆ
There is no documentation for this package.
Click to show internal directories.
Click to hide internal directories.