Add Visual Studio 2012/2013 backends (#8803)

* backends: Add a Visual Studio 2013 backend

This is more-or-less a quick port from the VS2015 backend, except that
we update the Visual Studio version strings and toolset versions
accordingly.  Also correct the generator string for Visual Studio 2015
in mesonbuild/cmake/common.py.

* backend: Add VS2012 backend

Similar to what we did for Visual Studio 2013, add a Visual Studio 2012
backend.

* vs2010backend.py: Implement `link_whole:` if needed

We actually need Visual Studio 2015 Update 2 to use `/WHOLEARCHIVE:`,
which is what we are currently using for `link_whole:` on Visual Studio.
For Visual Studio versions before that, we need to expand from the
static targets that were indicated by `link_whole:`, and any of the
sub-dependent targets that were pulled in via the dependent target's
`link_whole:`.  This wil ensure `link_whole:` would actually work in
such cases.

* vs2010backend.py: Handle objects from generated sources

Unforunately, we can't use backends.determine_ext_objs() reliably, as
the Visual Studio backends handle this differently.

* vs2010backend.py: Fix generating VS2010 projects

Visual Studio 2010 (at least the Express Edition) does not set the envvar
%VisualStudioVersion% in its command prompt, so fix generating VS2010
projects by taking account into this, so that we can determine the location
of vcvarsall.bat correctly.

* whole archive test: Disable on vs2012/2013 backends too

The Visual Studio 2012/2013 IDE has problems handling the items that would be
generated from this test case, so skip this test when using
--backend=vs[2012|2013].  This test does work for the Ninja backend when
VS2012 or VS2013 is used, though.

Consolidate this error message with XCode along with the vs2010 backend.

* docs: Add the new vs2012 and vs2013 backends

Let people know that we have backends for vs2012 and 2013.  Also let
people know that generating Visual Studio 2010 projects have been fixed
and the pre-vs2015 backends now handle the `link_whole:` project option.
pull/8921/head
fanc999 3 years ago committed by GitHub
parent 7588dbc587
commit edfe24178d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      docs/markdown/Builtin-options.md
  2. 4
      docs/markdown/Reference-manual.md
  3. 15
      docs/markdown/snippets/newvsbackends.md
  4. 6
      mesonbuild/backend/backends.py
  5. 36
      mesonbuild/backend/vs2010backend.py
  6. 38
      mesonbuild/backend/vs2012backend.py
  7. 38
      mesonbuild/backend/vs2013backend.py
  8. 4
      mesonbuild/cmake/common.py
  9. 2
      mesonbuild/coredata.py
  10. 11
      test cases/common/137 whole archive/meson.build

@ -69,7 +69,7 @@ machine](#specifying-options-per-machine) section for details.
| Option | Default value | Description | Is per machine | Is per subproject | | Option | Default value | Description | Is per machine | Is per subproject |
| ------ | ------------- | ----------- | -------------- | ----------------- | | ------ | ------------- | ----------- | -------------- | ----------------- |
| auto_features {enabled, disabled, auto} | auto | Override value of all 'auto' features | no | no | | auto_features {enabled, disabled, auto} | auto | Override value of all 'auto' features | no | no |
| backend {ninja, vs,<br>vs2010, vs2015, vs2017, vs2019, xcode} | ninja | Backend to use | no | no | | backend {ninja, vs,<br>vs2010, vs2012, vs2013, vs2015, vs2017, vs2019, xcode} | ninja | Backend to use | no | no |
| buildtype {plain, debug,<br>debugoptimized, release, minsize, custom} | debug | Build type to use | no | no | | buildtype {plain, debug,<br>debugoptimized, release, minsize, custom} | debug | Build type to use | no | no |
| debug | true | Debug | no | no | | debug | true | Debug | no | no |
| default_library {shared, static, both} | shared | Default library type | no | yes | | default_library {shared, static, both} | shared | Default library type | no | yes |

@ -1984,8 +1984,8 @@ the following methods.
*used as the `script_name` parameter. *used as the `script_name` parameter.
- `backend()` *(since 0.37.0)*: returns a string representing the - `backend()` *(since 0.37.0)*: returns a string representing the
current backend: `ninja`, `vs2010`, `vs2015`, `vs2017`, `vs2019`, current backend: `ninja`, `vs2010`, `vs2012`, `vs2013`, `vs2015`,
or `xcode`. `vs2017`, `vs2019`, or `xcode`.
- `build_root()`: returns a string with the absolute path to the build - `build_root()`: returns a string with the absolute path to the build
root directory. *(deprecated since 0.56.0)*: this function will return the root directory. *(deprecated since 0.56.0)*: this function will return the

@ -0,0 +1,15 @@
## New `vs2012` and `vs2013` backend options
Adds the ability to generate Visual Studio 2012 and 2013 projects. This is an
extension to the existing Visual Studio 2010 projects so that it is no longer
required to manually upgrade the generated Visual Studio 2010 projects.
Generating Visual Studio 2010 projects has also been fixed since its developer
command prompt does not provide a `%VisualStudioVersion%` envvar.
## Developer environment
Expand the support for the `link_whole:` project option for pre-Visual Studio 2015
Update 2, where previously Visual Studio 2015 Update 2 or later was required for
this, for the Ninja backend as well as the vs2010 (as well as the newly-added
vs2012 and vs2013 backends).

@ -199,6 +199,12 @@ def get_backend_from_name(backend: str, build: T.Optional[build.Build] = None, i
elif backend == 'vs2010': elif backend == 'vs2010':
from . import vs2010backend from . import vs2010backend
return vs2010backend.Vs2010Backend(build, interpreter) return vs2010backend.Vs2010Backend(build, interpreter)
elif backend == 'vs2012':
from . import vs2012backend
return vs2012backend.Vs2012Backend(build, interpreter)
elif backend == 'vs2013':
from . import vs2013backend
return vs2013backend.Vs2013Backend(build, interpreter)
elif backend == 'vs2015': elif backend == 'vs2015':
from . import vs2015backend from . import vs2015backend
return vs2015backend.Vs2015Backend(build, interpreter) return vs2015backend.Vs2015Backend(build, interpreter)

@ -27,7 +27,7 @@ from .. import mlog
from .. import compilers from .. import compilers
from ..interpreter import Interpreter from ..interpreter import Interpreter
from ..mesonlib import ( from ..mesonlib import (
MesonException, python_command, replace_if_different, OptionKey, File, MesonException, python_command, replace_if_different, OptionKey, version_compare,
) )
from ..environment import Environment, build_filename from ..environment import Environment, build_filename
@ -37,8 +37,14 @@ def autodetect_vs_version(build: T.Optional[build.Build], interpreter: T.Optiona
if not vs_install_dir: if not vs_install_dir:
raise MesonException('Could not detect Visual Studio: Environment variable VSINSTALLDIR is not set!\n' raise MesonException('Could not detect Visual Studio: Environment variable VSINSTALLDIR is not set!\n'
'Are you running meson from the Visual Studio Developer Command Prompt?') 'Are you running meson from the Visual Studio Developer Command Prompt?')
# VisualStudioVersion is set since Visual Studio 12.0, but sometimes # VisualStudioVersion is set since Visual Studio 11.0, but sometimes
# vcvarsall.bat doesn't set it, so also use VSINSTALLDIR # vcvarsall.bat doesn't set it, so also use VSINSTALLDIR
if vs_version == '11.0' or 'Visual Studio 11' in vs_install_dir:
from mesonbuild.backend.vs2012backend import Vs2012Backend
return Vs2012Backend(build, interpreter)
if vs_version == '12.0' or 'Visual Studio 12' in vs_install_dir:
from mesonbuild.backend.vs2013backend import Vs2013Backend
return Vs2013Backend(build, interpreter)
if vs_version == '14.0' or 'Visual Studio 14' in vs_install_dir: if vs_version == '14.0' or 'Visual Studio 14' in vs_install_dir:
from mesonbuild.backend.vs2015backend import Vs2015Backend from mesonbuild.backend.vs2015backend import Vs2015Backend
return Vs2015Backend(build, interpreter) return Vs2015Backend(build, interpreter)
@ -210,7 +216,7 @@ class Vs2010Backend(backends.Backend):
if 'VCINSTALLDIR' in os.environ: if 'VCINSTALLDIR' in os.environ:
vs_version = os.environ['VisualStudioVersion'] \ vs_version = os.environ['VisualStudioVersion'] \
if 'VisualStudioVersion' in os.environ else None if 'VisualStudioVersion' in os.environ else None
relative_path = 'Auxiliary\\Build\\' if vs_version >= '15.0' else '' relative_path = 'Auxiliary\\Build\\' if vs_version is not None and vs_version >= '15.0' else ''
script_path = os.environ['VCINSTALLDIR'] + relative_path + 'vcvarsall.bat' script_path = os.environ['VCINSTALLDIR'] + relative_path + 'vcvarsall.bat'
if os.path.exists(script_path): if os.path.exists(script_path):
if has_arch_values: if has_arch_values:
@ -1149,6 +1155,30 @@ class Vs2010Backend(backends.Backend):
lobj = self.build.targets[t.get_id()] lobj = self.build.targets[t.get_id()]
linkname = os.path.join(down, self.get_target_filename_for_linking(lobj)) linkname = os.path.join(down, self.get_target_filename_for_linking(lobj))
if t in target.link_whole_targets: if t in target.link_whole_targets:
if compiler.id == 'msvc' and version_compare(compiler.version, '<19.00.23918'):
# Expand our object lists manually if we are on pre-Visual Studio 2015 Update 2
l = t.extract_all_objects(False)
# Unforunately, we can't use self.object_filename_from_source()
gensrclist: T.List[File] = []
for gen in l.genlist:
for src in gen.get_outputs():
if self.environment.is_source(src) and not self.environment.is_header(src):
path = self.get_target_generated_dir(t, gen, src)
gen_src_ext = '.' + os.path.splitext(path)[1][1:]
extra_link_args.append(path[:-len(gen_src_ext)] + '.obj')
for src in l.srclist:
obj_basename = None
if self.environment.is_source(src) and not self.environment.is_header(src):
obj_basename = self.object_filename_from_source(t, src)
target_private_dir = self.relpath(self.get_target_private_dir(t),
self.get_target_dir(t))
rel_obj = os.path.join(target_private_dir, obj_basename)
extra_link_args.append(rel_obj)
extra_link_args.extend(self.flatten_object_list(t))
else:
# /WHOLEARCHIVE:foo must go into AdditionalOptions # /WHOLEARCHIVE:foo must go into AdditionalOptions
extra_link_args += compiler.get_link_whole_for(linkname) extra_link_args += compiler.get_link_whole_for(linkname)
# To force Visual Studio to build this project even though it # To force Visual Studio to build this project even though it

@ -0,0 +1,38 @@
# Copyright 2014-2016 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .vs2010backend import Vs2010Backend
from ..mesonlib import MesonException
from ..interpreter import Interpreter
from ..build import Build
import typing as T
class Vs2012Backend(Vs2010Backend):
def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter]):
super().__init__(build, interpreter)
self.name = 'vs2012'
self.vs_version = '2012'
if self.environment is not None:
# TODO: we assume host == build
comps = self.environment.coredata.compilers.host
if comps and all(c.id == 'intel-cl' for c in comps.values()):
c = list(comps.values())[0]
if c.version.startswith('19'):
self.platform_toolset = 'Intel C++ Compiler 19.0'
else:
# We don't have support for versions older than 2019 right now.
raise MesonException('There is currently no support for ICL before 19, patches welcome.')
if self.platform_toolset is None:
self.platform_toolset = 'v110'

@ -0,0 +1,38 @@
# Copyright 2014-2016 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .vs2010backend import Vs2010Backend
from ..mesonlib import MesonException
from ..interpreter import Interpreter
from ..build import Build
import typing as T
class Vs2013Backend(Vs2010Backend):
def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter]):
super().__init__(build, interpreter)
self.name = 'vs2013'
self.vs_version = '2013'
if self.environment is not None:
# TODO: we assume host == build
comps = self.environment.coredata.compilers.host
if comps and all(c.id == 'intel-cl' for c in comps.values()):
c = list(comps.values())[0]
if c.version.startswith('19'):
self.platform_toolset = 'Intel C++ Compiler 19.0'
else:
# We don't have support for versions older than 2019 right now.
raise MesonException('There is currently no support for ICL before 19, patches welcome.')
if self.platform_toolset is None:
self.platform_toolset = 'v120'

