mirror of
https://github.com/dlang/dmd.git
synced 2025-04-27 21:51:03 +03:00
Fix bugzilla 24748 - DMD can't output object files with fully qualified name, making -od overwirte each other file
This commit is contained in:
parent
da9105bc4e
commit
64df340150
9 changed files with 73 additions and 6 deletions
15
changelog/dmd.oq.dd
Normal file
15
changelog/dmd.oq.dd
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
Add `-oq` switch to DMD
|
||||||
|
|
||||||
|
The switch gives fully qualified names to object files, preventing name conflicts when using the `-od` switch
|
||||||
|
while compiling multiple modules with the same name, but inside different packages.
|
||||||
|
The switch already existed in LDC, but is now in dmd as well.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
$(CONSOLE
|
||||||
|
dmd -c -oq -od=. app.d util/app.d misc/app.d
|
||||||
|
)
|
||||||
|
|
||||||
|
This will output `app.obj`, `util.app.obj`, and `misc.app.obj`, instead of just `app.obj`.
|
||||||
|
|
||||||
|
`-oq` also applies to other outputs, such as DDoc (`-D -Dd=.`) and .di header generation (`-H -Hd=.`).
|
|
@ -690,6 +690,12 @@ dmd -cov -unittest myprog.d
|
||||||
off when generating an object, interface, or Ddoc file
|
off when generating an object, interface, or Ddoc file
|
||||||
name. $(SWLINK -op) will leave it on.`,
|
name. $(SWLINK -op) will leave it on.`,
|
||||||
),
|
),
|
||||||
|
Option("oq",
|
||||||
|
"Write object files with fully qualified file names",
|
||||||
|
`When compiling pkg/app.d, the resulting object file name will be pkg_app.obj
|
||||||
|
instead of app.o. This helps to prevent name conflicts when compiling multiple
|
||||||
|
packages in the same directory with the $(SWLINK -od) flag.`,
|
||||||
|
),
|
||||||
Option("os=<os>",
|
Option("os=<os>",
|
||||||
"sets target operating system to <os>",
|
"sets target operating system to <os>",
|
||||||
`Set the target operating system as other than the host.
|
`Set the target operating system as other than the host.
|
||||||
|
|
|
@ -349,8 +349,8 @@ extern (C++) final class Module : Package
|
||||||
const(char)[] arg; // original argument name
|
const(char)[] arg; // original argument name
|
||||||
ModuleDeclaration* md; // if !=null, the contents of the ModuleDeclaration declaration
|
ModuleDeclaration* md; // if !=null, the contents of the ModuleDeclaration declaration
|
||||||
const FileName srcfile; // input source file
|
const FileName srcfile; // input source file
|
||||||
const FileName objfile; // output .obj file
|
FileName objfile; // output .obj file
|
||||||
const FileName hdrfile; // 'header' file
|
FileName hdrfile; // 'header' file
|
||||||
FileName docfile; // output documentation file
|
FileName docfile; // output documentation file
|
||||||
const(ubyte)[] src; /// Raw content of the file
|
const(ubyte)[] src; /// Raw content of the file
|
||||||
uint errors; // if any errors in file
|
uint errors; // if any errors in file
|
||||||
|
@ -579,6 +579,22 @@ extern (C++) final class Module : Package
|
||||||
argdoc = arg;
|
argdoc = arg;
|
||||||
else
|
else
|
||||||
argdoc = FileName.name(arg);
|
argdoc = FileName.name(arg);
|
||||||
|
|
||||||
|
if (global.params.fullyQualifiedObjectFiles)
|
||||||
|
{
|
||||||
|
const fqn = md ? md.toString() : toString();
|
||||||
|
argdoc = FileName.replaceName(argdoc, fqn);
|
||||||
|
|
||||||
|
// add ext, otherwise forceExt will make nested.module into nested.<ext>
|
||||||
|
const bufferLength = argdoc.length + 1 + ext.length + /* null terminator */ 1;
|
||||||
|
char[] s = new char[bufferLength];
|
||||||
|
s[0 .. argdoc.length] = argdoc[];
|
||||||
|
s[argdoc.length] = '.';
|
||||||
|
s[$-1-ext.length .. $-1] = ext[];
|
||||||
|
s[$-1] = 0;
|
||||||
|
argdoc = s;
|
||||||
|
}
|
||||||
|
|
||||||
// If argdoc doesn't have an absolute path, make it relative to dir
|
// If argdoc doesn't have an absolute path, make it relative to dir
|
||||||
if (!FileName.absolute(argdoc))
|
if (!FileName.absolute(argdoc))
|
||||||
{
|
{
|
||||||
|
|
|
@ -7020,8 +7020,8 @@ public:
|
||||||
_d_dynamicArray< const char > arg;
|
_d_dynamicArray< const char > arg;
|
||||||
ModuleDeclaration* md;
|
ModuleDeclaration* md;
|
||||||
const FileName srcfile;
|
const FileName srcfile;
|
||||||
const FileName objfile;
|
FileName objfile;
|
||||||
const FileName hdrfile;
|
FileName hdrfile;
|
||||||
FileName docfile;
|
FileName docfile;
|
||||||
_d_dynamicArray< const uint8_t > src;
|
_d_dynamicArray< const uint8_t > src;
|
||||||
uint32_t errors;
|
uint32_t errors;
|
||||||
|
@ -8112,6 +8112,7 @@ struct Param final
|
||||||
_d_dynamicArray< const char > resfile;
|
_d_dynamicArray< const char > resfile;
|
||||||
_d_dynamicArray< const char > exefile;
|
_d_dynamicArray< const char > exefile;
|
||||||
_d_dynamicArray< const char > mapfile;
|
_d_dynamicArray< const char > mapfile;
|
||||||
|
bool fullyQualifiedObjectFiles;
|
||||||
bool timeTrace;
|
bool timeTrace;
|
||||||
uint32_t timeTraceGranularityUs;
|
uint32_t timeTraceGranularityUs;
|
||||||
const char* timeTraceFile;
|
const char* timeTraceFile;
|
||||||
|
@ -8191,12 +8192,13 @@ struct Param final
|
||||||
resfile(),
|
resfile(),
|
||||||
exefile(),
|
exefile(),
|
||||||
mapfile(),
|
mapfile(),
|
||||||
|
fullyQualifiedObjectFiles(),
|
||||||
timeTrace(false),
|
timeTrace(false),
|
||||||
timeTraceGranularityUs(500u),
|
timeTraceGranularityUs(500u),
|
||||||
timeTraceFile()
|
timeTraceFile()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting warnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, CLIIdentifierTable dIdentifierTable = (CLIIdentifierTable)0u, CLIIdentifierTable cIdentifierTable = (CLIIdentifierTable)0u, _d_dynamicArray< const char > argv0 = {}, Array<const char* > modFileAliasStrings = Array<const char* >(), Array<const char* > imppath = Array<const char* >(), Array<const char* > fileImppath = Array<const char* >(), _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), uint32_t debuglevel = 0u, uint32_t versionlevel = 0u, bool run = false, Array<const char* > runargs = Array<const char* >(), Array<const char* > cppswitches = Array<const char* >(), const char* cpp = nullptr, Array<const char* > objfiles = Array<const char* >(), Array<const char* > linkswitches = Array<const char* >(), Array<bool > linkswitchIsForCC = Array<bool >(), Array<const char* > libfiles = Array<const char* >(), Array<const char* > dllfiles = Array<const char* >(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}, bool timeTrace = false, uint32_t timeTraceGranularityUs = 500u, const char* timeTraceFile = nullptr) :
|
Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting warnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, CLIIdentifierTable dIdentifierTable = (CLIIdentifierTable)0u, CLIIdentifierTable cIdentifierTable = (CLIIdentifierTable)0u, _d_dynamicArray< const char > argv0 = {}, Array<const char* > modFileAliasStrings = Array<const char* >(), Array<const char* > imppath = Array<const char* >(), Array<const char* > fileImppath = Array<const char* >(), _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), uint32_t debuglevel = 0u, uint32_t versionlevel = 0u, bool run = false, Array<const char* > runargs = Array<const char* >(), Array<const char* > cppswitches = Array<const char* >(), const char* cpp = nullptr, Array<const char* > objfiles = Array<const char* >(), Array<const char* > linkswitches = Array<const char* >(), Array<bool > linkswitchIsForCC = Array<bool >(), Array<const char* > libfiles = Array<const char* >(), Array<const char* > dllfiles = Array<const char* >(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}, bool fullyQualifiedObjectFiles = false, bool timeTrace = false, uint32_t timeTraceGranularityUs = 500u, const char* timeTraceFile = nullptr) :
|
||||||
obj(obj),
|
obj(obj),
|
||||||
multiobj(multiobj),
|
multiobj(multiobj),
|
||||||
trace(trace),
|
trace(trace),
|
||||||
|
@ -8278,6 +8280,7 @@ struct Param final
|
||||||
resfile(resfile),
|
resfile(resfile),
|
||||||
exefile(exefile),
|
exefile(exefile),
|
||||||
mapfile(mapfile),
|
mapfile(mapfile),
|
||||||
|
fullyQualifiedObjectFiles(fullyQualifiedObjectFiles),
|
||||||
timeTrace(timeTrace),
|
timeTrace(timeTrace),
|
||||||
timeTraceGranularityUs(timeTraceGranularityUs),
|
timeTraceGranularityUs(timeTraceGranularityUs),
|
||||||
timeTraceFile(timeTraceFile)
|
timeTraceFile(timeTraceFile)
|
||||||
|
|
|
@ -248,6 +248,8 @@ extern (C++) struct Param
|
||||||
const(char)[] exefile;
|
const(char)[] exefile;
|
||||||
const(char)[] mapfile;
|
const(char)[] mapfile;
|
||||||
|
|
||||||
|
bool fullyQualifiedObjectFiles; // prepend module names to object files to prevent name conflicts with -od
|
||||||
|
|
||||||
// Time tracing
|
// Time tracing
|
||||||
bool timeTrace = false; /// Whether profiling of compile time is enabled
|
bool timeTrace = false; /// Whether profiling of compile time is enabled
|
||||||
uint timeTraceGranularityUs = 500; /// In microseconds, minimum event size to report
|
uint timeTraceGranularityUs = 500; /// In microseconds, minimum event size to report
|
||||||
|
|
|
@ -250,6 +250,10 @@ struct Param
|
||||||
DString resfile;
|
DString resfile;
|
||||||
DString exefile;
|
DString exefile;
|
||||||
DString mapfile;
|
DString mapfile;
|
||||||
|
bool fullyQualifiedObjectFiles;
|
||||||
|
bool timeTrace;
|
||||||
|
uint32_t timeTraceGranularityUs;
|
||||||
|
const char* timeTraceFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct structalign_t
|
struct structalign_t
|
||||||
|
|
|
@ -453,6 +453,17 @@ private int tryMain(size_t argc, const(char)** argv, ref Param params)
|
||||||
// m.deleteObjFile();
|
// m.deleteObjFile();
|
||||||
|
|
||||||
m.parse();
|
m.parse();
|
||||||
|
|
||||||
|
// Finalize output filenames. Update if `-oq` was specified (only feasible after parsing).
|
||||||
|
if (params.fullyQualifiedObjectFiles && m.md)
|
||||||
|
{
|
||||||
|
m.objfile = m.setOutfilename(params.objname, params.objdir, m.arg, FileName.ext(m.objfile.toString()));
|
||||||
|
if (m.docfile)
|
||||||
|
m.setDocfile();
|
||||||
|
if (m.hdrfile)
|
||||||
|
m.hdrfile = m.setOutfilename(params.dihdr.name, params.dihdr.dir, m.arg, hdr_ext);
|
||||||
|
}
|
||||||
|
|
||||||
if (m.filetype == FileType.dhdr)
|
if (m.filetype == FileType.dhdr)
|
||||||
{
|
{
|
||||||
// Remove m's object file from list of object files
|
// Remove m's object file from list of object files
|
||||||
|
|
|
@ -1286,6 +1286,11 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param
|
||||||
goto Lerror;
|
goto Lerror;
|
||||||
params.preservePaths = true;
|
params.preservePaths = true;
|
||||||
break;
|
break;
|
||||||
|
case 'q':
|
||||||
|
if (p[3])
|
||||||
|
goto Lerror;
|
||||||
|
params.fullyQualifiedObjectFiles = true;
|
||||||
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
error("-o no longer supported, use -of or -od");
|
error("-o no longer supported, use -of or -od");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
# -Xf=<filename>
|
# -Xf=<filename>
|
||||||
|
|
||||||
src_file=${OUTPUT_BASE}/src.d
|
src_file=${OUTPUT_BASE}/src.d
|
||||||
|
src_file_in_pkg=${OUTPUT_BASE}/pkg/src.d
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
{
|
{
|
||||||
|
@ -26,6 +27,8 @@ prepare()
|
||||||
mkdir -p ${OUTPUT_BASE}
|
mkdir -p ${OUTPUT_BASE}
|
||||||
echo "module mymod;" > ${OUTPUT_BASE}/mymod.d
|
echo "module mymod;" > ${OUTPUT_BASE}/mymod.d
|
||||||
echo "module src; import mymod;" > ${src_file}
|
echo "module src; import mymod;" > ${src_file}
|
||||||
|
mkdir ${OUTPUT_BASE}/pkg
|
||||||
|
echo "module pkg.src;" > ${src_file_in_pkg}
|
||||||
}
|
}
|
||||||
|
|
||||||
die()
|
die()
|
||||||
|
@ -59,7 +62,9 @@ $DMD -o- -od=${OUTPUT_BASE} -D -Df=${OUTPUT_BASE}/src.html -Hf=${OUTPUT_BASE}/sr
|
||||||
checkFiles;
|
checkFiles;
|
||||||
|
|
||||||
prepare;
|
prepare;
|
||||||
$DMD -o- -od=${OUTPUT_BASE} -D -Dd=${OUTPUT_BASE} -Hd=${OUTPUT_BASE} -I=${OUTPUT_BASE} -L=-v -Xf=${OUTPUT_BASE}/json.json ${src_file}
|
$DMD -o- -oq -od=${OUTPUT_BASE} -D -Dd=${OUTPUT_BASE} -Hd=${OUTPUT_BASE} -I=${OUTPUT_BASE} -L=-v -Xf=${OUTPUT_BASE}/json.json ${src_file} ${src_file_in_pkg}
|
||||||
checkFiles;
|
checkFiles;
|
||||||
|
checkFile ${OUTPUT_BASE}/pkg.src.di
|
||||||
|
checkFile ${OUTPUT_BASE}/pkg.src.html
|
||||||
|
|
||||||
clean;
|
clean;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue