Skip to content

Commit

Permalink
[build] Add Makefile build script generator
Browse files Browse the repository at this point in the history
  • Loading branch information
salkinium committed Feb 14, 2021
1 parent 2cf915c commit a85ec9d
Show file tree
Hide file tree
Showing 6 changed files with 462 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ git clone --recurse-submodules https://github.com/modm-io/modm.git

- Efficient and fast object-oriented C++20 API.
- Support for hundreds of AVR and ARM Cortex-M microcontrollers from Atmel and ST.
- Build system agnostic: Choose SCons, CMake or use your own.
- Build system agnostic: Choose SCons, CMake, Makefile or use your own.
- Data-driven, target-specific HAL generation using the lbuild engine.
- No memory allocations in HAL with very low overall RAM consumption.
- Highly-configurable modules with sensible defaults and lots of documentation.
Expand Down
2 changes: 1 addition & 1 deletion tools/build_script_generator/cmake/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def post_build(env):
env.outbasepath = "."
if env["include_cmakelists"]:
env.template("resources/CMakeLists.txt.in", "CMakeLists.txt")
if env["include_makefile"]:
if env["include_makefile"] and not env.has_module("::make"):
env.template("resources/Makefile.in", "Makefile")


Expand Down
122 changes: 122 additions & 0 deletions tools/build_script_generator/make/module.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2017-2018, Niklas Hauser
# Copyright (c) 2019, Raphael Lehmann
#
# This file is part of the modm project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# -----------------------------------------------------------------------------

from os.path import join, relpath, isdir, exists

def init(module):
module.name = ":build:make"
# module.description = FileReader("module.md")


def prepare(module, options):
module.add_option(
BooleanOption(name="include_makefile", default=True,
description=descr_include_makefile))

module.add_collector(
CallableCollector(name="flag_format",
description="Formatting compile flags for Make"))

return True


def build(env):
def flag_format(flag):
subs = {
"target_base": "$(MAKE_PROJECT_NAME)",
"project_source_dir": ".",
}
if "{" in flag:
return flag.format(**subs)
return None
env.collect("flag_format", flag_format)


def post_build(env):
repositories = [p for p in env.buildlog.repositories if isdir(env.real_outpath(p, basepath="."))]
repositories.sort(key=lambda name: "0" if name == "modm" else name)

subs = env.query("::device")
if subs["core"].startswith("cortex-m"):
# get memory information
subs["memories"] = env.query("::memories")
else:
subs["memories"] = []
# Add SCons specific data
subs.update({
"build_path": env.relative_outpath(env[":build:build.path"]),
"generated_paths": repositories,
})
if subs["platform"] == "avr":
subs.update(env.query("::avrdude_options"))
if subs["platform"] == "sam":
subs.update({"bossac_offset": env.get(":platform:cortex-m:linkerscript.flash_offset", None),
"bossac_options": " ".join(env.collector_values(":build:bossac.options"))})
# Set these substitutions for all templates
env.substitutions = subs

sources = env.query("::source_files")
def flags_format(flag):
for fmt in env.collector_values("flag_format"):
nflag = fmt(flag)
if nflag: return nflag;
return flag

for repo in repositories:
files = []
repo_filter = lambda scope: scope.repository == repo
repo_flags = env.query("::collect_flags")(env, repo_filter)

# Prepends -D to all CPP defines for this repo
for filename, fileflags in repo_flags.items():
for profile, flags in fileflags.get("cppdefines", {}).items():
repo_flags[filename]["cppdefines"][profile] = ["-D"+f for f in flags]

for f in sources[repo]:
files.append( (f, repo_flags[f]) )

include_paths = env.collector_values("::path.include", filterfunc=repo_filter)
libary_paths = env.collector_values("::path.library", filterfunc=repo_filter)
libaries = env.collector_values("::library", filterfunc=repo_filter)
packages = env.collector_values("::pkg-config", filterfunc=repo_filter)

subs.update({
"repo": repo,
"flags": repo_flags[None],
"sources": files,
"libraries": libaries,
"library_paths": libary_paths,
"include_paths": include_paths,
"packages": packages,
"is_modm": repo == "modm",
})
# Generate library SConscript
env.outbasepath = repo
env.template("resources/repo.mk.in", "repo.mk",
filters={"flags_format": flags_format,
"objectify": lambda f: f.rsplit(".", 1)[0]+".o"})

env.outbasepath = "modm"
env.template("resources/compiler.mk.in", "compiler.mk")

# these are the ONLY files that are allowed to NOT be namespaced with modm!
env.outbasepath = "."
if env["include_makefile"]:
env.template("resources/Makefile.in", "Makefile")


# ============================ Option Descriptions ============================
descr_include_makefile = """# Generate a Makefile
!!! warning "This overwrites any top-level `Makefile`!"
"""
85 changes: 85 additions & 0 deletions tools/build_script_generator/make/resources/Makefile.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Copyright (c) 2021, Niklas Hauser
#
# This file is part of the modm project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

APP_SRC := main.cpp

%% for path in generated_paths
include {{path}}/repo.mk
%% endfor

