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

DRYify makefile generators, Restructure build directory, Allow additional targets from projcet.yaml #394

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 21 additions & 15 deletions project_generator/templates/makefile.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

# This project was exported via the project generator. More information https://github.com/project-generator/project_generator

.SUFFIXES: .

CPU = {{core}}

# toolchain specific
Expand All @@ -41,6 +43,7 @@ TARGET_EXT = .a
{% endif %}

LD_SCRIPT = {{linker_file}}
VPATH += {{output_dir.rel_path}}

CC_SYMBOLS = {% for symbol in macros %} -D{{symbol}} {% endfor %}
ASM_SYMBOLS = {% block ASM_SYMBOLS %}{% endblock %}
Expand Down Expand Up @@ -76,16 +79,14 @@ C_FLAGS = {% for option in c_flags %} {{option}} {% endfor %}
CXX_FLAGS = {% for option in cxx_flags %} {{option}} {% endfor %}
ASM_FLAGS = {% for option in asm_flags %} {{option}} {% endfor %}

CFLAGS = $(C_FLAGS) $(INC_DIRS_F) -c $(CC_SYMBOLS)
CFLAGS += $(C_FLAGS) $(INC_DIRS_F) -c $(CC_SYMBOLS)
CXXFLAGS = $(CXX_FLAGS) $(INC_DIRS_F) -c $(CC_SYMBOLS)
ASFLAGS = $(ASM_FLAGS) $(INC_DIRS_F) -c $(ASM_SYMBOLS)

# Linker options
LD_OPTIONS += {% for option in ld_flags %} {{option}} {% endfor %}
LD_OPTIONS += {% block LD_OPTIONS %}{% endblock %}

OBJCPFLAGS = -O ihex

ARFLAGS = cr

ifeq ($(OS),Windows_NT)
Expand All @@ -95,34 +96,32 @@ else
endif

C_SRCS := {% for file in source_files_c %} {{file}} {% endfor %}
C_OBJS := $(patsubst %.c,$(OBJ_FOLDER)%.o,$(notdir $(C_SRCS)))
C_OBJS := $(patsubst %.c,$(OBJ_FOLDER)%.o,$(C_SRCS))

CPP_SRCS := {% for file in source_files_cpp %} {{file}} {% endfor %}
CPP_OBJS := $(patsubst %.cpp,$(OBJ_FOLDER)%.o,$(notdir $(CPP_SRCS)))
CPP_OBJS := $(patsubst %.cpp,$(OBJ_FOLDER)%.o,$(CPP_SRCS))

S_SRCS := {% for file in source_files_s %} {{file}} {% endfor %}
S_OBJS = $(patsubst %.s,$(OBJ_FOLDER)%.o,$(filter %.s,$(notdir $(S_SRCS))))
S_OBJS += $(patsubst %.S,$(OBJ_FOLDER)%.o,$(filter %.S,$(notdir $(S_SRCS))))
S_OBJS = $(patsubst %.s,$(OBJ_FOLDER)%.o,$(filter %.s,$(S_SRCS)))
S_OBJS += $(patsubst %.S,$(OBJ_FOLDER)%.o,$(filter %.S,$(S_SRCS)))

O_OBJS := {% for file in source_files_obj %} {{file}} {% endfor %}

VPATH := $(SRC_DIRS)

$(OBJ_FOLDER)%.o : %.c
$(OBJ_FOLDER)%.o : %.c | create_outputdir
@echo 'Building file: $(@F)'
@echo 'Invoking: MCU C Compiler'
$(CC) $(CFLAGS) $(COMMON_FLAGS) $< -o $@
@echo 'Finished building: $(@F)'
@echo ' '

$(OBJ_FOLDER)%.o : %.cpp
$(OBJ_FOLDER)%.o : %.cpp | create_outputdir
@echo 'Building file: $(@F)'
@echo 'Invoking: MCU C++ Compiler'
$(CXX) $(CXXFLAGS) $(COMMON_FLAGS) $< -o $@
@echo 'Finished building: $(@F)'
@echo ' '

