Skip to content

Commit bbbd94f

Browse files
committed
Maintain same environment for dmd -run
1 parent 44d849e commit bbbd94f

4 files changed

Lines changed: 85 additions & 10 deletions

File tree

src/dmd/dinifile.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ void updateRealEnvironment(StringTable* environment)
153153
memcpy(s + namelen + 1, value, valuelen);
154154
s[namelen + 1 + valuelen] = 0;
155155
//printf("envput('%s')\n", s);
156-
putenv(s);
156+
//putenv(s);
157157
return 0; // do all of them
158158
}
159159

src/dmd/link.d

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,27 @@ version (Windows) extern (C) int putenv(const char*);
3232
version (Windows) extern (C) int spawnlp(int, const char*, const char*, const char*, const char*);
3333
version (Windows) extern (C) int spawnl(int, const char*, const char*, const char*, const char*);
3434
version (Windows) extern (C) int spawnv(int, const char*, const char**);
35+
36+
string getenv2(const(char)* name)
37+
{
38+
auto result = getenv(name);
39+
return cast(string)result[0 .. strlen(result)];
40+
}
41+
int putenv2(const char[] name, const(char)* value)
42+
{
43+
return putenv2(name, value[0 .. strlen(value)]);
44+
}
45+
int putenv2(const char[] name, const char[] value)
46+
{
47+
auto fullLength = name.length + 1 + value.length;
48+
auto buffer = cast(char*)alloca(fullLength + 1);
49+
buffer[0 .. name.length] = name[];
50+
buffer[name.length] = '=';
51+
buffer[name.length + 1 .. fullLength ] = value[];
52+
buffer[fullLength] = '\0';
53+
return putenv(buffer);
54+
}
55+
3556
version (CRuntime_Microsoft)
3657
{
3758
// until the new windows bindings are available when building dmd.
@@ -151,6 +172,37 @@ version (Posix)
151172
}
152173
}
153174

175+
/**
176+
Use to restore an environment variable when this structure goes out of scope.
177+
*/
178+
struct EnvRestore(string varName)
179+
{
180+
private string _saved;
181+
private bool restore;
182+
183+
/**
184+
Access the saved environment variable value.
185+
*/
186+
string saved() const { return _saved; }
187+
188+
/**
189+
Call before the overriding the environment variable to save and restore it later.
190+
*/
191+
void saveToRestoreLater()
192+
{
193+
_saved = getenv2(varName);
194+
restore = true;
195+
}
196+
197+
~this()
198+
{
199+
if (restore)
200+
{
201+
putenv2(varName, _saved);
202+
}
203+
}
204+
}
205+
154206
/*****************************
155207
* Run the linker. Return status of execution.
156208
*/
@@ -264,8 +316,9 @@ public int runLINK()
264316
const(char)* linkcmd = getenv(global.params.is64bit ? "LINKCMD64" : "LINKCMD");
265317
if (!linkcmd)
266318
linkcmd = getenv("LINKCMD"); // backward compatible
319+
auto restorePATH = EnvRestore!"PATH"();
267320
if (!linkcmd)
268-
linkcmd = vsopt.linkerPath(global.params.is64bit);
321+
linkcmd = vsopt.linkerPath(global.params.is64bit, restorePATH);
269322

270323
int status = executecmd(linkcmd, p);
271324
if (lnkfilename)
@@ -738,15 +791,16 @@ version (Windows)
738791
{
739792
int status;
740793
size_t len;
794+
auto restore_CMDLINE = EnvRestore!"_CMDLINE"();
795+
741796
if (global.params.verbose)
742797
message("%s %s", cmd, args);
743798
if (!global.params.mscoff)
744799
{
745800
if ((len = strlen(args)) > 255)
746801
{
747-
char* q = cast(char*)alloca(8 + len + 1);
748-
sprintf(q, "_CMDLINE=%s", args);
749-
status = putenv(q);
802+
restore_CMDLINE.saveToRestoreLater();
803+
int status = putenv2("_CMDLINE", args);
750804
if (status == 0)
751805
{
752806
args = "@_CMDLINE";
@@ -1018,7 +1072,7 @@ version (Windows)
10181072
* Returns:
10191073
* absolute path to link.exe, just "link.exe" if not found
10201074
*/
1021-
const(char)* linkerPath(bool x64)
1075+
const(char)* linkerPath(bool x64, ref EnvRestore!"PATH" restorePATH)
10221076
{
10231077
const(char)* addpath;
10241078
if (auto p = getVCBinDir(x64, addpath))
@@ -1030,15 +1084,15 @@ version (Windows)
10301084
{
10311085
// debug info needs DLLs from $(VSInstallDir)\Common7\IDE for most linker versions
10321086
// so prepend it too the PATH environment variable
1033-
const char* path = getenv("PATH");
1034-
const pathlen = strlen(path);
1087+
restorePATH.saveToRestoreLater();
1088+
const char[] path = restorePATH.saved;
10351089
const addpathlen = strlen(addpath);
10361090

1037-
char* npath = cast(char*)mem.xmalloc(5 + pathlen + 1 + addpathlen + 1);
1091+
char* npath = cast(char*)mem.xmalloc(5 + path.length + 1 + addpathlen + 1);
10381092
memcpy(npath, "PATH=".ptr, 5);
10391093
memcpy(npath + 5, addpath, addpathlen);
10401094
npath[5 + addpathlen] = ';';
1041-
memcpy(npath + 5 + addpathlen + 1, path, pathlen + 1);
1095+
memcpy(npath + 5 + addpathlen + 1, path.ptr, path.length + 1);
10421096
putenv(npath);
10431097
}
10441098
return cmdbuf.extractString();
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import std.array, std.stdio, std.process, std.algorithm;
2+
void main()
3+
{
4+
foreach (varPair; environment.toAA().byKeyValue.array.sort!"a.key < b.key")
5+
{
6+
if (varPair.key != "_")
7+
{
8+
writeln(varPair.key, "=", varPair.value);
9+
}
10+
}
11+
}

test/runnable/sameenv.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env bash
2+
3+
$DMD -m${MODEL} -of${OUTPUT_BASE}/printenv${EXE} ${EXTRA_FILES}/printenv.d
4+
${OUTPUT_BASE}/printenv${EXE} > ${OUTPUT_BASE}/envFromExe.txt
5+
6+
$DMD -m${MODEL} -run ${EXTRA_FILES}/printenv.d > ${OUTPUT_BASE}/envFromRun.txt
7+
8+
diff -p ${OUTPUT_BASE}/envFromExe.txt ${OUTPUT_BASE}/envFromRun.txt
9+
10+
rm -f ${OUTPUT_BASE}/*

0 commit comments

Comments
 (0)