2017-02-11 21 views
1

В настоящее время я пытаюсь разработать библиотеки C и шаблоны проектов для STM8 microcontroller с использованием SDCC OS compiler. Моя цель - это (почти) NOOB-совместимая установка, похожая на Arduino, но с make + shellscripts вместо IDE (есть ограничения для моей амбиции ...)Arduino-like Makefile с зависимостями ...?

В настоящее время я борюсь с make, чтобы автоматически определять зависимости , В Arduino пользователь включает только соответствующие заголовки, например. «#include LCD-lib», а механизм сборки автоматически определяет зависимость и связывает соответствующие библиотеки. Не нужно вручную добавлять его в IDE или Makefile.

Мне нравится простота этого, но до сих пор я с треском провалился в создании соответствующего Makefile. В основном вот что должен сделать Makefile:

  1. сканируйте * .c файлы в корне проекта для включенных заголовков. Обратите внимание, что эти файлы находятся в другой папке lib
  2. добавить все включенные заголовки и (если есть) соответствующие C-файлы в процесс сборки
  3. , чтобы свести к минимуму время и размер компиляции, неиспользуемые файлы C в папке lib должны быть пропущен во время сборки

я уверен, что делают может сделать все выше - но не на моем уровне опыта с косметическим ... :-(

Вот структура папок я имею в виду:

├── 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) 

Я знаю, что много спросить, но удобный Makefile - моя главная блокирующая точка. Любая помощь высоко ценится!!! Заранее большое спасибо!

С уважением, Georg Icking-Konert

+0

Вы рассматривали загрузку другой IDE, например, Затмение на основе одного типа Simplicity Studio, строит простой проект со структурой, описанной и, видя, как IDE генерирует Makefiles? Это будет хорошей отправной точкой. –

+0

Обратите внимание, что в среде Arduino дополнительный код, сгенерированный пользовательским интерфейсом и/или библиотеками, добавляется к пользовательскому '.ino' -коду в каждом модуле компиляции. Вы можете сделать это с помощью Makefiles, добавив дополнительный шаг к обработке. (Один из способов сделать это - создать предварительно обработанные исходные файлы в каталоге сборки, используя препроцессор, подав ему отдельные части для каждого блока компиляции.) Что вам нужно сделать здесь, это пройти весь процесс сборки вручную (и напишите об этом), включая различные варианты обработки; затем используйте это как схему для написания Makefile. –

ответ

0

Примечание: Я понимаю, что этот ответ не отвечает всем вашим требованиям, на самом деле этот подход по-прежнему требует, чтобы вы указали имена соответствующих библиотек Arduino, которые вы используете в своем проекте, а также список путей к каталогам, которые должны быть включены в проект. Однако это решение наиболее близко к вашим требованиям, о которых я мог подумать, и это может помочь кому-то еще прочитать этот вопрос в будущем.


