Skip to content

Commit 0deb6c2

Browse files
committed
feat: generate prototypes for .ino files
Required implementing a ctags downloaded, much like for GCC and the CMSIS.
1 parent 4615254 commit 0deb6c2

7 files changed

+165
-20
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,4 @@ __pycache__/
3636
# CMake-related
3737
/CMSIS_5/
3838
/xpack-arm-none-eabi-gcc/
39+
/ctags

CMakeLists.txt

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.13)
33
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
44

55
include(ensure_CMSIS)
6+
include(ensure_ctags)
67

78
project("Arduino_Core_STM32" CXX C ASM)
89

@@ -23,9 +24,13 @@ set(BUILD_CORE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cores/arduino")
2324
set(BUILD_SYSTEM_PATH "${CMAKE_CURRENT_SOURCE_DIR}/system")
2425
set(BUILD_LIB_PATH "${CMAKE_CURRENT_SOURCE_DIR}/libraries")
2526
set(CMSIS5_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_5" CACHE STRING "Path to CMSIS_5")
27+
set(CTAGS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/ctags" CACHE STRING "Folder to find/put ctags in")
2628

2729
option(AUTODL_CMSIS OFF)
30+
option(AUTODL_CTAGS OFF)
31+
2832
ensure_CMSIS(${CMSIS5_PATH} ${AUTODL_CMSIS})
33+
ensure_ctags(${CTAGS_PATH} ${AUTODL_CTAGS})
2934

3035
add_library(base_config INTERFACE)
3136

cmake/ensure_binutils.cmake

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function(ensure_binutils XPACK_PATH AUTODL_XPACK)
2828
elseif (${HOST_OS} STREQUAL "Windows")
2929
set(OSCODE "win32")
3030
set(ARCHIVE_EXT ".zip")
31-
elseif (${HOST_OS} STREQUAL "Darwin ")
31+
elseif (${HOST_OS} STREQUAL "Darwin")
3232
set(OSCODE "darwin")
3333
set(ARCHIVE_EXT ".tar.gz")
3434
endif()

cmake/ensure_ctags.cmake

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
include(FetchContent)
2+
3+
function(ensure_ctags CTAGS_PATH AUTODL_CTAGS)
4+
find_program(CTAGS ctags PATHS ${CTAGS_PATH})
5+
if(EXISTS ${CTAGS})
6+
return()
7+
endif()
8+
9+
10+
cmake_host_system_information(
11+
RESULT HOSTINFO
12+
QUERY OS_NAME OS_PLATFORM
13+
)
14+
list(GET HOSTINFO 0 HOST_OS)
15+
list(GET HOSTINFO 1 HOST_ARCH)
16+
17+
unset(CPUCODE)
18+
string(TOUPPER ${HOST_ARCH} HOST_ARCH)
19+
if (${HOST_ARCH} MATCHES "^(AMD64|X86_64|x64)$")
20+
set(CPUCODE "x86_64")
21+
elseif (${HOST_ARCH} MATCHES "^(ARM|ARM64)$")
22+
# not sure there, am I specific enough?
23+
set(CPUCODE "armv6")
24+
elseif (${HOST_ARCH} MATCHES "^(I386|IA32|x86|i686)$")
25+
set(CPUCODE "i686")
26+
endif()
27+
28+
unset(OSCODE)
29+
unset(ARCHIVE_EXT)
30+
if (${HOST_OS} STREQUAL "Linux")
31+
if(${CPUCODE} STREQUAL "armv6")
32+
set(OSCODE "linux-gnueabihf")
33+
# ... I guess? Is there any further check to perform?
34+
else()
35+
set(OSCODE "pc-linux-gnu")
36+
endif()
37+
set(ARCHIVE_EXT ".tar.bz2")
38+
elseif (${HOST_OS} STREQUAL "Windows")
39+
if(${CPUCODE} MATCHES "i686|x86_64")
40+
# ctags supports only 32-bit for Windows
41+
set(CPUCODE "i686")
42+
set(OSCODE "mingw32")
43+
set(ARCHIVE_EXT ".zip")
44+
endif()
45+
elseif (${HOST_OS} STREQUAL "Darwin")
46+
if(${CPUCODE} STREQUAL "x86_64")
47+
set(OSCODE "apple-darwin")
48+
set(ARCHIVE_EXT ".zip")
49+
endif()
50+
endif()
51+
52+
if (DEFINED OSCODE AND DEFINED CPUCODE AND DEFINED ARCHIVE_EXT)
53+
if (${AUTODL_CTAGS})
54+
# the SHA512 file is of the form "hash_in_hexa filename"
55+
file(DOWNLOAD
56+
"https://github.com/arduino/ctags/releases/download/5.8-arduino11/ctags-5.8-arduino11-${CPUCODE}-${OSCODE}${ARCHIVE_EXT}.sha512"
57+
${CMAKE_CURRENT_BINARY_DIR}/ctags_sha512.txt
58+
)
59+
file(READ ${CMAKE_CURRENT_BINARY_DIR}/ctags_sha512.txt CHECKSUM_FULLTEXT)
60+
string(SUBSTRING "${CHECKSUM_FULLTEXT}" 0 128 CHECKSUM) # keep just the hash; 512 bits make 128 hex caracters
61+
62+
FetchContent_Declare(
63+
ctags
64+
SOURCE_DIR ${CTAGS_PATH}
65+
URL "https://github.com/arduino/ctags/releases/download/5.8-arduino11/ctags-5.8-arduino11-${CPUCODE}-${OSCODE}${ARCHIVE_EXT}"
66+
URL_HASH SHA512=${CHECKSUM}
67+
)
68+
if (NOT EXISTS ${CTAGS_PATH})
69+
message(STATUS "Downloading ctags...")
70+
FetchContent_MakeAvailable(ctags)
71+
endif()
72+
else() # supported platform, no autodl
73+
message(WARNING
74+
"
75+
Could not find Arduino's ctags. This tool is used to convert sketches to proper C++.
76+
Please install it and make it available in your $PATH, or let me make my private install using the AUTODL_CTAGS option.
77+
(You can ignore this warning if you understand the implications regarding the structure of your sketch.)
78+
"
79+
)
80+
endif()
81+
else() # unsupported platform
82+
message(WARNING
83+
"
84+
Could not find Arduino's ctags. This tool is used to convert sketches to proper C++.
85+
Please install it and make it available in your $PATH: https://github.com/arduino/ctags/releases/latest
86+
(You can ignore this warning if you understand the implications regarding the structure of your sketch.)
87+
"
88+
)
89+
endif()
90+
91+
find_program(CTAGS ctags PATHS ${CTAGS_PATH})
92+
endfunction()

cmake/handle_sketch.cmake

+1-19
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,7 @@ set(SCRIPTS_FOLDER ${CMAKE_CURRENT_LIST_DIR}/../scripts)
77
function(handle_sketch TGTNAME MAPFILE SRCLIST)
88
# TODO: have the sketch folder in the include path of base_config
99

10-
set(CURATED_SRC "")
11-
foreach(SRCFILE IN LISTS SRCLIST)
12-
if (${SRCFILE} MATCHES "\.ino$")
13-
configure_file(
14-
${SRCFILE}
15-
${SRCFILE}.cpp
16-
COPYONLY
17-
)
18-
set_source_files_properties(${SRCFILE}.cpp
19-
PROPERTIES
20-
COMPILE_OPTIONS "-include;Arduino.h"
21-
)
22-
list(APPEND CURATED_SRC ${SRCFILE}.cpp)
23-
else()
24-
list(APPEND CURATED_SRC ${SRCFILE})
25-
endif()
26-
endforeach()
27-
28-
add_executable(${TGTNAME} EXCLUDE_FROM_ALL ${CURATED_SRC})
10+
add_executable(${TGTNAME} EXCLUDE_FROM_ALL ${SRCLIST})
2911
target_link_libraries(${TGTNAME} stm32_runtime)
3012
target_link_options(${TGTNAME} PRIVATE
3113
LINKER:-Map,${MAPFILE}

cmake/sketch_preprocess_sources.cmake

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
cmake_minimum_required(VERSION 3.20) # cmake_path
2+
3+
set(SCRIPTS_FOLDER ${CMAKE_CURRENT_LIST_DIR}/../scripts)
4+
5+
function(sketch_preprocess_sources)
6+
cmake_parse_arguments(PARSE_ARGV 0 SPC "" "OUTPUT_VARIABLE" "SOURCES")
7+
set(SRCLIST "")
8+
foreach(SRCFILE IN LISTS SPC_SOURCES)
9+
if (${SRCFILE} MATCHES "\.ino$")
10+
cmake_path(GET SRCFILE FILENAME SRC_BASE_NAME)
11+
12+
configure_file(
13+
${SRCFILE}
14+
${CMAKE_CURRENT_BINARY_DIR}/${SRC_BASE_NAME}.cpp
15+
COPYONLY
16+
)
17+
18+
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${SRC_BASE_NAME}.h
19+
COMMAND ${CTAGS} -u --language-force=c++ -f ${CMAKE_CURRENT_BINARY_DIR}/${SRC_BASE_NAME}.ctags --c++-kinds=svpf --fields=KSTtzns --line-directives ${CMAKE_CURRENT_BINARY_DIR}/${SRC_BASE_NAME}.cpp
20+
COMMAND ${PYTHON3} ${SCRIPTS_FOLDER}/generate_header.py -i ${CMAKE_CURRENT_BINARY_DIR}/${SRC_BASE_NAME}.ctags -o ${CMAKE_CURRENT_BINARY_DIR}/${SRC_BASE_NAME}.h
21+
22+
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${SRC_BASE_NAME}.cpp
23+
BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${SRC_BASE_NAME}.ctags
24+
VERBATIM
25+
)
26+
27+
set_source_files_properties(${SRCFILE}.cpp
28+
PROPERTIES
29+
COMPILE_OPTIONS "-include;Arduino.h;-include;${SRCFILE}.h"
30+
OBJECT_DEPENDS "${SRCFILE}.h"
31+
)
32+
list(APPEND SRCLIST ${SRCFILE}.cpp)
33+
else()
34+
list(APPEND SRCLIST ${SRCFILE})
35+
endif()
36+
endforeach()
37+
set(${SPC_OUTPUT_VARIABLE} ${SRCLIST} PARENT_SCOPE)
38+
endfunction()

scripts/generate_header.py

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import pathlib
5+
import subprocess
6+
7+
parser = argparse.ArgumentParser()
8+
parser.add_argument("--source", "-i", type=pathlib.Path, required=True, help="ctags's output")
9+
parser.add_argument("--out", "-o", type=pathlib.Path, required=True, help="header to generate")
10+
11+
shargs = parser.parse_args()
12+
13+
14+
with open(shargs.source, "r") as infile :
15+
with open(shargs.out, "w") as outfile :
16+
for line in infile :
17+
line = line.strip()
18+
if line.startswith("!") or not line :
19+
continue
20+
21+
fields = line.split("\t")
22+
kind = fields[3].split(":", 1)[1]
23+
if kind == "function":
24+
symname = fields[0]
25+
signature = fields[5].split(":", 1)[1]
26+
rtype = fields[6].split(":", 1)[1]
27+
print(f"{rtype} {symname}{signature};", file=outfile)

0 commit comments

Comments
 (0)