No project description provided
Project description
pymaketool
pymaketool is an elegant and simple tool to build and manage large C/C++ projects and libraries. The main purpose is to simplify the build process by using Python to find and organize source files.
๐ my_project/
- ๐ Makefile โ root entry point
- ๐ .env โ environment variables (not committed)
๐ pymake/ โ build config folder
- ๐ Makefile.py โ๏ธ YOU write this ยท toolchain ยท flags ยท targets
- ๐ makefile.mk โ generated
- ๐ vars.mk โ generated
- ๐ srcs.mk โ generated
- ๐ targets.mk โ generated
๐ app/ โ source module
๐ inc/
- ๐ main.h
๐ src/
- ๐ main.c
- ๐ mk.py โ๏ธ YOU write this ยท recommended
from pm import mk mk(srcs=["src/main.c"], incs=["inc"])
## Or just: from pm import mk mk()
## Or nothing at all:
๐ utils/ โ another source module
- ๐ utils.c
- ๐ utils.h
- ๐ utils_mk.py โ๏ธ also supported
๐ build/ โ generated output
- โ๏ธ app โ final binary
๐ obj/
- ๐ app/src/main.o
- ๐ utils/utils.o
Quick Start
Install required packages:
Ubuntu
$ sudo apt-get install -y gcc make python3 python3-pip git time zip
Fedora
$ sudo dnf install python3 python3-pip time zip git gcc
Arch Linux
$ sudo pacman -S gcc make python python-pip time zip git
Install pymaketool:
$ pip3 install pymaketool
Create and build a new C project:
$ pynewproject CLinuxGCC
(author) Your name: Ericson
(project_name) Your project name: hello
$ cd hello
hello$ make
hello$ ./build/hello
Quick Start with Poetry
If you prefer Poetry for dependency management:
$ curl -sSL https://install.python-poetry.org | python3 -
$ pynewproject CLinuxGCC
(project_name) Your project name: hello
$ cd hello
hello$ poetry init --name hello --dependency pymaketool
hello$ poetry install
hello$ poetry run make
hello$ ./build/hello
Quick start in Docker
$ docker pull ericsonjoseph/pymaketool
$ docker run -it ericsonjoseph/pymaketool
ubuntu@$ pynewproject CLinuxGCC
Module Files (mk.py, *_mk.py, *.mk.py)
pymaketool discovers module files recursively. The shortest and recommended name is mk.py, but app_mk.py and app.mk.py still work.
Each module file describes one folder of C/C++ code.
Recommended DX: from pm import mk
# app/mk.py
from pm import mk
mk()
That is enough for most modules. mk() captures the current file path and auto-discovers sources and includes in the same directory.
If you want zero lines, an empty mk.py also works.
Common cases
Explicit files:
from pm import mk
mk(srcs=["src/main.c", "src/util.c"], incs=["inc"])
Exclude files from auto-discovery:
from pm import mk, skip
mk(srcs=skip("test*", "mock_*"), incs=[".", "include"])
C++ module:
from pm import mk
mk(lang="cpp")
When to use the class API
Use the class-based API only when you need custom module behavior, static libraries, or full control over discovery.
from pymakelib import module
@module.ModuleClass
class App(module.BasicCModule):
pass
Project Configuration (Makefile.py)
Makefile.py is the project entry point. It defines the toolchain, compiler flags, and build targets.
New API โ ProjectConfig (recommended)
# pymake/Makefile.py
from pymakelib import ProjectConfig, Makeclass, CompilerOpts, MKVARS, Target
from pymakelib.toolchain import get_gcc_linux
@Makeclass
class Build(ProjectConfig):
name = 'myapp'
output_dir = 'build/obj/'
compiler_set = get_gcc_linux() # or get_gcc_arm_none_eabi('/opt/arm/bin/')
def compiler_opts(self, opts: CompilerOpts) -> CompilerOpts:
opts.optimize = ['-O2']
opts.debugging = ['-g3']
opts.warnings = ['-Wall']
opts.standard = ['-std=c11']
opts.preprocessor = ['-MP', '-MMD']
opts.macros = {'VERSION': '"1.0"'}
return opts
def targets(self):
return {
'TARGET': Target(
file = f'build/{self.name}',
script = [MKVARS.LD, '-o', '$@', MKVARS.OBJECTS, MKVARS.LDFLAGS],
logkey = 'OUT',
),
}
Multi-output builds (ELF โ HEX โ BIN) โ target dict order defines the dependency chain:
def targets(self):
return {
'TARGET': Target(file='build/app.elf',
script=[MKVARS.LD, '-o', '$@', MKVARS.OBJECTS, MKVARS.LDFLAGS],
logkey='LINK'),
'TARGET_HEX': Target(file='build/app.hex',
script=['objcopy', '-O', 'ihex', MKVARS.TARGET, '$@'],
logkey='HEX'),
'TARGET_BIN': Target(file='build/app.bin',
script=[MKVARS.OBJCOPY, '-O', 'binary', MKVARS.TARGET, '$@'],
logkey='BIN'),
}
Phony targets (flash, format, testโฆ):
def getPhonyTargets(self):
return {
'flash': {
'deps': ['all'],
'logkey': 'FLASH',
'script': 'openocd -f board/board.cfg -c "program build/app.elf verify reset exit"',
},
}
IDE addons โ declare as a list attribute instead of a module-level call:
from pymakelib.eclipse_addon import EclipseAddon
from pymakelib.vscode_addon import VSCodeAddon
@Makeclass
class Build(ProjectConfig):
addons = [EclipseAddon, VSCodeAddon]
compiler_set = get_gcc_linux()
...
Linker options:
def linker_opts(self, opts: LinkerOpts) -> LinkerOpts:
opts.script = ['-T', 'link.ld']
opts.machine = ['-mthumb', '-mcpu=cortex-m4']
opts.libs = ['-lm', '-lc']
return opts
Environment variables (.env support)
# pymake/Makefile.py
from pymakelib import ProjectConfig, Makeclass, resolve_env
from pymakelib.toolchain import get_gcc_arm_none_eabi
@Makeclass
class Build(ProjectConfig):
env_file = '.env' # loaded automatically before any get* call
compiler_set = get_gcc_arm_none_eabi(resolve_env('XC32_PATH', '/opt/xc32/bin/'))
...
.env file (not committed to version control):
XC32_PATH=/opt/microchip/xc32/v4.60/bin
PROGRAMMER=PK5
load_dotenv() and resolve_env() are also available for module-level use:
from pymakelib import load_dotenv, resolve_env
load_dotenv()
TOOLCHAIN = resolve_env('TOOLCHAIN_PATH', '/usr/bin/')
Toolchain presets
| Function | Description |
|---|---|
get_gcc_linux() |
Host Linux GCC |
get_gpp_linux() |
Host Linux G++ (C++) |
get_gcc_arm_none_eabi() |
ARM bare-metal cross-compiler |
All return a CompilerSet dataclass with IDE autocompletion for every tool path.
Typed Configuration Reference
All new configuration types live in pymakelib and provide IDE autocompletion.
CompilerOpts
| Field | Makefile variable | Example |
|---|---|---|
macros |
-D defines |
{'DEBUG': None, 'VER': '"2.0"'} |
machine |
machine/arch flags | ['-mthumb', '-mcpu=cortex-m4'] |
optimize |
optimisation | ['-O2'] |
debugging |
debug info | ['-g3'] |
preprocessor |
preprocessor | ['-MP', '-MMD'] |
warnings |
warnings | ['-Wall', '-Werror'] |
standard |
language std | ['-std=c11'] |
general |
other flags | ['--coverage'] |
Target
Target(
file = 'build/app.elf', # output file path
script = [MKVARS.LD, '-o', '$@', # command tokens joined with spaces
MKVARS.OBJECTS, MKVARS.LDFLAGS],
logkey = 'LINK', # label shown in build output
)
script tokens are joined with a space into one Makefile recipe line. Use && for shell chaining: ['@mkdir -p $(dir $@) &&', MKVARS.LD, ...].
For install guide go to install-guide
For more documentation go to Read the Docs
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pymaketool-3.0.0rc5.tar.gz.
File metadata
- Download URL: pymaketool-3.0.0rc5.tar.gz
- Upload date:
- Size: 213.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.4 CPython/3.14.4 Linux/6.17.0-1010-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2040957e75e0ea36c3900e56272e3aa80306e3585a06da06d95c5aa089d3556a
|
|
| MD5 |
ccd3cb26856d5c5ace8f90a9d1a5aea5
|
|
| BLAKE2b-256 |
83130c6d8deb10d9326d555a3fd526f4ab162ae1f513b0ae62c6af4cdab46f34
|
File details
Details for the file pymaketool-3.0.0rc5-py3-none-any.whl.
File metadata
- Download URL: pymaketool-3.0.0rc5-py3-none-any.whl
- Upload date:
- Size: 248.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.4 CPython/3.14.4 Linux/6.17.0-1010-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f603daea3237d9c0c2b9972bc8085e52b7d2d8c41206d7632b07af75575adde
|
|
| MD5 |
792aec72ca7c1b777d2807830645704d
|
|
| BLAKE2b-256 |
85e7e5c0347bb844ef2a7ea6d2050d99b61f3656c613cb163d48e8fbfd283a78
|