$ pip install mekpie
v0.1.11
make building C as simple as pie
Mekpie is an opinionated build system for small scale C projects. The core premise of Mekpie is that you should not be spending time worrying about Make files, compiler arguments, or build times, when working on a small C project. By enforcing a simple directory structure and always providing a clean build, Mekpie saves you time and effort. For added convenience Mekpie takes notes from tools like Rust's cargo and Node's npm and provides options for building, running, cleaning, and testing your current project.
Mekpie is a small-scale project and is not supposed to replace tools like CMake or provide any sort of package management capabilities. Use Mekpie when the alternative is a shoddy Make file or manually compiling.
Currently Mekpie supports the gcc, clang, avr-gcc, and emscripten compilers, as well as allows users to write custom compiler configurations.
Mekpie is a python package. Use pip to install it!
$ pip install mekpie
Create a new project by running mekpie new
. Mekpie will walk you through the configuration.
$ mekpie new "project-name"
┌ Configuring mekpie...
│ Please provide a name for your project (default project-name):
│ Selected project-name.
│ Mekpie supports the following c compilers, please select one (compilers must be installed separately):
│ - gcc_clang for use with the gcc or clang compiler
│ - emscripten for use with the emscripten c to js compiler
│ - avr_gcc for use with avr-gcc and avrdude
│ Please select a cc (default gcc_clang):
│ Selected gcc_clang.
│ ┌ Configuring gcc_clang...
│ │ Please select a compiler command (default cc):
│ │ Selected cc.
│ │ Please select a debug command (default lldb):
│ │ Selected lldb.
│ └ gcc_clang configured!
└ mekpie configured!
project-name created successfully!
Then navigate to the project directory and run
$ mekpie run
Project successfully cleaned.
Project successfully built. (0.060s)
Hello, World!
That's it!
Mekpie is built for the IDE free lifestyle. These days I do most of my development in VSCode regardless of language. As a consequence, I am often writing small scripts to build my projects. Mekpie evolved from a python script I used in place of a Make file for my c projects. Rather than continuing to rewrite the script for every new project I decided to package this functionality together. Mekpie emphasizes simplicity and correctness over performance. Unlike most c build tools, which focus a great deal of effort on partial compilation, Mekpie recompiles the entire project from scratch every time you build, run, or test. This means that code is always fresh, and you will never have to run mekpie clean
(though you still can if you want to remove the executables). For small programs the overhead of starting up python will be comparatively slower than the actual compilation times, so I believe this approach is a suitable one for many projects.
Mekpie provides two commands for creating a project. mekpie new
will attempt to create a new project as a subdirectory of your current location. You will have to provide Mekpie a name for your project. This name will be used as the name for the directory as well as the main .c
file (don't worry you can change that later).
Alternatively, you can use the mekpie init
command to create a new project. In this case Mekpie will use the name of the current directory as the project name and setup the project in your current location.
When you create a project using either new
or init
the following directory structure will be generated.
project/ target/ includes/ src/ project-name.c tests/ mek.py .gitignore
The first folder generated by Mekpie, target/
, is used to store the debug and release binaries generated for your program.
The includes/
folder is automatically included as an includes directory to your compiler, so you can place any header files you want included in this directory. You can also place subdirectories within includes/
.
The src/
folder should contain all your .c
files. Like includes/
you can use subdirectories within. By default, a main file will be generated by Mekpie with a simple Hello World program to help you ensure everything is working correctly.
The tests/
folder should contain all your test files. Jump here to find out more about tests.
Mekpie automatically generates a .gitignore
, or appends to one that already exists. The final file created by Mekpie is mek.py
which is a small python file that allows you to configure Mekpie.
Configuration of Mekpie is done through the python file mek.py
in the root of your project directory. Mekpie will autogenerate a file like the following when you first create a project. Release and debug flags are also automatically generated based on the selected compiler configuration.
# This is a standard configuration file for mekpie
name = 'project-name'
main = 'project-name.c'
cc = gcc_clang(cmd='cc', dbg='lldb')
libs = []
flags = []
if options.release:
flags += ['-Wall', '-O']
else:
flags += ['-Wall', '-g']
As shown at the bottom of the configuration file, the command line options for the current build command will be provided to your configuration anytime it is read. This allows you to easily change your configuration depending on the build. In addition to release, the options object also provides options.quiet
, options.developer
, and options.mode
which correspond to their respective command line flags.
The following table describes each mek.py
variable in detail.
Variable | Default | Description |
---|---|---|
name | <projectname> | This is a default identifier for your project. |
main | <projectname>.c | This should be the entry point for your main program. By default, it will point at the c file auto-generated by Mekpie. |
cc | gcc_clang(...) | The c compiler configuration. Currently supported compilers include gcc_clang , avr_gcc , and emscripten . See Compiler Configurations for more details. |
libs | [] | Add any libraries you want linked with your project here. For instance, if you wanted to include the c math library you would change libs to ['m'] . |
flags | [] | These flags will be passed to the compiler whenever a file is compiled. For instance, to always produce verbose output from the compiler, flags could be changed to [-v] . |
compileflags | [] | These flags will only be passed to the compiler whenever an object is compiled. |
linkflags | [] | These flags will only be passed to the compiler whenever a file is linked. |
Mekpie provides three compiler configurations by default, gcc_clang
, gcc_avr
, and emscripten
. The easiest way to get started with these is to use the configuration helper when running mekpie new
or mekpie init
and then selecting your desired compiler configuration, however these can be changed at any point.
gcc_clang
This compiler configuration is designed for use with the gcc compiler, clang compiler, and MinGW compiler. Insert the following code into mek.py
to use this configuration
cc = gcc_clang(
cmd = 'cc', # This shell command for your compiler
dbg = 'gdb', # This shell command for your debugger
)
avr_gcc
This compiler configuration is designed for use with the AVR gcc compiler and avrdude. It will automatically compiler your code, convert it to hex format, and upload it via a serial port on your computer to a desired piece of hardware. This compiler configuration expects avr-gcc
and avrdude
to be available from the command line. Insert the following code into mek.py
to use this configuration
cc = avr_gcc(
hardware = 'atmega2560', # Your AVR hardware
programmer = 'wiring', # The programmer to use with avrdude
baud = '115200', # The upload baud rate (default 115200)
)
emscripten
This compiler configuration is designed for use with the Emscripten c to js compiler. It expects emcc
and node
to be available from the command line. Insert the following code into mek.py
to use this configuration
cc = emscripten()
There is currently limited support for providing your own compiler configuration. This is done by implementing the CompilerConfig
interface. For example
cc = CompilerConfig(
name = 'my_compiler_config', # The name of the config
compile = my_compiler_function, # Your compile function
link = my_link_function, # Your linking function
run = my_run_function, # Your running function
debug = my_debug_function, # Your debug function
once = my_once_function, # Your once function
)
Each function is passed the relevant variables to complete its expected task. As this feature is still in early development full documentation is not provided. See /mekpie/cc_gcc_clang.py
for an example implementation.
Typically, you will skip running mekpie build
when running your program, as building happens automatically for mekpie run
, mekpie debug
, and mekpie test
. mekpie run
will build and then execute the main file specified by your project configuration. You can specify a release build using --release
or -r
. You can provide program arguments to your main program by separating arguments to mekpie with --
. Everything after this symbol will be passed to your program, rather than Mekpie. For example
$ mekpie --release run -- ./some-path --flag 42
Use mekpie debug
if you want to start your program in your configured debugger. The usage of mekpie test
is broken down in the next section.
Mekpie provides simple facilities for testing your code. Add a test by placing a .c
file, with a main function, in tests/
. For example, if you created a test file like the following and placed it in a file named project-tests.c
void main() {
test_one();
test_two();
test_three();
...
}
void test_one() {
assert ...
}
You could run those tests with either of the following commands
$ mekpie test
$ mekpie test project-tests
You can provide any number of test names to the test command. All of these tests will be run. Alternatively, providing no test names will simply run all of the tests. Test files are compiled just like your program's main file, meaning they have access to all of your project's header files.
Note that in usage examples flags are provided before the command, however flags are not required to appear before a command unless that command takes an arbitrary number of arguments, such as mekpie test
which accepts any number of test names.
new
Creates a new project in a subdirectory of the provided name. The command will fail if the subdirectory already exists. If you want to initialize Mekpie in an already created directory us mekpie init
instead.
This command will create all of the necessary files to use mekpie run
to build and run a simple Hello World program in c.
Usage
$ mekpie [--changedir|--developer] new <project-name>
init
Behaves just like mekpie new
accept initializes the project in the current directory. The current directory's name will be used as the project name.
Usage
$ mekpie [--changedir|--developer] init
test
When no test names are provided this command will run all files contained in tests/
. If test names are provided only those test files whose names are included will be run. Any number of test names can be provided.
Usage
$ mekpie [--release|--quiet|--changedir|--developer] test [test-names...]
clean
Removes all existing executables from target/
.
Usage
$ mekpie [--changedir|--developer] clean
build
Attempts to create an executable in target/
.
Usage
$ mekpie [--release|--quiet|--changedir|--developer|--mode] build
run
Cleans, builds, and then runs the main file of the project. The main file of a project is specified in the project configuration.
Usage
$ mekpie [--release|--quiet|--changedir|--developer|--mode] run
debug
Cleans, builds, and then runs the debugger on the main file of the project.
Usage
$ mekpie [--quiet|--changedir|--developer|--mode] debug
dist
Cleans, builds, and then copies an executable into the project root. The executable will be given the same name as the project.
Usage
$ mekpie [--release|--quite|--changdir|--developer|--mode] dist
The following table describes Mekpie's command line options.
Option | Flag | Description |
---|---|---|
help | -h | Displays a command line usage help message. |
version | -V | Prints version info and exits. |
mode | -m | Provide a mode to the mekpie file. |
quiet | -q | This will suppress information from being printed to stdout. |
release | -r | When applicable the build will be done with the release configuration. By default, builds are done with the debug configuration. |
developer | -d | Runs Mekpie in developer mode. This produces additional logging and stack traces on errors. |
changedir | -c | Runs Mekpie command as if it had been invoked from the provided directory. Provide a path immediately after this flag. |
Feel free to send be bug reports or feature requests. If you are interested in my other work, checkout my website.
Email [email protected]