aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Reference-manual.md11
-rw-r--r--docs/markdown/snippets/winsubsystem.md22
-rw-r--r--mesonbuild/backend/ninjabackend.py5
-rw-r--r--mesonbuild/backend/vs2010backend.py9
-rw-r--r--mesonbuild/build.py23
-rw-r--r--mesonbuild/compilers/compilers.py7
-rw-r--r--mesonbuild/compilers/mixins/gnu.py14
-rw-r--r--mesonbuild/compilers/mixins/visualstudio.py3
-rw-r--r--test cases/windows/16 gui app/meson.build11
9 files changed, 94 insertions, 11 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 8bff428..c1e509e 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -599,8 +599,9 @@ be passed to [shared and static libraries](#library).
- `extra_files`: not used for the build itself but are shown as
source files in IDEs that group files by targets (such as Visual
Studio)
-- `gui_app`: when set to true flags this target as a GUI application on
- platforms where this makes a difference (e.g. Windows).
+- `gui_app`: when set to true flags this target as a GUI application
+ on platforms where this makes a differerence, **deprecated** since
+ 0.56.0, use `win_subsystem` instead.
- `link_args`: flags to use during linking. You can use UNIX-style
flags here for all platforms.
- `link_depends`: strings, files, or custom targets the link step
@@ -677,6 +678,12 @@ be passed to [shared and static libraries](#library).
- `pie` *(since 0.49.0)*: build a position-independent executable
- `native`: is a boolean controlling whether the target is compiled for the
build or host machines. Defaults to false, building for the host machine.
+- `win_subsystem` *(since 0.56.0)* specifies the subsystem type to use
+ on the Windows platform. Typical values include `console` for text
+ mode programs and `windows` for gui apps. The value can also contain
+ version specification such as `windows,6.0'. See [MSDN
+ documentation](https://docs.microsoft.com/en-us/cpp/build/reference/subsystem-specify-subsystem)
+ for the full list. The default value is `console`.
The list of `sources`, `objects`, and `dependencies` is always
flattened, which means you can freely nest and add lists while
diff --git a/docs/markdown/snippets/winsubsystem.md b/docs/markdown/snippets/winsubsystem.md
new file mode 100644
index 0000000..a7d589f
--- /dev/null
+++ b/docs/markdown/snippets/winsubsystem.md
@@ -0,0 +1,22 @@
+## Add support for all Windows subsystem types
+
+It is now possible to build things like Windows kernel drivers with
+the new `win_subsystem` keyword argument. This replaces the old
+`gui_app` keyword argument, which is now deprecated. You should update
+your project to use the new style like this:
+
+```meson
+# Old way
+executable(..., gui_app: 'true')
+# New way
+executable(..., win_subsystem: 'windows')
+```
+
+The argument supports versioning [as described on MSDN
+documentation](https://docs.microsoft.com/en-us/cpp/build/reference/subsystem-specify-subsystem).
+Thus to build a Windows kernel driver with a specific version you'd
+write something like this:
+
+```meson
+executable(..., win_subsystem: 'native,6.02')
+```
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index f816b1d..2ffbb85 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2587,7 +2587,10 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
# If gui_app is significant on this platform, add the appropriate linker arguments.
# Unfortunately this can't be done in get_target_type_link_args, because some misguided
# libraries (such as SDL2) add -mwindows to their link flags.
- commands += linker.get_gui_app_args(target.gui_app)
+ if target.gui_app is not None:
+ commands += linker.get_gui_app_args(target.gui_app)
+ else:
+ commands += linker.get_win_subsystem_args(target.win_subsystem)
return commands
def get_link_whole_args(self, linker, target):
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 86ddc1d..08360d3 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -754,8 +754,13 @@ class Vs2010Backend(backends.Backend):
self.handled_target_deps[target.get_id()] = []
if isinstance(target, build.Executable):
conftype = 'Application'
- if not target.gui_app:
- subsystem = 'Console'
+ if target.gui_app is not None:
+ if not target.gui_app:
+ subsystem = 'Console'
+ else:
+ # If someone knows how to set the version properly,
+ # please send a patch.
+ subsystem = target.win_subsystem.split(',')[0]
elif isinstance(target, build.StaticLibrary):
conftype = 'StaticLibrary'
elif isinstance(target, build.SharedLibrary):
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index be97634..8d2a22f 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -88,6 +88,7 @@ buildtarget_kwargs = set([
'sources',
'gnu_symbol_visibility',
'link_language',
+ 'win_subsystem',
])
known_build_target_kwargs = (
@@ -924,11 +925,21 @@ This will become a hard error in a future Meson release.''')
raise InvalidArguments('Main class must be a string')
self.main_class = main_class
if isinstance(self, Executable):
- self.gui_app = kwargs.get('gui_app', False)
- if not isinstance(self.gui_app, bool):
- raise InvalidArguments('Argument gui_app must be boolean.')
+ # This kwarg is deprecated. The value of "none" means that the kwarg
+ # was not specified and win_subsystem should be used instead.
+ self.gui_app = None
+ if 'gui_app' in kwargs:
+ mlog.deprecation('The gui_app kwarg is deprecated, use win_subsystem instead.')
+ if 'win_subsystem' in kwargs:
+ raise InvalidArguments('Can specify only gui_app or win_subsystem for a target, not both.')
+ self.gui_app = kwargs['gui_app']
+ if not isinstance(self.gui_app, bool):
+ raise InvalidArguments('Argument gui_app must be boolean.')
+ self.win_subsystem = self.validate_win_subsystem(kwargs.get('win_subsystem', 'console'))
elif 'gui_app' in kwargs:
raise InvalidArguments('Argument gui_app can only be used on executables.')
+ elif 'win_subsystem' in kwargs:
+ raise InvalidArguments('Argument win_subsystem can only be used on executables.')
extra_files = extract_as_list(kwargs, 'extra_files')
for i in extra_files:
assert(isinstance(i, File))
@@ -1000,6 +1011,12 @@ This will become a hard error in a future Meson release.''')
if self.gnu_symbol_visibility not in permitted:
raise InvalidArguments('GNU symbol visibility arg {} not one of: {}'.format(self.symbol_visibility, ', '.join(permitted)))
+ def validate_win_subsystem(self, value: str) -> str:
+ value = value.lower()
+ if re.fullmatch(r'(boot_application|console|efi_application|efi_boot_service_driver|efi_rom|efi_runtime_driver|native|posix|windows)(,\d+(\.\d+)?)?', value) is None:
+ raise InvalidArguments('Invalid value for win_subsystem: {}.'.format(value))
+ return value
+
def _extract_pic_pie(self, kwargs, arg):
# Check if we have -fPIC, -fpic, -fPIE, or -fpie in cflags
all_flags = self.extra_args['c'] + self.extra_args['cpp']
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 4b48e31..fa1046a 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -878,6 +878,13 @@ class Compiler(metaclass=abc.ABCMeta):
def get_gui_app_args(self, value: bool) -> T.List[str]:
return []
+ def get_win_subsystem_args(self, value: str) -> T.List[str]:
+ # This returns an empty array rather than throws to simplify the code.
+ # Otherwise we would have to check whenever calling this function whether
+ # the target is for Windows. There are also many cases where this is
+ # a meaningless choice, such as with Jave or C#.
+ return []
+
def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]:
raise EnvironmentException(
'Language {} does not support function attributes.'.format(self.get_display_language()))
diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py
index 41afadd..bb1fc66 100644
--- a/mesonbuild/compilers/mixins/gnu.py
+++ b/mesonbuild/compilers/mixins/gnu.py
@@ -219,6 +219,20 @@ class GnuLikeCompiler(Compiler, metaclass=abc.ABCMeta):
return ['-mwindows' if value else '-mconsole']
return []
+ def get_win_subsystem_args(self, value: str) -> T.List[str]:
+ args = []
+ if self.info.is_windows() or self.info.is_cygwin():
+ if 'windows' in value:
+ args = ['-Wl,--subsystem,windows']
+ elif 'console' in value:
+ args = ['-Wl,--subsystem,console']
+ else:
+ raise mesonlib.MesonException('Only "windows" and "console" are supported for win_subsystem with MinGW, not "{}".'.format(value))
+ if ',' in value:
+ args[-1] = args[-1] + ':' + value.split(',')[1]
+ return args
+
+
def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
for idx, i in enumerate(parameter_list):
if i[:2] == '-I' or i[:2] == '-L':
diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py
index 3494bee..75ab635 100644
--- a/mesonbuild/compilers/mixins/visualstudio.py
+++ b/mesonbuild/compilers/mixins/visualstudio.py
@@ -205,6 +205,9 @@ class VisualStudioLikeCompiler(Compiler, metaclass=abc.ABCMeta):
else:
return ['/SUBSYSTEM:CONSOLE']
+ def get_win_subsystem_args(self, value: str) -> T.List[str]:
+ return ['/SUBSYSTEM:' + value.upper()]
+
def get_pic_args(self) -> T.List[str]:
return [] # PIC is handled by the loader on Windows
diff --git a/test cases/windows/16 gui app/meson.build b/test cases/windows/16 gui app/meson.build
index 1570555..3021c43 100644
--- a/test cases/windows/16 gui app/meson.build
+++ b/test cases/windows/16 gui app/meson.build
@@ -6,16 +6,21 @@ project('gui_app_test', 'c')
#
console_lib = static_library('main', 'console_prog.c')
-executable('console', 'dummy.c', link_with: console_lib, gui_app: false)
+executable('console', 'dummy.c', link_with: console_lib, win_subsystem: 'console')
+executable('console2', 'dummy.c', link_with: console_lib, gui_app: false)
#
# also verify that the correct subsystem is set by executable(gui_app:)
#
-gui_prog = executable('gui_prog', 'gui_prog.c', gui_app: true)
-console_prog = executable('console_prog', 'console_prog.c', gui_app: false)
+gui_prog = executable('gui_prog', 'gui_prog.c', win_subsystem: 'windows,6.0')
+gui_prog2 = executable('gui_prog2', 'gui_prog.c', gui_app: true)
+console_prog = executable('console_prog', 'console_prog.c', win_subsystem: 'console')
+console_prog2 = executable('console_prog2', 'console_prog.c', gui_app: false)
tester = find_program('gui_app_tester.py')
test('is_gui', tester, args: [gui_prog, '2'])
+test('is_gui2', tester, args: [gui_prog2, '2'])
test('not_gui', tester, args: [console_prog, '3'])
+test('not_gui2', tester, args: [console_prog2, '3'])