具有依赖关系的Arduino类Makefile ...? [英] Arduino-like Makefile with dependencies...?

查看:285
本文介绍了具有依赖关系的Arduino类Makefile ...?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在为 STM8微控制器使用 SDCC OS编译器。我的目标是一个类似于Arduino的(几乎)与NOOB兼容的设置 - 但是使用make + shellscripts而不是IDE(对我的野心有限制)。



目前我正在努力与自动检测依赖关系。在Arduino中,用户只包括相关的标题,例如#include LCD-lib,构建机制自动检测依赖关系并链接各自的lib。不需要手动将其添加到IDE或Makefile中。



我喜欢简单,但到目前为止,我在创建各自的Makefile时失败了。基本上这是Makefile应该实现的:


  1. 扫描项目根目录中的* .c文件,以便包含头文件。请注意,这些文件位于不同的lib文件夹中

  2. 添加所有包含的标题和(如果存在)相应的C文件到构建过程

  3. 为了最大限度地缩短编译时间和大小,在构建过程中必须跳过lib文件夹中未使用的C文件。

我相信make可以做所有以上 - 但不是在我的水平的经验与...: - (



这是我想到的文件夹结构:

 ├──图书馆
│├──基地
││├──通用STM8来源和标题
│├ ──STM8S_Discovery
││└──板的具体来源和标题
│└──用户
│└──可选的用户库源和标题
├──项目
│├──示例(待填写)
││└──Basic_Project
││├──compile_upload.sh - >双击构建和上传
││├──config.h
││├──main.c
││└──Makefile - >应该检测./*.c和./*.h
中的依赖关系│└──User_Projects(仍然为空)
└──工具
├──programmer.py - >用于编程(已经从make制作)
└──terminal.py - >对于串行终端(已经在make中)

我知道这是很多问题,但是一个方便的Makefile是我的主要阻挡点。任何帮助高度赞赏!非常感谢!



Regards,
Georg Icking-Konert

解决方案<注意:我意识到这个答案不符合你的所有要求,实际上这个方法还需要你列出你在你的项目中使用的相关Arduino库的名称,以及要包括在项目中的目录的路径列表。然而,这个解决方案最接近你的要求,我可以想到,它可能还会帮助别人阅读这个问题。






我使用 Arduino Makefile


    <在您的主要工作空间目录
  1. 中,当您启动新的Arduino项目时,请将 Makefile.master 放在您的工作空间中的子目录


    • 创建一个包含 .pde / .ino 扩展名的单个文件 setup()和`loop()方法

    • 将剩余的逻辑放入 .c / .cpp / .h / .hpp 文件


  2. 添加一个项目Makefile 在这个子目录中设置项目细化设置,例如:

     #您的Arduino环境。 
    ARD_HOME = / usr / share / arduino
    ARD_BIN = $(ARD_HOME)/ hardware / tools / avr / bin

    #监视器波特率
    MON_SPEED = 4800

    #板设置。
    BOARD = uno
    PORT = / dev / ttyACM0
    PROGRAMMER = stk500v2

    #找到头文件和库的位置。
    INC_DIRS =
    MY_LIB_DIRS =
    LIBS =
    LIB_DIRS = $(addprefix $(ARD_HOME)/ libraries /,$(LIBS))$(MY_LIB_DIRS)

    include ../Makefile.master


  3. 使用 make all , make upload make monitor 等。

    / li>

确保您的 Unix / Linux 机器上安装了 picocom 等效)作为控制台串行监视器。在 MAC-OS 上,您可以通过相应地设置 MON_CMD 变量来使用屏幕






Makefile.master:



原始 Makefile.master Alan Burlison 编写,并由 Matthieu Weber 修改,可以找到 here



我进行了一些更改,使其符合我的配置,特别是我添加了以下代码:

  ### DEBUG编译### 
ifeq($(DEBUG),1)
ARD_FLAGS + = -DDEBUG_PROJ
C_FLAGS + = -g
CXX_FLAGS + = -g
其他
ARD_FLAGS + = -DNDEBUG_PROJ
endif

,随后删除 -g 选项从默认 C / CXX _FLAGS Makefile.master 中的条目。以这种方式,符号信息不会添加到 代码中,只有当代码使用 DEBUG = 1 代码屏蔽了

  #ifdef DEBUG_PROJ 
/ *这里的调试代码* /
#endif
//或
#ifndef NDEBUG_PROJ
/ *这里的调试代码* /
#endif

找到二进制文件,从而导致更小的发布可执行文件。



这里可以找到我的自己的 Makefile.master 版本:

 
#版权所有2011 Alan Burlison,alan@bleaklow.com。版权所有。
#随后由Matthieu Weber修改,matthieu.weber@jyu.fi。
#随后由Patrick Trentin修改,patrick.trentin.88@gmail.com
#使用须遵守许可条款。

#如果满足以下条件,则允许以源和二进制形式重新分发和使用
#修改:

#1 。源代码的再分发必须保留以上版权声明,
#此条件列表和以下免责声明。

#2.以二进制形式重新分发必须复制上述版权声明,
#此条件列表以及文档中的以下免责声明
#和/或其他材料与分配。

#此软件由ALAN BURLISON按原样提供,任何明示或暗示的
#保证,包括但不限于b
的暗示担保商品适销性对于特定用途的适用性是免责的。 IN
#事件ALAN BURLISON或贡献者对任何直接,间接,
#附带,特殊,惩戒性或后果性损害(包括但不限于b)替代产品或服务;使用,数据,
#或利润的损失或业务中断)无论如何导致和任何理论的
#责任,无论合同,严格责任或侵权(包括
#疏忽或以其他方式)以任何方式使用本软件,即使已被告知此类损害的可能性,b $ b#。

#在Arduino环境之外构建Arduino项目的Makefile

#这个makefile应该包含在以下
#form中的每个项目Makefile中:

#----------
#BOARD = mega
#PORT = / dev / term / 0
#INC_DIRS =。 ./common
#LIB_DIRS = ../libraries/Task ../../libraries/VirtualWire
#include ../../Makefile.master
#----- -----

#其中:
#BOARD:Arduino板类型,从$(ARD_HOME)/hardware/boards.txt
#端口:USB端口
#INC_DIRS:列出包含头文件的pf目录
#LIB_DIRS:包含库源的目录列表

#在使用此Makefile之前,您可以调整以下宏以适应
#你的环境,无论是直接编辑这个文件,还是通过在
#中定义它们,包含这个文件的Makefile,在这种情况下,它们将覆盖下面的
#定义:
#ARD_REV:arduino软件修订,例如0017,0018
#ARD_HOME:Arduino软件的安装目录。
#ARD_BIN:编译器二进制位置
#AVRDUDE:avrdude可执行文件的位置
#AVRDUDE_CONF:avrdude配置文件的位置
#PROGRAMMER:avrdude程序员类型
#MON_TERM :串行监视器的终端命令
#MON_CMD:串行监视器命令
#MON_SPEED:串行监视器速度


#全局配置。
ARD_REV?= 100
ARD_HOME?= / usr / local / arduino
ARD_BIN?= / usr / bin
AVRDUDE?= $(ARD_HOME)/ hardware / tools / avrdude
AVRDUDE_CONF?= $(ARD_HOME)/hardware/tools/avrdude.conf
MON_TERM?= xterm
MON_SPEED?= 57600
MON_CMD?= picocom
PORT?= $ (HOME)/ dev / arduino
BOARD?= atmega328

###这里不需要编辑。 ###

#检查所需的定义。

ifndef BOARD
$(错误$$(BOARD)未定义)
endif
ifndef PORT
$(错误$$(PORT)未定义)
endif

#版本特定设置
ARD_BOARDS = $(ARD_HOME)/hardware/arduino/boards.txt
ARD_SRC_DIR = $(ARD_HOME)/ hardware / arduino / cores / arduino
ARD_MAIN = $(ARD_SRC_DIR)/main.cpp

#标准宏。
SKETCH = $(notdir $(CURDIR))
BUILD_DIR = build
VPATH = $(LIB_DIRS)

#从boards.txt导出的宏
MCU:= $(shell sed -n's / $(BOARD)\.build\.mcu = \(。* \)/ \1 / p'< $(ARD_BOARDS))
F_CPU:= $(shell sed -n's / $(BOARD)\.build\.f_cpu = \(。* \)/ \1 / p'< $(ARD_BOARDS))
UPLOAD_SPEED:= \
$(shell sed -n's / $(BOARD)\.upload\.speed = \(。* \)/ \1 / p' $(ARD_BOARDS))
PROGRAMMER:= \
$(shell sed -n's / $(BOARD)\.upload\.protocol = \(。* \)/ \\ \\ 1 / p'< $(ARD_BOARDS))
ARD_VAR:= \
$(shell sed -n's / $(BOARD)\.build\.variant = \ 。* \)/ \1 / p'< $(ARD_BOARDS))

#更多特定于版本的设置
ARD_VAR_DIR = $(ARD_HOME)/ hardware / arduino / variants / $(ARD_VAR)

#构建工具。
CC = $(ARD_BIN)/ avr-gcc
CXX = $(ARD_BIN)/ avr-g ++
CXXFILT = $(ARD_BIN)/ avr-c ++ filt
OBJCOPY = $(ARD_BIN)/ avr-objcopy
OBJDUMP = $(ARD_BIN)/ avr-objdump
AR = $(ARD_BIN)/ avr-ar
SIZE = $(ARD_BIN)/ avr-大小
NM = $(ARD_BIN)/ avr-nm
MKDIR = mkdir -p
RM = rm -rf
MV = mv -f
LN = f

#编译器标志。
INC_FLAGS = \
$(addprefix -I,$(INC_DIRS))$(addprefix -I,$(LIB_DIRS))-I $(ARD_SRC_DIR)-I $(ARD_VAR_DIR)
ARD_FLAGS = -mmcu = $(MCU)-DF_CPU = $(F_CPU)-DARDUINO = $(ARD_REV)
C_CXX_FLAGS = \
-Wall -Wextra -Wundef -Wno-unused-parameter \
-fdiagnostics-show-option -Wa,-adhlns = $(BUILD_DIR)/ $ *。lst
C_FLAGS = \
$(C_CXX_FLAGS)-std = gnu99 -Wstrict-prototypes -Wno -old-style-declaration
CXX_FLAGS = $(C_CXX_FLAGS)

### DEBUG编译###
ifeq($(DEBUG),1)
ARD_FLAGS + = -DDEBUG_PROJ
C_FLAGS + = -g
CXX_FLAGS + = -g
else
ARD_FLAGS + = -DNDEBUG_PROJ
endif

#优化标志。
#优化大小,默认为无符号,打包数据。
#单独的部分,删除未使用的部分,缩短分支,跳转。
#不要内联,向量循环。没有例外。
#no os preamble,在序言中使用函数调用。
#http://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc/
#http://www.tty1.net/blog/2008-04-29-avr- gcc-optimisations_en.html
OPT_FLAGS = \
-Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \
-ffunction-sections -fdata-sections - Wl, - gc-sections, - relax \
-fno-inline-small-functions -fno-tree-scev-cprop -fno-exceptions \
-ffreestanding -mcall-prologues

#构建参数。
IMAGE = $(BUILD_DIR)/ $(SKETCH)
ARD_C_SRC = $(通配符$(ARD_SRC_DIR)/ *)c)
ARD_CXX_SRC = $(通配符$(ARD_SRC_DIR)/ *。cpp )
ARD_C_OBJ = $(patsubst%.c,%。o,$(notdir $(ARD_C_SRC)))
ARD_CXX_OBJ = $(patsubst%.cpp,%。o,$(notdir $(ARD_CXX_SRC ))
ARD_LIB = arduino
ARD_AR = $(BUILD_DIR)/ lib $(ARD_LIB).a
ARD_AR_OBJ = $(ARD_AR)($(ARD_C_OBJ)$(ARD_CXX_OBJ))
ARD_LD_FLAG = -l $(ARD_LIB)

#解决方法http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734
$(ARD_AR)(Tone .o):CXX_FLAGS + = -w

#素描库。
LIB_C_SRC = $(foreach ld,$(LIB_DIRS),$(通配符$(ld)/ *。c))
LIB_CXX_SRC = $(foreach ld,$(LIB_DIRS),$(通配符$
LIB_SRC = $(LIB_C_SRC)$(LIB_CXX_SRC)
ifneq$(strip $(LIB_C_SRC)$(LIB_CXX_SRC))
LIB_C_OBJ = $ (patsubst%.c,%。o,$(notdir $(LIB_C_SRC)))
LIB_CXX_OBJ = $(patsubst%.cpp,%。o,$(notdir $(LIB_CXX_SRC)))
LIB_LIB = library
LIB_AR = $(BUILD_DIR)/ lib $(LIB_LIB).a
LIB_AR_OBJ = $(LIB_AR)($(LIB_C_OBJ)$(LIB_CXX_OBJ))
LIB_LD_FLAG = LIB_LIB)
endif

#绘制PDE源。
SKT_PDE_SRC = $(通配符* .pde * .ino)
ifneq$(strip $(SKT_PDE_SRC))
SKT_PDE_OBJ = $(BUILD_DIR)/ $(SKETCH)_pde。 o
endif

#C和C ++源码。
SKT_C_SRC = $(通配符* .c)
SKT_CXX_SRC = $(通配符* .cpp)
ifneq$(strip $(SKT_C_SRC)$(SKT_CXX_SRC))
SKT_C_OBJ = $(patsubst%.c,%。o,$(SKT_C_SRC))
SKT_CXX_OBJ = $(patsubst%.cpp,%。o,$(SKT_CXX_SRC))
SKT_LIB = sketch
SKT_AR = $(BUILD_DIR)/ lib $(SKT_LIB).a
SKT_AR_OBJ = $(SKT_AR)/($(SKT_C_OBJ)$(SKT_CXX_OBJ))
SKT_LD_FLAG = -l $(SKT_LIB)
endif

#定义。
定义run-cc
@ $(CC)$(ARD_FLAGS)$(INC_FLAGS)-M -MT'$ @($%)'-MF $@_$*.dep $<
$(CC)-c $(C_FLAGS)$(OPT_FLAGS)$(ARD_FLAGS)$(INC_FLAGS)\
$< -o $(BUILD_DIR)/ $%
@ $(AR)rc $ @ $(BUILD_DIR)/ $%
@ $(RM)$(BUILD_DIR)/ $%
@ $ (CXXFILT) $(BUILD_DIR)/ $ *。lst> $(BUILD_DIR)/ $ *。lst.tmp
@ $(MV)$(BUILD_DIR)/ $ *。lst.tmp $(BUILD_DIR)/ $ *。lst
endef

定义run-cxx
@ $(CXX)$(ARD_FLAGS)$(INC_FLAGS)-M -MT'$ @($%)'-MF $@_$*.dep $<
$(CXX)-c $(CXX_FLAGS)$(OPT_FLAGS)$(ARD_FLAGS)$(INC_FLAGS)\
$< -o $(BUILD_DIR)/ $%
@ $(AR)rc $ @ $(BUILD_DIR)/ $%
@ $(RM)$(BUILD_DIR)/ $%
@ $ (CXXFILT) $(BUILD_DIR)/ $ *。lst> $(BUILD_DIR)/ $ *。lst.tmp
@ $(MV)$(BUILD_DIR)/ $ *。lst.tmp $(BUILD_DIR)/ $ *。lst
endef

#规则。
.PHONY:所有干净的上传监视器upload_monitor

全部:$(BUILD_DIR)$(IMAGE).hex

清洁:
$(RM) $(BUILD_DIR)

$(BUILD_DIR):
$(MKDIR)$ @

$(SKT_PDE_OBJ):$(SKT_PDE_SRC)
如果[ $(ARD_REV)-ge 100]然后\
echo'#includeArduino.h'> $(BUILD_DIR)/ $(草图)_pde.cpp; \
else \
echo'#includeWProgram.h'> $(BUILD_DIR)/ $(草图)_pde.cpp; \
fi
echo'#include$(SKT_PDE_SRC)'>> $(BUILD_DIR)/ $(SKETCH)_pde.cpp
$(LN)$(SKT_PDE_SRC)$(BUILD_DIR)/ $(SKT_PDE_SRC)
cd $(BUILD_DIR)&& $(CXX)-c $(subst build / ,, $(CXX_FLAGS))\
$(OPT_FLAGS)$(ARD_FLAGS)-I .. \
$(patsubst -I ..% ,-I ../..%,$(INC_FLAGS))\
$(SKETCH)_pde.cpp -o $(@ F)

(%.o):$ (ARD_SRC_DIR)/%c
$(run-cc)

(%.o):$(ARD_SRC_DIR)/%cpp
$(run-cxx)

(%.o):%.c
$(run-cc)

(%.o):%.cpp
$ -cxx)

$(BUILD_DIR)/%。d:%.c
$(run-cc-d)

$(BUILD_DIR)/%。 d:%.cpp
$(run-cxx-d)

$(IMAGE).hex:$(ARD_AR_OBJ)$(LIB_AR_OBJ)$(SKT_AR_OBJ)$(SKT_PDE_OBJ)
$(CC)$(CXX_FLAGS)$(OPT_FLAGS)$(ARD_FLAGS)-L $(BUILD_DIR)\
$(SKT_PDE_OBJ)$(SKT_LD_FLAG)$(LIB_LD_FLAG)$(ARD_LD_FLAG)-lm \
-o $(IMAGE).elf
$(OBJCOPY)-O ihex -j .eeprom --set-section-flags = .eeprom = alloc,load \
--no -change-warnings --change-section-lma .eeprom = 0 $(IMAGE).elf \
$(IMAGE).eep
$(OBJCOP Y)-O ihex -R .eeprom $(IMAGE).elf $(IMAGE).hex
$(OBJDUMP)-h -S $(IMAGE).elf | $(CXXFILT)-t> $(IMAGE).lst
$(SIZE)$(IMAGE).hex

上传:全部
- pkill -f'$(MON_CMD)* $(PORT) '
- 睡眠1
- stty -F $(PORT)hupcl
- $(AVRDUDE)-V -C $(AVRDUDE_CONF)-p $(MCU)-c $(PROGRAMMER) -P $(PORT)\
-b $(UPLOAD_SPEED)-D -Uflash:w:$(IMAGE).hex:i

监视器:
LD_LIBRARY_PATH = LD_PRELOAD = \
$(MON_TERM)-title'$(BOARD)$(PORT)'\
-e'$(MON_CMD)-b $(MON_SPEED)$(PORT)'&

upload_monitor:upload monitor

-include $(通配符$(BUILD_DIR)/ *。dep))
#vim:ft = make






使用示例:



给定一个 dir-tree ,如下所示:

  Base_Dir 
├──图书馆
│├──基础
││├──通用STM8来源和标题
│├──STM8S_Discovery
││└──板具体来源和标题
│└──用户
│└──可选的用户库源和标题
├──项目
│├──示例(待填写)
││└──Basic_Project
││├──config.h
│├──example.ino
││└──Makefile - >应该检测./*.c和./*.h
...

您可以在项目中放置 Makefile.master ,然后假设:




  • 您只需要 Library / Base Library / User 为此项目

  • 您需要在项目中使用 LiquidCrystal Arduino库



然后您将添加以下 Makefile 基本项目

 #您的Arduino环境。 
BASE_DIR = / path / to / Base_Dir#编辑
ARD_HOME = / usr / share / arduino#编辑,也许
ARD_BIN = $(ARD_HOME)/ hardware / tools / avr / bin

#监视器波特率
MON_SPEED = 4800

#单板设置。
BOARD = uno
PORT = / dev / ttyACM0
PROGRAMMER = stk500v2

#找到头文件和库的位置。
INC_DIRS =
MY_LIB_DIRS = $(BASE_DIR)/ Library / Base $(BASE_DIR)/ Library / User
LIBS = LiquidCrystal
LIB_DIRS = $(addprefix $(ARD_HOME)/ libraries /,$(LIBS))$(MY_LIB_DIRS)

include ../../Makefile.master

请注意, common.h 应该被自动检测,因为它位于并且不需要将后者添加到 INC_DIRS






<最后注意:上次我测试了这个配置,我使用的是 Arduino 源代码的版本 1.0.5 它的工作正常。


I am currently trying to develop C libraries and project templates for the STM8 microcontroller using the SDCC OS compiler. My target is a (nearly) NOOB-compatible setup similar to Arduino - but with make+shellscripts instead of an IDE (there are limits to my ambition...)

Currently I am struggling with make to auto-detect dependencies. In Arduino the user only includes the relevant headers, e.g. "#include LCD-lib", and the build mechanism automatically detects dependency and links the respective libs. No need to manually add it to an IDE or the Makefile.

I love the simplicity of that, but so far I have failed miserably in creating a respective Makefile. Basically here's what the Makefile should achieve:

  1. scan the *.c files in the project root for included headers. Note that these files are located in a different lib folder
  2. add all included headers and (if exist) the corresponding C-files to the build process
  3. to minimize compile time and size, unused C files in the lib folder must be skipped during build

I am confident that make can do all the above - but not at my level of experience with make... :-(

Here's the folder structure I have in mind:

├── Library
│   ├── Base
│   │   ├── general STM8 sources and headers 
│   ├── STM8S_Discovery
│   │   └── board specific sources and headers
│   └── User
│       └── optional user library sources and headers
├── Projects
│   ├── Examples (to be filled)
│   │   └── Basic_Project
│   │       ├── compile_upload.sh  --> double-click to build and upload
│   │       ├── config.h
│   │       ├── main.c
│   │       └── Makefile           --> should detect dependencies in ./*.c and ./*.h
│   └── User_Projects (still empty)
└── Tools
    ├── programmer.py              --> for programming (already works from make)
    └── terminal.py                --> for serial terminal (already works from make)

I know it's a lot to ask, but a convenient Makefile is my main blocking point. Any help is highly appreciated!!! Thanks a lot in advance!

Regards, Georg Icking-Konert

解决方案

Note: I realize that this answer doesn't meet all of your requirements, in fact this approach still requires you to list the names of relevant Arduino Libraries that you use in your project, as well as a list of paths to directories that should be included in the project. However, this solution is the closest to your requirements that I could think of and it might still help someone else reading this question down the road.


I use Arduino Makefile for this:

  1. put Makefile.master in your main work-space directory
  2. when you start a new Arduino project, you create it as a sub-directory in your workspace
    • create a single file with .pde/.ino extension containing setup() and `loop() methods
    • put the remaining logic into .c/.cpp/.h/.hpp files
  3. add a project Makefile that sets project-refined settings in this sub-directory, e.g.:

    # Your Arduino environment.
    ARD_HOME = /usr/share/arduino
    ARD_BIN = $(ARD_HOME)/hardware/tools/avr/bin
    
    # Monitor Baudrate
    MON_SPEED = 4800
    
    # Board settings.
    BOARD = uno
    PORT = /dev/ttyACM0
    PROGRAMMER = stk500v2
    
    # Where to find header files and libraries.
    INC_DIRS =
    MY_LIB_DIRS =
    LIBS =
    LIB_DIRS = $(addprefix $(ARD_HOME)/libraries/, $(LIBS)) $(MY_LIB_DIRS)
    
    include ../Makefile.master
    

  4. compile and run using make all, make upload, make monitor, etc.

Ensure that you have picocom installed on your Unix/Linux machine (or equivalent) as console serial monitor. On MAC-OS, you can use screen by setting the MON_CMD variable accordingly.


Makefile.master:

The original Makefile.master was written by Alan Burlison and modified by Matthieu Weber, and can be found here.

I made some changes so that it fits my configuration, in particular I've added these lines of code:

### DEBUG Compilation ###
ifeq ($(DEBUG), 1)
    ARD_FLAGS += -DDEBUG_PROJ
    C_FLAGS += -g
    CXX_FLAGS += -g
else
    ARD_FLAGS += -DNDEBUG_PROJ
endif

and subsequently removed -g option from default C/CXX _FLAGS entries in Makefile.master. In this way symbol information is not added on release code, and only when code is compiled with DEBUG=1 the code shielded by

#ifdef DEBUG_PROJ
    /* debug code here */
#endif
// or
#ifndef NDEBUG_PROJ
    /* debug code here */
#endif

finds its way into the binary, thus resulting smaller release executables.

Here you can find my own version of the Makefile.master:

#
# Copyright 2011 Alan Burlison, alan@bleaklow.com.  All rights reserved.
# Subsequently modified by Matthieu Weber, matthieu.weber@jyu.fi.
# Subsequently modified by Patrick Trentin, patrick.trentin.88@gmail.com
# Use is subject to license terms.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#  1. Redistributions of source code must retain the above copyright notice,
#     this list of conditions and the following disclaimer.
#
#  2. Redistributions in binary form must reproduce the above copyright notice,
#     this list of conditions and the following disclaimer in the documentation
#     and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY ALAN BURLISON "AS IS" AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL ALAN BURLISON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Makefile for building Arduino projects outside of the Arduino environment
#
# This makefile should be included into a per-project Makefile of the following
# form:
#
# ----------
# BOARD = mega
# PORT = /dev/term/0
# INC_DIRS = ../common
# LIB_DIRS = ../libraries/Task ../../libraries/VirtualWire
# include ../../Makefile.master
# ----------
#
# Where:
#   BOARD    : Arduino board type, from $(ARD_HOME)/hardware/boards.txt
#   PORT     : USB port
#   INC_DIRS : List pf directories containing header files
#   LIB_DIRS : List of directories containing library source
#
# Before using this Makefile you can adjust the following macros to suit
# your environment, either by editing this file directly or by defining them in
# the Makefile that includes this one, in which case they will override the
# definitions below:
#   ARD_REV      : arduino software revision, e.g. 0017, 0018
#   ARD_HOME     : installation directory of the Arduino software.
#   ARD_BIN      : location of compiler binaries
#   AVRDUDE      : location of avrdude executable
#   AVRDUDE_CONF : location of avrdude configuration file
#   PROGRAMMER   : avrdude programmer type
#   MON_TERM     : terminal command for serial monitor
#   MON_CMD      : serial monitor command
#   MON_SPEED    : serial monitor speed
#

# Global configuration.
ARD_REV ?= 100
ARD_HOME ?= /usr/local/arduino
ARD_BIN ?= /usr/bin
AVRDUDE ?= $(ARD_HOME)/hardware/tools/avrdude
AVRDUDE_CONF ?= $(ARD_HOME)/hardware/tools/avrdude.conf
MON_TERM ?= xterm
MON_SPEED ?= 57600
MON_CMD ?= picocom
PORT ?= $(HOME)/dev/arduino
BOARD ?= atmega328

### Nothing below here should require editing. ###

# Check for the required definitions.

ifndef BOARD
    $(error $$(BOARD) not defined)
endif
ifndef PORT
    $(error $$(PORT) not defined)
endif

# Version-specific settings
ARD_BOARDS = $(ARD_HOME)/hardware/arduino/boards.txt
ARD_SRC_DIR = $(ARD_HOME)/hardware/arduino/cores/arduino
ARD_MAIN = $(ARD_SRC_DIR)/main.cpp

# Standard macros.
SKETCH = $(notdir $(CURDIR))
BUILD_DIR = build
VPATH = $(LIB_DIRS)

# Macros derived from boards.txt
MCU := $(shell sed -n 's/$(BOARD)\.build\.mcu=\(.*\)/\1/p' < $(ARD_BOARDS))
F_CPU := $(shell sed -n 's/$(BOARD)\.build\.f_cpu=\(.*\)/\1/p' < $(ARD_BOARDS))
UPLOAD_SPEED := \
    $(shell sed -n 's/$(BOARD)\.upload\.speed=\(.*\)/\1/p' < $(ARD_BOARDS))
PROGRAMMER := \
    $(shell sed -n 's/$(BOARD)\.upload\.protocol=\(.*\)/\1/p' < $(ARD_BOARDS))
ARD_VAR := \
    $(shell sed -n 's/$(BOARD)\.build\.variant=\(.*\)/\1/p' < $(ARD_BOARDS))

# More Version-specific settings
ARD_VAR_DIR = $(ARD_HOME)/hardware/arduino/variants/$(ARD_VAR)

# Build tools.
CC = $(ARD_BIN)/avr-gcc
CXX = $(ARD_BIN)/avr-g++
CXXFILT = $(ARD_BIN)/avr-c++filt
OBJCOPY = $(ARD_BIN)/avr-objcopy
OBJDUMP = $(ARD_BIN)/avr-objdump
AR = $(ARD_BIN)/avr-ar
SIZE = $(ARD_BIN)/avr-size
NM = $(ARD_BIN)/avr-nm
MKDIR = mkdir -p
RM = rm -rf
MV = mv -f
LN = ln -f

# Compiler flags.
INC_FLAGS = \
    $(addprefix -I,$(INC_DIRS)) $(addprefix -I,$(LIB_DIRS)) -I$(ARD_SRC_DIR) -I$(ARD_VAR_DIR)
ARD_FLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU) -DARDUINO=$(ARD_REV)
C_CXX_FLAGS = \
    -Wall -Wextra -Wundef -Wno-unused-parameter \
    -fdiagnostics-show-option -Wa,-adhlns=$(BUILD_DIR)/$*.lst