Я использую ArduinoMakefile для этого:

  1. поставил Makefile.мастер в основном рабочем каталоге
  2. при запуске нового Arduino проекта, создать его как подкаталог в вашем рабочем пространстве
    • создать один файл с расширением .pde/.ino содержащего setup() и `цикл() методы
    • положить оставшуюся логику в .c/.cpp/.h/.hpp файлы
  3. добавить проекта Makefile тыс в наборах проект рафинированных настройки в этом подкаталоге, например:

    # 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. компилировать и запускать с помощью make all, make upload, make monitor и т.д.

Убедитесь, что у вас есть picocom установлен на ваш Unix/Linux машина (или ее эквивалент) как консольный последовательный монитор. На MAC-OS вы можете использовать экран, установив соответственно переменную MON_CMD.


Makefile.master:

оригинальный Makefile.master была написана Alan Burlison и модифицированы Matthieu Weber, и могут быть найдены here.

Я сделал некоторые изменения, так что он соответствует моей конфигурации, в частности, я добавил следующие строки кода:

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

и впоследствии удалены -g вариант из стандартных C/CXX _FLAGS записей в Makefile.master. Таким образом, информационный символ не добавляется на выпуск кода, и только тогда, когда код компилируется с DEBUG=1 код экранируется

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

находит свой путь в бинарный файл, таким образом, в результате чего меньший релиз исполняемых файлов.

Здесь вы можете найти мои собственные версия Makefile.мастер:

# 
# Copyright 2011 Alan Burlison, [email protected] All rights reserved. 
# Subsequently modified by Matthieu Weber, [email protected] 
# Subsequently modified by Patrick Trentin, [email protected] 
# 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 '[email protected]($%)' -MF [email protected]_$*.dep $< 
    $(CC) -c $(C_FLAGS) $(OPT_FLAGS) $(ARD_FLAGS) $(INC_FLAGS) \ 
     $< -o $(BUILD_DIR)/$% 
    @ $(AR) rc [email protected] $(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 '[email protected]($%)' -MF [email protected]_$*.dep $< 
    $(CXX) -c $(CXX_FLAGS) $(OPT_FLAGS) $(ARD_FLAGS) $(INC_FLAGS) \ 
     $< -o $(BUILD_DIR)/$% 
    @ $(AR) rc [email protected] $(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) [email protected] 

$(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 

Пример использования:

Учитывая реж дерево нравится следующим образом:

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 
... 

Вы можете разместить Makefile.master внутри Projects, то при условии, что:

  • Вам нужно только то, что находится в Library/Base и Library/User для этого проекта
  • Вы должны использовать LiquidCrystal Arduino библиотеки в проекте

, необходимо добавить следующее Makefile в 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 

Отметьте, что common.h должно быть автоматически обнаружено beca используйте его в ., и нет необходимости добавлять его в INC_DIRS.


Final Примечание: последний раз, когда я тестировала эту конфигурацию, я использовал версию 1.0.5 из Arduino исходного кода, и он работал безупречно.

0

Вы можете найти обсуждение, наряду с реализацией образца автоматического способа генерации зависимостей для GNU сделать here. Вы не говорите, что используете GNU make, поэтому я просто предполагаю.

Я не знаю, достаточно ли для вас этого или нет; из ваших заявлений о ваших требованиях было неясно.

+0

спасибо за ваш быстрый ответ, я посмотрю. И да, я использую GNU make. Извините, что не упоминал об этом. Я дам вам знать, если это соответствует моим потребностям - и уровень понимания ... – user7549304

0

Прежде всего, спасибо всем за быструю и значительную поддержку! Я должен был задать гораздо раньше ...

Теперь вернемся к моей проблеме (не более). Теперь я понимаю, что я на самом деле спросил 2 разных вопросы:

  • зависимостей от заголовков -> решаемых как Патрик или предложений по
  • Безумным учёным
  • обнаружить, что библиотека требуется, например, анализ звонков в main.o, или по # включает в main.c ...?

Я понимаю, что второй гораздо труднее достичь изнутри ...!? Но Makefile от Patrick делает удобную конфигурацию вручную. Так что это нормально для меня :-)

[add timeslip ...] Хорошо, задумавшись над чем-нибудь, будет ли следующая работа/иметь смысл?

  1. звонок, например. простак или питон скрипт внутри Makefile, чтобы изолировать все #included заголовков из * .c и * .h в каталоге проекта
  2. для каждого включенных хуга.ч проверки, если соответствующий make_xyz существует в одном из Lib каталогов (будет частью Lib)
  3. если да, включают в себя, что Makefile для компиляции в мастер Makefile

ли это каким-то образом иметь смысл ...? Еще раз спасибо и хорошо провести время, где бы вы ни были!

С уважением, Георг Icking-Konert

+0

Это пространство зарезервировано для * ответов *, которые фактически решают вашу проблему, вы должны нажать кнопку * [edit] * на свой вопрос, чтобы добавьте больше информации, а не создайте ответ. Сказав это, да, это жизнеспособный подход, и если вам удастся реализовать точку ** 1. ** размещение этого кода здесь будет хорошим ответом на ваш собственный вопрос. :) –

+0

hi Patrick, спасибо за совет. Как новичок здесь, я не знал об этом правиле. Надеюсь, что это правильно сейчас ... ;-) – user7549304

+0

hi again, Хорошо, я попытаюсь реализовать выше 1. как скрипт python, так как я также использую python для последовательного терминала. Надеюсь, это не займет слишком много времени. Должен ли я передать список требуемых * make_xyz * через файл со стандартным именем, которое статически включено в файл-мастер-файл ...? – user7549304

0

еще раз спасибо за вашу поддержку!

Следуя приведенному выше совету, я написал небольшой скрипт python, который использует генератор зависимости gcc (или фактически sdcc). Ниже сценарий сканирует все файлы проекта .c для #included заголовки с использованием gcc. Соответствующие файлы заголовков затем выполняются в папках проекта и библиотеки. Если существует соответствующий файл .c (тот же путь и имя, что и заголовок), он добавляется в Makefile. Этот процесс повторяется до тех пор, пока не будут найдены новые заголовки.

В результате создается файл Makefile, который только строит модули, которые составляют #include модулей в файле .c файла проекта - так же, как в среде Arduino. Это может быть не элегантно, а работа :-)

Линии 95-106 в сценарии являются компиляторами и конкретными проектами и должны быть соответствующим образом адаптированы. Получайте удовольствие и еще раз спасибо!

#!/usr/bin/python 

''' 
automatically create a Makefile with dependencies from 
all .c files in a starting directory 
''' 

# required modules 
import sys 
import os 
import platform 
import shlex 
from subprocess import Popen, PIPE 

# set OS specific 
OS = platform.system() 
if OS == 'Windows': 
    MAKE  = 'mingw32-make.exe' 
else: 
    MAKE  = 'make' 


################## 
# helper functions 
################## 

######### 
def getchar(): 
    """ 
    python equivalent of getchar() 
    """ 
    ch = 0 
    if OS == 'Windows': 
    import msvcrt as m 
    ch = m.getch() 
    sys.stdio.flush() 
    sys.stderr.flush() 
    else: 
    import sys, tty, termios 
    fd = sys.stdin.fileno() 
    old_settings = termios.tcgetattr(fd) 
    tty.setraw(sys.stdin.fileno()) 
    ch = sys.stdin.read(1) 
    return ch 
    # end getchar() 


######### 
def listFiles(start='.', pattern='.c'): 
    """ 
    return set of matching files in project folder incl. subfolders 
    """ 
    result = set() 
    for root, dirs, files in os.walk(start): 
    for file in files: 
     if file.endswith(pattern): 
     #print(os.path.join(root, file)) 
     result.add(os.path.join(root, file)) 
    return result 
    # end listFiles() 


######### 
def listSubdirs(start='.'): 
    """ 
    return set of subdirectories in given folder 
    """ 
    result = set() 
    for root, dirs, files in os.walk(start): 
    for dir in dirs: 
     #print(os.path.join(root, dir)) 
     result.add(os.path.join(root, dir)) 
    return result 
    # end listFiles() 


######### 
def get_exitcode_stdout_stderr(cmd): 
    """ 
    execute the external command and get its exitcode, stdout and stderr. 
    """ 
    args = shlex.split(cmd) 
    proc = Popen(args, stdout=PIPE, stderr=PIPE) 
    out, err = proc.communicate() 
    exitcode = proc.returncode 
    return exitcode, out, err 



################## 
# main program 
################## 

# set compile search paths 
ROOT_DIR = '../../../' 
TOOL_DIR = ROOT_DIR + 'Tools/' 
LIB_ROOT = ROOT_DIR + 'Library/' 
PRJ_ROOT = '.' 
OBJDIR = 'output' 
TARGET = 'main.ihx' 

# set command for creating dependencies and set search paths 
CC  = 'sdcc ' 
CFLAGS = '-mstm8 --std-sdcc99 --std-c99 ' 
LFLAGS = '-mstm8 -lstm8 --out-fmt-ihx ' 
DEPEND = '-MM ' 
INCLUDE = '-I. ' 
for dir in listSubdirs(PRJ_ROOT): 
    INCLUDE += '-I' + dir + ' ' 
for dir in listSubdirs(LIB_ROOT): 
    INCLUDE += '-I' + dir + ' ' 

# get set of .c files in project folder incl. subdirectories 
source_todo = listFiles(PRJ_ROOT,".c") 
source_done = set() 
header_done = set() 
object_done = set() 


# print message 
sys.stdout.write('start Makefile creation ... ') 
sys.stdout.flush() 


# generate generic Makefile header 
Makefile = open('Makefile', 'wb') 
Makefile.write('OBJDIR = '+OBJDIR+'\n') 
Makefile.write('TARGET = '+TARGET+'\n\n') 
Makefile.write('.PHONY: clean all default objects\n\n') 
Makefile.write('.PRECIOUS: $(TARGET)\n\n') 
Makefile.write('default: $(OBJDIR) $(OBJDIR)/$(TARGET)\n\n') 
Makefile.write('all: default\n\n') 
Makefile.write('# create output folder\n') 
Makefile.write('$(OBJDIR):\n') 
Makefile.write(' mkdir -p $(OBJDIR)\n') 
Makefile.write(' rm -fr -- -p\n\n') 

# iteratively add project sources to Makefile 
while (len(source_todo) > 0): 

    # get next pending source and mark as done 
    source = source_todo.pop() 
    source_done.add(source) 

    # convert Windows path to POSIX for Makefile 
    if OS == 'Windows': 
    source = source.replace('\\','/') 

    # use compiler generate dependency list 
    cmd = CC+DEPEND+CFLAGS+INCLUDE+source 
    #print cmd 
    exitcode, out, err = get_exitcode_stdout_stderr(cmd) 
    if (exitcode != 0): 
    print 'error: ' + err 
    getchar() 
    exit() 

    # append .c file with dependency and compile instruction to Makefile 
    Makefile.write('$(OBJDIR)/'+out) 
    #print(out) 
    Makefile.write('\t'+CC+CFLAGS+INCLUDE+'-c $< -o [email protected]\n\n') 

    # extract file list including object[0], source[1] and headers[2..N] 
    out = out.replace(':', '') 
    out = out.replace('\\', '') 
    out = out.replace('\n', '') 
    out = out.split() 
    #print out 

    # for all files returned by compiler... 
    for next in out: 

    # append object files for linker 
    if next.endswith('.rel'): 
     object_done.add(next) 

    # if corresponding source to header exists, add to pending sources 
    if next.endswith('.h'): 
     if next not in header_done:   # not yet in list 
     header_done.add(next)     # add to treated headers 
     if (os.path.isfile(next[:-1]+'c')): # if corresponding .c exists, add to todo list 
      source_todo.add(next[:-1]+'c') 


# link project object files 
Makefile.write('$(OBJDIR)/$(TARGET): ') 
for next in object_done: 
    Makefile.write('$(OBJDIR)/'+next+' ') 
Makefile.write('\n') 
Makefile.write('\t'+CC+LFLAGS) 
for next in object_done: 
    Makefile.write('$(OBJDIR)/'+next+' ') 
Makefile.write(' -o [email protected]\n') 

# close Makefile.dep 
Makefile.close() 


print('done\n') 
sys.stdout.write('press any key to exit') 
getchar() 
exit() 

# END OF MODULE 

 Смежные вопросы

  • Нет связанных вопросов^_^