Skip to content

Commit bf50036

Browse files
committed
Set compiler ID to GNU for XC16.
This enables CMake's handling of C standards and features.
1 parent d95718f commit bf50036

File tree

6 files changed

+190
-81
lines changed

6 files changed

+190
-81
lines changed

Modules/MicrochipBin2Hex.cmake

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#=============================================================================
2+
# Copyright 2016 Sam Hanes
3+
#
4+
# Distributed under the OSI-approved BSD License (the "License");
5+
# see accompanying file COPYING.txt for details.
6+
#
7+
# This software is distributed WITHOUT ANY WARRANTY; without even the
8+
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9+
# See the License for more information.
10+
#=============================================================================
11+
# (To distribute this file outside of CMake-Microchip,
12+
# substitute the full License text for the above reference.)
13+
14+
15+
function(bin2hex target)
16+
find_program(MICROCHIP_BIN2HEX
17+
NAMES ${_CMAKE_TOOLCHAIN_PREFIX}bin2hex bin2hex
18+
HINTS ${_CMAKE_TOOLCHAIN_LOCATION}
19+
)
20+
21+
if(NOT MICROCHIP_BIN2HEX)
22+
message(SEND_ERROR "No bin2hex program was found")
23+
endif()
24+
25+
function(get_target_property_fallback var target)
26+
set(result NOTFOUND)
27+
foreach(property ${ARGN})
28+
get_target_property(result ${target} ${property})
29+
if(result)
30+
break()
31+
endif()
32+
endforeach()
33+
set(${var} ${result} PARENT_SCOPE)
34+
endfunction()
35+
36+
get_target_property_fallback(in_f ${target}
37+
RUNTIME_OUTPUT_NAME
38+
OUTPUT_NAME
39+
NAME
40+
)
41+
42+
get_target_property_fallback(dir ${target}
43+
RUNTIME_OUTPUT_DIRECTORY
44+
BINARY_DIR
45+
)
46+
47+
get_filename_component(out_f ${in_f} NAME_WE)
48+
set(out_f "${out_f}.hex")
49+
50+
add_custom_command(
51+
TARGET ${target} POST_BUILD
52+
WORKING_DIRECTORY ${dir}
53+
COMMAND "${MICROCHIP_BIN2HEX}" "${in_f}"
54+
BYPRODUCTS ${dir}/${out_f}
55+
VERBATIM
56+
)
57+
58+
set_property(DIRECTORY APPEND
59+
PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
60+
${dir}/${out_f}
61+
)
62+
endfunction()

Modules/Platform/MicrochipMCU-C-XC16.cmake

Lines changed: 77 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -27,97 +27,93 @@ if(NOT EXISTS ${MICROCHIP_XC16_PATH})
2727
)
2828
endif()
2929

30-
# ensure that only the cross toolchain is searched for
31-
# tools, libraries, include files, and other similar things
3230
set(CMAKE_FIND_ROOT_PATH ${MICROCHIP_XC16_PATH})
33-
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
34-
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
35-
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
36-
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
37-
38-
# set up the toolchain executables
39-
find_program(CMAKE_C_COMPILER xc16-gcc)
40-
find_program(CMAKE_AR xc16-ar)
41-
find_program(CMAKE_LINKER xc16-ld)
42-
find_program(CMAKE_NM xc16-nm)
43-
find_program(CMAKE_OBJDUMP xc16-objdump)
44-
find_program(CMAKE_RANLIB xc16-ranlib)
45-
find_program(CMAKE_STRIP xc16-strip)
46-
find_program(XC16_BIN2HEX xc16-bin2hex)
47-
48-
# verify the comiler was found
49-
if(NOT CMAKE_C_COMPILER)
50-
message(FATAL_ERROR
51-
"XC16 path '${XC16_PATH}'"
52-
" does not contain an XC16 compiler"
53-
)
54-
endif()
55-
5631

57-
# verify that the MCU is supported
58-
set(MICROCHIP_XC16_LINKER_SCRIPT "p${MICROCHIP_MCU_MODEL}.gld")
59-
set(MICROCHIP_XC16_SUPPORT_DIR
60-
"${MICROCHIP_XC16_PATH}/support/${MICROCHIP_MCU_FAMILY}"
61-
)
62-
set(MICROCHIP_XC16_GLD_PATH
63-
"${MICROCHIP_XC16_SUPPORT_DIR}/gld/${MICROCHIP_XC16_LINKER_SCRIPT}"
64-
)
65-
if(NOT EXISTS ${MICROCHIP_XC16_GLD_PATH})
66-
message(SEND_ERROR
67-
"MCU '${MICROCHIP_MCU}' is not supported: linker script"
68-
" '${MICROCHIP_XC16_GLD_PATH}' does not exist."
69-
)
70-
endif()
7132

