Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Language IDEs » C / C++ IDE (CDT) » Indexer problems with mixed C, C++ code (The Eclipse CDT indexer is showing a lot of unresolved symbol errors, when the CDT 4 project was created with CMake and the code is a mix of C and C++.)
Indexer problems with mixed C, C++ code [message #1695217] Tue, 12 May 2015 18:08 Go to next message
Wolfgang Schmieder is currently offline Wolfgang SchmiederFriend
Messages: 1
Registered: May 2015
Junior Member
Hello,

I don't expect an answer. I just want to share my experience.


My fix is targeting ECLIPSE-CDT indexer problems with CMake generated projects that use mixed C/C++.

Problem: The Eclipse CDT indexer is showing a lot of unresolved symbol errors, when the CDT 4 project was created with CMake and the code is a mix of C and C++.

The root cause of the problem is the g++ builtin __cplusplus macro that is passed by CMake to the "Contributed PathEntry container" (Refer to Dialog "Project->Properties" item "C/C++ General -> Preprocessor Include Paths, Macros etc." tab "Entries->Setting Entries" for language C and language C++).

The "Contributed PathEntry container" is always the same for C and C++. In mixed C/C++ projects, header files often contain the following lines to let C++ code call the C functions.


#ifdef __cplusplus
extern "C" {
#endif

<...function declarations etc. ...>

#ifdef __cplusplus
}
#endif


Whenever the indexer compiles the code for code analysis, it has the macro __cplusplus set, independent of whether standard C or C++ source files are compiled. This is, because C and C++ use both the common "Contributed PathEntry container" with the __cplusplus macro set (CMake queries the g++ for builtin macros and places it in "Contributed PathEntry container").

The 'extern "C"' confuses the standard C compilation and the indexer is messed up.

Workaround:

I created a CMake file "language_provider.cmake" with a cmake macro "remove_from_SYSTEM_MACROS" that is able wipe out the __cplusplus macro
from the "Contributed PathEntry container".
Optionally it can wipe out all Compiler built in macros. Another cmake macro "remove_from_SYSTEM_MACROS" is able to wipe out all Compiler System Includes (I will explain later why this is useful).

The file "language_provider.cmake" contains an additional function "create_language_provider" that will create Language specific Compiler built in
macros for C and C++ for the "CDT gcc built-in Compiler Settings" - povider. (This was the right provider for my ARM cross gcc).

Do the following to fix the issue:
Include "language_provider.cmake" in your main CMakeLists.txt at a place after the toolchain is determined. In my case that was immediately after the cmake project(..) statement. The CMake fragment looks like this:



set(GCC_PREFIX "C:/gnu/arm-none-eabi/bin/arm-none-eabi-") # This is the location of the compiler with the prefix for my cross tool chain.
set(CXX_STANDARD_FLAG -std=gnu++11) # This is only if you are using C++11, otherwise don't pass a 3rd parameter to function "create_language_provider"
include(language_provider.cmake)
remove_from_SYSTEM_MACROS(CXX "__cplusplus;.*;")
create_language_provider("${CMAKE_BINARY_DIR}/.settings" "${GCC_PREFIX}-" "${CXX_STANDARD_FLAG}")



The above CMake fragment will solve the problem but will also have duplicate Compiler built in macros and duplicate System Include directories.
Duplicates are caused by the 2 providers: "Contributed PathEntry container" and "CDT gcc built-in Compiler Settings".

The duplicates can be avoided if you choose the following cmake code fragment instead:



set(GCC_PREFIX "C:/gnu/arm-none-eabi/bin/arm-none-eabi-") # This is the location of the compiler with the prefix for my cross tool chain.
set(CXX_STANDARD_FLAG -std=gnu++11) # This is only if you are using C++11, otherwise don't pass a 3rd parameter to function "create_language_provider"
include(language_provider.cmake)
remove_from_SYSTEM_MACROS(C)
remove_from_SYSTEM_INCLUDE_DIRS(C)
remove_from_SYSTEM_MACROS(CXX)
remove_from_SYSTEM_INCLUDE_DIRS(CXX)
create_language_provider("${CMAKE_BINARY_DIR}/.settings" "${GCC_PREFIX}-" "${CXX_STANDARD_FLAG}")



Both above solutions fixed my indexer problem almost. In my project, the subdirectories that I had to add with the add_subdirectory() statement were not a real subdirectories of my top level CMakeList.txt directory. So my resulting CDT project contained an extra folder called [Subprojects].
This folder I had to manually add as source folder to the C/C++ Project Paths (Menu "Projects->Properties").


If you are using Cygwin or MinGW gcc instead of a cross compile tool chain, you probably need to replace the following text in function 'create_language_provider':

'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector' by
'org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorCygwin' respectively by
'org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorMinGW'

I hope it will work, because I didn't test with Cygwin or MinGW toolchain.

Here is my environment which I used to test my fix:

Windows 7 64 bit
CMake 3.2.2
Arm Gnu Cross Toolchain arm-none-eabi version 4.7 from "GCC Arm Embedded Launchpad".
Eclipse Luna (4.4) with CDT 8.6

And here the contents of the macro 'language_provider.cmake':



# Create language specific (C/C++) compiler built in macros and include paths
message("${MESSAGE_TABS}language_provider.cmake ...")
SET(MESSAGE_TABS "${MESSAGE_TABS}\t")

#Try replacing in function create_language_provider the text:
# 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector' by
# 'org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorCygwin' if you use Cygwin toolchain, respectively by
# 'org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorMinGW' if you use MinGW toolchain.
# Note: The above settings for Cygwin / MinGW have not been tested yet.

function(create_language_provider OUTPUT_DIR COMMAND_PREFIX)
set(OUTPUT_FILE ${OUTPUT_DIR}/language.settings.xml)
file(WRITE ${OUTPUT_FILE} "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n")
file(APPEND ${OUTPUT_FILE} "<project>\n")
file(APPEND ${OUTPUT_FILE} "\t<configuration id=\"org.eclipse.cdt.core.default.config.1\" name=\"Configuration\">\n")
file(APPEND ${OUTPUT_FILE} "\t\t<extension point=\"org.eclipse.cdt.core.LanguageSettingsProvider\">\n")
file(APPEND ${OUTPUT_FILE} "\t\t\t<provider copy-of=\"extension\" id=\"org.eclipse.cdt.ui.UserLanguageSettingsProvider\"/>\n")
file(APPEND ${OUTPUT_FILE} "\t\t\t<provider-reference id=\"org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider\" ref=\"shared-provider\"/>\n")
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=\"CDT GCC Built-in Compiler Settings\" parameter=\"${COMMAND_PREFIX}\${COMMAND} \${FLAGS} ${ARGV2} -E -P -v -dD &quot;\${INPUTS}&quot;\" store-entries-with-project=\"true\">\n")
file(APPEND ${OUTPUT_FILE} "\t\t\t\t<language-scope id=\"org.eclipse.cdt.core.gcc\"/>\n")
file(APPEND ${OUTPUT_FILE} "\t\t\t\t<language-scope id=\"org.eclipse.cdt.core.g++\"/>\n")
file(APPEND ${OUTPUT_FILE} "\t\t\t</provider>\n")
file(APPEND ${OUTPUT_FILE} "\t\t\t<provider-reference id=\"org.eclipse.cdt.core.PathEntryScannerInfoLanguageSettingsProvider\" ref=\"shared-provider\"/>\n")
file(APPEND ${OUTPUT_FILE} "\t\t</extension>\n")
file(APPEND ${OUTPUT_FILE} "\t</configuration>\n")
file(APPEND ${OUTPUT_FILE} "</project>\n")
endfunction(create_language_provider)


