autodetect Visual Studio and linker options#7393
Conversation
|
Thanks for your pull request, @rainers! Bugzilla referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. |
src/ddmd/link.d
Outdated
| if(!key) | ||
| return def; | ||
|
|
||
| char[260] buf; |
src/ddmd/link.d
Outdated
| } | ||
| } | ||
|
|
||
| void Create(HKEY root, wstring keyname, bool x64hive = false) |
There was a problem hiding this comment.
I generally dislike using default arguments unless doing it for backwards compatibility. Since this is new code, please use explicit arguments.
src/ddmd/link.d
Outdated
| HRESULT hr; | ||
| } | ||
|
|
||
| const(char)* GetString(const(char)* szName, const(char)* def = null) |
src/ddmd/link.d
Outdated
| return def; | ||
|
|
||
| char[260] buf; | ||
| DWORD cnt = 260 * char.sizeof; |
There was a problem hiding this comment.
replace 260 with buf.length
src/ddmd/link.d
Outdated
| if (fileinfo.cFileName[0] >= '1' && fileinfo.cFileName[0] <= '9') | ||
| if (res is null || strcmp(res, fileinfo.cFileName.ptr) < 0) | ||
| if (FileName.exists(FileName.combine(FileName.combine(baseDir, fileinfo.cFileName.ptr), testfile))) | ||
| res = strdup(fileinfo.cFileName.ptr); |
There was a problem hiding this comment.
being in a loop, the res seems to be leaking memory upon reassignment
| while(FindNextFileA(h, &fileinfo)); | ||
| FindClose(h); | ||
|
|
||
| return res; |
There was a problem hiding this comment.
returning malloced memory should be documented
src/ddmd/link.d
Outdated
| res = strdup(fileinfo.cFileName.ptr); | ||
| } | ||
| while(FindNextFileA(h, &fileinfo)); | ||
| FindClose(h); |
There was a problem hiding this comment.
Return value is ignored - should check it for error
There was a problem hiding this comment.
Pretty unlikely to fail, and even if it does, should it abort a build?
src/ddmd/link.d
Outdated
|
|
||
| const(char)* GetString(const(char)* szName, const(char)* def = null) | ||
| { | ||
| if(!key) |
There was a problem hiding this comment.
Sometimes this PR uses if( and sometimes if (. Please use the latter style.
src/ddmd/link.d
Outdated
| { | ||
| if (!x64hive) | ||
| { | ||
| size_t len = strlen(szRegPath); |
src/ddmd/link.d
Outdated
| assert(len > 9 && szRegPath[0..9] == r"SOFTWARE\"); | ||
| char* npath = cast(char*)mem.xmalloc(len + 13); | ||
| strcpy(npath, r"SOFTWARE\WOW6432Node\"); | ||
| strcpy(npath + 21, szRegPath + 9); |
There was a problem hiding this comment.
Since in both calls to strcpy the lengths are known, use memcpy instead.
src/ddmd/link.d
Outdated
| { | ||
| pragma(lib, "advapi32.lib"); | ||
|
|
||
| this(HKEY root, const(char)* szRegPath, bool x64hive = false) |
src/ddmd/link.d
Outdated
| { | ||
| if(key) | ||
| { | ||
| RegCloseKey(key); |
src/ddmd/link.d
Outdated
|
|
||
| void Create(HKEY root, wstring keyname, bool x64hive = false) | ||
| { | ||
| HRESULT hr; |
There was a problem hiding this comment.
Declaration that is unused?
src/ddmd/link.d
Outdated
| const(char)* p; | ||
| alias p this; | ||
|
|
||
| PathBuilder opDiv(const(char)* name) |
There was a problem hiding this comment.
Please don't do non-arithmetic operator overloading.
src/ddmd/link.d
Outdated
|
|
||
| PathBuilder opDiv(const(char)* name) | ||
| { | ||
| if (!name) |
There was a problem hiding this comment.
The uses I see of PathBuilder suggest that name is never null, so this struct is kinda pointless. In fact, Filename.combine should do the right thing with a null second argument anyway. (I checked and it does not, so that should be fixed there, not adding a wrapper here.)
src/ddmd/link.d
Outdated
| auto sdk = PathBuilder(WindowsSdkDir) / "lib"; | ||
| if(FileName.exists(sdk / WindowsSdkVersion / "um" / arch / "kernel32.lib")) // SDK 10.0 | ||
| return sdk / WindowsSdkVersion / "um" / arch; | ||
| else if(FileName.exists(sdk / r"win8\um" / arch / "kernel32.lib")) // SDK 8.0 |
There was a problem hiding this comment.
I'd rather see a / b / c added as a function to root.filename, so it can be used elsewhere. It should use variadic parameters to list them, or an array literal, or even 2,3,4 parameter overloads.
There was a problem hiding this comment.
I introduced the PathBuilder struct because FileName.combine cannot be used with UFCS, but creates unreadable code if nesting multiple calls.
Using variadic parameters instead is almost as good, though, so I replaced PathBuilder with FileName.buildPath now.
src/ddmd/link.d
Outdated
| { | ||
| // debug info needs DLLs Common7\IDE for most linker versions | ||
| const char* path = getenv("PATH"); | ||
| const char* npath = FileName.combine(VSInstallDir, r"Common7\IDE"); |
There was a problem hiding this comment.
path and npath appear to never be used?
There was a problem hiding this comment.
Ooops, missing PATH modification.
| const(char)* VCInstallDir; | ||
| const(char)* VCToolsInstallDir; // used by VS 2017 | ||
|
|
||
| void initialize() |
There was a problem hiding this comment.
In general, all functions need Ddoc comments.
|
@WalterBright Thanks for review, I've addressed most comments. |
src/ddmd/link.d
Outdated
| } | ||
| } | ||
| while(FindNextFileA(h, &fileinfo)); | ||
| FindClose(h); |
There was a problem hiding this comment.
FindClose() returns 0 on failure. Please check it. https://msdn.microsoft.com/en-us/library/windows/desktop/aa364413(v=vs.85).aspx
There was a problem hiding this comment.
I know, but it feels a bit harsh to fail while a sensible result is already obtained. I've changed it nevertheless.
| { | ||
| enum x64hive = false; // VS registry entries always in 32-bit hive | ||
|
|
||
| version(Win64) |
There was a problem hiding this comment.
Wait a minute! Why would the 64 bit build of DMD behave differently here? Shouldn't this be if the memory model of the target is set to 64?
There was a problem hiding this comment.
No, the target architecture is not relevant here. The VS registry/Windows SDK keys are only found in the 32-bit registry hive. KEY_WOW64_32KEY doesn't seem good enough, I had to use WOW6432Node explicitly, while a 32-bit process is automatically mapped to that hive.
src/ddmd/link.d
Outdated
| } | ||
|
|
||
| /** | ||
| * retreive options to be passed to the Micrsoft linker |
There was a problem hiding this comment.
"retrieve", and "Microsoft"
src/ddmd/link.d
Outdated
| } | ||
|
|
||
| /** | ||
| * retreive path to the Micrsoft linker executable |
There was a problem hiding this comment.
"retrieve", and "Microsoft"
|
Much better. A couple more issues I commented on. I'm still not happy with the avoidable memory leaks, but it's not a deal breaker here. I do like how you fixed one leak by using realloc, I hadn't thought of that! |
FileName.combine sometimes returns newly allocated memory, sometimes one of the arguments. This makes it necessary to predict what happens if you want to free the memory later. As this is done nowhere else, I opted not to do it here for a few more hundred bytes of leakage. |
|
Could you please add a changelog entry mentioning that VC is now detected at link-time instead of at install-time. Should we remove the detection from the installer? |
|
Factoring this out into a separate dmd/windows_detect_vs module would make sense IMO. |
Will do.
Part of it. We might still want to allow the option of downloading VS if not found. Please note that the "light" runtime still needs the VC 2010 distributables. |
Done: #7493 |
This combines detection of latest VS and Windows SDK from Visual D and the DMD installer. All that is needed specific for -m64/-m32mscoff in sc.ini is
Releated bugzilla issues:
https://issues.dlang.org/show_bug.cgi?id=16688
https://issues.dlang.org/show_bug.cgi?id=17999
https://issues.dlang.org/show_bug.cgi?id=14849