.DEFAULT_GOAL := size
.PHONY: library build bin listing
library: $(LIBRARIES)
build: $(ELF_FILE)
bin: $(BIN_FILE)
listing: $(LSS_FILE)

.PHONY: clean
clean:
@rm -rf $(BUILDPATH)

port?=auto
%% if core.startswith("avr")
.PHONY: program
program: build
@python3 modm/modm_tools/avrdude.py -p $(CONFIG_AVRDUDE_DEVICE) $(CONFIG_AVRDUDE_PROGRAMMER) $(CONFIG_AVRDUDE_OPTIONS) \
-P $(if $(CONFIG_AVRDUDE_PORT),$(CONFIG_AVRDUDE_PORT),$(port)) $(CONFIG_AVRDUDE_BAUDRATE) \
$(ELF_FILE)

.PHONY: size
size: build
@(cd $(BUILDPATH) && $(OBJDUMP) -Pmem-usage $(MODM_PROJECT_NAME).elf)

%% elif core.startswith("cortex-m")
.PHONY: size
size: build
@echo "Memory usage···" $(MODM_PROJECT_NAME).elf
@python3 modm/modm_tools/size.py $(ELF_FILE) $(CONFIG_DEVICE_MEMORY)

.PHONY: program
program: build
@python3 modm/modm_tools/openocd.py $(addprefix -f ,$(MODM_OPENOCD_CONFIGFILES)) $(ELF_FILE)

.PHONY: program-bmp
program-bmp: build
@python3 modm/modm_tools/bmp.py -p $(port) $(ELF_FILE)

.PHONY: program-dfu
program-dfu: bin
@dfu-util -v -E2 -R -i 0 -a 0 -s 0x08000000:leave -D $(BIN_FILE)

%% if platform in ["sam"]
.PHONY: program-bossac
program-bossac: bin
@python3 modm/modm_tools/bossac.py -p $(port) --offset $(if $($(MODM_BOSSAC_OFFSET) < 4096),4096,$(MODM_BOSSAC_OFFSET)) $(MODM_BOSSAC_OPTIONS) $(BIN_FILE)
%% endif

ui?=tui
.PHONY: debug
debug: build
@python3 modm/modm_tools/gdb.py $(addprefix -x ,$(MODM_GDBINIT)) $(addprefix -x ,$(MODM_OPENOCD_GDBINIT)) \
$(ELF_FILE) -ui=$(ui) \
openocd $(addprefix -f ,$(MODM_OPENOCD_CONFIGFILES))

.PHONY: debug-bmp
debug-bmp: build
@python3 modm/modm_tools/bmp.py $(addprefix -x ,$(MODM_GDBINIT)) \
$(ELF_FILE) -ui=$(ui) \
bmp -p $(port)

.PHONY: debug-coredump
debug-coredump: build
@python3 modm/modm_tools/gdb.py $(addprefix -x ,$(MODM_GDBINIT)) \
$(ELF_FILE) -ui=$(ui) \
crashdebug --binary-path modm/ext/crashcatcher/bins

fcpu?=0
.PHONY: log-itm
log-itm:
@python3 modm/modm_tools/log.py itm openocd -f modm/openocd.cfg -fcpu $(fcpu)
%% endif
55 changes: 55 additions & 0 deletions tools/build_script_generator/make/resources/compiler.mk.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Copyright (c) 2021, Niklas Hauser
#
# This file is part of the modm project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

%% if core.startswith("cortex-m")
C_PREFIX := arm-none-eabi-
%% elif core.startswith("avr")
C_PREFIX := avr-
%% endif

ifeq ($(OS),Windows_NT)
C_SUFFIX := .exe
else
%% if platform == "hosted"
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
C_SUFFIX := -10
endif
%% endif
endif

CC := $(C_PREFIX)gcc$(C_SUFFIX)
CXX := $(C_PREFIX)g++$(C_SUFFIX)
ASM := $(CC)

ifeq ($(C_SUFFIX),)
AS := $(C_PREFIX)as
AR := $(C_PREFIX)ar
NM := $(C_PREFIX)nm
RANLIB := $(C_PREFIX)ranlib
else
AS := $(CXX)
AR := $(C_PREFIX)gcc-ar$(C_SUFFIX)
NM := $(C_PREFIX)gcc-nm$(C_SUFFIX)
RANLIB := $(C_PREFIX)gcc-ranlib$(C_SUFFIX)
endif

OBJCOPY := $(C_PREFIX)objcopy
OBJDUMP := $(C_PREFIX)objdump
SIZE := $(C_PREFIX)size
STRIP := $(C_PREFIX)strip
DEBUGGER := $(C_PREFIX)gdb
CPPFILT := $(C_PREFIX)c++filt

%% if platform == "hosted"
ifeq ($(UNAME_S),Darwin)
# Using homebrew include and lib paths on macOS
CPPDEFINES += -I/usr/local/include
LIBPATH += -L/usr/local/lib
endif
%% endif
Loading

0 comments on commit a85ec9d

Please sign in to comment.