From 82b0f6ab282867a0d815f991cd60227402bb61c0 Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Sun, 4 Mar 2018 18:38:35 -0500 Subject: [PATCH] Bug 531985 - Support Container build with new Core Build - add support for Container build to Meson - add fixes to MesonBuildConfiguration clean build to use sh -c like normal meson build - add new refreshScannerInfo method to MesonBuildConfiguration to re-process the commands json file so indexing will correctly switch from local to Container build and vice-versa - add MESON_PROJECT_ARGUMENTS to IMesonConstants - in MesonBuildConfigurationProvider getCBuildConfiguration method, remove checks for toolChainfile and for Container build, name the configuration based on the image name Change-Id: Ia8a85c05e0cb9d46d2987ed4d39fcee914302467 --- .../meson/core/MesonBuildConfiguration.java | 59 ++++++++--- .../core/MesonBuildConfigurationProvider.java | 24 +++-- .../cdt/internal/meson/core/Messages.java | 2 + .../internal/meson/core/messages.properties | 2 + .../cdt/meson/core/IMesonConstants.java | 1 + .../ui/properties/MesonPropertyPage.java | 98 ++++++++++++++----- .../cdt/meson/ui/properties/Messages.java | 9 +- .../meson/ui/properties/messages.properties | 4 + 8 files changed, 152 insertions(+), 47 deletions(-) diff --git a/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/MesonBuildConfiguration.java b/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/MesonBuildConfiguration.java index 58712293c09..23a6496ca91 100644 --- a/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/MesonBuildConfiguration.java +++ b/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/MesonBuildConfiguration.java @@ -38,7 +38,10 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.core.runtime.jobs.Job; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; @@ -147,6 +150,11 @@ public class MesonBuildConfiguration extends CBuildConfiguration { b.append(" "); //$NON-NLS-1$ b.append(userArgs); } + String projOptions = getProperty(IMesonConstants.MESON_PROJECT_OPTIONS); + if (projOptions != null) { + b.append(" "); //$NON-NLS-1$ + b.append(projOptions); + } b.append(" "); //$NON-NLS-1$ b.append(getBuildDirectory().toString()); argsList.add(b.toString()); @@ -169,7 +177,8 @@ public class MesonBuildConfiguration extends CBuildConfiguration { org.eclipse.core.runtime.Path shPath = new org.eclipse.core.runtime.Path("/bin/sh"); //$NON-NLS-1$ outStream.write(String.join(" ", envStr != null ? envStr : "", //$NON-NLS-1$ //$NON-NLS-2$ - "sh -c \"meson", userArgs != null ? userArgs : "", getBuildDirectory().getParent().getParent().toString() + "\"\n")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + "sh -c \"meson", userArgs != null ? userArgs : "", projOptions != null ? projOptions : "", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + getBuildDirectory().getParent().getParent().toString() + "\"\n")); //$NON-NLS-1$ org.eclipse.core.runtime.Path workingDir = new org.eclipse.core.runtime.Path(getBuildDirectory().getParent().getParent().toString()); Process p = launcher.execute(shPath, argsList.toArray(new String[0]), env, workingDir, monitor); if (p == null || launcher.waitAndRead(outStream, outStream, SubMonitor.convert(monitor)) != ICommandLauncher.OK) { @@ -235,8 +244,8 @@ public class MesonBuildConfiguration extends CBuildConfiguration { project.refreshLocal(IResource.DEPTH_INFINITE, monitor); - // Load compile_commands.json file - processCompileCommandsFile(monitor); + // Process compile_commands.json file and generate Scanner info + refreshScannerInfo(); outStream.write(String.format(Messages.MesonBuildConfiguration_BuildingComplete, buildDir.toString())); @@ -255,6 +264,13 @@ public class MesonBuildConfiguration extends CBuildConfiguration { ConsoleOutputStream outStream = console.getOutputStream(); Path buildDir = getBuildDirectory(); + + outStream.write(String.format(Messages.MesonBuildConfiguration_BuildingIn, buildDir.toString())); + + if (!Files.exists(buildDir.resolve("build.ninja"))) { //$NON-NLS-1$ + console.getOutputStream().write(Messages.MesonBuildConfiguration_NoNinjaFileToClean); + return; + } try (ErrorParserManager epm = new ErrorParserManager(project, getBuildDirectoryURI(), this, getToolChain().getErrorParserIds())) { @@ -263,16 +279,16 @@ public class MesonBuildConfiguration extends CBuildConfiguration { String cleanCommand = getProperty(IMesonConstants.CLEAN_COMMAND); if (cleanCommand == null) { - cleanCommand = "ninja clean"; //$NON-NLS-1$ + cleanCommand = "ninja clean -v"; //$NON-NLS-1$ } String[] command = cleanCommand.split(" "); //$NON-NLS-1$ - Path cmdPath = findCommand(command[0]); - if (cmdPath != null) { - command[0] = cmdPath.toString(); - } + IPath cmd = new org.eclipse.core.runtime.Path("sh"); + + List argList = new ArrayList<>(); + argList.add("-c"); //$NON-NLS-1$ + argList.add(cleanCommand); - IPath cmd = new org.eclipse.core.runtime.Path(command[0]); ICommandLauncher launcher = CommandLauncherManager.getInstance().getCommandLauncher(this); launcher.setProject(getProject()); @@ -280,17 +296,13 @@ public class MesonBuildConfiguration extends CBuildConfiguration { ((ICBuildCommandLauncher)launcher).setBuildConfiguration(this); } - String[] commandargs = new String[0]; - if (command.length > 1) { - commandargs = Arrays.copyOfRange(command, 1, command.length); - } org.eclipse.core.runtime.Path workingDir = new org.eclipse.core.runtime.Path(buildDir.toString()); String[] env = new String[0]; outStream.write(String.join(" ", command) + '\n'); //$NON-NLS-1$ - launcher.execute(cmd, commandargs, env, workingDir, monitor); - if (launcher.waitAndRead(epm.getOutputStream(), epm.getOutputStream(), SubMonitor.convert(monitor)) != ICommandLauncher.OK) { + Process p = launcher.execute(cmd, argList.toArray(new String[0]), env, workingDir, monitor); + if (p == null || launcher.waitAndRead(epm.getOutputStream(), epm.getOutputStream(), SubMonitor.convert(monitor)) != ICommandLauncher.OK) { String errMsg = launcher.getErrorMessage(); console.getErrorStream().write(String.format(Messages.MesonBuildConfiguration_RunningNinjaFailure, errMsg)); return; @@ -303,6 +315,23 @@ public class MesonBuildConfiguration extends CBuildConfiguration { } } + @Override + public void refreshScannerInfo() throws CoreException { + Job job = new Job(Messages.MesonBuildConfiguration_RefreshingScannerInfo) { + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + processCompileCommandsFile(monitor); + } catch (CoreException e) { + return e.getStatus(); + } + return Status.OK_STATUS; + } + }; + // TODO: should this have a scheduling rule?? + job.schedule(); + } + private void processCompileCommandsFile(IProgressMonitor monitor) throws CoreException { IProject project = getProject(); Path commandsFile = getBuildDirectory().resolve("compile_commands.json"); //$NON-NLS-1$ diff --git a/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/MesonBuildConfigurationProvider.java b/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/MesonBuildConfigurationProvider.java index c321a73a8b0..9df0954722c 100644 --- a/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/MesonBuildConfigurationProvider.java +++ b/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/MesonBuildConfigurationProvider.java @@ -72,11 +72,11 @@ public class MesonBuildConfigurationProvider implements ICBuildConfigurationProv MesonBuildConfiguration mesonConfig = new MesonBuildConfiguration(config, name); IMesonToolChainFile tcFile = mesonConfig.getToolChainFile(); IToolChain toolChain = mesonConfig.getToolChain(); - if (toolChain == null || tcFile == null) { - // config not complete? + if (toolChain == null) { + // config not complete return null; } - if (!toolChain.equals(tcFile.getToolChain())) { + if (tcFile != null && !toolChain.equals(tcFile.getToolChain())) { // toolchain changed return new MesonBuildConfiguration(config, name, tcFile.getToolChain(), tcFile, mesonConfig.getLaunchMode()); @@ -109,13 +109,19 @@ public class MesonBuildConfigurationProvider implements ICBuildConfigurationProv // create config StringBuilder configName = new StringBuilder("meson."); //$NON-NLS-1$ configName.append(launchMode); - if (os != null) { + if ("linux-container".equals(os)) { //$NON-NLS-1$ + String osConfigName = toolChain.getProperty("linux-container-id"); //$NON-NLS-1$ configName.append('.'); - configName.append(os); - } - if (arch != null && !arch.isEmpty()) { - configName.append('.'); - configName.append(arch); + configName.append(osConfigName); + } else { + if (os != null) { + configName.append('.'); + configName.append(os); + } + if (arch != null && !arch.isEmpty()) { + configName.append('.'); + configName.append(arch); + } } String name = configName.toString(); int i = 0; diff --git a/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/Messages.java b/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/Messages.java index e36b6c4478f..01a38ab54ba 100644 --- a/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/Messages.java +++ b/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/Messages.java @@ -20,10 +20,12 @@ public class Messages extends NLS { public static String MesonBuildConfiguration_Cleaning; public static String MesonBuildConfiguration_RunningMeson; public static String MesonBuildConfiguration_RunningNinja; + public static String MesonBuildConfiguration_RefreshingScannerInfo; public static String MesonBuildConfiguration_RunningMesonFailure; public static String MesonBuildConfiguration_RunningNinjaFailure; public static String MesonBuildConfiguration_NoToolchainFile; public static String MesonBuildConfiguration_NoNinjaFile; + public static String MesonBuildConfiguration_NoNinjaFileToClean; public static String MesonBuildConfiguration_ProcCompCmds; public static String MesonBuildConfiguration_ProcCompJson; diff --git a/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/messages.properties b/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/messages.properties index cc9366ae29b..4c46e97c1b0 100644 --- a/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/messages.properties +++ b/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/internal/meson/core/messages.properties @@ -13,11 +13,13 @@ MesonBuildConfiguration_BuildingComplete=Build complete: %s\n MesonBuildConfiguration_Cleaning=Cleaning %s MesonBuildConfiguration_RunningMeson=Running meson MesonBuildConfiguration_RunningNinja=Running ninja +MesonBuildConfiguration_RefreshingScannerInfo=Refreshing Scanner Info MesonBuildConfiguration_ProcCompCmds=Processing compile commands %s MesonBuildConfiguration_ProcCompJson=Processing compile_commands.json MesonBuildConfiguration_NoToolchainFile=No toolchain file found for this target. MesonBuildConfiguration_RunningMesonFailure=Failure running meson: %s MesonBuildConfiguration_RunningNinjaFailure=Failure running ninja: %s +MesonBuildConfiguration_NoNinjaFileToClean=No ninja.build file so clean has nothing to do MesonBuildConfiguration_NoNinjaFile=Meson did not create a ninja.build file so build cannot complete diff --git a/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/meson/core/IMesonConstants.java b/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/meson/core/IMesonConstants.java index e2aa905a9bb..3f79e47d4b7 100644 --- a/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/meson/core/IMesonConstants.java +++ b/build/org.eclipse.cdt.meson.core/src/org/eclipse/cdt/meson/core/IMesonConstants.java @@ -14,6 +14,7 @@ public interface IMesonConstants { public static final String MESON_ARGUMENTS = "meson.arguments"; //$NON-NLS-1$ public static final String MESON_ENV = "meson.environment"; //$NON-NLS-1$ + public static final String MESON_PROJECT_OPTIONS = "meson.project.options"; //$NON-NLS-1$ public static final String NINJA_ENV = "meson.ninja.environment"; //$NON-NLS-1$ public static final String NINJA_ARGUMENTS = "meson.ninja.arguments"; //$NON-NLS-1$ public static final String MESON_ENV_SEPARATOR = "|"; //$NON-NLS-1$ diff --git a/build/org.eclipse.cdt.meson.ui/src/org/eclipse/cdt/meson/ui/properties/MesonPropertyPage.java b/build/org.eclipse.cdt.meson.ui/src/org/eclipse/cdt/meson/ui/properties/MesonPropertyPage.java index 5a40ec6d229..03a930d4467 100644 --- a/build/org.eclipse.cdt.meson.ui/src/org/eclipse/cdt/meson/ui/properties/MesonPropertyPage.java +++ b/build/org.eclipse.cdt.meson.ui/src/org/eclipse/cdt/meson/ui/properties/MesonPropertyPage.java @@ -27,6 +27,7 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CommandLauncherManager; import org.eclipse.cdt.core.ICommandLauncher; import org.eclipse.cdt.core.build.CBuildConfiguration; +import org.eclipse.cdt.core.build.ICBuildCommandLauncher; import org.eclipse.cdt.core.build.ICBuildConfiguration; import org.eclipse.cdt.core.resources.IConsole; import org.eclipse.cdt.meson.core.IMesonConstants; @@ -65,6 +66,7 @@ public class MesonPropertyPage extends PropertyPage { private boolean configured; private CBuildConfiguration buildConfig; private Text envText; + private Text projText; @Override protected Control createContents(Composite parent) { @@ -84,25 +86,39 @@ public class MesonPropertyPage extends PropertyPage { if (configured) { ICommandLauncher launcher = CommandLauncherManager.getInstance().getCommandLauncher(project.getActiveBuildConfig().getAdapter(ICBuildConfiguration.class)); - Process p = launcher.execute(new Path("meson"), new String[] { "configure", buildDir}, new String[0], sourceDir, new NullProgressMonitor()); - ByteArrayOutputStream stdout = new ByteArrayOutputStream(); - ByteArrayOutputStream stderr = new ByteArrayOutputStream(); - int rc = -1; - try { - if (launcher.waitAndRead(stdout, stderr, new NullProgressMonitor()) == ICommandLauncher.OK) { - p.waitFor(); + launcher.setProject(project); + if (launcher instanceof ICBuildCommandLauncher) { + ((ICBuildCommandLauncher)launcher).setBuildConfiguration(buildConfig); + } + Process p = launcher.execute(new Path("/bin/sh"), new String[] { "-c", "meson configure " + buildDir}, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + new String[0], sourceDir, new NullProgressMonitor()); + if (p != null) { + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + ByteArrayOutputStream stderr = new ByteArrayOutputStream(); + int rc = -1; + try { + if (launcher.waitAndRead(stdout, stderr, new NullProgressMonitor()) == ICommandLauncher.OK) { + p.waitFor(); + } + rc = p.exitValue(); + } catch (InterruptedException e) { + // ignore for now + } + if (rc == 0) { + componentList = parseConfigureOutput(stdout, composite); } - rc = p.exitValue(); - } catch (InterruptedException e) { - // ignore for now } - if (rc == 0) { - componentList = parseConfigureOutput(stdout, composite); - } - } else { ICommandLauncher launcher = CommandLauncherManager.getInstance().getCommandLauncher(project.getActiveBuildConfig().getAdapter(ICBuildConfiguration.class)); - Process p = launcher.execute(new Path("meson"), new String[] { "-h"}, new String[0], sourceDir, new NullProgressMonitor()); + launcher.setProject(project); + if (launcher instanceof ICBuildCommandLauncher) { + ((ICBuildCommandLauncher)launcher).setBuildConfiguration(buildConfig); + } + Process p = launcher.execute(new Path("/bin/sh"), new String[] { "-c", "meson -h"}, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + new String[0], sourceDir, new NullProgressMonitor()); + if (p == null) { + return null; + } ByteArrayOutputStream stdout = new ByteArrayOutputStream(); ByteArrayOutputStream stderr = new ByteArrayOutputStream(); int rc = -1; @@ -118,13 +134,13 @@ public class MesonPropertyPage extends PropertyPage { Map argMap = new HashMap<>(); String mesonArgs = buildConfig.getProperty(IMesonConstants.MESON_ARGUMENTS); if (mesonArgs != null) { - String[] argStrings = mesonArgs.split("\\s+"); + String[] argStrings = mesonArgs.split("\\s+"); //$NON-NLS-1$ for (String argString : argStrings) { - String[] s = argString.split("="); + String[] s = argString.split("="); //$NON-NLS-1$ if (s.length == 2) { argMap.put(s[0], s[1]); } else { - argMap.put(argString, "true"); + argMap.put(argString, "true"); //$NON-NLS-1$ } } } @@ -135,7 +151,7 @@ public class MesonPropertyPage extends PropertyPage { layout.marginRight = 10; group.setLayout(layout); group.setLayoutData(new GridData(GridData.FILL_BOTH)); - group.setText("Environment"); + group.setText(Messages.MesonPropertyPage_env_group); Label envLabel = new Label(group, SWT.NONE); envLabel.setText(Messages.MesonPropertyPage_env_label); @@ -157,6 +173,33 @@ public class MesonPropertyPage extends PropertyPage { data.horizontalSpan = 1; envText.setLayoutData(data); + group = new Group(composite, SWT.BORDER); + layout = new GridLayout(2, true); + layout.marginLeft = 10; + layout.marginRight = 10; + group.setLayout(layout); + group.setLayoutData(new GridData(GridData.FILL_BOTH)); + group.setText(Messages.MesonPropertyPage_project_group); + + Label projLabel = new Label(group, SWT.NONE); + projLabel.setText(Messages.MesonPropertyPage_project_label); + data = new GridData(GridData.FILL, GridData.FILL, true, false); + data.grabExcessHorizontalSpace = true; + data.horizontalSpan = 1; + projLabel.setLayoutData(data); + + String mesonProjOptions = buildConfig.getProperty(IMesonConstants.MESON_PROJECT_OPTIONS); + + projText = new Text(group, SWT.BORDER); + if (mesonProjOptions != null) { + projText.setText(mesonProjOptions); + } + projText.setToolTipText(Messages.MesonPropertyPage_project_tooltip); + data = new GridData(GridData.FILL, GridData.FILL, true, false); + data.grabExcessHorizontalSpace = true; + data.horizontalSpan = 1; + projText.setLayoutData(data); + // default buildtype based on active build configuration // user can always override and we will use override from then on String defaultBuildType = "release"; //$NON-NLS-1$ @@ -195,13 +238,14 @@ public class MesonPropertyPage extends PropertyPage { public boolean performOk() { List args = new ArrayList<>(); if (configured) { + args.add("meson"); //$NON-NLS-1$ args.add("configure"); //$NON-NLS-1$ for (IMesonPropertyPageControl control : componentList) { if (control.isValueChanged()) { args.add(control.getConfiguredString()); //$NON-NLS-1$ //$NON-NLS-2$ } } - if (args.size() == 1) { + if (args.size() == 2) { return true; } try { @@ -209,8 +253,17 @@ public class MesonPropertyPage extends PropertyPage { IPath sourceDir = project.getLocation(); String buildDir = project.getLocation().append("build").append(configName).toOSString(); //$NON-NLS-1$ ICommandLauncher launcher = CommandLauncherManager.getInstance().getCommandLauncher(project.getActiveBuildConfig().getAdapter(ICBuildConfiguration.class)); - args.add(buildDir); - Process p = launcher.execute(new Path("meson"), args.toArray(new String[0]), new String[0], sourceDir, new NullProgressMonitor()); + launcher.setProject(project); + if (launcher instanceof ICBuildCommandLauncher) { + ((ICBuildCommandLauncher)launcher).setBuildConfiguration(buildConfig); + } + StringBuilder b = new StringBuilder(); + for (String arg : args) { + b.append(arg); + b.append(" "); //$NON-NLS-1$ + } + b.append(buildDir); + Process p = launcher.execute(new Path("/bin/sh"), new String[] { "-c", b.toString() }, new String[0], sourceDir, new NullProgressMonitor()); //$NON-NLS-1$ //$NON-NLS-2$ int rc = -1; IConsole console = CCorePlugin.getDefault().getConsole(); console.start(project); @@ -258,6 +311,7 @@ public class MesonPropertyPage extends PropertyPage { } buildConfig.setProperty(IMesonConstants.MESON_ARGUMENTS, mesonargs.toString()); buildConfig.setProperty(IMesonConstants.MESON_ENV, envText.getText().trim()); + buildConfig.setProperty(IMesonConstants.MESON_PROJECT_OPTIONS, projText.getText().trim()); } return true; } diff --git a/build/org.eclipse.cdt.meson.ui/src/org/eclipse/cdt/meson/ui/properties/Messages.java b/build/org.eclipse.cdt.meson.ui/src/org/eclipse/cdt/meson/ui/properties/Messages.java index aef4f6a5f60..85466cc5c3a 100644 --- a/build/org.eclipse.cdt.meson.ui/src/org/eclipse/cdt/meson/ui/properties/Messages.java +++ b/build/org.eclipse.cdt.meson.ui/src/org/eclipse/cdt/meson/ui/properties/Messages.java @@ -23,10 +23,17 @@ public class Messages extends NLS { public static String MesonPropertyPage_configure_failed; public static String MesonPropertyPage_terminated_rc; - public static String MesonPropertyPage_options_group; + + public static String MesonPropertyPage_env_group; public static String MesonPropertyPage_env_tooltip; public static String MesonPropertyPage_env_label; + public static String MesonPropertyPage_project_group; + public static String MesonPropertyPage_project_tooltip; + public static String MesonPropertyPage_project_label; + + public static String MesonPropertyPage_options_group; + public static String MesonPropertyPage_prefix_tooltip; public static String MesonPropertyPage_libdir_tooltip; public static String MesonPropertyPage_libexecdir_tooltip; diff --git a/build/org.eclipse.cdt.meson.ui/src/org/eclipse/cdt/meson/ui/properties/messages.properties b/build/org.eclipse.cdt.meson.ui/src/org/eclipse/cdt/meson/ui/properties/messages.properties index 7ba5cc72633..8f3de93545c 100644 --- a/build/org.eclipse.cdt.meson.ui/src/org/eclipse/cdt/meson/ui/properties/messages.properties +++ b/build/org.eclipse.cdt.meson.ui/src/org/eclipse/cdt/meson/ui/properties/messages.properties @@ -18,6 +18,10 @@ MesonPropertyPage_configure_failed=Meson configure command failed (see console o MesonPropertyPage_terminated_rc=Command terminated with rc={0}\n MesonPropertyPage_options_group=Options +MesonPropertyPage_project_group=Project +MesonPropertyPage_project_label=Options +MesonPropertyPage_project_tooltip=Use this for manually specifying one or more project options (-D option) +MesonPropertyPage_env_group=Environment MesonPropertyPage_env_tooltip=Environment variables for initial meson call MesonPropertyPage_env_label=Environment