@ -39,7 +39,9 @@ backend_generator_map = {
'ninja': 'Ninja', 'ninja': 'Ninja',
'xcode': 'Xcode', 'xcode': 'Xcode',
'vs2010': 'Visual Studio 10 2010', 'vs2010': 'Visual Studio 10 2010',
'vs2015': 'Visual Studio 15 2017', 'vs2012': 'Visual Studio 11 2012',
'vs2013': 'Visual Studio 12 2013',
'vs2015': 'Visual Studio 14 2015',
'vs2017': 'Visual Studio 15 2017', 'vs2017': 'Visual Studio 15 2017',
'vs2019': 'Visual Studio 16 2019', 'vs2019': 'Visual Studio 16 2019',
} }

@ -44,7 +44,7 @@ if T.TYPE_CHECKING:
CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, str, T.Tuple[str, ...], str] CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, str, T.Tuple[str, ...], str]
version = '0.58.999' version = '0.58.999'
backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'vs2019', 'xcode'] backendlist = ['ninja', 'vs', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'vs2017', 'vs2019', 'xcode']
default_yielding = False default_yielding = False

@ -1,15 +1,14 @@
project('whole archive', 'c') project('whole archive', 'c')
if meson.backend() == 'xcode' if meson.backend() == 'xcode' or \
error('MESON_SKIP_TEST: whole-archive not supported in Xcode. Patches welcome.') meson.backend() == 'vs2010' or \
meson.backend() == 'vs2012' or \
meson.backend() == 'vs2013'
error('MESON_SKIP_TEST: whole-archive not supported in Xcode nor pre-VS2015 IDE. Patches welcome.')
endif endif
add_project_arguments('-I' + meson.source_root(), language : 'c') add_project_arguments('-I' + meson.source_root(), language : 'c')
if meson.backend() == 'vs2010'
error('MESON_SKIP_TEST whole-archive not supported in VS2010. Patches welcome.')
endif
# Test 1: link_whole keeps all symbols # Test 1: link_whole keeps all symbols
# Make static func1 # Make static func1
subdir('st_func1') subdir('st_func1')

Loading…
Cancel
Save