如何让MIDL搜索附加的包含目录以获取合格路径

14

更新: 在向 Microsoft 提出支持请求六个月后,该请求已被拒绝,他们声称这不是一个错误(因为文档没有明确说明所看到的行为不是正确的)。他们拒绝了 DCR ,并表示由于过去 10 年中没有收到任何投诉,很明显这不是一种常见用例。

这是一个动员令,如果您遇到了相同的问题,请向 Microsoft 发出支持请求,以便他们了解应当对其进行修复。我知道至少有人遇到了同样的问题,因为我在 Chrome 的源代码注释中发现了这条评论:

# Building .idl files.
# This is a total mess. MIDL needs to be run from $OPEN_DIR because it's too
# stupid to apply its include paths to a relative path like "ui/ie/bla.idl"
# (it only looks in the current dir). So we have to jump through hoops to fix
# up our relative include paths and output files。


原始问题:

我有以下文件结构:

  • C:\first\Foo.idl
  • C:\second\Bar.idl

Bar.idl 包含以下行:

import "first/Foo.idl";
如何在从C:\second编译时让midl编译Bar.idl文件?如果我直接导入Foo.idl(而没有指定first/),那么指定first作为附加包含目录就足够了(midl /I c:\ first Bar.idl),它会找到Foo.idl。或者,如果我从C:\(midl second\Bar.idl)编译,那也可以。问题是,在使用命令行midl /I C:\ Bar.idl从C:\second编译时,出现以下编译错误:c1:致命错误C1083:无法打开源文件:“first\Foo.idl”:没有这样的文件或目录。看起来midl只会搜索相对于当前目录的相对路径,并且将附加的包含目录仅用于未经修改的文件名,这种行为特定于import关键字。使用include时结果如预期。我想能够添加两个不同的额外包含目录,以便如果本地机器上存在该文件,midl将使用该版本,否则它将从服务器获取文件(因此chdir到根文件夹不是选择)。有没有办法解决这个问题?

自您上次更新以来,您是否找到了解决此问题的方法? - Henry Merriam
@HenryMerriam 不是的,我联系了微软支持,他们说他们认为这不是一个错误,因为它并没有明确违反文档。由于他们以前没有听到过这个请求,他们觉得这并不重要,不能改变当前的行为 :( - Motti
3个回答

4

到了2020年末,MIDL 3.0已经发布了。然而,OP所描述的问题仍然存在。但如果你使用Visual Studio,有一种简单的方法来解决这个问题。

如果你要将一个.idl文件添加到一个项目中,在添加文件后,以下MSBuild代码会在项目文件中生成:

<ItemGroup>
  <Midl Include="Folder1\YourCustomFile.idl" />
</ItemGroup>

如果您在另一个文件夹中添加了第二个文件并引用了第一个文件,则会生成另一个条目:
<ItemGroup>
  <Midl Include="Folder1\YourCustomFile.idl" />
  <Midl Include="Folder2\YourSecondCustomFile.idl" />
</ItemGroup>

问题在于,如果您编译该代码,MIDL编译器将不会知道任何其他包含目录。因此,如果您添加:
#include "YourCustomFile.idl"
YourSecondCustomFile.idl文件开头,MIDL编译器不会在Folder1中搜索任何需要包含的.idl文件,导致编译失败。
但是,通过添加AdditionalIncludeDirectories MSBuild项目元数据,您可以影响将哪些文件夹作为附加包含目录传递给MIDL编译器。
因此,要指示MIDL编译器在编译YourSecondCustomFile.idl时搜索Folder1中的包含文件,请按以下方式修改MSBuild代码:
<ItemGroup>
  <Midl Include="Folder1\YourCustomFile.idl" />
  <Midl Include="Folder2\YourSecondCustomFile.idl">
    <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)Folder1</AdditionalIncludeDirectories>
  </Midl>
</ItemGroup>

ProjectDir 是一个MSBuild属性,它指向包含当前项目的目录(至少在C++项目中是这样)。; 用于分隔不同的目录。每个目录将作为单独的目录传递给MIDL编译器,以用于搜索包含文件。

