digitalmars.D.learn - DMD Refuses to Compile Multiple Source Files
- Samwise (38/38) Jan 17 2017 Alright. For the sake of this argument, I'm going to post all the
- James Buren (2/2) Jan 17 2017 Import the source file containing the external function instead
- Samwise (6/8) Jan 17 2017 This seems like a workaround more than a permanent solution. It
- Stefan Koch (5/14) Jan 17 2017 In extern (D) functions (which is the default)
- Samwise (11/26) Jan 17 2017 Without changing anything about the hello.d file from above, and
- ketmar (3/8) Jan 17 2017 yep. *both* prototype and real declaration should be `extern(C)`.
- Samwise (3/12) Jan 17 2017 I have both the header in hello.d and the actual function in
- ketmar (2/5) Jan 17 2017 nope. it works.
- Mike Parker (6/20) Jan 17 2017 extern(C), not simply extern. It turns off the name mangling. But
- Samwise (7/14) Jan 18 2017 Alright, so I misunderstood what ketmar was saying. His solution
- Nicholas Wilson (4/21) Jan 18 2017 Yes. Take a look at some random projects from code.dlang.org and
- Samwise (2/2) Jan 18 2017 Thanks loads. I got it working using those modules.
- Mike Parker (49/57) Jan 18 2017 First, let's get some terminology straightened out. This:
- Mike Parker (3/5) Jan 18 2017 Sorry, this should read "make the implementations available to
- Samwise (6/11) Mar 07 2017 Alright, so I misunderstood what ketmar was saying. His solution
Alright. For the sake of this argument, I'm going to post all the stuff about a really tiny boring program that quite literally does nothing, even though I found this issue when I was working with a much larger project with more functions. Basically I'm getting errors when I attempt to compile multiple source files using the DMD. It does not matter whether it's through dub or just straight DMD. A few little code snippets and DMD output (The dub output is basically the same as the DMD, just with a few more lines): hello.d (This file contains the main function, as you can see. I put the headers in here to simplify things.): import std.stdio; int getReturnCode(); int main() { writeln("Hello World!"); return getReturnCode(); } getReturnCode.d (This file is the home of my cute function, which does nothing...): int getReturnCode() { return 4; } Those were the complete contents of my two basic program files. The Compilation works fine (Can generate both object files using the -c switch with the DMD). However, it just stops when linking... $ dmd getReturnCode.d hello.d getReturnCode.o: In function `_Dmain': hello.d:(.text._Dmain+0x17): undefined reference to `_D5hello13getReturnCodeFZi' collect2: error: ld returned 1 exit status --- errorlevel 1 This basic output is what I'm getting whenever I try to compile a main function using a function call that is for a function not included in the main.d, regardless of pretty much any other thing. Thank you for reading and at least attempting to help me solve this issue... ~Sam
Jan 17 2017
Import the source file containing the external function instead of writing that prototype. It should compile then.
Jan 17 2017
On Wednesday, 18 January 2017 at 02:48:45 UTC, James Buren wrote:Import the source file containing the external function instead of writing that prototype. It should compile then.This seems like a workaround more than a permanent solution. It would work, but still. I'm also not sure about the syntax for that (Given that getReturnCode.d is in the same directory as hello.d). ~Sam
Jan 17 2017
On Wednesday, 18 January 2017 at 03:11:08 UTC, Samwise wrote:On Wednesday, 18 January 2017 at 02:48:45 UTC, James Buren wrote:In extern (D) functions (which is the default) The module name is part of the mangled name. What you are trying to do would work , if the getReturnType would be extern(C).Import the source file containing the external function instead of writing that prototype. It should compile then.This seems like a workaround more than a permanent solution. It would work, but still. I'm also not sure about the syntax for that (Given that getReturnCode.d is in the same directory as hello.d). ~Sam
Jan 17 2017
On Wednesday, 18 January 2017 at 03:25:47 UTC, Stefan Koch wrote:On Wednesday, 18 January 2017 at 03:11:08 UTC, Samwise wrote:Without changing anything about the hello.d file from above, and the only change being adding the extern keyword to the getReturnValue.d like this: extern int getReturnCode() { return 4; } still does not compile using the command from above. I may very well be misunderstanding you though. I've not been doing this particularly long... ~SamOn Wednesday, 18 January 2017 at 02:48:45 UTC, James Buren wrote:In extern (D) functions (which is the default) The module name is part of the mangled name. What you are trying to do would work , if the getReturnType would be extern(C).Import the source file containing the external function instead of writing that prototype. It should compile then.This seems like a workaround more than a permanent solution. It would work, but still. I'm also not sure about the syntax for that (Given that getReturnCode.d is in the same directory as hello.d). ~Sam
Jan 17 2017
On Wednesday, 18 January 2017 at 03:37:46 UTC, Samwise wrote:extern int getReturnCode() { return 4; } still does not compile using the command from above. I may very well be misunderstanding you though.yep. *both* prototype and real declaration should be `extern(C)`. `(C)` part is important too!
Jan 17 2017
On Wednesday, 18 January 2017 at 03:51:50 UTC, ketmar wrote:On Wednesday, 18 January 2017 at 03:37:46 UTC, Samwise wrote:I have both the header in hello.d and the actual function in getReturnCode.d as extern, and it still fails with the same error.extern int getReturnCode() { return 4; } still does not compile using the command from above. I may very well be misunderstanding you though.yep. *both* prototype and real declaration should be `extern(C)`. `(C)` part is important too!
Jan 17 2017
On Wednesday, 18 January 2017 at 04:06:23 UTC, Samwise wrote:I have both the header in hello.d and the actual function in getReturnCode.d as extern, and it still fails with the same error.nope. it works.
Jan 17 2017
On Wednesday, 18 January 2017 at 04:06:23 UTC, Samwise wrote:On Wednesday, 18 January 2017 at 03:51:50 UTC, ketmar wrote:extern(C), not simply extern. It turns off the name mangling. But really, the proper thing to do is to drop the prototype and import the module with the implementation. It's tge way modules are intended to be used. Unless you're doing something specidic like writing a library that calls an arbitrary user function.On Wednesday, 18 January 2017 at 03:37:46 UTC, Samwise wrote:I have both the header in hello.d and the actual function in getReturnCode.d as extern, and it still fails with the same error.extern int getReturnCode() { return 4; } still does not compile using the command from above. I may very well be misunderstanding you though.yep. *both* prototype and real declaration should b `extern(C)`. `(C)` part is important too!
Jan 17 2017
On Wednesday, 18 January 2017 at 04:25:42 UTC, Mike Parker wrote:extern(C), not simply extern. It turns off the name mangling. But really, the proper thing to do is to drop the prototype and import the module with the implementation. It's tge way modules are intended to be used. Unless you're doing something specidic like writing a library that calls an arbitrary user function.Alright, so I misunderstood what ketmar was saying. His solution did work. I'm just not sure I understand what you are trying to say here:But really, the proper thing to do is to drop the prototype and import the module with the implementation.This will still preserve my multiple source files, without worrying about the headers, right? Thanks, ~Sam
Jan 18 2017
On Wednesday, 18 January 2017 at 19:28:20 UTC, Samwise wrote:On Wednesday, 18 January 2017 at 04:25:42 UTC, Mike Parker wrote:Yes. Take a look at some random projects from code.dlang.org and look at the way they have laid out their modules and what they import and from where.extern(C), not simply extern. It turns off the name mangling. But really, the proper thing to do is to drop the prototype and import the module with the implementation. It's tge way modules are intended to be used. Unless you're doing something specidic like writing a library that calls an arbitrary user function.Alright, so I misunderstood what ketmar was saying. His solution did work. I'm just not sure I understand what you are trying to say here:But really, the proper thing to do is to drop the prototype and import the module with the implementation.This will still preserve my multiple source files, without worrying about the headers, right? Thanks, ~Sam
Jan 18 2017
Thanks loads. I got it working using those modules. ~Sam
Jan 18 2017
On Wednesday, 18 January 2017 at 19:28:20 UTC, Samwise wrote:Alright, so I misunderstood what ketmar was saying. His solution did work. I'm just not sure I understand what you are trying to say here:First, let's get some terminology straightened out. This: int getReturnCode(); is not a "header". It's a function declaration (or function prototype). Both C and C++ are sensitive to the location of declarations and implementations, i.e. you can't call a function or use a type unless it has been declared or implemented before the point at which it is called: ``` // Error! funcA is used before it is declared void funcB() { funcA(); } void funcA() { ... } ``` The example can be fixed by either moving the implementation of funcA above the implementation of funkB, or adding a prototype of funcA above funkB: ``` void funcA(); void funcB() { funcA(); } void funcA() { ... } ``` In C and C++, a "header" is a file that is used to collect publicly usable type and function declarations in one place. This saves the work of declaring them in every source file that needs them. D was designed with a module system to avoid the need for function prototypes and header files. You can still use them, as they are handy when interfacing with C and C++ programs, but they are not required. D is also not sensitive to the location of type and function implementations. The first example above would not be an error in D. You can implement a function before or after its point of use. So the D way is to forego the use of function prototypes entirely. You implement your functions and types in modules (source files), then use the import statement to make the declarations in other modules. So your initial example becomes: ``` // main.d import std.stdio; import returncode; int main() { writeln("Hello World!"); return getReturnCode(); } // returncode.d module returncode; int getReturnCode() { return 4; } ```But really, the proper thing to do is to drop the prototype and import the module with the implementation.This will still preserve my multiple source files, without worrying about the headers, right? Thanks, ~Sam
Jan 18 2017
On Wednesday, 18 January 2017 at 23:12:15 UTC, Mike Parker wrote:(source files), then use the import statement to make the declarations in other modules.Sorry, this should read "make the implementations available to other modules".
Jan 18 2017
On Wednesday, 18 January 2017 at 04:25:42 UTC, Mike Parker wrote:extern(C), not simply extern. It turns off the name mangling. But really, the proper thing to do is to drop the prototype and import the module with the implementation. It's tge way modules are intended to be used. Unless you're doing something specidic like writing a library that calls an arbitrary user function.Alright, so I misunderstood what ketmar was saying. His solution did work. I'm just not sure I understand what you are trying to say here: I've started using dub for things, and I've learned a lot since this thread. Anyway, thanks for the support with this everybody.
Mar 07 2017