add cmake exporter for CLion use

pull/5476/head
Matthias L. Jugel 2017-11-10 22:23:03 +01:00
parent c2784c8962
commit 07b21abc75
4 changed files with 337 additions and 1 deletions

View File

@ -33,6 +33,7 @@ from tools.export import embitz, coide, kds, simplicity, atmelstudio, mcuxpresso
from tools.export import sw4stm32, e2studio, zip, cmsis, uvision, cdt, vscode
from tools.export import gnuarmeclipse
from tools.export import qtcreator
from tools.export import cmake
from tools.export import nb
from tools.targets import TARGET_NAMES
@ -63,7 +64,8 @@ EXPORTERS = {
'qtcreator': qtcreator.QtCreator,
'vscode_gcc_arm' : vscode.VSCodeGcc,
'vscode_iar' : vscode.VSCodeIAR,
'vscode_armc5' : vscode.VSCodeArmc5
'vscode_armc5' : vscode.VSCodeArmc5,
'cmake_gcc_arm': cmake.GccArm
}
ERROR_MESSAGE_UNSUPPORTED_TOOLCHAIN = """

View File

@ -0,0 +1,94 @@
# This file was automagically generated by mbed.org.
# If you would like to add your own targets, create a
# project.cmake file locally in your project directory.
CMAKE_MINIMUM_REQUIRED(VERSION 3.9)
SET(CMAKE_SYSTEM_NAME Generic)
#SET(CMAKE_SYSTEM_PROCESSOR arm)
SET(CMAKE_CROSSCOMPILING TRUE)
# force compiler settings
SET(CMAKE_C_COMPILER_WORKS TRUE)
SET(CMAKE_CXX_COMPILER_WORKS TRUE)
SET(CMAKE_ASM_COMPILER_INIT "{{asm}}")
SET(CMAKE_C_COMPILER_INIT "{{cc}}")
SET(CMAKE_CXX_COMPILER_INIT "{{cxx}}")
SET(CMAKE_CXX_LINK_EXECUTABLE "{{ld}}")
{% if pp -%}
SET(PREPROC "{{pp}}")
{%- endif %}
{% if hex_files %}
SET(SREC_CAT "srec_cat")
{%- endif %}
# here starts the project
PROJECT({{name}} C CXX ASM)
#SET(CMAKE_VERBOSE_MAKEFILE ON)
SET(CMAKE_C_FLAGS "{{cc_flags}} -include mbed_config.h")
SET(CMAKE_CXX_FLAGS "{{cxx_flags}} -include mbed_config.h")
SET(CMAKE_ASM_FLAGS "{{asm_flags}} -include mbed_config.h")
SET(CMAKE_LINKER_FLAGS "{{ld_flags}}")
SET(LD_SYS_LIBS "{{ld_sys_libs|join(" ")}}")
SET(ELF2BIN {{elf2bin}})
SET(CMAKE_EXE_LINKER_FLAGS "{{ld_flags}} {{link_script_option}} ${LD_SYS_LIBS}")
ADD_DEFINITIONS(
{% for d in symbols %}-D{{d}}
{% endfor %})
INCLUDE_DIRECTORIES(
{% for p in include_paths %}{{p}}
{% endfor %})
{% for libname,libsrcs in libs.items() %}
# target for library "{{libname}}"
ADD_LIBRARY({{libname}} STATIC EXCLUDE_FROM_ALL
{% for libsrc in libsrcs %}{{libsrc}}
{% endfor %})
{% endfor %}
# executable {{name}}
ADD_EXECUTABLE({{name}} EXCLUDE_FROM_ALL
{% for src in sources %}{{src}}
{% endfor %})
TARGET_LINK_LIBRARIES({{name}}
{% for libname in libs %}{{libname}}
{% endfor %})
##########################################################################
# mbed-cli specific targets
##########################################################################
# detect the build type and select the corresponding cli profile
SET(MBED_BUILD_PROFILE "")
STRING(TOLOWER ${CMAKE_BUILD_TYPE} LOWERCASE_CMAKE_BUILD_TYPE)
IF(LOWERCASE_CMAKE_BUILD_TYPE MATCHES debug)
SET(MBED_BUILD_PROFILE "mbed-os/tools/profiles/debug.json")
ELSEIF(LOWERCASE_CMAKE_BUILD_TYPE MATCHES relwithdebinfo)
SET(MBED_BUILD_PROFILE "mbed-os/tools/profiles/develop.json")
ELSEIF(LOWERCASE_CMAKE_BUILD_TYPE MATCHES release)
SET(MBED_BUILD_PROFILE "mbed-os/tools/profiles/release.json")
ELSEIF(LOWERCASE_CMAKE_BUILD_TYPE MATCHES minsizerel)
SET(MBED_BUILD_PROFILE "mbed-os/tools/profiles/release.json")
ELSE()
MESSAGE(WARNING "Build type '${CMAKE_BUILD_TYPE}' is unknown, using debug profile")
SET(MBED_BUILD_PROFILE "mbed-os/tools/profiles/debug.json")
ENDIF()
# optional custom target to build via mbed-cli
MESSAGE(STATUS "Creating target 01-{{name}} for mbed compilation...")
ADD_CUSTOM_TARGET(01-{{name}} ALL
COMMAND ${CMAKE_COMMAND} -E echo "mbed compile --build BUILD/${CMAKE_BUILD_TYPE} ${MBED_BUILD_PROFILE}"
COMMAND mbed compile --build BUILD/${CMAKE_BUILD_TYPE} --profile ${MBED_BUILD_PROFILE}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
SOURCES ${SOURCE_FILES} ${SYS_SOURCE_FILES})
IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/project.cmake)
INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/project.cmake)
ELSE()
MESSAGE(STATUS "Add a local project.cmake file to add your own targets.")
ENDIF()

View File

@ -0,0 +1,15 @@
# CLion CMakeLists.txt Generator
This exporter generates a CMakeLists.txt file that can be used to
develop mbed using [IntelliJ CLion](https://www.jetbrains.com/clion/).
It will not create a functional CMake build system that mimics the
mbed build system, but rather uses the mbed-cli itself to compile
the targets. The generated files help CLion to understand the
includes and dependencies of your code.
Run the following command to create/overwrite your CMakeLists.txt.
```
mbed export -i cmake_gcc_arm
```
> Run the command again if files or libraries have been added or removed.

View File

@ -0,0 +1,225 @@
"""
mbed SDK
Copyright (c) 2011-2016 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import re
import shutil
from os import remove
from os.path import splitext, basename, exists
from subprocess import Popen, PIPE
from jinja2.exceptions import TemplateNotFound
from tools.export.exporters import Exporter
from tools.utils import NotSupportedException
class CMake(Exporter):
"""Generic CMake template that mimics the behavior of the python build
system
"""
TEMPLATE = 'CMakeLists.txt'
MBED_CONFIG_HEADER_SUPPORTED = True
PREPROCESS_ASM = False
@classmethod
def is_target_supported(cls, target_name):
return True
def generate(self):
"""Generate the CMakefiles.txt
"""
self.resources.win_to_unix()
sources = set(self.resources.c_sources + \
self.resources.cpp_sources + \
self.resources.s_sources + \
self.resources.headers)
libnames = [l[:-4] for l in self.resources.lib_refs]
libs = {re.sub(r'^[.]/', '', l): sorted([f for f in sources if f.startswith(l)]) for l in libnames}
libs = {k: v for k, v in libs.items() if len(v) != 0}
srcs = sorted([f for f in sources if f not in [item for sublist in libs.values() for item in sublist]])
libraries = [self.prepare_lib(basename(lib)) for lib
in self.resources.libraries]
sys_libs = [self.prepare_sys_lib(lib) for lib
in self.toolchain.sys_libs]
ctx = {
'name': self.project_name,
'target': self.target,
'sources': srcs,
'libs': libs,
'libraries': libraries,
'ld_sys_libs': sys_libs,
'include_paths': sorted(list(set(self.resources.inc_dirs))),
'library_paths': sorted(self.resources.lib_dirs),
'linker_script': self.resources.linker_script,
'hex_files': self.resources.hex_files,
'ar': basename(self.toolchain.ar),
'cc': basename(self.toolchain.cc[0]),
'cc_flags': " ".join(self.toolchain.cc[1:]),
'cxx': basename(self.toolchain.cppc[0]),
'cxx_flags': " ".join(self.toolchain.cppc[1:]),
'asm': basename(self.toolchain.asm[0]),
'asm_flags': " ".join(self.toolchain.asm[1:]),
'symbols': self.toolchain.get_symbols(),
'ld': basename(self.toolchain.ld[0]),
'ld_flags': " ".join(self.toolchain.ld[1:]),
'elf2bin': basename(self.toolchain.elf2bin),
'link_script_ext': self.toolchain.LINKER_EXT,
'link_script_option': self.LINK_SCRIPT_OPTION,
'user_library_flag': self.USER_LIBRARY_FLAG,
'needs_asm_preproc': self.PREPROCESS_ASM,
}
if hasattr(self.toolchain, "preproc"):
ctx['pp'] = " ".join(["\'" + part + "\'" for part
in ([basename(self.toolchain.preproc[0])] +
self.toolchain.preproc[1:] +
self.toolchain.ld[1:])])
else:
ctx['pp'] = None
for templatefile in ['cmake/%s.tmpl' % self.TEMPLATE]:
try:
self.gen_file(templatefile, ctx, 'CMakeLists.txt')
break
except TemplateNotFound:
pass
else:
raise NotSupportedException("This make tool is in development")
@staticmethod
def build(project_name, log_name="build_log.txt", cleanup=True):
""" Build Make project """
# > Make -j
cmd = ["make", "-j"]
# Build the project
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
out, err = p.communicate()
ret_code = p.returncode
out_string = "=" * 10 + "STDOUT" + "=" * 10 + "\n"
out_string += out
out_string += "=" * 10 + "STDERR" + "=" * 10 + "\n"
out_string += err
if ret_code == 0:
out_string += "SUCCESS"
else:
out_string += "FAILURE"
print out_string
if log_name:
# Write the output to the log file
with open(log_name, 'w+') as f:
f.write(out_string)
# Cleanup the exported and built files
if cleanup:
remove("CMakeLists.txt")
remove(log_name)
# legacy .build directory cleaned if exists
if exists('.build'):
shutil.rmtree('.build')
if exists('BUILD'):
shutil.rmtree('BUILD')
if ret_code != 0:
# Seems like something went wrong.
return -1
else:
return 0
class GccArm(CMake):
"""GCC ARM specific cmake target"""
NAME = 'CMake-GCC-ARM'
TOOLCHAIN = "GCC_ARM"
LINK_SCRIPT_OPTION = "-T"
USER_LIBRARY_FLAG = "-L"
@staticmethod
def prepare_lib(libname):
if "lib" == libname[:3]:
libname = libname[3:-2]
return "-l" + libname
@staticmethod
def prepare_sys_lib(libname):
return "-l" + libname
# class Arm(CMake):
# """ARM Compiler generic cmake target"""
# LINK_SCRIPT_OPTION = "--scatter"
# USER_LIBRARY_FLAG = "--userlibpath "
#
# @staticmethod
# def prepare_lib(libname):
# return libname
#
# @staticmethod
# def prepare_sys_lib(libname):
# return libname
#
# def generate(self):
# if self.resources.linker_script:
# new_script = self.toolchain.correct_scatter_shebang(
# self.resources.linker_script)
# if new_script is not self.resources.linker_script:
# self.resources.linker_script = new_script
# self.generated_files.append(new_script)
# return super(Arm, self).generate()
#
#
# class Armc5(Arm):
# """ARM Compiler 5 (armcc) specific makefile target"""
# NAME = 'CMake-ARMc5'
# TOOLCHAIN = "ARM"
# PREPROCESS_ASM = True
#
#
# class Armc6(Arm):
# """ARM Compiler 6 (armclang) specific generic makefile target"""
# NAME = 'CMake-ARMc6'
# TOOLCHAIN = "ARMC6"
#
#
# class IAR(CMake):
# """IAR specific cmake target"""
# NAME = 'CMake-IAR'
# TOOLCHAIN = "IAR"
# LINK_SCRIPT_OPTION = "--config"
# USER_LIBRARY_FLAG = "-L"
#
# @staticmethod
# def prepare_lib(libname):
# if "lib" == libname[:3]:
# libname = libname[3:]
# return "-l" + splitext(libname)[0]
#
# @staticmethod
# def prepare_sys_lib(libname):
# if "lib" == libname[:3]:
# libname = libname[3:]
# return "-l" + splitext(libname)[0]