这应该解决编译问题。我认为无法使用Visual Studio用户界面添加AdditionalIncludeDirectories项元数据,因此您应该在文本编辑器中直接编辑Visual Studio项目。

请注意,项元数据对于每个单独的MIDL文件是有效的,即对于引用其他MIDL文件的每个MIDL文件都必须添加AdditionalIncludeDirectories

如果您需要在多个AdditionalIncludeDirectories中具有相同的内容,则可以像这样在项目文件的其他位置定义属性:

<PropertyGroup>
  <AdditionalMidlIncludeDirectories>$(ProjectDir);$(ProjectDir)Folder1;$(ProjectDir)Folder2</AdditionalMidlIncludeDirectories>
</PropertyGroup>

然后你在所有地方都使用该属性。你可以将相同的AdditionalIncludeDirectories语句添加到每个MIDL中,这将确保相同的包含目录用于每个MIDL编译器调用:

<ItemGroup>
  <Midl Include="Folder1\YourCustomFile.idl">
    <AdditionalIncludeDirectories>$(AdditionalMidlIncludeDirectories)</AdditionalIncludeDirectories>
  </Midl>
  <Midl Include="Folder2\YourSecondCustomFile.idl">
    <AdditionalIncludeDirectories>$(AdditionalMidlIncludeDirectories)</AdditionalIncludeDirectories>
  </Midl>
</ItemGroup>

编辑:

如下方评论中所提到的,可以通过应用 MSBuild 的 ItemDefinitionGroup 来进一步简化代码。 ItemDefinitionGroup 用于向 MSBuild 项目项添加元数据,这意味着可以自动将 AdditionalIncludeDirectories 元数据添加到每个 Midl 元素中。 ItemDefinitionGroup 的定义如下:

<ItemDefinitionGroup>
  <Midl>
    <AdditionalIncludeDirectories>
      $(ProjectDir);
      $(ProjectDir)Folder1;
      $(ProjectDir)Folder2
    </AdditionalIncludeDirectories>
  </Midl>
</ItemDefinitionGroup>

这将简化Midl ItemGroup,如下所示:
<ItemGroup>
  <Midl Include="Folder1\YourCustomFile.idl" />
  <Midl Include="Folder2\YourSecondCustomFile.idl" />
</ItemGroup>

1
您可以使用 <ItemDefinitionGroup> 来为项目中的所有 Midl 项设置默认的 AdditionalIncludeDirectories 值,这样您就不需要为每个项单独指定了。 - Aaron Schultz
感谢您的输入。我之前不知道 MSBuild 的 ItemDefinitionGroup 元素。您的建议确实可行,我已经相应地更新了我的答案。 - ackh

2

正如您所述,虽然这很愚蠢,但 Microsoft 支持已经确认这不是一个错误。以下是可能的解决方法。

1. 使用 /I 开关

使用 /I 开关来指定 c:\firstc:\second,并且指定 import "Foo.idl" 而不是相对路径。

如果命令行过长,请指定响应文件。

2. 使用符号链接

使用符号链接或联接到包含目录中,将它们引用到一个已知目录下的单个层次结构中。然后您可以使用相对于该目录的路径。

预构建步骤可能用于维护符号链接。

MKLINK.exe 可以创建联接或符号链接。

3. 使用附加的构建步骤

创建一个附加的构建步骤,它将所需的文件复制到已知位置,然后从那里导入它们。


实际情况比 firstsecond 多一些,事实上我相信如果我添加所有可能的目录,我将超过最大命令行长度。 - Motti
@Motti,这就是响应文件的作用。 - Ben
这可能可以运行,但是对于大型项目来说,远远不能维护。如果Microsoft支持“/I”的明智语义,则会好得多。 - Motti

1

这是一次召集...

12年6个月后,我带着我的干草叉来了,准备出发。

与此同时,为了更容易地解决问题,您可以前往项目属性 -> MIDL -> 通用 -> 其他包含目录。将其设置为 "$(MSBuildProjectDirectory)\YourSubFolder" 即可正常工作。


1
谢谢光临!请把您的草叉放在角落里,一旦我们达到五个人的法定数量(预计约为2081年),我们就会冲击微软的办公室。 - Motti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接