为什么其他模块没有被编译?
我有两个文件:Main.d
和 ImportMe.d
。他们的目的应该是不言自明的。它们位于同一目录中,并且没有显式的模块声明。但是,当我尝试编译 Main.d
时,我收到“符号未找到”错误!
$ dmd Main.d -I.
Undefined symbols:
"_D8ImportMe12__ModuleInfoZ", referenced from:
_D4Main12__ModuleInfoZ in Main.o
"_D8ImportMe8SayHelloFxAyaZv", referenced from:
__Dmain in Main.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
--- errorlevel 1
同时编译这两个文件效果很好。
$ dmd Main.d ImportMe.d
不过,您不必使用标准库来执行此操作。它有什么不同之处?通过 -I
更改包含路径没有可见的效果。
I have two files: Main.d
and ImportMe.d
. Their purposes should be self-explanatory. They are in the same directory, and have no explicit module declaration. When I try to compile Main.d
, though, I get a "symbols not found" error!
$ dmd Main.d -I.
Undefined symbols:
"_D8ImportMe12__ModuleInfoZ", referenced from:
_D4Main12__ModuleInfoZ in Main.o
"_D8ImportMe8SayHelloFxAyaZv", referenced from:
__Dmain in Main.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
--- errorlevel 1
Compiling both files at the same time works fine.
$ dmd Main.d ImportMe.d
You don't have to do this with the standard library, though. What is it doing differently? Changing the include path via -I
has no visible effect.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
编译模块时,dmd 必须在其导入路径中包含该模块所需的所有模块的 .d 或 .di 文件。
-I
允许您将路径添加到导入路径。但是,这不会构建其他模块。它只是为 dmd 提供构建您请求其构建的模块所需的内容。当您链接时,dmd 需要程序中使用的所有模块的目标文件或库二进制文件,否则它将抱怨未定义的符号(-L
可用于链接器标志如果你想链接到库中)。链接步骤使用 C 链接器,因此它根本不了解 D,也不了解有关模块的任何信息。因此,如果分两步进行编译和链接,则首先单独编译每个模块或与其他模块一起编译,生成目标文件或库文件,具体取决于您传递给编译器的标志(目标文件是默认值)。然后,您可以在链接阶段将这些目标文件和库链接在一起,生成可执行文件。
当您使用 dmd 而不传递
-c
或-lib
时,它将同时进行编译和链接,因此您必须向其提供您需要的所有模块。打算编译,或者当它到达链接步骤时,它会抱怨未定义的符号。它不会神奇地编译您要求它编译导入的所有模块。如果您想要这种行为,您需要使用 rdmd 等工具。dmd 能够找到 druntime 和 Phobos,而无需您指定它们,因为 dmd.conf(在 Posix 上)或 sc.ini(在 Windows 上)。该配置文件将适当的 .d 和 .di 文件添加到导入路径,并将 libphobos.a 或 phobos.lib (取决于平台)添加到 DFLAGS ,以便 dmd 在编译时可以找到这些模块模块并可以在链接阶段链接到库中。它还添加了标准库工作所需的任何其他标志(例如 Linux 上的 librt 中的链接)。如果您将这些文件中的任何一个移动到非标准位置,则您需要更改该配置文件,以便 dmd 仍然可以找到它们。
When you compile a module, dmd must have the .d or .di files for all of the modules that that module needs in its import path.
-I
allows you to add paths to the import path. However, that does not build those other modules. It just gives dmd what it needs to build the module that you requested it to build. And when you link, dmd needs either the object files or the library binaries for all of the modules being used in the program, otherwise it's going to complain about undefined symbols (-L
can be used for linker flags if you want to link in libraries). The linking step uses the C linker, so it's not D-aware at all and doesn't know anything about modules.So, if you compile and link in two steps, you first compile each module separately or together with other modules, generating either object files or library files, depending on the flags that you pass the compiler (object files are the default). You then link those object files and libraries together in the linking stage, generating the executable.
When you use dmd without passing it
-c
or-lib
, it's going to do both the compiling and the linking together, so you must provide it all of the modules that you intend to compile, or when it gets to the linking step, it's going to complain about undefined symbols. It doesn't magically go and compile all of the modules that the modules that you ask it to compile import. If you want that sort of behavior, you need to use a tool such as rdmd.dmd is able to find druntime and Phobos without you having to specify them because of dmd.conf (on Posix) or sc.ini (on Windows). That configuration file adds the appropriate .d and .di files to the import path and adds libphobos.a or phobos.lib (depending on the platform) to
DFLAGS
so that dmd can find those modules when compiling your modules and can link in the library in the linking phase. It also adds in any other flags that the standard library needs to work (such as linking in librt on Linux). If you move any of those files to non-standard places, it's that configuration file that you need to change to make it so that dmd can still find them.您不必指定标准库中的模块,因为编译器会隐式地将预编译的标准库 .lib 文件传递给链接器。对于您自己的项目,请考虑使用 rdmd 或其他构建工具。
You don't have to specify modules from the standard library because the compiler implicitly passes the precompiled standard library .lib file to the linker. For your own projects, consider using rdmd or another build tool.