Skip to content

Commit

Permalink
Maintain same environment for dmd -run
Browse files Browse the repository at this point in the history
Fix issue 18729
  • Loading branch information
marler8997 committed Apr 5, 2018
1 parent 44d849e commit 462442a
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 10 deletions.
68 changes: 59 additions & 9 deletions src/dmd/link.d
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,23 @@ version (Windows) extern (C) int putenv(const char*);
version (Windows) extern (C) int spawnlp(int, const char*, const char*, const char*, const char*);
version (Windows) extern (C) int spawnl(int, const char*, const char*, const char*, const char*);
version (Windows) extern (C) int spawnv(int, const char*, const char**);

string dgetenv(const(char)* name)
{
auto result = getenv(name);
return cast(string)result[0 .. strlen(result)];
}
int dputenv(const char[] name, const char[] value)
{
auto fullLength = name.length + 1 + value.length;
auto buffer = cast(char*)alloca(fullLength + 1);
buffer[0 .. name.length] = name[];
buffer[name.length] = '=';
buffer[name.length + 1 .. fullLength ] = value[];
buffer[fullLength] = '\0';
return putenv(buffer);
}

version (CRuntime_Microsoft)
{
// until the new windows bindings are available when building dmd.
Expand Down Expand Up @@ -151,6 +168,37 @@ version (Posix)
}
}

/**
Use to restore an environment variable when this structure goes out of scope.
*/
struct EnvRestore(string varName)
{
private string savedValue;
private bool restore;

/**
Access the saved environment variable value.
*/
string getSavedValue() const { return savedValue; }

/**
Call before the overriding the environment variable to save and restore it later.
*/
void saveToRestoreLater()
{
savedValue = dgetenv(varName);
restore = true;
}

~this()
{
if (restore)
{
dputenv(varName, savedValue);
}
}
}

/*****************************
* Run the linker. Return status of execution.
*/
Expand Down Expand Up @@ -264,8 +312,9 @@ public int runLINK()
const(char)* linkcmd = getenv(global.params.is64bit ? "LINKCMD64" : "LINKCMD");
if (!linkcmd)
linkcmd = getenv("LINKCMD"); // backward compatible
auto restorePATH = EnvRestore!"PATH"();
if (!linkcmd)
linkcmd = vsopt.linkerPath(global.params.is64bit);
linkcmd = vsopt.linkerPath(global.params.is64bit, restorePATH);

int status = executecmd(linkcmd, p);
if (lnkfilename)
Expand Down Expand Up @@ -738,15 +787,16 @@ version (Windows)
{
int status;
size_t len;
auto restore_CMDLINE = EnvRestore!"_CMDLINE"();

if (global.params.verbose)
message("%s %s", cmd, args);
if (!global.params.mscoff)
{
if ((len = strlen(args)) > 255)
{
char* q = cast(char*)alloca(8 + len + 1);
sprintf(q, "_CMDLINE=%s", args);
status = putenv(q);
restore_CMDLINE.saveToRestoreLater();
status = dputenv("_CMDLINE", args[0 .. len]);
if (status == 0)
{
args = "@_CMDLINE";
Expand Down Expand Up @@ -1018,7 +1068,7 @@ version (Windows)
* Returns:
* absolute path to link.exe, just "link.exe" if not found
*/
const(char)* linkerPath(bool x64)
const(char)* linkerPath(bool x64, ref EnvRestore!"PATH" restorePATH)
{
const(char)* addpath;
if (auto p = getVCBinDir(x64, addpath))
Expand All @@ -1030,15 +1080,15 @@ version (Windows)
{
// debug info needs DLLs from $(VSInstallDir)\Common7\IDE for most linker versions
// so prepend it too the PATH environment variable
const char* path = getenv("PATH");
const pathlen = strlen(path);
restorePATH.saveToRestoreLater();
const char[] path = restorePATH.getSavedValue;
const addpathlen = strlen(addpath);

char* npath = cast(char*)mem.xmalloc(5 + pathlen + 1 + addpathlen + 1);
char* npath = cast(char*)mem.xmalloc(5 + path.length + 1 + addpathlen + 1);
memcpy(npath, "PATH=".ptr, 5);
memcpy(npath + 5, addpath, addpathlen);
npath[5 + addpathlen] = ';';
memcpy(npath + 5 + addpathlen + 1, path, pathlen + 1);
memcpy(npath + 5 + addpathlen + 1, path.ptr, path.length + 1);
putenv(npath);
}
return cmdbuf.extractString();
Expand Down
3 changes: 2 additions & 1 deletion src/dmd/mars.d
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,8 @@ private int tryMain(size_t argc, const(char)** argv)
sections.push(envsection.ptr);
parseConfFile(&environment, global.inifilename, inifilepath, inifile.len, inifile.buffer, &sections);
getenv_setargv(readFromEnv(&environment, "DFLAGS"), &arguments);
updateRealEnvironment(&environment);
// TODO: not sure why dmd is doing this
//updateRealEnvironment(&environment);
environment.reset(1); // don't need environment cache any more

if (parseCommandLine(arguments, argc, global.params, files))
Expand Down
11 changes: 11 additions & 0 deletions test/runnable/extra-files/printenv.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import std.array, std.stdio, std.process, std.algorithm;
void main()
{
foreach (varPair; environment.toAA().byKeyValue.array.sort!"a.key < b.key")
{
if (varPair.key != "_")
{
writeln(varPair.key, "=", varPair.value);
}
}
}
10 changes: 10 additions & 0 deletions test/runnable/sameenv.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash

$DMD -m${MODEL} -of${OUTPUT_BASE}/printenv${EXE} ${EXTRA_FILES}/printenv.d
${OUTPUT_BASE}/printenv${EXE} > ${OUTPUT_BASE}/envFromExe.txt

$DMD -m${MODEL} -run ${EXTRA_FILES}/printenv.d > ${OUTPUT_BASE}/envFromRun.txt

diff -p ${OUTPUT_BASE}/envFromExe.txt ${OUTPUT_BASE}/envFromRun.txt

rm -f ${OUTPUT_BASE}/*

0 comments on commit 462442a

Please sign in to comment.