macro(remove_from_SYSTEM_ITEM LANGUAGE ITEM_TYPE CACHE_DOC_STRING)
# message("${MESSAGE_TABS}CMAKE_EXTRA_GENERATOR_${LANGUAGE}${ITEM_TYPE} = ${CMAKE_EXTRA_GENERATOR_${LANGUAGE}${ITEM_TYPE}}")
set(TEMP_VAR)
if(${ARGC} LESS 4)
# There is no regular expression, so remove everything
message("${MESSAGE_TABS}wiping ${CACHE_DOC_STRING}")
else(${ARGC} LESS 4)
# The extra argument ist treated as an regular expression. Every match will be removed.
message("${MESSAGE_TABS}Removing ${ARGN} from ${CACHE_DOC_STRING}")

set(TEMP_VAR "${CMAKE_EXTRA_GENERATOR_${LANGUAGE}${ITEM_TYPE}}")
STRING(REGEX REPLACE "${ARGN}" "" TEMP_VAR "${TEMP_VAR}")
endif(${ARGC} LESS 4)
set(CMAKE_EXTRA_GENERATOR_${LANGUAGE}${ITEM_TYPE} "${TEMP_VAR}" CACHE INTERNAL "${CACHE_DOC_STRING}")
# message("${MESSAGE_TABS}CMAKE_EXTRA_GENERATOR_${LANGUAGE}${ITEM_TYPE} = ${CMAKE_EXTRA_GENERATOR_${LANGUAGE}${ITEM_TYPE}}")
endmacro(remove_from_SYSTEM_ITEM ITEM_TYPE)

# Remove a string from C or CXX system include directories.
# The string to be removed is passed as a regular expression within the optional the last argument
# If there is no regular expression, ALL system include directories will be removed.
macro(remove_from_SYSTEM_INCLUDE_DIRS LANGUAGE)
set(system_DOC_STRING "${LANGUAGE} compiler system include directories")
remove_from_SYSTEM_ITEM(${LANGUAGE} _SYSTEM_INCLUDE_DIRS "${system_DOC_STRING}" ${ARGN})
endmacro(remove_from_SYSTEM_INCLUDE_DIRS)

# Remove a string from C or CXX system defined macros.
# The string to be removed is passed as a regular expression within the optional the last argument
# If there is no regular expression, ALL system defined macros will be removed.
macro(remove_from_SYSTEM_MACROS LANGUAGE)
set(system_DOC_STRING "${LANGUAGE} compiler system defined macros")
remove_from_SYSTEM_ITEM(${LANGUAGE} _SYSTEM_DEFINED_MACROS "${system_DOC_STRING}" ${ARGN})
endmacro(remove_from_SYSTEM_MACROS)

if(NOT ${MESSAGE_TABS} STREQUAL "")
STRING(SUBSTRING ${MESSAGE_TABS} 1 -1 MESSAGE_TABS)
endif(NOT ${MESSAGE_TABS} STREQUAL "")
message("${MESSAGE_TABS}language_provider.cmake done.\n")


I hope that will help other people facing the same problem.
Re: Indexer problems with mixed C, C++ code [message #1741386 is a reply to message #1695217] Wed, 24 August 2016 15:24 Go to previous message
Devin Callahan is currently offline Devin CallahanFriend
Messages: 1
Registered: August 2016
Junior Member
A+++

Solved my problem with this exact issue. Thank you very much!
Previous Topic:using RSE with ssh, getting no autocomplete/ error detection
Next Topic:Arduino: Cannot make connection
Goto Forum:
  


Current Time: Fri Apr 26 08:24:43 GMT 2024

Powered by FUDForum. Page generated in 0.03622 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top