fix Issue 10711 - shared phobos library should not depend on _Dmain#2476
fix Issue 10711 - shared phobos library should not depend on _Dmain#2476MartinNowak merged 1 commit intodlang:masterfrom
Conversation
|
Once it's pulled, I'll remove entrypoint.d from druntime. |
|
Alternatively we could compile entrypoint.d as a separate object file/library which is only linked when an executable is built. I don't know which approach is best. |
I felt that having yet another library would be confusing to users. |
|
Another library might be, but a single object file inside druntime.lib should do this correctly without any hardcoding in the compiler. The linker should be capable of only pulling in the object file if main is needed, right? |
|
Also needs dlang/druntime#572 |
That works fine as long as druntime is a library. When it's a DLL, then that code is always there, and as the bug report says, _Dmain will be undefined if you attempt to load it from a C++ program. |
|
Doesn't that mean you just exclude the object file when building druntime as a dll? We have to link it differently anyway, so there it doesn't need to be the exact same objects. (I could be wrong here) |
Then it doesn't work with a D main(). libphobos.so must work when loaded by both a C++ program or a D program. |
Why not? |
So you are proposing there should be two libraries... Throwing in a third possibility. I had initially envisioned that cmain would be in it's own object file that gets pushed into the linker command at the end of compilation, eg: This wouldn't be different from gcc with compiling in crtstart.o and crtend.o into C programs. |
Because it says "_Dmain is undefined" when you try to link a C++ program that does not have a D main() in it to libphobos.so, because libphobos.so will have a reference to _Dmain. Look at entrypoint.d, it references _Dmain. |
|
@ibuclaw That's exactly what I suggested, or at least tried to. |
|
@WalterBright The C main and D main functions should be in the same object file. |
That's what this pull does. |
|
|
We have a couple of uses case here:
(Have I missed a uses case?) Necessary libraries/object files:
This is how it will link with the different use cases:
|
Exactly, which is why it fixes the problem. |
What happens then when you try to build an executable without providing a D main function? |
I chose a method that makes it unnecessary to deal with entrypoint.o. The idea is to minimize user-facing problems. |
When linking with libphobos.so, you get a lovely message "_Dmain is undefined" from the linker, as http://d.puremagic.com/issues/show_bug.cgi?id=10711 shows. |
How is that possible when https://github.com/D-Programming-Language/druntime/blob/master/src/rt/entrypoint.d#L27 If you remove that you won't get any linker errors? |
|
Note the use case - writing a C++ program and loading "plugin" DLLs written in D. There is no D main() or D entry point - yet it must still work. |
|
See my comment above: #2476 (comment) |
It's referenced from entrypoint.d.
And then your D programs all fail because libphobos2.so is never initialized and your D main() never gets called. |
And my reply: I chose a method that makes it unnecessary to deal with entrypoint.o. The idea is to minimize user-facing problems. |
You are removing it with this pull request: dlang/druntime#572 and I can't see it being added by this one.
Yes, exactly, but as I said above, you're removing it. |
|
@jacob-carlborg I just don't know what you're getting at. Yes, this pull and the druntime one work together to REMOVE the entrypoint code from the library and puts it in the compiler. That way it's there when it's needed and not there when it isn't. |
If it wasn't obvious, the compiler will automatically link with entrypoint.o if it builds an executable. I don't see what the user-facing problems are. |
|
Yes, and I replied: I chose a method that makes it unnecessary to deal with entrypoint.o. The idea is to minimize user-facing problems. The user-facing problems is he has to add entrypoint.o in his makefiles (if he is linking with other than dmd) and entrypoint.o must be generated in all its incarnations, and inserted into the right locations on the user's machine.
On Windows: No crash. |
src/func.c
Outdated
There was a problem hiding this comment.
This sizeof is not auto-portable to D. sizeof(code) / sizeof(code[0]) will work, or strlen(code)
There was a problem hiding this comment.
I'm not aware of any case where sizeof(code) will not work, as 'char' in any usable (with D) C++ compiler has size 1.
There was a problem hiding this comment.
In D sizeof(code) will give 4, as code is a char *.
There was a problem hiding this comment.
sizeof(code) -> code.length :o)
|
Another user facing problem is linking: Does dmd add in entrypoint.o or not? dmd doesn't look inside .o files that it is linking to see if there's a _Dmain in them. Those files may contain a C main() and the user is doing his own initialization. If those files are creating a plugin, adding in entrypoint.o will cause errors. |
|
Ok, I got a linker error for the C main function: I guess that's ok. |
It's the same as with dmd before this change. |
No, currently, without this change, it complains about an undefined _Dmain symbol. |
|
On windows I get (with the old dmd) the same no start address message. I suppose Linux is different. |
Which instantly tells you 'whoops' I forgot to put in an
a. Static library => b. Shared library => Hypothetically there could be a rare instance when the user for whatever reason puts in their own
|
|
@ibuclaw or we could have the D compiler itself generate the entrypoint code, and then there's no need to add a compiler switch, add more documentation explaining it, manage entrypoint.o, add complex logic to the compiler to decide whether or not to add in entrypoint.o, tell people they have to modify their makefiles, answer user questions about what entrypoint.o is and why their setup can't find it, etc. It's 3 lines of code. |
|
@ibuclaw dmd can generate library files directly - there's no need to use ar or ranlib. Also, shared libraries certainly can have a D main() in them. Granted, this is unusual. I develop with my own extern(C) main in a D program when I am porting D to a new platform. It's usually because there's no phobos library to link with yet. As for dmd generating functions, it already does that in several other cases. Why not add the necessary wrapper code if a D main() is encountered? |
|
@WalterBright - don't doubt you for a moment there. I've never honestly looked at what dmd can/can't do in link.c - infact I've never even looked at link.c... Shared libraries could have a D main, but D main does not depend on entrypoint.o, so there is no problem with this. A program written in C/C++ could have the following which calls the D main from the library. However if the compiler generates and emits a C main upon seeing a D main... When porting to a new platform, there's chance that there's no druntime library to link with either - For example I started off on ARM this way before getting things to a usable level, then added in druntime, then phobos into the library. In Debian ports, there are also no library included with the D compiler for them (SPARC, IA64, PPC, MIPS), and I expect a similar thing to be done when we finally get round to porting druntime/phobos to these platforms. So automatically generating a C main becomes unhelpful in the event that no _d_run_main exists in the library/no library to link to. I assume other cases you are referring to array ops / typeinfo (eg: core functionality)? |
There was a problem hiding this comment.
It should take the address of _Dmain not main. Also the declaration extern(C) int _Dmain(char[][] args); is missing.
There was a problem hiding this comment.
It should take the address of _Dmain not main
The symbol is referred to as "main" inside the D code. _Dmain is unknown.
Also the declaration extern(C) int _Dmain(char[][] args); is missing.
No, it's not, as this code is compiled in the context of D main().
There was a problem hiding this comment.
Ah, just saw that while testing. Works fine.
There was a problem hiding this comment.
This change broke my pull#2130. In the context of the module which declares D main(), &main is essentially ambiguous between extern(C) main and extern(D) main.
I'm trying to fix the issue in #2130. @WalterBright , could you please see my fix?
There was a problem hiding this comment.
@WalterBright I opened a PR #2540 for better C-main addition.
Similar argument, when you compile an object file with a D main function but use a different linker then entrypoint.o would be missing, i.e. we would force people to use dmd for linking which would likely break some build tools.
Then you can't have a D main but have to start with a C main. Despite the issue the change looks good. |
|
fix Issue 10711 - shared phobos library should not depend on _Dmain
Then you'd miss all kind of startup code and C initialization.
If you don't have a runtime you can easily start from an earlier entry point like C's main or define a custom one. |
|
Change is still borderline compiler specific as it depends on that the rt/ modules match what dmd comes shipped with, with a leniency towards that we'll be linking against a shared library (something that for the time being, absolutely zero of your work on shared library/dso has been merged in and it will never be merged in as far as the forseeable future holds). |
http://d.puremagic.com/issues/show_bug.cgi?id=10711
This moves code that was formerly in druntime's src/rt/entrypoint.d into the compiler itself.