Skip to content

Commit 07b21ab

Browse files
committed
add cmake exporter for CLion use
1 parent c2784c8 commit 07b21ab

File tree

4 files changed

+337
-1
lines changed

4 files changed

+337
-1
lines changed

tools/export/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
from tools.export import sw4stm32, e2studio, zip, cmsis, uvision, cdt, vscode
3434
from tools.export import gnuarmeclipse
3535
from tools.export import qtcreator
36+
from tools.export import cmake
3637
from tools.export import nb
3738
from tools.targets import TARGET_NAMES
3839

@@ -63,7 +64,8 @@
6364
'qtcreator': qtcreator.QtCreator,
6465
'vscode_gcc_arm' : vscode.VSCodeGcc,
6566
'vscode_iar' : vscode.VSCodeIAR,
66-
'vscode_armc5' : vscode.VSCodeArmc5
67+
'vscode_armc5' : vscode.VSCodeArmc5,
68+
'cmake_gcc_arm': cmake.GccArm
6769
}
6870

6971
ERROR_MESSAGE_UNSUPPORTED_TOOLCHAIN = """
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# This file was automagically generated by mbed.org.
2+
# If you would like to add your own targets, create a
3+
# project.cmake file locally in your project directory.
4+
5+
CMAKE_MINIMUM_REQUIRED(VERSION 3.9)
6+
SET(CMAKE_SYSTEM_NAME Generic)
7+
#SET(CMAKE_SYSTEM_PROCESSOR arm)
8+
SET(CMAKE_CROSSCOMPILING TRUE)
9+
10+
# force compiler settings
11+
SET(CMAKE_C_COMPILER_WORKS TRUE)
12+
SET(CMAKE_CXX_COMPILER_WORKS TRUE)
13+
14+
SET(CMAKE_ASM_COMPILER_INIT "{{asm}}")
15+
SET(CMAKE_C_COMPILER_INIT "{{cc}}")
16+
SET(CMAKE_CXX_COMPILER_INIT "{{cxx}}")
17+
SET(CMAKE_CXX_LINK_EXECUTABLE "{{ld}}")
18+
19+
{% if pp -%}
20+
SET(PREPROC "{{pp}}")
21+
{%- endif %}
22+
{% if hex_files %}
23+
SET(SREC_CAT "srec_cat")
24+
{%- endif %}
25+
26+
# here starts the project
27+
PROJECT({{name}} C CXX ASM)
28+
#SET(CMAKE_VERBOSE_MAKEFILE ON)
29+
30+
SET(CMAKE_C_FLAGS "{{cc_flags}} -include mbed_config.h")
31+
SET(CMAKE_CXX_FLAGS "{{cxx_flags}} -include mbed_config.h")
32+
SET(CMAKE_ASM_FLAGS "{{asm_flags}} -include mbed_config.h")
33+
SET(CMAKE_LINKER_FLAGS "{{ld_flags}}")
34+
35+
SET(LD_SYS_LIBS "{{ld_sys_libs|join(" ")}}")
36+
SET(ELF2BIN {{elf2bin}})
37+
38+
SET(CMAKE_EXE_LINKER_FLAGS "{{ld_flags}} {{link_script_option}} ${LD_SYS_LIBS}")
39+
40+
ADD_DEFINITIONS(
41+
{% for d in symbols %}-D{{d}}
42+
{% endfor %})
43+
INCLUDE_DIRECTORIES(
44+
{% for p in include_paths %}{{p}}
45+
{% endfor %})
46+
47+
{% for libname,libsrcs in libs.items() %}
48+
# target for library "{{libname}}"
49+
ADD_LIBRARY({{libname}} STATIC EXCLUDE_FROM_ALL
50+
{% for libsrc in libsrcs %}{{libsrc}}
51+
{% endfor %})
52+
{% endfor %}
53+
54+
# executable {{name}}
55+
ADD_EXECUTABLE({{name}} EXCLUDE_FROM_ALL
56+
{% for src in sources %}{{src}}
57+
{% endfor %})
58+
TARGET_LINK_LIBRARIES({{name}}
59+
{% for libname in libs %}{{libname}}
60+
{% endfor %})
61+
62+
##########################################################################
63+
# mbed-cli specific targets
64+
##########################################################################
65+
66+
# detect the build type and select the corresponding cli profile
67+
SET(MBED_BUILD_PROFILE "")
68+
STRING(TOLOWER ${CMAKE_BUILD_TYPE} LOWERCASE_CMAKE_BUILD_TYPE)
69+
IF(LOWERCASE_CMAKE_BUILD_TYPE MATCHES debug)
70+
SET(MBED_BUILD_PROFILE "mbed-os/tools/profiles/debug.json")
71+
ELSEIF(LOWERCASE_CMAKE_BUILD_TYPE MATCHES relwithdebinfo)
72+
SET(MBED_BUILD_PROFILE "mbed-os/tools/profiles/develop.json")
73+
ELSEIF(LOWERCASE_CMAKE_BUILD_TYPE MATCHES release)
74+
SET(MBED_BUILD_PROFILE "mbed-os/tools/profiles/release.json")
75+
ELSEIF(LOWERCASE_CMAKE_BUILD_TYPE MATCHES minsizerel)
76+
SET(MBED_BUILD_PROFILE "mbed-os/tools/profiles/release.json")
77+
ELSE()
78+
MESSAGE(WARNING "Build type '${CMAKE_BUILD_TYPE}' is unknown, using debug profile")
79+
SET(MBED_BUILD_PROFILE "mbed-os/tools/profiles/debug.json")
80+
ENDIF()
81+
82+
# optional custom target to build via mbed-cli
83+
MESSAGE(STATUS "Creating target 01-{{name}} for mbed compilation...")
84+
ADD_CUSTOM_TARGET(01-{{name}} ALL
85+
COMMAND ${CMAKE_COMMAND} -E echo "mbed compile --build BUILD/${CMAKE_BUILD_TYPE} ${MBED_BUILD_PROFILE}"
86+
COMMAND mbed compile --build BUILD/${CMAKE_BUILD_TYPE} --profile ${MBED_BUILD_PROFILE}
87+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
88+
SOURCES ${SOURCE_FILES} ${SYS_SOURCE_FILES})
89+
90+
IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/project.cmake)
91+
INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/project.cmake)
92+
ELSE()
93+
MESSAGE(STATUS "Add a local project.cmake file to add your own targets.")
94+
ENDIF()

tools/export/cmake/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# CLion CMakeLists.txt Generator
2+
3+
This exporter generates a CMakeLists.txt file that can be used to
4+
develop mbed using [IntelliJ CLion](https://www.jetbrains.com/clion/).
5+
6+
It will not create a functional CMake build system that mimics the
7+
mbed build system, but rather uses the mbed-cli itself to compile
8+
the targets. The generated files help CLion to understand the
9+
includes and dependencies of your code.
10+
11+
Run the following command to create/overwrite your CMakeLists.txt.
12+
```
13+
mbed export -i cmake_gcc_arm
14+
```
15+
> Run the command again if files or libraries have been added or removed.

tools/export/cmake/__init__.py

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
"""
2+
mbed SDK
3+
Copyright (c) 2011-2016 ARM Limited
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
"""
17+
import re
18+
import shutil
19+
from os import remove
20+
from os.path import splitext, basename, exists
21+
from subprocess import Popen, PIPE
22+
23+
from jinja2.exceptions import TemplateNotFound
24+
25+
from tools.export.exporters import Exporter
26+
from tools.utils import NotSupportedException
27+
28+
29+
class CMake(Exporter):
30+
"""Generic CMake template that mimics the behavior of the python build
31+
system
32+
"""
33+
34+
TEMPLATE = 'CMakeLists.txt'
35+
36+
MBED_CONFIG_HEADER_SUPPORTED = True
37+
38+
PREPROCESS_ASM = False
39+
40+
@classmethod
41+
def is_target_supported(cls, target_name):
42+
return True
43+
44+
def generate(self):
45+
"""Generate the CMakefiles.txt
46+
"""
47+
self.resources.win_to_unix()
48+
49+
sources = set(self.resources.c_sources + \
50+
self.resources.cpp_sources + \
51+
self.resources.s_sources + \
52+
self.resources.headers)
53+
54+
libnames = [l[:-4] for l in self.resources.lib_refs]
55+
libs = {re.sub(r'^[.]/', '', l): sorted([f for f in sources if f.startswith(l)]) for l in libnames}
56+
libs = {k: v for k, v in libs.items() if len(v) != 0}
57+
srcs = sorted([f for f in sources if f not in [item for sublist in libs.values() for item in sublist]])
58+
59+
libraries = [self.prepare_lib(basename(lib)) for lib
60+
in self.resources.libraries]
61+
sys_libs = [self.prepare_sys_lib(lib) for lib
62+
in self.toolchain.sys_libs]
63+
64+
ctx = {
65+
'name': self.project_name,
66+
'target': self.target,
67+
'sources': srcs,
68+
'libs': libs,
69+
'libraries': libraries,
70+
'ld_sys_libs': sys_libs,
71+
'include_paths': sorted(list(set(self.resources.inc_dirs))),
72+
'library_paths': sorted(self.resources.lib_dirs),
73+
'linker_script': self.resources.linker_script,
74+
'hex_files': self.resources.hex_files,
75+
'ar': basename(self.toolchain.ar),
76+
'cc': basename(self.toolchain.cc[0]),
77+
'cc_flags': " ".join(self.toolchain.cc[1:]),
78+
'cxx': basename(self.toolchain.cppc[0]),
79+
'cxx_flags': " ".join(self.toolchain.cppc[1:]),
80+
'asm': basename(self.toolchain.asm[0]),
81+
'asm_flags': " ".join(self.toolchain.asm[1:]),
82+
'symbols': self.toolchain.get_symbols(),
83+
'ld': basename(self.toolchain.ld[0]),
84+
'ld_flags': " ".join(self.toolchain.ld[1:]),
85+
'elf2bin': basename(self.toolchain.elf2bin),
86+
'link_script_ext': self.toolchain.LINKER_EXT,
87+
'link_script_option': self.LINK_SCRIPT_OPTION,
88+
'user_library_flag': self.USER_LIBRARY_FLAG,
89+
'needs_asm_preproc': self.PREPROCESS_ASM,
90+
}
91+
92+
if hasattr(self.toolchain, "preproc"):
93+
ctx['pp'] = " ".join(["\'" + part + "\'" for part
94+
in ([basename(self.toolchain.preproc[0])] +
95+
self.toolchain.preproc[1:] +
96+
self.toolchain.ld[1:])])
97+
else:
98+
ctx['pp'] = None
99+
100+
for templatefile in ['cmake/%s.tmpl' % self.TEMPLATE]:
101+
try:
102+
self.gen_file(templatefile, ctx, 'CMakeLists.txt')
103+
break
104+
except TemplateNotFound:
105+
pass
106+
else:
107+
raise NotSupportedException("This make tool is in development")
108+
109+
@staticmethod
110+
def build(project_name, log_name="build_log.txt", cleanup=True):
111+
""" Build Make project """
112+
# > Make -j
113+
cmd = ["make", "-j"]
114+
115+
# Build the project
116+
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
117+
out, err = p.communicate()
118+
ret_code = p.returncode
119+
120+
out_string = "=" * 10 + "STDOUT" + "=" * 10 + "\n"
121+
out_string += out
122+
out_string += "=" * 10 + "STDERR" + "=" * 10 + "\n"
123+
out_string += err
124+
125+
if ret_code == 0:
126+
out_string += "SUCCESS"
127+
else:
128+
out_string += "FAILURE"
129+
130+
print out_string
131+
132+
if log_name:
133+
# Write the output to the log file
134+
with open(log_name, 'w+') as f:
135+
f.write(out_string)
136+
137+
# Cleanup the exported and built files
138+
if cleanup:
139+
remove("CMakeLists.txt")
140+
remove(log_name)
141+
# legacy .build directory cleaned if exists
142+
if exists('.build'):
143+
shutil.rmtree('.build')
144+
if exists('BUILD'):
145+
shutil.rmtree('BUILD')
146+
147+
if ret_code != 0:
148+
# Seems like something went wrong.
149+
return -1
150+
else:
151+
return 0
152+
153+
154+
class GccArm(CMake):
155+
"""GCC ARM specific cmake target"""
156+
NAME = 'CMake-GCC-ARM'
157+
TOOLCHAIN = "GCC_ARM"
158+
LINK_SCRIPT_OPTION = "-T"
159+
USER_LIBRARY_FLAG = "-L"
160+
161+
@staticmethod
162+
def prepare_lib(libname):
163+
if "lib" == libname[:3]:
164+
libname = libname[3:-2]
165+
return "-l" + libname
166+
167+
@staticmethod
168+
def prepare_sys_lib(libname):
169+
return "-l" + libname
170+
171+
172+
# class Arm(CMake):
173+
# """ARM Compiler generic cmake target"""
174+
# LINK_SCRIPT_OPTION = "--scatter"
175+
# USER_LIBRARY_FLAG = "--userlibpath "
176+
#
177+
# @staticmethod
178+
# def prepare_lib(libname):
179+
# return libname
180+
#
181+
# @staticmethod
182+
# def prepare_sys_lib(libname):
183+
# return libname
184+
#
185+
# def generate(self):
186+
# if self.resources.linker_script:
187+
# new_script = self.toolchain.correct_scatter_shebang(
188+
# self.resources.linker_script)
189+
# if new_script is not self.resources.linker_script:
190+
# self.resources.linker_script = new_script
191+
# self.generated_files.append(new_script)
192+
# return super(Arm, self).generate()
193+
#
194+
#
195+
# class Armc5(Arm):
196+
# """ARM Compiler 5 (armcc) specific makefile target"""
197+
# NAME = 'CMake-ARMc5'
198+
# TOOLCHAIN = "ARM"
199+
# PREPROCESS_ASM = True
200+
#
201+
#
202+
# class Armc6(Arm):
203+
# """ARM Compiler 6 (armclang) specific generic makefile target"""
204+
# NAME = 'CMake-ARMc6'
205+
# TOOLCHAIN = "ARMC6"
206+
#
207+
#
208+
# class IAR(CMake):
209+
# """IAR specific cmake target"""
210+
# NAME = 'CMake-IAR'
211+
# TOOLCHAIN = "IAR"
212+
# LINK_SCRIPT_OPTION = "--config"
213+
# USER_LIBRARY_FLAG = "-L"
214+
#
215+
# @staticmethod
216+
# def prepare_lib(libname):
217+
# if "lib" == libname[:3]:
218+
# libname = libname[3:]
219+
# return "-l" + splitext(libname)[0]
220+
#
221+
# @staticmethod
222+
# def prepare_sys_lib(libname):
223+
# if "lib" == libname[:3]:
224+
# libname = libname[3:]
225+
# return "-l" + splitext(libname)[0]

0 commit comments

Comments
 (0)