Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[question] Why use ninja in meson to replace meson's built-in compilation #9922

Closed
1 task done
deadash opened this issue Nov 2, 2021 · 15 comments · Fixed by #9990
Closed
1 task done

[question] Why use ninja in meson to replace meson's built-in compilation #9922

deadash opened this issue Nov 2, 2021 · 15 comments · Fixed by #9990
Assignees
Milestone

Comments

@deadash
Copy link

deadash commented Nov 2, 2021

Use meson to compile, only support backend to ninja, if I modify it to not support anything else, such as vs, I also need to use msbuild to compile.

The following is the code

def build(self, args=None, build_dir=None, targets=None):
    if not self._conanfile.should_build:
        return
    conan_v2_error("build_type setting should be defined.", not self._build_type)
    self._run_ninja_targets(args=args, build_dir=build_dir, targets=targets)

If I change the compilation of ninja to meson, it can also be successful, as follows

self._run_meson_command(subcommand='compile', args=args, build_dir=build_dir)

I omitted the generation target here, meson is supported.

Using ninja also has the problem that the meson file cannot be changed when the meson file is changed.

If I use vs as backend, there will be errors, as follows

def _run_ninja_targets(self, args=None, build_dir=None, targets=None):
    if self.backend != "ninja":
        raise ConanException("Build only supported with 'ninja' backend")
@lasote lasote self-assigned this Nov 2, 2021
@lasote lasote assigned SSE4 and unassigned lasote Nov 2, 2021
@SSE4
Copy link
Contributor

SSE4 commented Nov 2, 2021

hello!

I think it's just a historic thing, AFAIK meson is usually used in conjunction with ninja and pkg-config, that's at least the main use-case I am aware of. backend agnostic compile command is a pretty new thing, introduced in the very recent release of meson 0.54, while Conan implementation of build helper pre-dates that.

right now, I don't know, what are the use-cases and the benefits of other backends (e.g. vs) over ninja. I would love to hear more about your use case, so feel free to share any additional details.

the meson file cannot be changed when the meson file is changed

sorry, but I don't get it, what exactly does it mean, can you elaborate?

@deadash
Copy link
Author

deadash commented Nov 2, 2021

Hello,

the meson file cannot be changed when the meson file is changed

This means that when I modify the content of meson.build, ninja does not modify it, and it will be modified at the same time when I use meson compile to generate it.

No special test is performed, and the build directory needs to be deleted every time the meson.build file changes during use.

There is not much difference between ninja and VS, but VS is easy to make a little change, such as modifying the toolset, etc. In addition, I can directly open the project with the IDE.
In terms of speed, ninja must be compiled faster.

Meson supports vs as backend, I think conan-meson should also support vs as backend.

The strange thing is that the files generated by conan using cmake as the backend are also vs, not ninja.

An example that can benefit from vs as a backend is as follows.

Modify meson to support toolset changes.

---
 mesonbuild/backend/vs2015backend.py | 3 ++-
 mesonbuild/backend/vs2017backend.py | 2 +-
 mesonbuild/backend/vs2019backend.py | 2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/mesonbuild/backend/vs2015backend.py b/mesonbuild/backend/vs2015backend.py
index bdc1675a2..a1f4e78c9 100644
--- a/mesonbuild/backend/vs2015backend.py
+++ b/mesonbuild/backend/vs2015backend.py
@@ -17,6 +17,7 @@ from ..mesonlib import MesonException
 from ..interpreter import Interpreter
 from ..build import Build
 import typing as T
+import os
 
 
 class Vs2015Backend(Vs2010Backend):
@@ -35,4 +36,4 @@ class Vs2015Backend(Vs2010Backend):
                     # 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 = 'v140'
+                self.platform_toolset = os.environ.get('VS_TOOLSET', 'v140')
diff --git a/mesonbuild/backend/vs2017backend.py b/mesonbuild/backend/vs2017backend.py
index fa216065c..7c8c97c8f 100644
--- a/mesonbuild/backend/vs2017backend.py
+++ b/mesonbuild/backend/vs2017backend.py
@@ -41,7 +41,7 @@ class Vs2017Backend(Vs2010Backend):
                         # 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 = 'v141'
+            self.platform_toolset = os.environ.get('VS_TOOLSET', 'v141')
         # WindowsSDKVersion should be set by command prompt.
         sdk_version = os.environ.get('WindowsSDKVersion', None)
         if sdk_version:
