如何以编程方式更改文件的Eclipse CDT工具设置?

时间:2013-11-19 01:39:09

标签: java eclipse plugins eclipse-cdt

我想以编程方式(从插件)更改CDT托管构建项目中单个文件的“工具设置”选项卡中“其他设置”中的“其他标志”字段。 (有关截图以及如何使用UI进行此更改的简要说明,请参阅this Eclipse documentation page。)

注意:当我接近解决方案时,我已经更新了两次。但是我没有在最后添加更新(正如我对更短的问题所做的那样),而是在修改整个问题。如果看到面包屑导致我现在的位置有帮助,您可以阅读历史记录。

以下代码将导致写入.cproject文件的设置(我将在下面详细介绍),但是当我打开文件的Properties对话框,然后单击C / C ++ Build-> Settings时然后杂项,更改不会出现在“其他标志”字段中(就像我使用对话框进行更改时一样)。

IWorkbench workbench = PlatformUI.getWorkbench();
IWorkbenchWindow workbenchwindow = workbench.getActiveWorkbenchWindow();
IWorkbenchPage workbenchpage = workbenchwindow.getActivePage();
IEditorPart editorpart = workbenchpage.getActiveEditor();
IEditorInput editorinput = editorpart.getEditorInput();
IResource file = ((IFileEditorInput)editorinput).getFile();
IProject project = file.getProject();
IManagedBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(project);
IConfiguration[] configurations = buildInfo.getManagedProject().getConfigurations();
IConfiguration conf = configurations[0];
IFileInfo fileInfo = conf.createFileInfo(file.getFullPath());
ITool[] tools = fileInfo.getTools();
ITool tool = tools[0];
IOption option = tool.getOptionById("my.gnu.compiler.misc.other");
String oldOptionValue = option.getDefaultValue().toString();
String newOptionValue = oldOptionValue + " -eg";
ManagedBuildManager.setOption(fileInfo, tool, option, newOptionValue);
ManagedBuildManager.saveBuildInfo(project, true);

我查看了手动更改工具设置的.cproject文件与运行上述代码后的其他.cproject文件之间的差异。以下是各自的相关位。

以下是.cproject文件中的XML,其中手动更改了工具设置:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
    <storageModule moduleId="org.eclipse.cdt.core.settings">
        <cconfiguration id="com.company.product.toolchain.configuration.changed.1964078554">
...
            <storageModule moduleId="cdtBuildSystem" version="4.0.0">
                <configuration artifactName="${ProjName}" buildProperties="" cleanCommand="rm -f" description="" id="com.company.product.toolchain.configuration.changed.1964078554" name="changed" parent="com.company.product.toolchain.configuration.changed">
...
                    <fileInfo id="com.company.product.toolchain.configuration.changed.1964078554.915152327" name="code.cpp" rcbsApplicability="disable" resourcePath="src/code.cpp" toolsToInvoke="com.company.product.toolchain.compiler.1643348654.1411455203">
                        <tool id="com.company.product.toolchain.compiler.1643348654.1411455203" name="Company GNU compilers" superClass="com.company.product.toolchain.compiler.1643348654">
                            <option id="company.gnu.compiler.misc.other.789167779" name="Other flags" superClass="company.gnu.compiler.misc.other" value="-c -fmessage-length=0 -eg" valueType="string"/>
                            <inputType id="com.company.product.toolchain.cxxinputtype.877052163" name="C++ Input" superClass="com.company.product.toolchain.cxxinputtype"/>
                            <inputType id="com.company.product.toolchain.cinputtype.1390394900" name="C input" superClass="com.company.product.toolchain.cinputtype"/>
                        </tool>
                    </fileInfo>
...

以下是.cproject文件中的XML,它们以编程方式进行了更改:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
    <storageModule moduleId="org.eclipse.cdt.core.settings">
        <cconfiguration id="com.company.product.toolchain.configuration.changed.2057644715">
...
            <storageModule moduleId="cdtBuildSystem" version="4.0.0">
                <configuration artifactName="${ProjName}" buildProperties="" cleanCommand="rm -f" description="" id="com.company.product.toolchain.configuration.changed.2057644715" name="changed" parent="com.company.product.toolchain.configuration.changed">
