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

[bug] MesonToolchain -LIBPATH is ignored? #11398

Closed
SSE4 opened this issue Jun 5, 2022 · 10 comments · Fixed by #11557
Closed

[bug] MesonToolchain -LIBPATH is ignored? #11398

SSE4 opened this issue Jun 5, 2022 · 10 comments · Fixed by #11557
Assignees
Milestone

Comments

@SSE4
Copy link
Contributor

SSE4 commented Jun 5, 2022

to be honest, I currently don't understand it conan client issue or even meson issue (I mean meson-build project iself).

migrating Glib to MesonToolchain in conan-io/conan-center-index#11053, I had to put the following workaround:

        ldflags = tc.vars().get("LDFLAGS")
        ldflags = ldflags.replace("-LIBPATH", "/LIBPATH")
        tc.environment.define('LDFLAGS', ldflags)

which appears to be working normally.

so, if I try without a workaround, I get Library gnuintl found: NO (while with old Meson build helper it's found).
digging into the logs I can see (in meson-log.txt):

Command line:  cl /LIBPATH:C:\Users\sse4\.conan\data\zlib\1.2.12\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib /LIBPATH:C:\Users\sse4\.conan\data\libffi\3.4.2\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib /LIBPATH:C:\Users\sse4\.conan\data\pcre\8.45\_\_\package\7a162084f5550c625a8950e9b1175d1474d2fbab\lib /LIBPATH:C:\Users\sse4\.conan\data\libgettext\0.21\_\_\package\e0c22822cdf05b624135e1696ae5cb784a23aeb3\lib /LIBPATH:C:\Users\sse4\.conan\data\bzip2\1.0.8\_\_\package\589a23dff5fdb23a7fb851223eb766480ead0a9a\lib /LIBPATH:C:\Users\sse4\.conan\data\libiconv\1.16\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib -IC:\Users\sse4\.conan\data\zlib\1.2.12\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\include -IC:\Users\sse4\.conan\data\libffi\3.4.2\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\include -IC:\Users\sse4\.conan\data\pcre\8.45\_\_\package\7a162084f5550c625a8950e9b1175d1474d2fbab\include -IC:\Users\sse4\.conan\data\libgettext\0.21\_\_\package\e0c22822cdf05b624135e1696ae5cb784a23aeb3\include -IC:\Users\sse4\.conan\data\bzip2\1.0.8\_\_\package\589a23dff5fdb23a7fb851223eb766480ead0a9a\include -IC:\Users\sse4\.conan\data\libiconv\1.16\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\include C:\.conan\96ccea\1\build_subfolder\meson-private\tmpx47m1x8r\testfile.c /FeC:\.conan\96ccea\1\build_subfolder\meson-private\tmpx47m1x8r\output.exe /nologo /showIncludes /utf-8 /MDd -DFFI_BUILDING -DPCRE_STATIC=1 /nologo /showIncludes /utf-8 /Od /Oi- gnuintl.lib /link /nologo /release /nologo 

Code:
 int main(void) { return 0; }

Compiler stdout:
 testfile.c
LINK : fatal error LNK1181: cannot open input file 'gnuintl.lib'

Compiler stderr:
 cl : Command line warning D9002 : ignoring unknown option '/LIBPATH:C:\Users\sse4\.conan\data\zlib\1.2.12\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib'
cl : Command line warning D9002 : ignoring unknown option '/LIBPATH:C:\Users\sse4\.conan\data\libffi\3.4.2\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib'
cl : Command line warning D9002 : ignoring unknown option '/LIBPATH:C:\Users\sse4\.conan\data\pcre\8.45\_\_\package\7a162084f5550c625a8950e9b1175d1474d2fbab\lib'
cl : Command line warning D9002 : ignoring unknown option '/LIBPATH:C:\Users\sse4\.conan\data\libgettext\0.21\_\_\package\e0c22822cdf05b624135e1696ae5cb784a23aeb3\lib'
cl : Command line warning D9002 : ignoring unknown option '/LIBPATH:C:\Users\sse4\.conan\data\bzip2\1.0.8\_\_\package\589a23dff5fdb23a7fb851223eb766480ead0a9a\lib'
cl : Command line warning D9002 : ignoring unknown option '/LIBPATH:C:\Users\sse4\.conan\data\libiconv\1.16\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib'

we can see -LIBPATH arguments are passed into command line, but in a wrong order (they have to be passed at the end, after the /link):

The /link option and its linker options must appear after any file names and CL options.

that's probably due to how meson inserts link_args into the command line.
in the toolchain (conan_meson_native.ini) I see linking flags are set:

c_link_args = ['-LIBPATH:C:\Users\sse4\.conan\data\zlib\1.2.12\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib', '-LIBPATH:C:\Users\sse4\.conan\data\libffi\3.4.2\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib', '-LIBPATH:C:\Users\sse4\.conan\data\pcre\8.45\_\_\package\7a162084f5550c625a8950e9b1175d1474d2fbab\lib', '-LIBPATH:C:\Users\sse4\.conan\data\libgettext\0.21\_\_\package\e0c22822cdf05b624135e1696ae5cb784a23aeb3\lib', '-LIBPATH:C:\Users\sse4\.conan\data\bzip2\1.0.8\_\_\package\589a23dff5fdb23a7fb851223eb766480ead0a9a\lib', '-LIBPATH:C:\Users\sse4\.conan\data\libiconv\1.16\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib']
cpp_link_args = ['-LIBPATH:C:\Users\sse4\.conan\data\zlib\1.2.12\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib', '-LIBPATH:C:\Users\sse4\.conan\data\libffi\3.4.2\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib', '-LIBPATH:C:\Users\sse4\.conan\data\pcre\8.45\_\_\package\7a162084f5550c625a8950e9b1175d1474d2fbab\lib', '-LIBPATH:C:\Users\sse4\.conan\data\libgettext\0.21\_\_\package\e0c22822cdf05b624135e1696ae5cb784a23aeb3\lib', '-LIBPATH:C:\Users\sse4\.conan\data\bzip2\1.0.8\_\_\package\589a23dff5fdb23a7fb851223eb766480ead0a9a\lib', '-LIBPATH:C:\Users\sse4\.conan\data\libiconv\1.16\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib']

I've tried to manually insert the /link at the beginning of c_link_args/cpp_link_args, but it didn't help.
the only thing that reliably fixed it was replacing -LIBPATH with /LIBPATH, now it gets the correct command line and libintl is found:

Command line:  cl -IC:\Users\sse4\.conan\data\zlib\1.2.12\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\include -IC:\Users\sse4\.conan\data\libffi\3.4.2\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\include -IC:\Users\sse4\.conan\data\pcre\8.45\_\_\package\7a162084f5550c625a8950e9b1175d1474d2fbab\include -IC:\Users\sse4\.conan\data\libgettext\0.21\_\_\package\e0c22822cdf05b624135e1696ae5cb784a23aeb3\include -IC:\Users\sse4\.conan\data\bzip2\1.0.8\_\_\package\589a23dff5fdb23a7fb851223eb766480ead0a9a\include -IC:\Users\sse4\.conan\data\libiconv\1.16\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\include C:\.conan\96ccea\1\build_subfolder\meson-private\tmpclicrq26\testfile.c /FeC:\.conan\96ccea\1\build_subfolder\meson-private\tmpclicrq26\output.exe /nologo /showIncludes /utf-8 /MDd -DFFI_BUILDING -DPCRE_STATIC=1 /nologo /showIncludes /utf-8 /Od /Oi- gnuintl.lib /link /nologo /release /nologo /LIBPATH:C:\Users\sse4\.conan\data\zlib\1.2.12\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib /LIBPATH:C:\Users\sse4\.conan\data\libffi\3.4.2\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib /LIBPATH:C:\Users\sse4\.conan\data\pcre\8.45\_\_\package\7a162084f5550c625a8950e9b1175d1474d2fbab\lib /LIBPATH:C:\Users\sse4\.conan\data\libgettext\0.21\_\_\package\e0c22822cdf05b624135e1696ae5cb784a23aeb3\lib /LIBPATH:C:\Users\sse4\.conan\data\bzip2\1.0.8\_\_\package\589a23dff5fdb23a7fb851223eb766480ead0a9a\lib /LIBPATH:C:\Users\sse4\.conan\data\libiconv\1.16\_\_\package\d057732059ea44a47760900cb5e4855d2bea8714\lib 

Code:
 int main(void) { return 0; }

Compiler stdout:
 testfile.c

Compiler stderr:
 
Library gnuintl found: YES

/cc @ericLemanissier

Environment Details (include every applicable attribute)

  • Operating System+version:
  • Compiler+version:
  • Conan version:
  • Python version:

Steps to reproduce (Include if Applicable)

Logs (Executed commands with output) (Include/Attach if Applicable)

@memsharded
Copy link
Member

To clarify, the workaround decsribed above tc.environment.define('LDFLAGS', ldflags) is from AutotoolsDeps, not MesonToolchain.

This indeed looks difficult to know without some good understanding of Meson. Please let me know if someone can guess what is the necessary fix.

@ericLemanissier
Copy link
Contributor

I had this problem in the past, and tried to fix it in meson, but it seemed to me that it had somehow been fixed at some point in time (?)
mesonbuild/meson#6735

@franramirez688
Copy link
Contributor

@SSE4 So, the problem seems to be from Meson itself? Which Meson version are you using?
If you use the meson_lib template (conan new hello/1.0 -m meson_lib) and try to pass some link arguments is happening as well? I have been trying to figure it out, but I didn't get any conclusion about it.

@SSE4
Copy link
Contributor Author

SSE4 commented Jun 6, 2022

@SSE4 So, the problem seems to be from Meson itself?

probably, but I am not fully sure.

Which Meson version are you using?

0.61.2

If you use the meson_lib template (conan new hello/1.0 -m meson_lib) and try to pass some link arguments is happening as well?

maybe I need to prepare some minimal examples to illustate the problem. it will take some time.

@SSE4
Copy link
Contributor Author

SSE4 commented Jun 6, 2022

@franramirez688 I was able to extract relevant parts to the minimal example and make a simple test from it.
it currently requires 3 workarounds to pass the test (well, maybe I am missing something simple, and workarounds are not needed, and it's just my misunderstanding on how to use toolchains correctly).
you can try removing/commenting these workarounds one by one to see various build errors. hope it helps.

diff --git a/conans/test/functional/toolchains/meson/test_pkg_config_reuse.py b/conans/test/functional/toolchains/meson/test_pkg_config_reuse.py
index ea2a87ba0..2330f79aa 100644
--- a/conans/test/functional/toolchains/meson/test_pkg_config_reuse.py
+++ b/conans/test/functional/toolchains/meson/test_pkg_config_reuse.py
@@ -57,3 +57,78 @@ class MesonPkgConfigTest(TestMesonBase):
         self.assertIn("Hello World Release!", self.t.out)
 
         self._check_binary()
+
+
+class MesonPkgConfigTest2(TestMesonBase):
+    def test_req(self):
+        from conans.test.utils.tools import TestClient
+        # causes an additional headache: LINK : fatal error LNK1181: cannot open input file 'with.obj'
+        self.t = TestClient(path_with_spaces=False)
+        self.t.run("new hello/0.1 -s")
+        self.t.run("create . hello/0.1@ %s" % self._settings_str)
+        app = gen_function_cpp(name="main", includes=["hello"], calls=["hello"])
+
+        conanfile_py = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.meson import Meson, MesonToolchain
+        from conan.tools.gnu import AutotoolsDeps
+
+
+        class App(ConanFile):
+            settings = "os", "arch", "compiler", "build_type"
+            requires = "hello/0.1"
+
+            def layout(self):
+                self.folders.build = "build"
+
+            def generate(self):
+                # workaround 1 : propagate lib/include directories to the meson toolchain
+                tc = AutotoolsDeps(self)
+
+                # workaround 2 : replace "-LIBPATH" with "/LIBPATH"
+                ldflags = tc.vars().get("LDFLAGS")
+                ldflags = ldflags.replace("-LIBPATH", "/LIBPATH")
+                tc.environment.define('LDFLAGS', ldflags)
+                # end of workaround 2
+
+                # workaround 3 : propagate CPPFLAGS to CFLAGS/CXXFLAGS as meson doesn't read CPPFLAGS
+                cppflags = tc.vars().get("CPPFLAGS")
+                tc.environment.append('CFLAGS', cppflags)
+                tc.environment.append('CXXFLAGS', cppflags)
+                # end of workaround 3
+
+                tc.generate()
+                self.buildenv.compose_env(tc.environment)
+                # end of workaround 1
+
+                tc = MesonToolchain(self)
+                tc.generate()
+
+            def build(self):
+                meson = Meson(self)
+                meson.configure()
+                meson.build()
+        """)
+
+        meson_build = textwrap.dedent("""
+        project('tutorial', 'cpp')
+        cxx = meson.get_compiler('cpp')
+        hello = cxx.find_library('hello', required : true)
+        executable('demo', 'main.cpp', dependencies: hello)
+        """)
+
+        self.t.save({"conanfile.py": conanfile_py,
+                     "meson.build": meson_build,
+                     "main.cpp": app},
+                    clean_first=True)
+
+        self.t.run("install . %s" % self._settings_str)
+
+        try:
+            self.t.run("build .")
+        except Exception as e:
+            meson_log = os.path.join(self.t.current_folder, "build", "meson-logs", "meson-log.txt")
+            with open(meson_log, "r") as f:
+                log = f.read()
+                print(log)
+            raise e

@franramirez688
Copy link
Contributor

@SSE4 I guess a better approach could be using Meson + pkg-config.

Given your previous example, change the test a little bit:

        conanfile_py = textwrap.dedent("""
        from conan import ConanFile
        from conan.tools.meson import Meson


        class App(ConanFile):
            settings = "os", "arch", "compiler", "build_type"
            requires = "hello/0.1"
            generators = "PkgConfigDeps", "MesonToolchain"

            def layout(self):
                self.folders.build = "build"

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

        meson_build = textwrap.dedent("""
        project('tutorial', 'cpp')
        cxx = meson.get_compiler('cpp')
        hello = dependency('hello', method : 'pkg-config')
        executable('demo', 'main.cpp', dependencies: hello)
        """)

You don't need a workaround anymore. Could it be more supported pkg-config than autotools?

@SSE4
Copy link
Contributor Author

SSE4 commented Jun 6, 2022

yes, with pkg-config it works flawlessly.
but real libraries (e.g. GLib) don't always use pkg-config. in reality, some of the libraries don't even have any .pc files, so meson has to work with that. so this line cannot be replaced:

hello = cxx.find_library('hello', required : true)

so the request is not to support meson + pkg-config integration (which we already know it works), but to support other wild user-cases (e.g. find_library)

@franramirez688
Copy link
Contributor

Meson version: 0.63.0
Compiler: MSVC 193

@SSE4 I've been figuring it out more profound, and I can say this is a Meson bug.

As this comment is saying, Meson is translating the flag correctly but not adequately ordered (after the /link option):

Command line:  cl /LIBPATH:C:\Users\franc\AppData\Local\Temp\tmp8q94hfsgconans\pathwithoutspaces\data\hello\0.1\_\_\package\2c1ca78479f39feb24204f0be31f282947545be1\lib ............. /link /nologo /release /nologo

But, if we replace the -LIBPATH with /LIBPATH it works:

Command line:  cl  ..............  /link /nologo /release /nologo /LIBPATH:C:\Users\franc\AppData\Local\Temp\tmp05lad4aqconans\pathwithoutspaces\data\hello\0.1\_\_\package\2c1ca78479f39feb24204f0be31f282947545be1\lib

@SSE4
Copy link
Contributor Author

SSE4 commented Jul 4, 2022

okay, we need to report an issue to meson itself.
it means no Windows builds with MesonToolchain for some time, unless I find out how to make a workaround.
/cc @ericLemanissier

@ericLemanissier
Copy link
Contributor

I got to the same conclusion some time ago, hence my old PR mesonbuild/meson#6735, but I don't think I reported the issue

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

Successfully merging a pull request may close this issue.

4 participants