diff --git a/mesonbuild/backend/vs2019backend.py b/mesonbuild/backend/vs2019backend.py
index 8f304e48e..ef2b4ecd3 100644
--- a/mesonbuild/backend/vs2019backend.py
+++ b/mesonbuild/backend/vs2019backend.py
@@ -35,7 +35,7 @@ class Vs2019Backend(Vs2010Backend):
                     self.platform_toolset = 'Intel C++ Compiler 19.0'
                 # We don't have support for versions older than 2019 right now.
             if not self.platform_toolset:
-                self.platform_toolset = 'v142'
+                self.platform_toolset = os.environ.get('VS_TOOLSET', 'v142')
             self.vs_version = '2019'
         # WindowsSDKVersion should be set by command prompt.
         sdk_version = os.environ.get('WindowsSDKVersion', None)
-- 
2.28.0.windows.1

Modify conan to support toolset change

command = 'meson "%s" "%s" %s' % (source_dir, self.build_dir, arg_list)
with environment_append({"PKG_CONFIG_PATH": pc_paths,
    "VS_TOOLSET": self._settings.get_safe('compiler.toolset')}):
    self._run(command)

After the modification, the toolset of conan can be passed to meson to generate.

In theory, ninja should also be able to modify and support toolset, but I haven’t thought of a good way yet.

In addition, if I use meson as the compilation, after modifying the meson.build file, the corresponding generated files will also change, such as ninja or vs as the backend.

@deadash
Copy link
Author

deadash commented Nov 3, 2021

I tested it. When msbuild and meson use VS as the backend, there is a difference between the exe generated by the two.

So it’s best to use meson’s built-in generation instead of ninja generation.

@SSE4
Copy link
Contributor

SSE4 commented Nov 4, 2021

yes, I agree it could be useful to support VS as the backend in Meson.
it's unlikely this will be ever applied to the old build helper (it's going to be removed soon anyway), but new build helper definitely may take an advantage of this. it aligns with CMake build helper behavior, where you can choose generator (VS, Ninja, NMake, etc.). and as meson support for backend-agnostic build commands is now complete, nothing prevents us from adding support of such commands to conan client. I also find editing generated VS files with IDE useful.

@deadash
Copy link
Author

deadash commented Nov 4, 2021

I tried the new build helper tool, there are many problems.

  1. after setting x86, MesonToolchain generates conan_meson_cross.ini, but the compilation is conan_meson_native.ini.
  2. does not support vs as backend.
  3. Even if the conan_meson_native.ini is generated with the default configuration, it cannot be found during the build, but it can be executed manually.

The first problem arises because the environment is switched, which causes the build os to change. In fact, there is no need to judge what cross, and the corresponding arch will be automatically generated if there are environment variables.

The third problem should be that the current path has changed, and manual execution is possible.

@lasote
Copy link
Contributor

lasote commented Nov 8, 2021

@SSE4 Could you check the MesonToolchain feedback especially regarding 1 and 3 points?

@SSE4
Copy link
Contributor

SSE4 commented Nov 9, 2021

@SSE4 Could you check the MesonToolchain feedback especially regarding 1 and 3 points?

yes, I am checking, will report with my findings

@SSE4
Copy link
Contributor

SSE4 commented Nov 9, 2021

I am using very simple conanfile.py to reproduce:

from conans import ConanFile, CMake, tools

from conan.tools.meson import Meson, MesonToolchain

class TestMesonConan(ConanFile):
    name = "test_meson"
    version = "1.0"
    license = "<Put the package license here>"
    author = "<Put your name here> <And your email here>"
    url = "<Package recipe repository url here, for issues about the package>"
    description = "<Description of TestMeson here>"
    topics = ("<Put some tag here>", "<here>", "<and here>")
    settings = "os", "compiler", "build_type", "arch"
    options = {"shared": [True, False], "fPIC": [True, False]}
    default_options = {"shared": False, "fPIC": True}
    generators = "cmake"
    exports_sources = "meson.build", "hello.cpp"

    def config_options(self):
        if self.settings.os == "Windows":
            del self.options.fPIC
    
    def generate(self):
        tc = MesonToolchain(self)
        tc.generate()

    def source(self):
        pass

    def build(self):
        meson = Meson(self)
        meson.configure()
        meson.build()

    def package(self):
        meson = Meson(self)
        meson.configure()
        meson.install()

    def package_info(self):
        self.cpp_info.libs = ["hello"]

with meson.build:

project('tutorial', 'cpp')
library('hello', 'hello.cpp', install: true)

and x86 profile

include(default)
[settings]
arch=x86

regarind point 1.

the issue happens in single profile mode, e.g. running the following command:

