1# SPDX-License-Identifier: Apache-2.0
2
3# cmake: Eclipse CDT4 generator amendment
4#
5#1. The generator handles just the COMPILE_DEFINITIONS.
6#   (See: __ZEPHYR_SUPERVISOR__)
7#   For the defines in INTERFACE_COMPILE_DEFINITIONS
8#   a special handling is necessary.
9#
10#   Solution:
11#   The amendment function generates a macro header file
12#   ${CMAKE_BINARY_DIR}/zephyr/include/generated/cmake_intdef.h
13#   based on INTERFACE_COMPILE_DEFINITIONS and appends the
14#   defines from the file to
15#   CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS.
16#
17#2. Eclipse CDT4 indexer has problems with CMake 'Eclipse CDT4 - x'
18#   generator projects that use mixed C/C++.
19#   The Eclipse CDT4 indexer is showing a lot of unresolved symbol
20#   errors, when the project was created with CMake generator and
21#   the code is a mix of C and C++.
22#   The root cause of the problem is the g++ built-in __cplusplus macro,
23#   that is passed by CMake generator in the '.cproject' file.
24#   The defines in '.cproject' are always the same for C and C++.
25#   In mixed C/C++ projects, the header files often contain the following
26#   lines to let C++ code call the C functions:
27#
28#   #ifdef __cplusplus
29#   extern "C" {
30#   #endif
31#
32#   < header content >
33#
34#   #ifdef __cplusplus
35#   }
36#   #endif
37#
38#   Whenever the Eclipse CDT4 indexer compiles the code for
39#   code analysis, it has the macro __cplusplus set,
40#   independent of whether standard C or C++ source files are compiled.
41#   The 'extern "C"' confuses the standard C compilation and the indexer
42#   is messed up.
43#
44#   Solution:
45#   The amendment function deletes the __cplusplus entry from
46#   CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS.
47#
48#3. The amendment function appends the defines from
49#   ${CMAKE_BINARY_DIR}/zephyr/include/generated/autoconf.h to
50#   CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS.
51#
52function(eclipse_cdt4_generator_amendment _param_defs)
53#
54# _param_defs handled values:
55#
56#   1 - work mode: "C and CXX includes, defines in .cproject without __cplusplus"
57#   2 - work mode: "C and CXX includes, defines in .cproject with __cplusplus"
58#   5 - work mode: "C and CXX includes, defines in Eclipse with project defines"
59#
60# In any other case,
61# the C and CXX includes, defines setting in Eclipse is the user task.
62#
63##   EXPERIMENTAL:
64##   3 - work mode: "C and CXX includes, defines in .settings - [EXPERIMENTAL]"
65##   4 - work mode: "C and CXX includes, defines in .settings with project defines - [EXPERIMENTAL]"
66#
67message("   Eclipse CDT4 generator amendment mode:")
68if (${_param_defs} EQUAL 1)
69  set(_work_mode "C and CXX includes, defines in .cproject without __cplusplus")
70  message("   ${_work_mode}")
71  message("   with project includes and defines")
72elseif (${_param_defs} EQUAL 2)
73  set(_work_mode "C and CXX includes, defines in .cproject with __cplusplus")
74  message("   ${_work_mode}")
75  message("   with project includes and defines")
76#elseif (${_param_defs} EQUAL 3)
77#  set(_work_mode "C and CXX includes, defines in .settings - [EXPERIMENTAL]")
78#  message("   ${_work_mode}")
79#  message("   without project defines")
80#elseif (${_param_defs} EQUAL 4)
81#  set(_work_mode "C and CXX includes, defines in .settings with project defines - [EXPERIMENTAL]")
82#  message("   ${_work_mode}")
83elseif (${_param_defs} EQUAL 5)
84  set(_work_mode "C and CXX includes, defines in Eclipse with project defines")
85  message("   ${_work_mode}")
86else(${_param_defs} EQUAL 1)
87  set(_work_mode "C and CXX includes, defines setting in Eclipse is the user task")
88  message("   ${_work_mode}")
89endif(${_param_defs} EQUAL 1)
90
91set(OUTPUT_FILE ${CMAKE_BINARY_DIR}/zephyr/include/generated/cmake_intdef.h)
92file(WRITE ${OUTPUT_FILE}  "/* Generated by eclipse_cd4_generator_amendment.cmake */\n")
93file(APPEND ${OUTPUT_FILE} "/* The header contains the defines collected from the */\n")
94file(APPEND ${OUTPUT_FILE} "/*   INTERFACE_COMPILE_DEFINITIONS target property    */\n")
95file(APPEND ${OUTPUT_FILE} "/*        corresponding to zephyr_interface           */\n")
96get_target_property(_int_comp_def zephyr_interface INTERFACE_COMPILE_DEFINITIONS)
97foreach( d ${_int_comp_def} )
98  string(REGEX MATCH "([A-Za-z_][A-Za-z0-9_]*) *=* *(.*) *$" _dummy "${d}")
99  file(APPEND ${OUTPUT_FILE} "#define ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}\n")
100endforeach()
101
102if (${_work_mode} STREQUAL "C and CXX includes, defines in Eclipse with project defines")
103  message("")
104  message("   -------------------------------------------------------------------------")
105  message("   Add the following two command line parameters:")
106  message("")
107  message("   -imacros ${CMAKE_BINARY_DIR}/zephyr/include/generated/cmake_intdef.h")
108  message("   -imacros ${AUTOCONF_H}")
109  message("")
110  message("   to 'CDT cross GCC Built-in Compiler Settings' provider command definition")
111  message("   -------------------------------------------------------------------------")
112  message("")
113endif()
114
115if ( (${_work_mode} STREQUAL "C and CXX includes, defines in .settings - [EXPERIMENTAL]") OR
116     (${_work_mode} STREQUAL "C and CXX includes, defines in .settings with project defines - [EXPERIMENTAL]") )
117
118  set(OUTPUT_FILE ${CMAKE_BINARY_DIR}/.settings/language.settings.xml)
119  file(WRITE ${OUTPUT_FILE} "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n")
120
121  file(APPEND ${OUTPUT_FILE} "<project>\n")
122  file(APPEND ${OUTPUT_FILE} "\t<configuration id=\"org.eclipse.cdt.core.default.config.1\" name=\"Configuration\">\n")
123  file(APPEND ${OUTPUT_FILE} "\t\t<extension point=\"org.eclipse.cdt.core.LanguageSettingsProvider\">\n")
124  file(APPEND ${OUTPUT_FILE} "\t\t\t<provider copy-of=\"extension\" id=\"org.eclipse.cdt.ui.UserLanguageSettingsProvider\"/>\n")
125  file(APPEND ${OUTPUT_FILE} "\t\t\t<provider-reference id=\"org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider\" ref=\"shared-provider\"/>\n")
126  file(APPEND ${OUTPUT_FILE} "\t\t\t<provider-reference id=\"org.eclipse.cdt.core.PathEntryScannerInfoLanguageSettingsProvider\" ref=\"shared-provider\"/>\n")
127  if (${_work_mode} STREQUAL "C and CXX includes, defines in .settings with project defines - [EXPERIMENTAL]")
128    file(APPEND ${OUTPUT_FILE} "\t\t\t<provider class=\"org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector\" console=\"false\" id=\"org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector\" keep-relative-paths=\"false\" name=\"Zephyr autoconf and SDK Compiler Settings\" parameter=\"${CROSS_COMPILE}\${COMMAND} \${FLAGS} -imacros ${CMAKE_BINARY_DIR}/zephyr/include/generated/cmake_intdef.h -imacros ${AUTOCONF_H} -E -P -v -dD &quot;\${INPUTS}&quot;\" store-entries-with-project=\"true\">\n")
129  else ()
130    file(APPEND ${OUTPUT_FILE} "\t\t\t<provider class=\"org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector\" console=\"false\" id=\"org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector\" keep-relative-paths=\"false\" name=\"Zephyr autoconf and SDK Compiler Settings\" parameter=\"${CROSS_COMPILE}\${COMMAND} \${FLAGS} -E -P -v -dD &quot;\${INPUTS}&quot;\" store-entries-with-project=\"true\">\n")
131  endif ()
132  file(APPEND ${OUTPUT_FILE} "\t\t\t\t<language-scope id=\"org.eclipse.cdt.core.gcc\"/>\n")
133  file(APPEND ${OUTPUT_FILE} "\t\t\t\t<language-scope id=\"org.eclipse.cdt.core.g++\"/>\n")
134  file(APPEND ${OUTPUT_FILE} "\t\t\t</provider>\n")
135  file(APPEND ${OUTPUT_FILE} "\t\t</extension>\n")
136  file(APPEND ${OUTPUT_FILE} "\t</configuration>\n")
137  file(APPEND ${OUTPUT_FILE} "</project>\n")
138
139endif ()
140
141if ( (${_work_mode} STREQUAL "C and CXX includes, defines in .cproject without __cplusplus") OR
142     (${_work_mode} STREQUAL "C and CXX includes, defines in .cproject with __cplusplus") OR
143     (${_work_mode} STREQUAL "C and CXX includes, defines in .settings - [EXPERIMENTAL]") )
144
145  if ( (${_work_mode} STREQUAL "C and CXX includes, defines in .cproject without __cplusplus") OR
146       (${_work_mode} STREQUAL "C and CXX includes, defines in .cproject with __cplusplus") )
147
148    if (${_work_mode} STREQUAL "C and CXX includes, defines in .cproject without __cplusplus")
149      # Delete __cplusplus define
150      set(TEMP_VAR "${CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS}")
151      STRING(REGEX REPLACE "__cplusplus;.*;" "" TEMP_VAR "${TEMP_VAR}")
152      set(CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS "${TEMP_VAR}" CACHE INTERNAL "CXX compiler system defined macros")
153    endif()
154
155  else()
156
157    # Wiping C compiler system defined macros and include directories
158    if (CMAKE_C_COMPILER_ID MATCHES GNU)
159      set(CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS "" CACHE INTERNAL "C compiler system include directories")
160      set(CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS "" CACHE INTERNAL "C compiler system defined macros")
161    endif ()
162    # Wiping CXX compiler system defined macros and include directories
163    if ("${CMAKE_CXX_COMPILER_ID}" MATCHES GNU)
164      set(CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS "" CACHE INTERNAL "CXX compiler system include directories")
165      set(CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS "" CACHE INTERNAL "CXX compiler system defined macros")
166    endif ()
167
168  endif()
169
170  file(STRINGS ${CMAKE_BINARY_DIR}/zephyr/include/generated/cmake_intdef.h _int_comp_def)
171  set (_resultDefines "${CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS}")
172  foreach( d ${_int_comp_def} )
173    string(REGEX MATCH "^#define +([A-Za-z_][A-Za-z0-9_]*) *(.*) *$" _dummy "${d}")
174    if (NOT ("${CMAKE_MATCH_1}" STREQUAL "") )
175      list(APPEND _resultDefines "${CMAKE_MATCH_1}")
176      if ("${CMAKE_MATCH_2}" STREQUAL "")
177        list(APPEND _resultDefines "")
178      else()
179        list(APPEND _resultDefines "${CMAKE_MATCH_2}")
180      endif()
181    endif()
182  endforeach()
183  set (CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS "${_resultDefines}" CACHE INTERNAL "C compiler system defined macros")
184
185  file(STRINGS ${AUTOCONF_H} _auto_conf)
186  set (_resultDefines "${CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS}")
187  foreach( d ${_auto_conf} )
188    string(REGEX MATCH "^#define +([A-Za-z_][A-Za-z0-9_]*) *(.*) *$" _dummy "${d}")
189    if (NOT ("${CMAKE_MATCH_1}" STREQUAL "") )
190      list(APPEND _resultDefines "${CMAKE_MATCH_1}")
191      if ("${CMAKE_MATCH_2}" STREQUAL "")
192        list(APPEND _resultDefines " ")
193      else()
194        list(APPEND _resultDefines "${CMAKE_MATCH_2}")
195      endif()
196    endif()
197  endforeach()
198  set (CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS "${_resultDefines}" CACHE INTERNAL "C compiler system defined macros")
199
200endif()
201
202endfunction(eclipse_cdt4_generator_amendment _param_defs)
203