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 Mar 20, 2021
1 parent bf7fe82 commit 0dccf3e
Show file tree
Hide file tree
Showing 9 changed files with 1,118 additions and 27 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 @@ -132,7 +132,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
135 changes: 135 additions & 0 deletions tools/build_script_generator/make/module.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#!/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": "$(CURDIR)",
"gccpath": "$(GCC_BASE)",
}
if "{" in flag:
return flag.format(**subs)
return None
env.collect("flag_format", flag_format)


def post_build(env):
is_unittest = len(env["::unittest.source"])
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
linkerscript = env.get(":platform:cortex-m:linkerscript.override")
linkerscript = env.relative_outpath(linkerscript) if linkerscript \
else "modm/link/linkerscript.ld"
subs.update({
"build_path": env.relative_outpath(env["::build.path"]),
"generated_paths": repositories,
"linkerscript": linkerscript,
"is_unittest": is_unittest,
"program_extension": "exe" if env[":target"].identifier.family == "windows" else "elf",
})
if is_unittest:
subs["unittest_source"] = env.relative_outpath(env["::unittest.source"])
if len(env["::image.source"]):
subs["image_source"] = env.relative_outpath(env["::image.source"])
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("::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/config.mk.in", "config.mk")
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`!"
"""
Loading

0 comments on commit 0dccf3e

Please sign in to comment.