From 477c066885ae69f1ccbb8a7745e8319a64ff4c1f Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Wed, 31 Oct 2018 10:02:35 +0000 Subject: [PATCH] Bug 1408675 p1. Set Eclipse CDT per-directory defines in the right place. r=botond We've been setting per-directory defines in the "CDT Managed Build Setting Entries" which are ignored(!) during indexing since we don't use the Eclipse managed build system (we use mach). We need to set the defines as "CDT User Setting Entries". Differential Revision: https://phabricator.services.mozilla.com/D12008 --HG-- extra : rebase_source : 33125ed706a531df9cd46249baaffeef5a2ec559 --- .../mozbuild/mozbuild/backend/cpp_eclipse.py | 191 ++++++++++-------- 1 file changed, 110 insertions(+), 81 deletions(-) diff --git a/python/mozbuild/mozbuild/backend/cpp_eclipse.py b/python/mozbuild/mozbuild/backend/cpp_eclipse.py index 6115171675fc..1da35703e599 100644 --- a/python/mozbuild/mozbuild/backend/cpp_eclipse.py +++ b/python/mozbuild/mozbuild/backend/cpp_eclipse.py @@ -10,6 +10,7 @@ import os import shutil import subprocess import types +from xml.sax.saxutils import quoteattr import xml.etree.ElementTree as ET from .common import CommonBackend @@ -199,24 +200,77 @@ class CppEclipseBackend(CommonBackend): if e.errno != errno.ENOENT: raise - def _define_entry(self, name, value): - define = ET.Element('entry') - define.set('kind', 'macro') - define.set('name', name) - define.set('value', value) - return ET.tostring(define) - def _write_language_settings(self, fh): - settings = LANGUAGE_SETTINGS_TEMPLATE + def add_objdir_include_path(relpath): + p = os.path.join(self.environment.topobjdir, relpath) + return LANGUAGE_SETTINGS_TEMPLATE_DIR_INCLUDE.replace("@INCLUDE_PATH@", p) - settings = settings.replace('@GLOBAL_INCLUDE_PATH@', os.path.join(self.environment.topobjdir, 'dist/include')) - settings = settings.replace('@NSPR_INCLUDE_PATH@', os.path.join(self.environment.topobjdir, 'dist/include/nspr')) - settings = settings.replace('@IPDL_INCLUDE_PATH@', os.path.join(self.environment.topobjdir, 'ipc/ipdl/_ipdlheaders')) - settings = settings.replace('@PREINCLUDE_FILE_PATH@', os.path.join(self.environment.topobjdir, 'dist/include/mozilla-config.h')) - settings = settings.replace('@DEFINE_MOZILLA_INTERNAL_API@', self._define_entry('MOZILLA_INTERNAL_API', '1')) - settings = settings.replace("@COMPILER_FLAGS@", self._cxx + " " + self._cppflags); + def add_define(name, value): + define = LANGUAGE_SETTINGS_TEMPLATE_DIR_DEFINE + define = define.replace("@NAME@", name) + # We use quoteattr here because some defines contain characters + # such as "<" and '"' which need proper XML escaping. + define = define.replace("@VALUE@", quoteattr(value)) + return define - fh.write(settings) + fh.write(LANGUAGE_SETTINGS_TEMPLATE_HEADER) + + # Unfortunately, whenever we set a user defined include path or define + # on a directory, Eclipse ignores user defined include paths and defines + # on ancestor directories. That means that we need to add all the + # common include paths and defines to every single directory entry that + # we add settings for. (Fortunately that doesn't appear to have a + # noticeable impact on the time it takes to open the generated Eclipse + # project.) We do that by generating a template here that we can then + # use for each individual directory in the loop below. + # + dirsettings_template = LANGUAGE_SETTINGS_TEMPLATE_DIR_HEADER + + # Add OS_COMPILE_CXXFLAGS args (same as OS_COMPILE_CFLAGS): + dirsettings_template = dirsettings_template.replace('@PREINCLUDE_FILE_PATH@', os.path.join(self.environment.topobjdir, 'dist/include/mozilla-config.h')) + + # Add EXTRA_INCLUDES args: + dirsettings_template += add_objdir_include_path('dist/include') + + # Add OS_INCLUDES args: + # XXX media/webrtc/trunk/webrtc's moz.builds reset this. + dirsettings_template += add_objdir_include_path('dist/include/nspr') + + # Finally, add anything else that makes things work better. + # + # Because of https://developer.mozilla.org/en-US/docs/Eclipse_CDT#Headers_are_only_parsed_once + # we set MOZILLA_INTERNAL_API for all directories to make sure + # headers are indexed with MOZILLA_INTERNAL_API set. Unfortunately + # this means that MOZILLA_EXTERNAL_API code will suffer. + # + # TODO: If we're doing this for MOZILLA_EXTERNAL_API then we may want + # to do it for other LIBRARY_DEFINES's defines too. Well, at least for + # STATIC_EXPORTABLE_JS_API which may be important to JS people. + # (The other two LIBRARY_DEFINES defines -- MOZ_HAS_MOZGLUE and + # IMPL_LIBXUL -- don't affect much and probably don't matter to anyone). + # + # TODO: Should we also always set DEBUG so that DEBUG code is always + # indexed? Or is there significant amounts of non-DEBUG code that + # would be adversely affected? + # + # TODO: Investigate whether the ordering of directories in the project + # file can be used to our advantage so that the first indexing of + # important headers has the defines we want. + # + dirsettings_template += add_objdir_include_path('ipc/ipdl/_ipdlheaders') + dirsettings_template += add_define('MOZILLA_INTERNAL_API', '1') + + for path, defines in self._paths_to_defines.items(): + dirsettings = dirsettings_template + dirsettings = dirsettings.replace('@RELATIVE_PATH@', path) + for k, v in defines.items(): + if v == True: + v = "" + dirsettings += add_define(k, str(v)) + dirsettings += LANGUAGE_SETTINGS_TEMPLATE_DIR_FOOTER + fh.write(dirsettings) + + fh.write(LANGUAGE_SETTINGS_TEMPLATE_FOOTER.replace("@COMPILER_FLAGS@", self._cxx + " " + self._cppflags)) def _write_launch_files(self, launch_dir): bin_dir = os.path.join(self.environment.topobjdir, 'dist') @@ -252,20 +306,6 @@ class CppEclipseBackend(CommonBackend): cproject_header = cproject_header.replace('@PROJECT_TOPSRCDIR@', self.environment.topobjdir) cproject_header = cproject_header.replace('@MACH_COMMAND@', os.path.join(self.environment.topsrcdir, 'mach')) fh.write(cproject_header) - - for path, defines in self._paths_to_defines.items(): - folderinfo = CPROJECT_TEMPLATE_FOLDER_INFO_HEADER - folderinfo = folderinfo.replace('@FOLDER_ID@', str(random.randint(1000000, 99999999999))) - folderinfo = folderinfo.replace('@FOLDER_NAME@', 'tree/' + path) - fh.write(folderinfo) - for k, v in defines.items(): - define = ET.Element('listOptionValue') - define.set('builtIn', 'false') - define.set('value', str(k) + "=" + str(v)) - fh.write(ET.tostring(define)) - fh.write(CPROJECT_TEMPLATE_FOLDER_INFO_FOOTER) - - fh.write(CPROJECT_TEMPLATE_FOOTER) @@ -388,23 +428,6 @@ CPROJECT_TEMPLATE_HEADER = """ """ -CPROJECT_TEMPLATE_FOLDER_INFO_HEADER = """ - - - - - - - - - -""" CPROJECT_TEMPLATE_FILEINFO = """