...
                    <fileInfo id="com.company.product.toolchain.configuration.changed.2057644715./test3/src/code.cpp" name="code.cpp" rcbsApplicability="disable" resourcePath="test3/src/code.cpp" toolsToInvoke="com.company.product.toolchain.compiler.1482360042.1005761865">
                        <tool id="com.company.product.toolchain.compiler.1482360042.1005761865" name="Company GNU compilers" superClass="com.company.product.toolchain.compiler.1482360042">
                            <option id="company.gnu.compiler.misc.other.999025984" superClass="company.gnu.compiler.misc.other" value="-c -fmessage-length=0 -eg" valueType="string"/>
                            <inputType id="com.company.product.toolchain.cxxinputtype.1253686787" name="C++ Input" superClass="com.company.product.toolchain.cxxinputtype"/>
                            <inputType id="com.company.product.toolchain.cinputtype.1141524787" name="C input" superClass="com.company.product.toolchain.cinputtype"/>
                        </tool>
                    </fileInfo>
...

除了我认为是某种GUID的数字之外,还有三个不同之处:

  1. 出于某种原因,程序化更改中fileInfo元素的id属性包含文件的路径,包括项目名称:id="com.company.product.toolchain.configuration.changed.2057644715./test3/src/code.cpp"

  2. resourcePath元素的fileInfo属性值包含项目名称,仅包含在程序化更改中:resourcePath="test3/src/code.cpp"

  3. option元素中的fileInfo元素作为名称属性(name="Other flags"),与对话框中的字段匹配,仅在手动更改中。

  4. 我猜测这些差异中的一个或全部是阻止我的程序化更改与手动更改“兼容”(因此它们显示在对话框中)。我试图找出如何创建IFileInfo,IOption(和ITool?)对象而不会导致这些差异。我正在尝试找到如何为对话框创建这些对象,但还没有。

    任何建议表示赞赏。

    更新:我在an answer from Doug Schaefer上收到cdt-dev mailing list个问题。他建议我“在某些地方坚持断点,看看用户界面是如何做到的。”我回信了:

    我一直这样做。我在org.eclipse.cdt.managedbuilder.core.ManagedBuildManager.setOption(IResourceInfo, IHoldsOptions, IOption, String)中设置了一个断点,当我打开文件的“属性”对话框,展开“C / C ++ Build”,选择“设置”,然后在“工具设置”选项卡中选择“其他”时触发。我可以看到参数,并且假设我可以使用相同的参数调用setOption,我将在.cproject文件中获得相同的结果。但我无法弄清楚如何做到这一点。您对我如何确定这些对象的创建位置有什么建议吗?我可以在那里设置断点吗?

    更新#2: Vladimir的答案解决了我的问题。虽然我更关心上面两个.cproject文件片段中的差异编号3,但关键是差异2并且项目名称包含在差异1中。

    我更改了代码以将IFileInfo对象创建为:

    IFileInfo fileInfo = conf.createFileInfo(file.getProjectRelativePath());
    

    ...导致fileInfo元素没有项目名称:

    <fileInfo id="com.company.product.toolchain.configuration.changed.838214286.src/code.cpp" name="code.cpp" rcbsApplicability="disable" resourcePath="src/code.cpp" toolsToInvoke="com.company.product.toolchain.compiler.2027651356.1970239371">
    

    ...最重要的是,导致程序化更改显示在单个文件的“工具设置”选项卡的“其他设置”字段中的“其他标志”字段中。 (我猜.cproject文件中的其他差异并不重要。)

2 个答案:

答案 0 :(得分:2)

我怀疑你的IFileInfo创建可能存在问题。以下是我们用于获取IResourceInfo以供翻译单元设置每个文件选项的代码:

protected IResourceInfo getResourceInfo(ITranslationUnit translationUnit, ICProjectDescription prjDescription) {

    ICProject cProject = translationUnit.getCProject();
    if (cProject != null) {
        ICConfigurationDescription cfgDescription = prjDescription.getActiveConfiguration();
        IConfiguration configuration = ManagedBuildManager.getConfigurationForDescription(cfgDescription);
        IPath projectPath = translationUnit.getResource().getProjectRelativePath(); 
        IResourceInfo ri = configuration.getResourceInfo(projectPath, true);

        if (ri == null) { 
            ri = configuration.createFileInfo(projectPath);
        }

        return ri;
    }

    return null;
}

请注意这一行,特别是:

IPath projectPath = translationUnit.getResource().getProjectRelativePath();

也许,您只需要在代码中使用getProjectRelativePath()吗?

答案 1 :(得分:1)

通常,您可以为不同的对象设置选项,即配置(如果您希望该选项适用于配置中给定类型的所有文件)或资源(如果您希望该选项仅应用于文件)在文件夹或单个文件中。)

setOption()有多个原型;看起来你使用了适用于文件资源的那个。

在我的GNU ARM Eclipse插件中,我成功使用了另一个版本:

setOption(IConfiguration config, IHoldsOptions holder, IOption option, String value)

您可以在this file第583行查看示例。

我想这也适用于你的情况。