aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/backend/backends.py32
-rw-r--r--mesonbuild/backend/ninjabackend.py9
-rw-r--r--mesonbuild/backend/vs2010backend.py62
-rw-r--r--test cases/common/110 extract same name/lib.c3
-rw-r--r--test cases/common/110 extract same name/main.c6
-rw-r--r--test cases/common/110 extract same name/meson.build6
-rw-r--r--test cases/common/110 extract same name/src/lib.c3
7 files changed, 80 insertions, 41 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 8d0b0f6..d352b8b 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -142,7 +142,7 @@ class Backend():
return os.path.relpath(os.path.join('dummyprefixdir', todir),\
os.path.join('dummyprefixdir', fromdir))
- def flatten_object_list(self, target, proj_dir_to_build_root='', include_dir_names=True):
+ def flatten_object_list(self, target, proj_dir_to_build_root=''):
obj_list = []
for obj in target.get_objects():
if isinstance(obj, str):
@@ -150,7 +150,7 @@ class Backend():
self.build_to_src, target.get_subdir(), obj)
obj_list.append(o)
elif isinstance(obj, build.ExtractedObjects):
- obj_list += self.determine_ext_objs(obj, proj_dir_to_build_root, include_dir_names)
+ obj_list += self.determine_ext_objs(obj, proj_dir_to_build_root)
else:
raise MesonException('Unknown data type in object list.')
return obj_list
@@ -210,28 +210,21 @@ class Backend():
return c
raise RuntimeError('Unreachable code')
- def determine_ext_objs(self, extobj, proj_dir_to_build_root='', include_dir_names=True):
+ def object_filename_from_source(self, target, source):
+ return source.fname.replace('/', '_').replace('\\', '_') + '.' + self.environment.get_object_suffix()
+
+ def determine_ext_objs(self, extobj, proj_dir_to_build_root=''):
result = []
targetdir = self.get_target_private_dir(extobj.target)
- suffix = '.' + self.environment.get_object_suffix()
for osrc in extobj.srclist:
- osrc_base = osrc.fname
- if not self.source_suffix_in_objs:
- osrc_base = '.'.join(osrc.split('.')[:-1])
# If extracting in a subproject, the subproject
# name gets duplicated in the file name.
pathsegs = osrc.subdir.split(os.sep)
if pathsegs[0] == 'subprojects':
pathsegs = pathsegs[2:]
fixedpath = os.sep.join(pathsegs)
- if include_dir_names:
- objbase = osrc_base.replace('/', '_').replace('\\', '_')
- else:
- # vs2010 backend puts all obj files without directory prefixes into build dir, so just
- # use the file name without a directory (will be stripped by os.path.basename() below).
- objbase = osrc_base
- objname = os.path.join(proj_dir_to_build_root,
- targetdir, os.path.basename(objbase) + suffix)
+ objname = os.path.join(proj_dir_to_build_root, targetdir,
+ self.object_filename_from_source(extobj.target, osrc))
result.append(objname)
return result
@@ -388,6 +381,15 @@ class Backend():
exe_arr = exe.get_command()
return exe_arr
+ def replace_extra_args(self, args, genlist):
+ final_args = []
+ for a in args:
+ if a == '@EXTRA_ARGS@':
+ final_args += genlist.get_extra_args()
+ else:
+ final_args.append(a)
+ return final_args
+
def eval_custom_target_command(self, target, absolute_paths=False):
if not absolute_paths:
ofilenames = [os.path.join(self.get_target_dir(target), i) for i in target.output]
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 8e8fa42..f5c992c 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -129,7 +129,6 @@ class NinjaBackend(backends.Backend):
def __init__(self, build):
super().__init__(build)
- self.source_suffix_in_objs = True
self.ninja_filename = 'build.ninja'
self.fortran_deps = {}
self.all_outputs = {}
@@ -1349,13 +1348,7 @@ rule FORTRAN_DEP_HACK
relout = self.get_target_private_dir(target)
args = [x.replace("@SOURCE_DIR@", self.build_to_src).replace("@BUILD_DIR@", relout)
for x in args]
- final_args = []
- for a in args:
- if a == '@EXTRA_ARGS@':
- final_args += genlist.get_extra_args()
- else:
- final_args.append(a)
- cmdlist = exe_arr + final_args
+ cmdlist = exe_arr + self.replace_extra_args(args, genlist)
elem = NinjaBuildElement(self.all_outputs, outfiles, 'CUSTOM_COMMAND', infilename)
if len(extra_dependencies) > 0:
elem.add_dep(extra_dependencies)
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index f06f5f6..d345f3d 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -16,6 +16,8 @@ import os, sys
import pickle
from mesonbuild import compilers
+from mesonbuild.build import BuildTarget
+from mesonbuild.mesonlib import File
from . import backends
from .. import build
from .. import dependencies
@@ -35,8 +37,35 @@ class Vs2010Backend(backends.Backend):
def __init__(self, build):
super().__init__(build)
self.project_file_version = '10.0.30319.1'
- # foo.c compiles to foo.obj, not foo.c.obj
- self.source_suffix_in_objs = False
+ self.sources_conflicts = {}
+
+ def object_filename_from_source(self, target, source):
+ basename = os.path.basename(source.fname)
+ filename_without_extension = '.'.join(basename.split('.')[:-1])
+ if basename in self.sources_conflicts[target.get_id()]:
+ # If there are multiple source files with the same basename, we must resolve the conflict
+ # by giving each a unique object output file.
+ filename_without_extension = '.'.join(source.fname.split('.')[:-1]).replace('/', '_').replace('\\', '_')
+ return filename_without_extension + '.' + self.environment.get_object_suffix()
+
+ def resolve_source_conflicts(self):
+ for name, target in self.build.targets.items():
+ if not isinstance(target, BuildTarget):
+ continue
+ conflicts = {}
+ for s in target.get_sources():
+ if hasattr(s, 'held_object'):
+ s = s.held_object
+ if not isinstance(s, File):
+ continue
+ basename = os.path.basename(s.fname)
+ conflicting_sources = conflicts.get(basename, None)
+ if conflicting_sources is None:
+ conflicting_sources = []
+ conflicts[basename] = conflicting_sources
+ conflicting_sources.append(s)
+ self.sources_conflicts[target.get_id()] = {name: src_conflicts for name, src_conflicts in conflicts.items()
+ if len(src_conflicts) > 1}
def generate_custom_generator_commands(self, target, parent_node):
all_output_files = []
@@ -51,26 +80,24 @@ class Vs2010Backend(backends.Backend):
exe = generator.get_exe()
infilelist = genlist.get_infilelist()
outfilelist = genlist.get_outfilelist()
- if isinstance(exe, build.BuildTarget):
- exe_file = os.path.join(self.environment.get_build_dir(), self.get_target_filename(exe))
- else:
- exe_file = exe.get_command()[0]
+ exe_arr = self.exe_object_to_cmd_array(exe)
base_args = generator.get_arglist()
+ target_private_dir = self.relpath(self.get_target_private_dir(target), self.get_target_dir(target))
for i in range(len(infilelist)):
if len(infilelist) == len(outfilelist):
- sole_output = os.path.join(self.get_target_private_dir(target), outfilelist[i])
+ sole_output = os.path.join(target_private_dir, outfilelist[i])
else:
sole_output = ''
curfile = infilelist[i]
infilename = os.path.join(self.environment.get_source_dir(), curfile)
outfiles = genlist.get_outputs_for(curfile)
- outfiles = [os.path.join(self.get_target_private_dir(target), of) for of in outfiles]
+ outfiles = [os.path.join(target_private_dir, of) for of in outfiles]
all_output_files += outfiles
args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output)\
for x in base_args]
- args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()).replace("@BUILD_DIR@", self.get_target_private_dir(target))
+ args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()).replace("@BUILD_DIR@", target_private_dir)
for x in args]
- fullcmd = [exe_file] + args
+ fullcmd = exe_arr + self.replace_extra_args(args, genlist)
commands.append(' '.join(self.special_quote(fullcmd)))
inputs.append(infilename)
outputs.extend(outfiles)
@@ -86,6 +113,7 @@ class Vs2010Backend(backends.Backend):
return all_output_files
def generate(self, interp):
+ self.resolve_source_conflicts()
self.interpreter = interp
self.platform = 'Win32'
self.buildtype = self.environment.coredata.get_builtin_option('buildtype')
@@ -522,7 +550,7 @@ class Vs2010Backend(backends.Backend):
linkname = os.path.join(rel_path, lobj.get_import_filename())
additional_links.append(linkname)
additional_objects = []
- for o in self.flatten_object_list(target, down, include_dir_names=False):
+ for o in self.flatten_object_list(target, down):
assert(isinstance(o, str))
additional_objects.append(o)
if len(additional_links) > 0:
@@ -551,11 +579,7 @@ class Vs2010Backend(backends.Backend):
relpath = h.rel_to_builddir(proj_to_src_root)
ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath)
for h in gen_hdrs:
- if isinstance(h, str):
- relpath = h
- else:
- relpath = h.rel_to_builddir(proj_to_src_root)
- ET.SubElement(inc_hdrs, 'CLInclude', Include = relpath)
+ ET.SubElement(inc_hdrs, 'CLInclude', Include=h)
if len(sources) + len(gen_src) + len(pch_sources) > 0:
inc_src = ET.SubElement(root, 'ItemGroup')
for s in sources:
@@ -563,9 +587,11 @@ class Vs2010Backend(backends.Backend):
inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath)
self.add_pch(inc_cl, proj_to_src_dir, pch_sources, s)
self.add_additional_options(s, inc_cl, extra_args, additional_options_set)
+ basename = os.path.basename(s.fname)
+ if basename in self.sources_conflicts[target.get_id()]:
+ ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + self.object_filename_from_source(target, s)
for s in gen_src:
- relpath = self.relpath(s, target.subdir)
- inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath)
+ inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=s)
self.add_pch(inc_cl, proj_to_src_dir, pch_sources, s)
self.add_additional_options(s, inc_cl, extra_args, additional_options_set)
for lang in pch_sources:
diff --git a/test cases/common/110 extract same name/lib.c b/test cases/common/110 extract same name/lib.c
new file mode 100644
index 0000000..6bdeda7
--- /dev/null
+++ b/test cases/common/110 extract same name/lib.c
@@ -0,0 +1,3 @@
+int func1() {
+ return 23;
+}
diff --git a/test cases/common/110 extract same name/main.c b/test cases/common/110 extract same name/main.c
new file mode 100644
index 0000000..dc57dd5
--- /dev/null
+++ b/test cases/common/110 extract same name/main.c
@@ -0,0 +1,6 @@
+int func1();
+int func2();
+
+int main(int argc, char **argv) {
+ return !(func1() == 23 && func2() == 42);
+}
diff --git a/test cases/common/110 extract same name/meson.build b/test cases/common/110 extract same name/meson.build
new file mode 100644
index 0000000..9384c47
--- /dev/null
+++ b/test cases/common/110 extract same name/meson.build
@@ -0,0 +1,6 @@
+project('object extraction', 'c')
+
+lib = shared_library('somelib', ['lib.c', 'src/lib.c'])
+obj = lib.extract_objects(['lib.c', 'src/lib.c'])
+exe = executable('main', 'main.c', objects: obj)
+test('extraction', exe)
diff --git a/test cases/common/110 extract same name/src/lib.c b/test cases/common/110 extract same name/src/lib.c
new file mode 100644
index 0000000..68e6ab9
--- /dev/null
+++ b/test cases/common/110 extract same name/src/lib.c
@@ -0,0 +1,3 @@
+int func2() {
+ return 42;
+}