$(OBJ_FOLDER)%.o : %.s
$(OBJ_FOLDER)%.o : %.s | create_outputdir
@echo 'Building file: $(@F)'
@echo 'Invoking: MCU Assembler'
$(AS) $(ASFLAGS) $(COMMON_FLAGS) $< -o $@
Expand All @@ -131,14 +130,18 @@ $(OBJ_FOLDER)%.o : %.s

PRE_BUILD_SCRIPT := $(shell{% for command in pre_build_script %} ../../../{{command}} && {% endfor %} true)

all: create_outputdir $(OBJ_FOLDER)$(TARGET)$(TARGET_EXT) print_info
all: $(OBJ_FOLDER)$(TARGET)$(TARGET_EXT) print_info
{% for command in post_build_script %} ../../../{{command}} && {% endfor %} true

create_outputdir:
ifeq ($(OS),Windows_NT)
-mkdir $(OUT_DIR)
-@mkdir $(OUT_FOLDER)
{% for dir in source_paths %}
-@mkdir $(OBJ_FOLDER){{dir}}{% endfor %}
else
$(shell mkdir $(OBJ_FOLDER) 2>/dev/null)
@mkdir -p $(OBJ_FOLDER) 2>/dev/null
{% for dir in source_paths %}
@mkdir -p $(OBJ_FOLDER){{dir}} 2>/dev/null{% endfor %}
endif

{% if output_type == 'exe' %}
Expand Down Expand Up @@ -172,6 +175,9 @@ print_info:
@echo ' '
{% endif %}

{% for rule in additional_targets %}{{rule}}
{% endfor %}

# Other Targets
clean:
@echo 'Removing entire out directory'
Expand Down
4 changes: 2 additions & 2 deletions project_generator/templates/makefile_armcc.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% extends "makefile.tmpl" %}
{% extends "makefile.tmpl" %}

{% block CC %}armcc{% endblock %}
{% block CXX %}armcc{% endblock %}
Expand All @@ -12,5 +12,5 @@
{% block objcopy_output %}--output{% endblock %}

{% block COMMON_FLAGS %} --cpu $(CPU) --$(INSTRUCTION_MODE){% endblock %}
{% block LD_OPTIONS %}--strict --scatter $(LD_SCRIPT) $(patsubst %,--predefine "%",$(CC_SYMBOLS) $(INC_DIRS_F)){% endblock %}
{% block LD_OPTIONS %}--strict --scatter $(filter %.sct, $^) $(patsubst %,--predefine "%",$(CC_SYMBOLS) $(INC_DIRS_F)){% endblock %}
{% block ASM_SYMBOLS %}{% for symbol in macros %} --pd "{{ morph_define(symbol) }}" {% endfor %}{% endblock %}
2 changes: 1 addition & 1 deletion project_generator/templates/makefile_gcc.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@
{% block TOBIN %}-O binary{% endblock %}

{% block COMMON_FLAGS %} -mcpu=$(CPU) -m$(INSTRUCTION_MODE) -MMD -MP $(CC_SYMBOLS) {% endblock %}
{% block LD_OPTIONS %} -mcpu=$(CPU) -m$(INSTRUCTION_MODE) -Wl,-Map=$(OBJ_FOLDER)$(TARGET).map,--cref -T$(LD_SCRIPT){% endblock %}
{% block LD_OPTIONS %} -mcpu=$(CPU) -m$(INSTRUCTION_MODE) -Wl,-Map=$(OBJ_FOLDER)$(TARGET).map,--cref -T$(filter-out %.o, $^){% endblock %}
{% block ASM_SYMBOLS %}$(CC_SYMBOLS){% endblock %}
127 changes: 6 additions & 121 deletions project_generator/tools/gccarm.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import copy
import os
from copy import deepcopy
import logging
import ntpath
import subprocess
from itertools import chain

from os.path import join, normpath,dirname
from project_generator_definitions.definitions import ProGenDef

from .tool import Tool,Exporter
from ..util import SOURCE_KEYS
from .makefile import MakefileTool

logger = logging.getLogger('progen.tools.gccarm')

class MakefileGccArm(Tool, Exporter):

# http://www.gnu.org/software/make/manual/html_node/Running.html
ERRORLEVEL = {
0: 'no errors)',
1: 'targets not already up to date',
2: 'errors'
}

SUCCESSVALUE = 0

optimization_options = ['O0', 'O1', 'O2', 'O3', 'Os']

generated_projects = {
'path': '',
'files': {
'makefile' : '',
}
}
class MakefileGccArm(MakefileTool):

def __init__(self, workspace, env_settings):
self.workspace = workspace
self.env_settings = env_settings
MakefileTool.__init__(self, workspace, env_settings, logging)

@staticmethod
def get_toolnames():
Expand All @@ -59,102 +32,14 @@ def get_toolnames():
def get_toolchain():
return 'gcc_arm'

def _parse_specific_options(self, data):
""" Parse all specific setttings. """
data['common_flags'] = []
data['ld_flags'] = []
data['c_flags'] = []
data['cxx_flags'] = []
data['asm_flags'] = []
for k, v in data['misc'].items():
if type(v) is list:
if k not in data:
data[k] = []
data[k].extend(v)
else:
if k not in data:
data[k] = ''
data[k] = v

def _get_libs(self, project_data):
project_data['lib_paths'] =[]
project_data['libraries'] =[]
for lib in project_data['source_files_lib']:
head, tail = ntpath.split(lib)
file = tail
if (os.path.splitext(file)[1] != ".a"):
logging.debug("Found %s lib with non-valid extension (!=.a)" % file)
continue
else:
file = file.replace(".a","")
project_data['lib_paths'].append(head)
project_data['libraries'].append(file.replace("lib",''))

def export_workspace(self):
logger.debug("Makefile GCC ARM currently does not support workspaces")

def export_project(self):
""" Processes misc options specific for GCC ARM, and run generator """
generated_projects = copy.deepcopy(self.generated_projects)
generated_projects = deepcopy(self.generated_projects)
self.process_data_for_makefile(self.workspace)
generated_projects['path'], generated_projects['files']['makefile'] = self.gen_file_jinja('makefile_gcc.tmpl', self.workspace, 'Makefile', self.workspace['output_dir']['path'])
return generated_projects

def get_generated_project_files(self):
return {'path': self.workspace['path'], 'files': [self.workspace['files']['makefile']]}

def process_data_for_makefile(self, project_data):
#Flatten our dictionary, we don't need groups
for key in SOURCE_KEYS:
project_data[key] = list(chain(*project_data[key].values()))
self._get_libs(project_data)
self._parse_specific_options(project_data)

project_data['toolchain'] = 'arm-none-eabi-'
project_data['toolchain_bin_path'] = self.env_settings.get_env_settings('gcc')

pro_def = ProGenDef()

if pro_def.get_mcu_core(project_data['target'].lower()):
project_data['core'] = pro_def.get_mcu_core(project_data['target'].lower())[0]
else:
raise RuntimeError(
"Target: %s not found, Please add the target to https://github.com/project-generator/project_generator_definitions" % project_data['target'].lower())

# gcc arm is funny about cortex-m4f.
if project_data['core'] == 'cortex-m4f':
project_data['core'] = 'cortex-m4'

# change cortex-m0+ to cortex-m0plus
if project_data['core'] == 'cortex-m0+':
project_data['core'] = 'cortex-m0plus'

def build_project(self):
# cwd: relpath(join(project_path, ("gcc_arm" + project)))
# > make all
path = dirname(self.workspace['files']['makefile'])
logger.debug("Building GCC ARM project: %s" % path)

args = ['make', 'all']
logger.debug(args)

try:
ret_code = None
ret_code = subprocess.call(args, cwd=path)
except:
logger.error("Project: %s build error whilst calling make. Is it in your PATH?" % self.workspace['files']['makefile'])
return -1
else:
if ret_code != self.SUCCESSVALUE:
# Seems like something went wrong.
if ret_code < 3:
logger.error("Project: %s build failed with the status: %s" %
(self.ERRORLEVEL[ret_code], self.workspace['files']['makefile']))
else:
logger.error("Project: %s build failed with unknown error. Returned: %s" %
(ret_code, self.workspace['files']['makefile']))
return -1
else:
logger.info("Build succeeded with the status: %s" %
self.ERRORLEVEL[ret_code])
return 0
MakefileTool.process_data_for_makefile(self, project_data)
Loading