7233

73-
add_compile_options(
74-
"-mcpu=${MICROCHIP_MCU_MODEL}"
75-
)
34+
# Unfortunately the normal CMake compiler detection process doesn't work
35+
# with XC16. It functions by compiling a file which uses preprocessor
36+
# conditionals to determine the compiler type and version and puts that
37+
# information in string literals, then running `strings` on the output
38+
# file and parsing out the detected values. That fails for XC16 because
39+
# string literals are not packed contiguously and therefore `strings`
40+
# can't find them.
41+
#
42+
# In intermediate object files, XC16 handles character literals as
43+
# 16-bit integers and string literals as arrays of character literals.
44+
# The strings therefore appear in the file with a zero byte after each
45+
# character. See the "MPLAB XC16 C Compiler User's Guide" (DS50002071E)
46+
# section 8.9 "Literal Constant Types and Formats".
47+
#
48+
# In the final executable file that issue is resolved as by that point
49+
# the compiler has optimized the 16-bit character literals down to 8-bit
50+
# values. `strings` still doesn't work, however. Program memory on the
51+
# 16-bit MCUs uses 24-bit words but is addressed on 16-bit boundaries.
52+
# Each program word therefore has an extra addressable byte which
53+
# doesn't actually exist. In the executable file that byte is included
54+
# and always zero, so string literals are written as groups of three
55+
# characters separated by zero bytes.
56+
#
57+
#
58+
# We therefore have to implement compiler version detection ourselves.
59+
# Fortunately that's quite easy as we know we're dealing with XC16 and
60+
# it has a `--version` switch that produces both the GCC anc XC16
61+
# version numbers. We still allow CMake's feature detection and test
62+
# routines to run as they still find some useful information.
7663

77-
string(APPEND CMAKE_C_LINK_FLAGS
78-
" -mcpu=${MICROCHIP_MCU_MODEL}"
79-
" -Wl,--script,${MICROCHIP_XC16_LINKER_SCRIPT}"
80-
)
8164

65+
find_program(CMAKE_C_COMPILER "xc16-gcc")
8266

83-
# adds an Intel HEX conversion to the given target
84-
function(bin2hex target)
85-
function(get_target_property_fallback var target)
86-
set(result NOTFOUND)
87-
foreach(property ${ARGN})
88-
get_target_property(result ${target} ${property})
89-
if(result)
90-
break()
91-
endif()
92-
endforeach()
93-
set(${var} ${result} PARENT_SCOPE)
94-
endfunction()
95-
96-
get_target_property_fallback(in_f ${target}
97-
RUNTIME_OUTPUT_NAME
98-
OUTPUT_NAME
99-
NAME
100-
)
10167

102-
get_target_property_fallback(dir ${target}
103-
RUNTIME_OUTPUT_DIRECTORY
104-
BINARY_DIR
105-
)
68+
# bypass CMake compiler detection
69+
set(CMAKE_C_COMPILER_ID_RUN 1)
10670

107-
get_filename_component(out_f ${in_f} NAME_WE)
108-
set(out_f "${out_f}.hex")
71+
# set the compiler ID manually
72+
set(CMAKE_C_COMPILER_ID GNU)
73+
set(MICROCHIP_C_COMPILER_ID XC16)
74+
set(CMAKE_COMPILER_IS_GNUCC 1)
10975

