Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[scons] Simplify Scons tooling, misc. fixes and improvements #558

Merged
merged 10 commits into from
Feb 26, 2021
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ CMakeLists.txt

# ignore generated code in the example folder
examples/**/modm
examples/**/artifacts
examples/**/compile_commands.json
examples/**/SConstruct
examples/**/Makefile
Expand Down
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
[submodule "ext/modm-devices"]
path = ext/modm-devices
url = https://github.com/modm-io/modm-devices.git
[submodule "ext/dlr/scons-build-tools"]
path = ext/dlr/scons-build-tools
url = https://github.com/modm-io/scons-build-tools.git
[submodule "ext/ros/ros-lib"]
path = ext/ros/ros-lib
url = https://github.com/modm-io/ros-lib
Expand Down
5 changes: 4 additions & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ Make sure you've [installed all tools required for building modm](https://modm.i

## TL;DR

To compile any example:

```
cd modm/examples/generic/blinky # cd into the example
lbuild build # generate modm library (call only once)
scons program # compile and upload to your development board
```
Expand All @@ -19,7 +22,7 @@ To debug with GDB in TUI mode:

```
scons program profile=debug # compile and upload debug profile
scons gdb profile=debug # launch OpenOCD and GDB for debugging
scons debug profile=debug # launch OpenOCD and GDB for debugging
```

To generate your target specific Doxygen documentation:
Expand Down
1 change: 0 additions & 1 deletion ext/dlr/scons-build-tools
Submodule scons-build-tools deleted from 6c35aa
11 changes: 10 additions & 1 deletion src/modm/platform/core/cortex/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,14 @@ def prepare(module, options):
maximum=2 ** 16,
default="3*1024"))

if "f" in options[":target"].get_driver("core")["type"]:
module.add_option(
EnumerationOption(
name="float-abi",
description="Floating point ABI",
enumeration=["soft", "softfp", "hard"],
default="hard"))

salkinium marked this conversation as resolved.
Show resolved Hide resolved
memories = listify(options[":target"].get_driver("core")["memory"])

# Cortex-M0 does not have remappable vector table, so it will remain in Flash
Expand Down Expand Up @@ -258,6 +266,7 @@ def build(env):
"with_fault_storage": env.has_module(":platform:fault"),
"with_memory_traits": env.has_module(":architecture:memory"),
"with_assert": env.has_module(":architecture:assert"),
"with_fpu": env.get("float-abi", "soft") != "soft",
})
env.outbasepath = "modm/src/modm/platform/core"

Expand Down Expand Up @@ -345,7 +354,7 @@ def build(env):
"7f": "-mfpu=fpv5-sp-d16",
"7fd": "-mfpu=fpv5-d16",
}[fpu]
env.collect(":build:archflags", "-mfloat-abi=hard", fpu_spec)
env.collect(":build:archflags", "-mfloat-abi={}".format(env["float-abi"]), fpu_spec)
single_precision = ("-sp-" in fpu_spec)
if single_precision:
env.collect(":build:ccflags", "-fsingle-precision-constant",
Expand Down
2 changes: 1 addition & 1 deletion src/modm/platform/core/cortex/module.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ This module adds these architecture specific [compiler options][options]:

- `-mcpu=cortex-m{type}`: the target to compile for.
- `-mthumb`: only Thumb2 instruction set is supported.
- `-mfloat-abi=hard`: if FPU available use the fastest ABI available.
- `-mfloat-abi={soft, softfp, hard}`: the FPU ABI: `hard` is fastest.
- `-mfpu=fpv{4, 5}-{sp}-d16`: single or double precision FPU.
- `-fsingle-precision-constant`: if SP-FPU, treat all FP constants as SP.
- `-Wdouble-promotion`: if SP-FPU, warn if FPs are promoted to doubles.
Expand Down
2 changes: 1 addition & 1 deletion src/modm/platform/core/cortex/startup.c.in
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ void __modm_startup(void)
SCB_EnableICache();
%% endif

%% if "f" in core
%% if with_fpu
// Enable FPU in privileged and user mode
SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2));
%% endif
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Copyright (c) 2018, Sergiy Yevtushenko
# Copyright (c) 2018-2019, Niklas Hauser
# Copyright (c) 2018-2019, 2021, Niklas Hauser
#
# This file is part of the modm project.
#
Expand All @@ -13,7 +13,9 @@ endif()

set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
%% if platform == "hosted"
find_package(PkgConfig)
%% endif

