@@ -27,97 +27,93 @@ if(NOT EXISTS ${MICROCHIP_XC16_PATH})
2727 )
2828endif ()
2929
30- # ensure that only the cross toolchain is searched for
31- # tools, libraries, include files, and other similar things
3230set (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)
123105endfunction ()
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+ )
0 commit comments