Skip to content

Commit

Permalink
Merge pull request #73 from bxparks/develop
Browse files Browse the repository at this point in the history
merge 1.5.0 into master
  • Loading branch information
bxparks authored Dec 8, 2022
2 parents a344895 + c649408 commit e84a534
Show file tree
Hide file tree
Showing 15 changed files with 186 additions and 56 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/aunit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ on: [push]
jobs:
build:

runs-on: ubuntu-20.04
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3

- name: Setup
run: |
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
# Changelog

* Unreleased
* 1.5.0 (2022-12-08)
* Support compiling plain `*.c` files in libraries and in the application.
* The C files are assumed to be written in C11.
* Define the `-D ARDUINO=100` macro.
* Some 3rd party libraries test for `ARDUINO >= 100` to check if it's
being compiled under Arduino.
* Many will compile under EpoxyDuino with this macro set.
* Add `make run` target which runs the binary generated by `make all`.
* Useful in the `vim` editor where `:make run` will invoke the quickfix
feature so that the editor will jump directly to the file and line
where the AUnit assertion failure occurred.
* Update the example `for` loops to invoke `make -C {dir} run` instead
of running the binary directly. The `vim` editor can parse the output
caused by the `-C` flag, and automatically generate the correct path
to the files in the subdirectories.
* 1.4.0 (2022-11-06)
* Add `memcmp_P()` by @dawidchyrzynski in
[PR#71](https://github.com/bxparks/EpoxyDuino/pull/71).
Expand Down
109 changes: 78 additions & 31 deletions EpoxyDuino.mk
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,19 @@ EPOXY_DUINO_PARENT_DIR := $(abspath $(EPOXY_DUINO_DIR)/..)
# directory.
ARDUINO_LIB_DIRS ?=

# C macro to select a specific core. Valid options are:
# EPOXY_CORE_AVR (default), EPOXY_CORE_ESP8266.
# CPP macro to select a specific core. Valid options are:
# EPOXY_CORE_AVR (default), and EPOXY_CORE_ESP8266.
EPOXY_CORE ?= EPOXY_CORE_AVR

# Define the directory where the <Arduino.h> and other core API files are
# located. The default is $(EPOXY_DUINO_DIR)/cores/epoxy.
EPOXY_CORE_PATH ?= $(EPOXY_DUINO_DIR)/cores/epoxy

# Find the directory paths of the libraries listed in ARDUINO_LIBS by looking
# under directory given by EPOXY_DUINO_LIB_DIR, the directory given by
# EPOXY_DUINO_PARENT_DIR to look for siblings, and each directory listed in
# ARDUINO_LIB_DIRS.
# at the following:
# 1) under the directory given by EPOXY_DUINO_LIB_DIR,
# 2) the sibling directories under EPOXY_DUINO_PARENT_DIR, and
# 3) each directory listed in ARDUINO_LIB_DIRS.
EPOXY_MODULES := $(foreach lib,$(ARDUINO_LIBS),${EPOXY_DUINO_LIB_DIR}/${lib})
EPOXY_MODULES += $(foreach lib,$(ARDUINO_LIBS),${EPOXY_DUINO_PARENT_DIR}/${lib})
EPOXY_MODULES += \
Expand Down Expand Up @@ -118,27 +119,37 @@ EPOXY_MODULES += \
# like c++ on FreeBSD is actualy clang++. It's possible that FreeBSD has the
# latest GNU version of libstdc++, but I'm not sure.
#
# I added EXTRA_CXXFLAGS to allow end-user Makefiles to specify additional
# CXXFLAGs.
# The CFLAGS assume that any C files are C11 files (not C99) because my
# AceTimeC library requires C11. It may be possible to override that by passing
# the `-std=c99` flag in the EXTRA_CFLAGS variable (which overrides the
# `-std=c11` flag), but this has not been tested.
#
# I added EXTRA_CXXFLAGS and EXTRA_CFLAGS to allow end-user Makefiles to
# specify additional flags to CXXFLAGS and CFLAGS.
ifeq ($(UNAME), Linux)
CXX ?= g++
CXXFLAGS ?= -Wextra -Wall -std=gnu++11 -fno-exceptions -fno-threadsafe-statics -flto
CXXFLAGS ?= -Wextra -Wall -std=gnu++11 -flto \
-fno-exceptions -fno-threadsafe-statics
CFLAGS ?= -Wextra -Wall -std=c11 -flto
else ifeq ($(UNAME), Darwin)
CXX ?= clang++
CXXFLAGS ?= -Wextra -Wall -std=c++11 -stdlib=libc++
CFLAGS ?= -Wextra -Wall -std=c11
else ifeq ($(UNAME), FreeBSD)
CXX ?= clang++
CXXFLAGS ?= -Wextra -Wall -std=c++11 -stdlib=libc++
CFLAGS ?= -Wextra -Wall -std=c11
endif
CXXFLAGS += $(EXTRA_CXXFLAGS)
CFLAGS += $(EXTRA_CFLAGS)

# Pre-processor flags (-I, -D, etc), mostly for header files.
CPPFLAGS += $(EXTRA_CPPFLAGS)
# Define a macro to indicate that EpoxyDuino is being used. Defined here
# instead of Arduino.h so that files like 'compat.h' can determine the
# compile-time environment without having to include <Arduino.h>.
# Also define UNIX_HOST_DUINO for backwards compatibility.
CPPFLAGS += -D UNIX_HOST_DUINO -D EPOXY_DUINO -D $(EPOXY_CORE)
CPPFLAGS += -D ARDUINO=100 -D UNIX_HOST_DUINO -D EPOXY_DUINO -D $(EPOXY_CORE)
# Add the header files for the Core files.
CPPFLAGS += -I$(EPOXY_CORE_PATH)
# Add the header files for libraries. Old Arduino libraries place the header
Expand All @@ -150,52 +161,88 @@ CPPFLAGS += $(foreach module,$(EPOXY_MODULES),$(CPPFLAGS_EXPANSION))
# Linker settings (e.g. -lm).
LDFLAGS ?=

# Generate list of C++ srcs to compile.
# Collect list of C and C++ srcs to compile.
#
# 1) Add the source files in the Core directory. Support subdirectory
# 1) Collect the source files in the Epoxy Core directory. Support subdirectory
# expansions up to 3 levels below the given target. (There might be a better
# way to do this using GNU Make but I can't find a mechanism that doesn't barf
# when the 'src/' directory doesn't exist.)
EPOXY_SRCS := $(wildcard $(EPOXY_CORE_PATH)/*.cpp) \
$(wildcard $(EPOXY_CORE_PATH)/*/*.cpp) \
$(wildcard $(EPOXY_CORE_PATH)/*/*/*.cpp) \
$(wildcard $(EPOXY_CORE_PATH)/*/*/*/*.cpp)
# 2) Add the source files of the libraries. Old Arduino libraries place the
# source files at the top level. Later Arduino libraries put the source files
# under the src/ directory. Also support 3 levels of subdirectories.
MODULE_EXPANSION = $(wildcard $(module)/*.cpp) \
# 2) Collect the source files of the libraries referenced by the EPOXY_MODULES
# parameter. Old Arduino libraries place the source files at the top level.
# Later Arduino libraries put the source files under the src/ directory. Also
# support 3 levels of subdirectories. Support both C and C++ libraries files.
MODULE_EXPANSION_CPP = $(wildcard $(module)/*.cpp) \
$(wildcard $(module)/src/*.cpp) \
$(wildcard $(module)/src/*/*.cpp) \
$(wildcard $(module)/src/*/*/*.cpp) \
$(wildcard $(module)/src/*/*/*/*.cpp)
EPOXY_SRCS += $(foreach module,$(EPOXY_MODULES),$(MODULE_EXPANSION))
# 3) Add the source files in the application directory, also 3 levels down.
EPOXY_SRCS += $(wildcard *.cpp) $(wildcard */*.cpp) $(wildcard */*/*.cpp) \
MODULE_EXPANSION_C = $(wildcard $(module)/*.c) \
$(wildcard $(module)/src/*.c) \
$(wildcard $(module)/src/*/*.c) \
$(wildcard $(module)/src/*/*/*.c) \
$(wildcard $(module)/src/*/*/*/*.c)
MODULE_SRCS_CPP += $(foreach module,$(EPOXY_MODULES),$(MODULE_EXPANSION_CPP))
MODULE_SRCS_C += $(foreach module,$(EPOXY_MODULES),$(MODULE_EXPANSION_C))
# 3) Collect the source files in the application directory, also 3 levels down.
APP_SRCS_CPP += $(wildcard *.cpp) \
$(wildcard */*.cpp) \
$(wildcard */*/*.cpp) \
$(wildcard */*/*/*.cpp)

# Objects including *.o from *.ino
OBJS += $(EPOXY_SRCS:%.cpp=%.o) $(APP_NAME).o

# Finally, the rule to generate the binary for the application.
APP_SRCS_C += $(wildcard *.c) \
$(wildcard */*.c) \
$(wildcard */*/*.c) \
$(wildcard */*/*/*.c)

# Generate the list of object files from the *.cpp, *.c, and *.ino files.
OBJS += $(EPOXY_SRCS:%.cpp=%.o)
OBJS += $(MODULE_SRCS_CPP:%.cpp=%.o)
OBJS += $(MODULE_SRCS_C:%.c=%.o)
OBJS += $(APP_SRCS_CPP:%.cpp=%.o)
OBJS += $(APP_SRCS_C:%.c=%.o)
OBJS +=$(APP_NAME).o

# Finally the rule to generate the *.out binary file for the application.
$(APP_NAME).out: $(OBJS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)

# We need to add a rule to treat .ino file as just a normal .cpp.
$(APP_NAME).o: $(APP_NAME).ino $(DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -x c++ -c $<

%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@

# This simple rule does not capture all header dependencies of a given cpp
# file. Maybe it's better to make each cpp to depend on all headers of a given
# module, and force a recompilation of all cpp files. As far as I understand,
# this is what the Arduino IDE does upon each compile iteration.
# We don't need this rule because the implicit GNU Make rules for converting
# *.c and *.cpp into *.o files are sufficient.
#
# %.o: %.cpp
# $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@

# The following simple rules do not capture all header dependencies of a given
# *.cpp or *.c file. It's probably better to make each *.cpp and *.c to depend
# on all headers of a given module, and force a recompilation of all the files.
# As far as I understand, this is what the Arduino IDE does upon each compile
# iteration. But this is good enough for now, but has the disadvantage that we
# have to run `make clean` more often than necessary to reset all the
# dependencies.
%.cpp: %.h
%.c: %.h

.PHONY: all clean $(MORE_CLEAN)
.PHONY: all clean run $(MORE_CLEAN)

# Use 'make all' or just 'make' to compile the binary.
all: $(APP_NAME).out

# Use 'make run' to run the binary created by 'make all'. This is useful when
# the (APP_NAME).out is an AUnit unit test. You can execute ': make run' inside
# the vim editor. The error message of AUnit (as of v1.7) is compatible with
# the quickfix errorformat of vim, so vim will automatically detect assertion
# errors and jump directly to the line where the assertion failed.
run:
./$(APP_NAME).out

# Use 'make clean' to remove intermediate '*.o' files, the target '*.out' file,
# and any generated files defined by $(GENERATED).
clean: $(MORE_CLEAN)
rm -f $(OBJS) $(APP_NAME).out $(GENERATED)
80 changes: 74 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ The disadvantages are:
environments (e.g. 16-bit `int` versus 32-bit `int`, or 32-bit `long` versus
64-bit `long`).

**Version**: 1.4.0 (2022-11-06)
**Version**: 1.5.0 (2022-12-08)

**Changelog**: See [CHANGELOG.md](CHANGELOG.md)

Expand Down Expand Up @@ -195,11 +195,20 @@ $ make clean
$ make
```

The executable will be created with a `.out` extension. To run it, just type:
The executable will be created with a `.out` extension. To run it, type
one of the following:
```
$ ./BlinkSOS.out
$ make run
```

If you run `:make run` command inside the `vim` editor, it knows how to parse
the file and line number contained in the assertion messages generated by
[AUnit](https://github.com/bxparks/AUnit). The `vim` editor will jump directly
to the file and line where the assertion failure occurred. See
https://vimhelp.org/quickfix.txt.html for information on the `quickfix` feature
and the `errorformat` format that parses the GNU Make output.

The output that would normally be printed on the `Serial` on an Arduino
board will be sent to the `STDOUT` of the Linux, MacOS, or FreeBSD terminal. The
output should be identical to what would be shown on the serial port of the
Expand Down Expand Up @@ -233,6 +242,13 @@ for these additional libraries at the following locations:
* under each of the additional directories listed in `ARDUINO_LIB_DIRS` (see
below)

Version v1.5 supports compiling and linking plain C files in the third-party
libraries (defined by `ARDUINO_LIBS`) or in the application directory itself.
The C files are assumed to be written in C11 and are compiled using the `cc`
compiler. It may be possible to override the compiler flags by adding `-std=c99`
into the `EXTRA_CFLAGS` in the Makefile (which clobbers the default `-std=c11`)
but this has not been tested.

<a name="AdditionalLibraryLocations"></a>
### Additional Arduino Library Locations

Expand Down Expand Up @@ -404,7 +420,7 @@ runtests:
set -e; \
for i in *Test/Makefile; do \
echo '==== Running:' $$(dirname $$i); \
$$(dirname $$i)/$$(dirname $$i).out; \
$(MAKE) -C $$(dirname $$i) run; \
done

clean:
Expand All @@ -426,7 +442,16 @@ $ make -C tests tests
$ make -C tests runtests | grep failed
```

These parent Makefiles can be used in Continuous Integration, as shown below.
If you run `:make runtests` inside the `vim` editor, it knows how to parse the
diagnostic outputs generated by GNU Make (as it changes directories through the
`-C` flag), and it knows how to parse the file and line number contained in the
assertion messages generated by [AUnit](https://github.com/bxparks/AUnit). The
`vim` editor will jump directly to the file and line where the assertion failure
occurred. See https://vimhelp.org/quickfix.txt.html for information on the
`quickfix` feature and the `errorformat` format that parses the GNU Make output.

These parent Makefiles can also be used in Continuous Integration, as shown
below.

<a name="ContinuousIntegration"></a>
### Continuous Integration
Expand Down Expand Up @@ -461,8 +486,16 @@ you can use that instead by specifying the `CXX` makefile variable:
```
$ make CXX=clang++
```
(This tells `make` to set the `CXX` variable to `clang++` within the context of
`EpoxyDuino.mk` which causes `clang++` to be used over the default `g++`.)

This tells `make` to set the `CXX` variable to `clang++` within the context of
`EpoxyDuino.mk` which causes `clang++` to be used over the default `g++`.

If you have C files in your library or application, you can use to following to
compile the C files using `clang` instead of `cc` (which is the same as `gcc` on
Linux):
```
$ make CXX=clang++ CC=clang
```

One reason to use `clang++` instead of `g++` is that the `clang++` compiler will
sometimes catch a different set of programming errors.
Expand All @@ -487,6 +520,12 @@ variable, like this:
$ make EXTRA_CXXFLAGS='-g'
```

or

```
$ make EXTRA_CXXFLAGS='-g' EXTRA_CFLAGS='-g'
```

<a name="AdditionalCleanUp"></a>
### Additional Clean Up

Expand Down Expand Up @@ -822,6 +861,35 @@ The `pin` parameter should satisfy `0 <= pin < 32`. If `pin >= 32`, then
<a name="SupportedArduinoFeatures"></a>
## Supported Arduino Features

<a name="ArduinoMacros"></a>
### Arduino Macros

The following C-preprocessor macros are defined:

* `ARDUINO=100`
* Indicates compilation under Arduino.
* `EPOXY_DUINO`
* Indicates compilation under EpoxyDuino
* `UNIX_HOST_DUINO`
* For backwards compatibility with previous version of `EpoxyDuino`
which was named `UnixHostDuino`.
* `EPOXY_CORE_AVR`
* Defined when the Makefile variable `EPOXY_CORE` is set to
`ARDUINO_ARCH_AVR`.
* This is the default.
* `EPOXY_CORE_ESP8266`
* Defined when the Makefile variable `EPOXY_CORE` is set to
`ARDUINO_ARCH_ESP8266`.

The following are **not** defined. Many third party libraries tend to break with
those defined because EpoxyDuino does not emulate those environments perfectly:

* `ARDUINO_ARCH_AVR`
* `ARDUINO_ARCH_ESP8266`
* `ARDUINO_ARCH_ESP32`
* `ESP8266`
* `ESP32`

<a name="ArduinoFunctions"></a>
### Arduino Functions

Expand Down
4 changes: 2 additions & 2 deletions cores/epoxy/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
#define EPOXY_DUINO_EPOXY_ARDUINO_H

// xx.yy.zz => xxyyzz (without leading 0)
#define EPOXY_DUINO_VERSION 10400
#define EPOXY_DUINO_VERSION_STRING "1.4.0"
#define EPOXY_DUINO_VERSION 10500
#define EPOXY_DUINO_VERSION_STRING "1.5.0"

#include <algorithm> // min(), max()
#include <cmath> // abs()
Expand Down
2 changes: 1 addition & 1 deletion examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ all:
set -e; \
for i in */Makefile; do \
echo '==== Making:' $$(dirname $$i); \
$(MAKE) -C $$(dirname $$i) -j; \
$(MAKE) -C $$(dirname $$i); \
done

clean:
Expand Down
2 changes: 1 addition & 1 deletion libraries/EpoxyEepromAvr/examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ all:
set -e; \
for i in */Makefile; do \
echo '==== Making:' $$(dirname $$i); \
$(MAKE) -C $$(dirname $$i) -j; \
$(MAKE) -C $$(dirname $$i); \
done

clean:
Expand Down
4 changes: 2 additions & 2 deletions libraries/EpoxyEepromAvr/tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ tests:
set -e; \
for i in *Test/Makefile; do \
echo '==== Making:' $$(dirname $$i); \
$(MAKE) -C $$(dirname $$i) -j; \
$(MAKE) -C $$(dirname $$i); \
done

runtests:
set -e; \
for i in *Test/Makefile; do \
echo '==== Running:' $$(dirname $$i); \
$$(dirname $$i)/$$(dirname $$i).out; \
$(MAKE) -C $$(dirname $$i) run; \
done

clean:
Expand Down
Loading

0 comments on commit e84a534

Please sign in to comment.