if(NOT TOOL_EXECUTABLE_PREFIX)
%% if core.startswith("cortex-m")
Expand Down Expand Up @@ -44,11 +46,11 @@ set(CMAKE_C_COMPILER "${TOOL_EXECUTABLE_PREFIX}gcc${TOOL_EXECUTABLE_SUFFIX}" CAC
set(CMAKE_CXX_COMPILER "${TOOL_EXECUTABLE_PREFIX}g++${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "c++")
set(CMAKE_ASM_COMPILER "${CMAKE_C_COMPILER}" CACHE INTERNAL "asm")

set(CMAKE_AR "${TOOL_EXECUTABLE_PREFIX}ar" CACHE INTERNAL "ar")
set(CMAKE_RANLIB "${TOOL_EXECUTABLE_PREFIX}ranlib" CACHE INTERNAL "ranlib")
if(TOOL_EXECUTABLE_SUFFIX STREQUAL "")
set(CMAKE_AS "${TOOL_EXECUTABLE_PREFIX}as" CACHE INTERNAL "as")
set(CMAKE_NM "${TOOL_EXECUTABLE_PREFIX}nm" CACHE INTERNAL "nm")
set(CMAKE_AR "${TOOL_EXECUTABLE_PREFIX}ar" CACHE INTERNAL "ar")
set(CMAKE_RANLIB "${TOOL_EXECUTABLE_PREFIX}ranlib" CACHE INTERNAL "ranlib")
else()
set(CMAKE_AS "${CMAKE_CXX_COMPILER}" CACHE INTERNAL "as")
set(CMAKE_NM "${TOOL_EXECUTABLE_PREFIX}gcc-nm${TOOL_EXECUTABLE_SUFFIX}" CACHE INTERNAL "nm")
Expand All @@ -71,6 +73,12 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

# Used to make stdlibc++ paths in ELF relative to compiler
find_program(MODM_GCC_PATH NAMES ${CMAKE_C_COMPILER})
get_filename_component(MODM_GCC_PATH ${MODM_GCC_PATH} REALPATH)
get_filename_component(MODM_GCC_PATH ${MODM_GCC_PATH} DIRECTORY)
get_filename_component(MODM_GCC_PATH ${MODM_GCC_PATH} DIRECTORY)

if(APPLE)
%% if platform == "hosted"
# Using homebrew include and lib paths on macOS
Expand Down
1 change: 1 addition & 0 deletions tools/build_script_generator/cmake/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def build(env):
subs = {
"target_base": "${CMAKE_PROJECT_NAME}",
"project_source_dir": "${CMAKE_CURRENT_SOURCE_DIR}",
"gccpath": "${MODM_GCC_PATH}",
}
if "{" in flag:
return flag.format(**subs)
Expand Down
3 changes: 2 additions & 1 deletion tools/build_script_generator/cmake/resources/Makefile.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Copyright (c) 2018, Sergiy Yevtushenko
# Copyright (c) 2018-2019, Niklas Hauser
# Copyright (c) 2018-2019, 2021, Niklas Hauser
#
# This file is part of the modm project.
#
Expand Down Expand Up @@ -59,6 +59,7 @@ program-bmp: build
ui?=tui
debug: build
@python3 modm/modm_tools/gdb.py -x modm/gdbinit -x modm/openocd_gdbinit \
-ex "dir $(dir $(realpath $(dir $(realpath $(shell which arm-none-eabi-gcc)))))" \
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: This Makefile will get a make over via the ::make generator, so this is currently more of an ugly placeholder.

$(ELF_FILE) -ui=$(ui) \
openocd -f modm/openocd.cfg

Expand Down
2 changes: 2 additions & 0 deletions tools/build_script_generator/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ def common_compiler_flags(compiler, target):
"-funsigned-char",
"-fwrapv",
# "-fmerge-all-constants",
"-ffile-prefix-map={project_source_dir}=.",
"-ffile-prefix-map={gccpath}=.",

"-g3",
"-gdwarf-3",
Expand Down
7 changes: 6 additions & 1 deletion tools/build_script_generator/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,14 @@ def prepare(module, options):
module.add_collector(
PathCollector(name="path.library",
description="Search path for static libraries"))
def validate_library(library):
if library.startswith("lib") or library.endswith(".a"):
raise ValueError("Libraries must only contain `name` not `libname.a`!")
return library
module.add_collector(
StringCollector(name="library",
description="Libraries to link against"))
description="Libraries to link against",
validate=validate_library))
module.add_collector(
StringCollector(name="pkg-config",
description="Packages to configure against"))
Expand Down
55 changes: 30 additions & 25 deletions tools/build_script_generator/scons/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ def prepare(module, options):
module.add_option(
PathOption(name="cache_dir", default="", empty_ok=True, absolute=True,
description=descr_cache_dir))
module.add_option(
PathOption(name="path.artifact", default="artifacts", absolute=True,
description=descr_path_artifact))
module.add_option(
PathOption(name="image.source", default="", empty_ok=True, absolute=True,
description=descr_image_source))
Expand Down Expand Up @@ -64,8 +67,9 @@ def build(env):