110-
add_custom_command(
111-
TARGET ${target} POST_BUILD
112-
WORKING_DIRECTORY ${dir}
113-
COMMAND ${XC16_BIN2HEX} ${in_f}
114-
COMMENT "Creating HEX for ${target}"
115-
BYPRODUCTS ${dir}/${out_f}
116-
VERBATIM
76+
# call the compiler to check its version
77+
function(_xc16_get_version)
78+
execute_process(
79+
COMMAND "${CMAKE_C_COMPILER}" "--version"
80+
OUTPUT_VARIABLE output
81+
ERROR_VARIABLE output
82+
RESULT_VARIABLE result
11783
)
11884

119-
set_property(DIRECTORY APPEND
120-
PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
121-
${dir}/${out_f}
122-
)
85+
if(result)
86+
message(FATAL_ERROR
87+
"Calling '${CMAKE_C_COMPILER} --version' failed."
88+
)
89+
endif()
90+
91+
if(output MATCHES "([0-9]+[.0-9]+).*XC16, Microchip v([0-9]+\.[0-9]+)")
92+
set(gnu_version ${CMAKE_MATCH_1})
93+
set(xc16_version ${CMAKE_MATCH_2})
94+
else()
95+
message(FATAL_ERROR
96+
"Failed to parse output of '${CMAKE_C_COMPILER} --version'."
97+
)
98+
endif()
99+
100+
string(REPLACE "_" "." gnu_version ${gnu_version})
101+
string(REPLACE "_" "." xc16_version ${xc16_version})
102+
103+
set(CMAKE_C_COMPILER_VERSION ${gnu_version} PARENT_SCOPE)
104+
set(MICROCHIP_C_COMPILER_VERSION ${xc16_version} PARENT_SCOPE)
123105
endfunction()
106+
_xc16_get_version()
107+
108+
# set the default C standard manually
109+
# this is required by `Compiler/Gnu-C`
110+
set(CMAKE_C_STANDARD_COMPUTED_DEFAULT 90)
111+
112+
113+
add_compile_options(
114+
"-mcpu=${MICROCHIP_MCU_MODEL}"
115+
)
116+
string(APPEND CMAKE_C_LINK_FLAGS
117+
" -mcpu=${MICROCHIP_MCU_MODEL}"
118+
" -Wl,--script,p${MICROCHIP_MCU_MODEL}.gld"
119+
)

Modules/Platform/MicrochipMCU-C.cmake

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,10 @@ else()
2222
" is supported yet."
2323
)
2424
endif()
25+
26+
if(MICROCHIP_C_COMPILER_ID)
27+
message(STATUS
28+
"Using Microchip C compiler ${MICROCHIP_C_COMPILER_ID}"
29+
" ${MICROCHIP_C_COMPILER_VERSION}"
30+
)
31+
endif()
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#=============================================================================
2+
# Copyright 2016 Sam Hanes
3+
#
4+
# Distributed under the OSI-approved BSD License (the "License");
5+
# see accompanying file COPYING.txt for details.
6+
#
7+
# This software is distributed WITHOUT ANY WARRANTY; without even the
8+
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9+
# See the License for more information.
10+
#=============================================================================
11+
# (To distribute this file outside of CMake-Microchip,
12+
# substitute the full License text for the above reference.)
13+
14+
# this module is called after the compiler has been determined
15+
# to set up information specific to Microchip GNU C compilers
16+
17+
# for XC16, inject properties that may have been missed
18+
# see `Platform/MicrochipMCU-C-XC16` for explanation
19+
if(MICROCHIP_C_COMPILER_ID STREQUAL "XC16")
20+
if(NOT CMAKE_C_COMPILE_FEATURES)
21+
set(CMAKE_C_COMPILE_FEATURES "c_function_prototypes;c_restrict;c_variadic_macros")
22+
set(CMAKE_C90_COMPILE_FEATURES "c_function_prototypes")
23+
set(CMAKE_C99_COMPILE_FEATURES "c_restrict;c_variadic_macros")
24+
set(CMAKE_C11_COMPILE_FEATURES "")
25+
endif()
26+
27+
if(NOT CMAKE_C_SIZEOF_DATA_PTR)
28+
set(CMAKE_C_SIZEOF_DATA_PTR 2)
29+
endif()
30+
31+
if(NOT CMAKE_C_COMPILER_ABI)
32+
set(CMAKE_C_COMPILER_ABI ELF)
33+
endif()
34+
endif()

Modules/Platform/MicrochipMCU-Initialize.cmake

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,11 @@
1313

1414
# This module is loaded prior to the compiler search to set up enough of
1515
# the platform configuration that an appropriate compiler can be found.
16+
17+
# ensure that only the cross toolchain is searched for
18+
# tools, libraries, include files, and other similar things
19+
set(CMAKE_FIND_ROOT_PATH "")
20+
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
21+
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
22+
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
23+
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

Modules/Platform/MicrochipMCU.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
2121
set(CMAKE_SYSTEM_INCLUDE_PATH /include)
2222
set(CMAKE_SYSTEM_LIBRARY_PATH /lib)
2323
set(CMAKE_SYSTEM_PROGRAM_PATH /bin)
24+
25+
include(MicrochipBin2Hex)

0 commit comments

Comments
 (0)