$ conan create . test_meson/1.0@  --profile=x86 
...
[vcvarsall.bat] Environment initialized for: 'x86'
Could not find any valid candidate for native files: conan_meson_native.ini
ERROR: Cannot find specified native file: conan_meson_native.ini           

NOTE, there is a warning above:

test_meson/1.0: WARN: Using the new toolchains and generators without specifying a build profile (e.g: -pr:b=default) is discouraged and might cause failures and unexpected behavior

with two profiles there is a different error:

$ conan create . test_meson/1.0@  --profile:host=x86 --profile:build=default
...
meson.build:1:0: ERROR: 'cpp' compiler binary not defined in cross or native file

as noted in #9710, Meson, unlike CMake, is not so smart, and cannot automatically deduce the compiler executable in case of cross-compiling.
after adding two lines to the x86 profile:

[env]
CC=cl
CXX=cl

it builds successfully via two profiles.

so there are two sub-points:
1a. should we fix MesonToolchain for 1 profile use-case? I don't think so, as it's going to be no longer supported very soon. I recommend to always use two profiles with MesonToolchain.
2b. how about automatically deducing cl compiler executable for the arch=x86 and compiler=Visual Studio? well, it has pros and cons, on one side things will start to work out of the box, on the other hand, it's easy to add these two variables, and we decided to use less auto-detection and magic going forward. anyway, it's not hard to implement, if necessaey, I believe.

@SSE4
Copy link
Contributor

SSE4 commented Nov 9, 2021

about point 2, it's relatively easy change, so I've drafted a PR: #9990
I think it's safe and useful change

@SSE4
Copy link
Contributor

SSE4 commented Nov 9, 2021

about point 3, I think you actually have found a serious bug!
there is an inconsistency between Meson (build helper) and MesonToolchain (generator), as they right now use a different function for cross_building:

# meson/toolchain.py
from conans.client.tools.oss import cross_building, get_cross_building_settings

# meson/meson.py
from conan.tools.cross_building import cross_building

as these two functions behave differently, there are situations when they return a different value
conans.client.tools.oss is an old thing, which shouldn't be used by the new toolchain.
I've created #9992 to fix the problem

@deadash
Copy link
Author

deadash commented Nov 9, 2021

Yes, I also found that there are two identical functions. After a simple debugging, I found that the function logic is the same in the problem I debugged. If the cross_meson_native.ini file exists, the generation will still fail. I think there is a problem with the current path, I will check it carefully later.

@lasote
Copy link
Contributor

lasote commented Nov 10, 2021

1a. should we fix MesonToolchain for 1 profile use-case? I don't think so, as it's going to be no longer supported very soon. I recommend to always use two profiles with MesonToolchain

Exactly, the new Toolchains are supposed to work only with 2 profiles.

2b. how about automatically deducing cl compiler executable for the arch=x86 and compiler=Visual Studio? well, it has pros and cons, on one side things will start to work out of the box, on the other hand, it's easy to add these two variables, and we decided to use less auto-detection and magic going forward. anyway, it's not hard to implement, if necessaey, I believe.

We should add a note in the documentation, if you want to cross-build with meson you have to specify your compiler in the profile. I think this is easy and good enough.

EDIT: Is there a way to specify the compiler via Meson (at the ini files?) we might consider in that case to add a new property to specify the cross compiler.

@SSE4
Copy link
Contributor

SSE4 commented Nov 11, 2021

We should add a note in the documentation, if you want to cross-build with meson you have to specify your compiler in the profile. I think this is easy and good enough.

okay, I've opened conan-io/docs#2296 for that

EDIT: Is there a way to specify the compiler via Meson (at the ini files?) we might consider in that case to add a new property to specify the cross compiler.

yes, you can specify it in cross-file INI like:

    [binaries]
    c = 'cl'
    cpp = 'cl'

I need to think about it. I suppose it has to be done in the uniform way (e.g. with cmake), something like tools.meson.mesontoolchain:cc and tools.meson.mesontoolchain:cxx (not sure about exact names yet).

P.S. not directly related to this particular issue, but maybe you can also help me to move forward with another 2 meson issues: #9713 #9710, they are kinda important as well, especially for conan-center

@lasote
Copy link
Contributor

lasote commented Nov 16, 2021

yes, you can specify it in cross-file INI like:

Mhh, so maybe we can adjust them automatically based on the build compiler, right?
@memsharded WDYT?

@memsharded
Copy link
Member

#9990 implemented support to change Meson backend, will be available in 1.43.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants