aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/backend/vs2010backend.py
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2017-01-28 00:19:48 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2017-01-28 05:14:12 +0530
commit57ec097b5fb08081e458b2b4946ee5943ba8c032 (patch)
tree9b1337e9ea3b8df4102ed390fc568bcc1520904c /mesonbuild/backend/vs2010backend.py
parent991ace04afdd2eb010f8c94c00de7c3e1f197f60 (diff)
downloadmeson-57ec097b5fb08081e458b2b4946ee5943ba8c032.zip
meson-57ec097b5fb08081e458b2b4946ee5943ba8c032.tar.gz
meson-57ec097b5fb08081e458b2b4946ee5943ba8c032.tar.bz2
vs: Use CompilerArgs() for compile and link args
At the same time also fix the order in which they are added. They now match the order used in the Ninja backend.
Diffstat (limited to 'mesonbuild/backend/vs2010backend.py')
-rw-r--r--mesonbuild/backend/vs2010backend.py178
1 files changed, 117 insertions, 61 deletions
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 31a4c0e..f0d125d 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -23,6 +23,7 @@ from .. import dependencies
from .. import mlog
from .. import compilers
from ..build import BuildTarget
+from ..compilers import CompilerArgs
from ..mesonlib import MesonException, File
from ..environment import Environment
@@ -426,24 +427,25 @@ class Vs2010Backend(backends.Backend):
pch_out.text = '$(IntDir)$(TargetName)-%s.pch' % lang
def add_additional_options(self, lang, parent_node, file_args):
- if len(file_args[lang]) == 0:
- # We only need per file options if they were not set per project.
- return
- args = file_args[lang] + ['%(AdditionalOptions)']
+ args = []
+ for arg in file_args[lang].to_native():
+ if arg == '%(AdditionalOptions)':
+ args.append(arg)
+ else:
+ args.append(self.escape_additional_option(arg))
ET.SubElement(parent_node, "AdditionalOptions").text = ' '.join(args)
def add_preprocessor_defines(self, lang, parent_node, file_defines):
- if len(file_defines[lang]) == 0:
- # We only need per file options if they were not set per project.
- return
- defines = file_defines[lang] + ['%(PreprocessorDefinitions)']
+ defines = []
+ for define in file_defines[lang]:
+ if define == '%(PreprocessorDefinitions)':
+ defines.append(define)
+ else:
+ defines.append(self.escape_preprocessor_define(define))
ET.SubElement(parent_node, "PreprocessorDefinitions").text = ';'.join(defines)
def add_include_dirs(self, lang, parent_node, file_inc_dirs):
- if len(file_inc_dirs[lang]) == 0:
- # We only need per file options if they were not set per project.
- return
- dirs = file_inc_dirs[lang] + ['%(AdditionalIncludeDirectories)']
+ dirs = file_inc_dirs[lang]
ET.SubElement(parent_node, "AdditionalIncludeDirectories").text = ';'.join(dirs)
@staticmethod
@@ -668,29 +670,98 @@ class Vs2010Backend(backends.Backend):
# Arguments, include dirs, defines for all files in the current target
target_args = []
target_defines = []
- target_inc_dirs = ['.', self.relpath(self.get_target_private_dir(target),
- self.get_target_dir(target)),
- proj_to_src_dir] + generated_files_include_dirs
+ target_inc_dirs = []
# Arguments, include dirs, defines passed to individual files in
# a target; perhaps because the args are language-specific
- file_args = dict((lang, []) for lang in target.compilers)
+ #
+ # file_args is also later split out into defines and include_dirs in
+ # case someone passed those in there
+ file_args = dict((lang, CompilerArgs(comp)) for lang, comp in target.compilers.items())
file_defines = dict((lang, []) for lang in target.compilers)
file_inc_dirs = dict((lang, []) for lang in target.compilers)
- for l, args in self.environment.coredata.external_args.items():
+ # The order in which these compile args are added must match
+ # generate_single_compile() and generate_basic_compiler_args()
+ for l, comp in target.compilers.items():
+ if l in file_args:
+ file_args[l] += compilers.get_base_compile_args(self.environment.coredata.base_options, comp)
+ file_args[l] += comp.get_option_compile_args(self.environment.coredata.compiler_options)
+ # Add compile args added using add_project_arguments()
+ for l, args in self.build.projects_args.get(target.subproject, {}).items():
if l in file_args:
file_args[l] += args
+ # Add compile args added using add_global_arguments()
+ # These override per-project arguments
for l, args in self.build.global_args.items():
if l in file_args:
file_args[l] += args
- for l, args in self.build.projects_args.get(target.subproject, {}).items():
+ # Compile args added from the env: CFLAGS/CXXFLAGS, etc. We want these
+ # to override all the defaults, but not the per-target compile args.
+ for l, args in self.environment.coredata.external_args.items():
if l in file_args:
file_args[l] += args
+ for args in file_args.values():
+ # This is where Visual Studio will insert target_args, target_defines,
+ # etc, which are added later from external deps (see below).
+ args += ['%(AdditionalOptions)', '%(PreprocessorDefinitions)', '%(AdditionalIncludeDirectories)']
+ # Add include dirs from the `include_directories:` kwarg on the target
+ # and from `include_directories:` of internal deps of the target.
+ #
+ # Target include dirs should override internal deps include dirs.
+ #
+ # Include dirs from internal deps should override include dirs from
+ # external deps.
+ # These are per-target, but we still add them as per-file because we
+ # need them to be looked in first.
+ for d in target.get_include_dirs():
+ for i in d.get_incdirs():
+ curdir = os.path.join(d.get_curdir(), i)
+ args.append('-I' + self.relpath(curdir, target.subdir)) # build dir
+ args.append('-I' + os.path.join(proj_to_src_root, curdir)) # src dir
+ for i in d.get_extra_build_dirs():
+ curdir = os.path.join(d.get_curdir(), i)
+ args.append('-I' + self.relpath(curdir, target.subdir)) # build dir
+ # Add per-target compile args, f.ex, `c_args : ['/DFOO']`. We set these
+ # near the end since these are supposed to override everything else.
for l, args in target.extra_args.items():
if l in file_args:
- file_args[l] += compiler.unix_args_to_native(args)
- for l, comp in target.compilers.items():
- if l in file_args:
- file_args[l] += comp.get_option_compile_args(self.environment.coredata.compiler_options)
+ file_args[l] += args
+ # The highest priority includes. In order of directory search:
+ # target private dir, target build dir, generated sources include dirs,
+ # target source dir
+ for args in file_args.values():
+ t_inc_dirs = ['.', self.relpath(self.get_target_private_dir(target),
+ self.get_target_dir(target))]
+ t_inc_dirs += generated_files_include_dirs + [proj_to_src_dir]
+ args += ['-I' + arg for arg in t_inc_dirs]
+
+ # Split preprocessor defines and include directories out of the list of
+ # all extra arguments. The rest go into %(AdditionalOptions).
+ for l, args in file_args.items():
+ for arg in args[:]:
+ if arg.startswith(('-D', '/D')) or arg == '%(PreprocessorDefinitions)':
+ file_args[l].remove(arg)
+ # Don't escape the marker
+ if arg == '%(PreprocessorDefinitions)':
+ define = arg
+ else:
+ define = arg[2:]
+ # De-dup
+ if define in file_defines[l]:
+ file_defines[l].remove(define)
+ file_defines[l].append(define)
+ elif arg.startswith(('-I', '/I')) or arg == '%(AdditionalIncludeDirectories)':
+ file_args[l].remove(arg)
+ # Don't escape the marker
+ if arg == '%(AdditionalIncludeDirectories)':
+ inc_dir = arg
+ else:
+ inc_dir = arg[2:]
+ # De-dup
+ if inc_dir not in file_inc_dirs[l]:
+ file_inc_dirs[l].append(inc_dir)
+
+ # Split compile args needed to find external dependencies
+ # Link args are added while generating the link command
for d in target.get_external_deps():
# Cflags required by external deps might have UNIX-specific flags,
# so filter them out if needed
@@ -699,50 +770,22 @@ class Vs2010Backend(backends.Backend):
if arg.startswith(('-D', '/D')):
define = arg[2:]
# De-dup
- if define not in target_defines:
- target_defines.append(define)
+ if define in target_defines:
+ target_defines.remove(define)
+ target_defines.append(define)
elif arg.startswith(('-I', '/I')):
inc_dir = arg[2:]
# De-dup
if inc_dir not in target_inc_dirs:
target_inc_dirs.append(inc_dir)
else:
- # De-dup
- if arg not in target_args:
- target_args.append(arg)
-
- # Split preprocessor defines and include directories out of the list of
- # all extra arguments. The rest go into %(AdditionalOptions).
- for l, args in file_args.items():
- file_args[l] = []
- for arg in args:
- if arg.startswith(('-D', '/D')):
- define = self.escape_preprocessor_define(arg[2:])
- # De-dup
- if define not in file_defines[l]:
- file_defines[l].append(define)
- elif arg.startswith(('-I', '/I')):
- inc_dir = arg[2:]
- # De-dup
- if inc_dir not in file_inc_dirs[l]:
- file_inc_dirs[l].append(inc_dir)
- else:
- file_args[l].append(self.escape_additional_option(arg))
+ target_args.append(arg)
languages += gen_langs
if len(target_args) > 0:
target_args.append('%(AdditionalOptions)')
ET.SubElement(clconf, "AdditionalOptions").text = ' '.join(target_args)
- for d in target.include_dirs:
- for i in d.incdirs:
- curdir = os.path.join(d.curdir, i)
- target_inc_dirs.append(self.relpath(curdir, target.subdir)) # build dir
- target_inc_dirs.append(os.path.join(proj_to_src_root, curdir)) # src dir
- for i in d.get_extra_build_dirs():
- curdir = os.path.join(d.curdir, i)
- target_inc_dirs.append(self.relpath(curdir, target.subdir)) # build dir
-
target_inc_dirs.append('%(AdditionalIncludeDirectories)')
ET.SubElement(clconf, 'AdditionalIncludeDirectories').text = ';'.join(target_inc_dirs)
target_defines.append('%(PreprocessorDefinitions)')
@@ -773,19 +816,27 @@ class Vs2010Backend(backends.Backend):
resourcecompile = ET.SubElement(compiles, 'ResourceCompile')
ET.SubElement(resourcecompile, 'PreprocessorDefinitions')
+
+ # Linker options
link = ET.SubElement(compiles, 'Link')
- # Put all language args here, too.
- extra_link_args = compiler.get_option_link_args(self.environment.coredata.compiler_options)
+ extra_link_args = CompilerArgs(compiler)
# FIXME: Can these buildtype linker args be added as tags in the
# vcxproj file (similar to buildtype compiler args) instead of in
# AdditionalOptions?
extra_link_args += compiler.get_buildtype_linker_args(self.buildtype)
- for l in self.environment.coredata.external_link_args.values():
- extra_link_args += l
if not isinstance(target, build.StaticLibrary):
- extra_link_args += target.link_args
if isinstance(target, build.SharedModule):
extra_link_args += compiler.get_std_shared_module_link_args()
+ # Add link args added using add_project_link_arguments()
+ extra_link_args += self.build.get_project_link_args(compiler, target.subproject)
+ # Add link args added using add_global_link_arguments()
+ # These override per-project link arguments
+ extra_link_args += self.build.get_global_link_args(compiler)
+ # Link args added from the env: LDFLAGS. We want these to
+ # override all the defaults but not the per-target link args.
+ extra_link_args += self.environment.coredata.external_link_args[compiler.get_language()]
+ # Only non-static built targets need link args and link dependencies
+ extra_link_args += target.link_args
# External deps must be last because target link libraries may depend on them.
for dep in target.get_external_deps():
extra_link_args += dep.get_link_args()
@@ -793,8 +844,13 @@ class Vs2010Backend(backends.Backend):
if isinstance(d, build.StaticLibrary):
for dep in d.get_external_deps():
extra_link_args += dep.get_link_args()
- extra_link_args = compiler.unix_args_to_native(extra_link_args)
- (additional_libpaths, additional_links, extra_link_args) = self.split_link_args(extra_link_args)
+ # Add link args for c_* or cpp_* build options. Currently this only
+ # adds c_winlibs and cpp_winlibs when building for Windows. This needs
+ # to be after all internal and external libraries so that unresolved
+ # symbols from those can be found here. This is needed when the
+ # *_winlibs that we want to link to are static mingw64 libraries.
+ extra_link_args += compiler.get_option_link_args(self.environment.coredata.compiler_options)
+ (additional_libpaths, additional_links, extra_link_args) = self.split_link_args(extra_link_args.to_native())
if len(extra_link_args) > 0:
extra_link_args.append('%(AdditionalOptions)')
ET.SubElement(link, "AdditionalOptions").text = ' '.join(extra_link_args)