Conan: [bug] Link order (in CONAN_LIBS) is not preserved.

Created on 28 Jan 2020  路  3Comments  路  Source: conan-io/conan

Environment Details (include every applicable attribute)

  • Operating System+version: Windows 10 build 1909 [Version 10.0.18363.592]
  • Compiler+version: any
  • Conan version: 1.21
  • Python version: 3.7

Steps to reproduce (Include if Applicable)

  1. Apply the following patch to an empty dir
diff --git a/conan_link_order/conanfile.txt b/conan_link_order/conanfile.txt
new file mode 100644
index 0000000..15d4f96
--- /dev/null
+++ b/conan_link_order/conanfile.txt
@@ -0,0 +1,6 @@
+[requires]
+TestA/1.0.0@test/develop
+TestB/1.0.0@test/develop
+
+[generators]
+qmake
diff --git a/conan_link_order/test_a/conanfile.py b/conan_link_order/test_a/conanfile.py
new file mode 100644
index 0000000..6a693db
--- /dev/null
+++ b/conan_link_order/test_a/conanfile.py
@@ -0,0 +1,18 @@
+from conans import ConanFile
+
+
+class TestA(ConanFile):
+    name = "TestA"
+    version = "1.0.0"
+    description = "TestA"
+    exports = "*.a"
+
+    def package(self):
+        super().package()
+
+        self.copy("*", src=".", dst="lib")
+
+    def package_info(self):
+        super().package_info()
+
+        self.cpp_info.libs = ["lib1", "lib2", "lib3"]
diff --git a/conan_link_order/test_a/liblib1.a b/conan_link_order/test_a/liblib1.a
new file mode 100644
index 0000000..e69de29
diff --git a/conan_link_order/test_a/liblib2.a b/conan_link_order/test_a/liblib2.a
new file mode 100644
index 0000000..e69de29
diff --git a/conan_link_order/test_a/liblib3.a b/conan_link_order/test_a/liblib3.a
new file mode 100644
index 0000000..e69de29
diff --git a/conan_link_order/test_b/conanfile.py b/conan_link_order/test_b/conanfile.py
new file mode 100644
index 0000000..5822ad8
--- /dev/null
+++ b/conan_link_order/test_b/conanfile.py
@@ -0,0 +1,20 @@
+from conans import ConanFile
+
+
+class TestB(ConanFile):
+    name = "TestB"
+    version = "1.0.0"
+    description = "TestB"
+    exports = "*.a"
+
+    requires = "TestA/1.0.0@test/develop"
+
+    def package(self):
+        super().package()
+
+        self.copy("*", src=".", dst="lib")
+
+    def package_info(self):
+        super().package_info()
+
+        self.cpp_info.libs = ["lib4", "lib3", "lib1"]
diff --git a/conan_link_order/test_b/liblib4.a b/conan_link_order/test_b/liblib4.a
new file mode 100644
index 0000000..e69de29
  1. Create 'test*' packages
  2. Install 'test*' packages

Expected result

CONAN_LIBS += -llib4 -llib3 -llib1 -llib2

Actual result

CONAN_LIBS += -llib4 -llib1 -llib2 -llib3

question

Most helpful comment

Hi, Dmitry!
Thank you a lot for the example, I was able to reproduce the issue.

I see multiple problems with current behaviour:

  1. cpp_info.libs is supposed to be used only for libraries in the package itself. The problem with defining libraries out of your package - is that you're bypassing the natural order of dependencies in the graph. Diamonds will spawn different linking strings in different subgraphs.
  2. Conan doesn't report an error when it finds library names but without actual libraries present.
  3. I've tried different modifications and found out a very nasty bug - if your package is actually creating libraries with names that are already used by a different package in the graph - it doesn't report an error and simply order the link string in the natural order of the graph.

In that sense - the result you get is intended behaviour.

All 3 comments

Hi, Dmitry!
Thank you a lot for the example, I was able to reproduce the issue.

I see multiple problems with current behaviour:

  1. cpp_info.libs is supposed to be used only for libraries in the package itself. The problem with defining libraries out of your package - is that you're bypassing the natural order of dependencies in the graph. Diamonds will spawn different linking strings in different subgraphs.
  2. Conan doesn't report an error when it finds library names but without actual libraries present.
  3. I've tried different modifications and found out a very nasty bug - if your package is actually creating libraries with names that are already used by a different package in the graph - it doesn't report an error and simply order the link string in the natural order of the graph.

In that sense - the result you get is intended behaviour.

OK, I agree, in case of 3+ packages keeping order of other (not own) libs may break the whole linking order. Please close the issue.

Thanks!

Closing the issue as solved! Thanks @Minimonium for the anwser and inversigation. Indeed Conan resolves conflicts at reference/node level, not at library name level at this moment. This affects for example the "global"consumption of libraries in CMake, that's why we would like to transition to components and using cmake targets.

Was this page helpful?
0 / 5 - 0 ratings