def flag_format(flag):
subs = {
"target_base": "\"${TARGET.base}\"",
"project_source_dir": "abspath(\"..\")",
"target_base": '"${TARGET.base}"',
"project_source_dir": 'env["BASEPATH"]',
"gccpath": 'env["GCC_PATH"]'
}
flag = '"{}"'.format(flag)
vals = ["{}={}".format(t, r) for t, r in subs.items() if "{{{}}}".format(t) in flag]
Expand All @@ -80,15 +84,16 @@ def build(env):
# SCons tools and toolpaths
toolpaths = {
"scons/site_tools",
"ext/dlr/scons/site_tools"
}
tools = {
"build_target",
"comstr",
"find_files",
"gcc_retarget",
"qtcreator",
"settings_buildpath",
"template",
"utils_buildformat",
"utils",
"utils_buildpath",
}
if env.has_module(":communication:xpcc:generator"):
tools.add("xpcc_generator")
Expand All @@ -101,30 +106,16 @@ def build(env):

device = env.query("::device")
if device["core"].startswith("cortex-m"):
tools.update({"compiler_arm_none_eabi_gcc", "size", "log_itm", "artifact",
"openocd", "openocd_remote", "bmp", "crashdebug", "dfu"})
tools.update({"size", "log_itm", "artifact", "openocd",
"openocd_remote", "bmp", "crashdebug", "dfu"})
if device["platform"] in ["sam"]:
tools.update({"bossac"})
elif device["core"].startswith("avr"):
tools.update({"compiler_avr_gcc", "size", "avrdude"})
else: # hosted
tools.update({"compiler_hosted_gcc"})
tools.update({"size", "avrdude"})

env.collect("path.tools", *toolpaths)
env.collect("tools", *tools)

# Add common DLR SCons build tools
tools.update({
"settings_gcc_default_internal",
"utils_common",
"utils_gcc_version",
})
env.outbasepath = "modm/ext/dlr/scons/site_tools"
for tool in tools:
path = repopath("ext/dlr/scons-build-tools/site_tools/{}.py".format(tool))
if exists(path):
env.copy(path, "{}.py".format(tool))

# Copy only these modm SCons build tools
env.outbasepath = "modm/scons/"
for tool in tools:
Expand All @@ -137,10 +128,16 @@ def build(env):
env.copy("site_tools/info.c.in")

# Generate the env.BuildTarget tool
linkerscript = env.get(":platform:cortex-m:linkerscript.override")
linkerscript = env.relative_outpath(linkerscript) if linkerscript \
else "$BASEPATH/modm/link/linkerscript.ld"
env.substitutions = env.query("::device")
env.substitutions["upload_with_artifact"] = env.has_module(":crashcatcher")
env.substitutions["with_compilation_db"] = env.has_module(":build:compilation_db")
env.substitutions["program_extension"] = ".exe" if env[":target"].identifier.family == "windows" else ".elf"
env.substitutions.update({
"upload_with_artifact": env.has_module(":crashcatcher"),
"with_compilation_db": env.has_module(":build:compilation_db"),
"program_extension": ".exe" if env[":target"].identifier.family == "windows" else ".elf",
"linkerscript": linkerscript,
})
env.outbasepath = "modm/scons/site_tools"
env.template("resources/build_target.py.in", "build_target.py")

Expand All @@ -167,6 +164,7 @@ def post_build(env):
subs.update({
"build_path": env.relative_outpath(env[":build:build.path"]),
"cache_dir": env.relative_outpath(cache_dir) if len(cache_dir) else "",
"artifact_path": env.relative_outpath(env["path.artifact"]),
"generated_paths": repositories,
"is_unittest": is_unittest,

Expand Down Expand Up @@ -252,6 +250,13 @@ If value is `$cache`, the cache is placed into the top-level `build/` folder.
You can disable CacheDir by setting an empty string.
"""

descr_path_artifact = """# Path to Artifact Store

The artifact folder contains ELF files named by their GNU build id hash. This
allows identification of firmware on the device via serial output and is useful
for archiving or post-mortem debugging.
"""

descr_image_source = """# Path to directory containing .pbm files"""

descr_unittest_source = """# Path to directory containing unittests
Expand Down
Loading