C_FLAGS = \
    $(C_CXX_FLAGS) -std=gnu99 -Wstrict-prototypes -Wno-old-style-declaration
CXX_FLAGS = $(C_CXX_FLAGS)

### DEBUG Compilation ###
ifeq ($(DEBUG), 1)
    ARD_FLAGS += -DDEBUG_PROJ
    C_FLAGS += -g
    CXX_FLAGS += -g
else
    ARD_FLAGS += -DNDEBUG_PROJ
endif

# Optimiser flags.
#     optimise for size, unsigned by default, pack data.
#     separate sections, drop unused ones, shorten branches, jumps.
#     don't inline, vectorise loops. no exceptions.
#     no os preamble, use function calls in prologues.
# http://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc/
# http://www.tty1.net/blog/2008-04-29-avr-gcc-optimisations_en.html
OPT_FLAGS = \
     -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \
    -ffunction-sections -fdata-sections -Wl,--gc-sections,--relax \
    -fno-inline-small-functions -fno-tree-scev-cprop -fno-exceptions \
    -ffreestanding -mcall-prologues

# Build parameters.
IMAGE = $(BUILD_DIR)/$(SKETCH)
ARD_C_SRC = $(wildcard $(ARD_SRC_DIR)/*.c)
ARD_CXX_SRC = $(wildcard $(ARD_SRC_DIR)/*.cpp)
ARD_C_OBJ = $(patsubst %.c,%.o,$(notdir $(ARD_C_SRC)))
ARD_CXX_OBJ = $(patsubst %.cpp,%.o,$(notdir $(ARD_CXX_SRC)))
ARD_LIB = arduino
ARD_AR = $(BUILD_DIR)/lib$(ARD_LIB).a
ARD_AR_OBJ = $(ARD_AR)($(ARD_C_OBJ) $(ARD_CXX_OBJ))
ARD_LD_FLAG = -l$(ARD_LIB)

# Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734
$(ARD_AR)(Tone.o) : CXX_FLAGS += -w

# Sketch libraries.
LIB_C_SRC = $(foreach ld,$(LIB_DIRS),$(wildcard $(ld)/*.c))
LIB_CXX_SRC = $(foreach ld,$(LIB_DIRS),$(wildcard $(ld)/*.cpp))
LIB_SRC = $(LIB_C_SRC) $(LIB_CXX_SRC)
ifneq "$(strip $(LIB_C_SRC) $(LIB_CXX_SRC))" ""
    LIB_C_OBJ = $(patsubst %.c,%.o,$(notdir $(LIB_C_SRC)))
    LIB_CXX_OBJ = $(patsubst %.cpp,%.o,$(notdir $(LIB_CXX_SRC)))
    LIB_LIB = library
    LIB_AR = $(BUILD_DIR)/lib$(LIB_LIB).a
    LIB_AR_OBJ = $(LIB_AR)($(LIB_C_OBJ) $(LIB_CXX_OBJ))
    LIB_LD_FLAG = -l$(LIB_LIB)
endif

# Sketch PDE source.
SKT_PDE_SRC = $(wildcard *.pde *.ino)
ifneq "$(strip $(SKT_PDE_SRC))" ""
    SKT_PDE_OBJ = $(BUILD_DIR)/$(SKETCH)_pde.o
endif

# C and C++ source.
SKT_C_SRC = $(wildcard *.c)
SKT_CXX_SRC = $(wildcard *.cpp)
ifneq "$(strip $(SKT_C_SRC) $(SKT_CXX_SRC))" ""
    SKT_C_OBJ = $(patsubst %.c,%.o,$(SKT_C_SRC))
    SKT_CXX_OBJ = $(patsubst %.cpp,%.o,$(SKT_CXX_SRC))
    SKT_LIB = sketch
    SKT_AR = $(BUILD_DIR)/lib$(SKT_LIB).a
    SKT_AR_OBJ = $(SKT_AR)/($(SKT_C_OBJ) $(SKT_CXX_OBJ))
    SKT_LD_FLAG = -l$(SKT_LIB)
endif

# Definitions.
define run-cc
    @ $(CC) $(ARD_FLAGS) $(INC_FLAGS) -M -MT '$@($%)' -MF $@_$*.dep $<
    $(CC) -c $(C_FLAGS) $(OPT_FLAGS) $(ARD_FLAGS) $(INC_FLAGS) \
        $< -o $(BUILD_DIR)/$%
    @ $(AR) rc $@ $(BUILD_DIR)/$%
    @ $(RM) $(BUILD_DIR)/$%
    @ $(CXXFILT) < $(BUILD_DIR)/$*.lst > $(BUILD_DIR)/$*.lst.tmp
    @ $(MV) $(BUILD_DIR)/$*.lst.tmp $(BUILD_DIR)/$*.lst
endef

define run-cxx
    @ $(CXX) $(ARD_FLAGS) $(INC_FLAGS) -M -MT '$@($%)' -MF $@_$*.dep $<
    $(CXX) -c $(CXX_FLAGS) $(OPT_FLAGS) $(ARD_FLAGS) $(INC_FLAGS) \
        $< -o $(BUILD_DIR)/$%
    @ $(AR) rc $@ $(BUILD_DIR)/$%
    @ $(RM) $(BUILD_DIR)/$%
    @ $(CXXFILT) < $(BUILD_DIR)/$*.lst > $(BUILD_DIR)/$*.lst.tmp
    @ $(MV) $(BUILD_DIR)/$*.lst.tmp $(BUILD_DIR)/$*.lst
endef

# Rules.
.PHONY : all clean upload monitor upload_monitor

all : $(BUILD_DIR) $(IMAGE).hex

clean :
    $(RM) $(BUILD_DIR)

$(BUILD_DIR) :
    $(MKDIR) $@

$(SKT_PDE_OBJ) : $(SKT_PDE_SRC)
    if [ $(ARD_REV) -ge 100 ]; then \
    echo '#include "Arduino.h"' > $(BUILD_DIR)/$(SKETCH)_pde.cpp; \
    else \
    echo '#include "WProgram.h"' > $(BUILD_DIR)/$(SKETCH)_pde.cpp; \
    fi
    echo '#include "$(SKT_PDE_SRC)"' >> $(BUILD_DIR)/$(SKETCH)_pde.cpp
    $(LN) $(SKT_PDE_SRC) $(BUILD_DIR)/$(SKT_PDE_SRC)
    cd $(BUILD_DIR) && $(CXX) -c $(subst build/,,$(CXX_FLAGS)) \
        $(OPT_FLAGS) $(ARD_FLAGS) -I.. \
        $(patsubst -I..%,-I../..%,$(INC_FLAGS)) \
        $(SKETCH)_pde.cpp -o $(@F)

(%.o) : $(ARD_SRC_DIR)/%.c
    $(run-cc)

(%.o) : $(ARD_SRC_DIR)/%.cpp
    $(run-cxx)

(%.o) : %.c
    $(run-cc)

(%.o) : %.cpp
    $(run-cxx)

$(BUILD_DIR)/%.d : %.c
    $(run-cc-d)

$(BUILD_DIR)/%.d : %.cpp
    $(run-cxx-d)

$(IMAGE).hex : $(ARD_AR_OBJ) $(LIB_AR_OBJ) $(SKT_AR_OBJ) $(SKT_PDE_OBJ)
    $(CC) $(CXX_FLAGS) $(OPT_FLAGS) $(ARD_FLAGS) -L$(BUILD_DIR) \
        $(SKT_PDE_OBJ) $(SKT_LD_FLAG) $(LIB_LD_FLAG) $(ARD_LD_FLAG) -lm \
        -o $(IMAGE).elf
    $(OBJCOPY) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load \
        --no-change-warnings --change-section-lma .eeprom=0 $(IMAGE).elf \
        $(IMAGE).eep
    $(OBJCOPY) -O ihex -R .eeprom $(IMAGE).elf $(IMAGE).hex
    $(OBJDUMP) -h -S $(IMAGE).elf | $(CXXFILT) -t > $(IMAGE).lst
    $(SIZE) $(IMAGE).hex

upload : all
    - pkill -f '$(MON_CMD).*$(PORT)'
    - sleep 1
    - stty -F $(PORT) hupcl
    - $(AVRDUDE) -V -C$(AVRDUDE_CONF) -p$(MCU) -c$(PROGRAMMER) -P$(PORT) \
        -b$(UPLOAD_SPEED) -D -Uflash:w:$(IMAGE).hex:i

monitor :
    LD_LIBRARY_PATH= LD_PRELOAD= \
        $(MON_TERM) -title '$(BOARD) $(PORT)' \
        -e '$(MON_CMD) -b $(MON_SPEED) $(PORT)' &

upload_monitor : upload monitor

-include $(wildcard $(BUILD_DIR)/*.dep))
# vim:ft=make


Use Example:

Given a dir-tree like follows:

Base_Dir
├── Library
│   ├── Base
│   │   ├── general STM8 sources and headers 
│   ├── STM8S_Discovery
│   │   └── board specific sources and headers
│   └── User
│       └── optional user library sources and headers
├── Projects
│   ├── Examples (to be filled)
│   │   └── Basic_Project
│   │       ├── config.h
│   │       ├── example.ino
│   │       └── Makefile           --> should detect dependencies in ./*.c and ./*.h
...

You could place Makefile.master within Projects, then assuming that:

  • You only need what is in Library/Base and Library/User for this project
  • You need to use LiquidCrystal Arduino Library in your project

then you would add the following Makefile into Basic Project:

# Your Arduino environment.
BASE_DIR = /path/to/Base_Dir              # to edit
ARD_HOME = /usr/share/arduino             # to edit, maybe
ARD_BIN = $(ARD_HOME)/hardware/tools/avr/bin

# Monitor Baudrate
MON_SPEED = 4800

# Board settings.
BOARD = uno
PORT = /dev/ttyACM0
PROGRAMMER = stk500v2

# Where to find header files and libraries.
INC_DIRS =
MY_LIB_DIRS= $(BASE_DIR)/Library/Base $(BASE_DIR)/Library/User 
LIBS= LiquidCrystal
LIB_DIRS = $(addprefix $(ARD_HOME)/libraries/, $(LIBS)) $(MY_LIB_DIRS)

include ../../Makefile.master

Note that common.h should be automatically detected because it is located in ., and there should be no need to add the latter to INC_DIRS.


Final Note: last time I tested this configuration I was using version 1.0.5 of Arduino source code, and it was working flawlessly.

这篇关于具有依赖关系的Arduino类Makefile ...?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