Coder Social home page Coder Social logo

C++ mixed linking about buck2 HOT 4 CLOSED

cbarrete avatar cbarrete commented on April 28, 2024
C++ mixed linking

from buck2.

Comments (4)

cjhopman avatar cjhopman commented on April 28, 2024 6

I think the missing piece here is preferred_linkage. link_style says how a target wants to consume its dependencies when it is being linked as a shared lib or executable, preferred_linkage indicates how a library wants to be consumed.

For A -> B -> C -> D

If these all have preferred_linkage="any" (the default), and the all have link_style="shared", you'll get:

A.so -> B.so -> C.so -> D.so

Change A to link_style = "static" and you get

A.so -> B.a -> C.a -> D.a

If you then change C to preferred_linkage = "shared" you'd get

A.so -> B.a -> C.so -> D.so

Note there that C got a D.so, not a D.a. A link_style attribute only affects the linking of the target itself. When C is built as a shared lib, it uses its own link_style, not the one from A.

If you changed C's link_style to "static", you'd get:

A.so -> B.a -> C.so -> D.a

from buck2.

cbarrete avatar cbarrete commented on April 28, 2024

Here's a minimal repro on top of a bare buck2 init --git with the 2024-02-15 release:

diff --git a/BUCK b/BUCK
index 1cb6b38..5d96647 100644
--- a/BUCK
+++ b/BUCK
@@ -1,7 +1,18 @@
-# A list of available rules and their signatures can be found here: https://buck2.build/docs/api/rules/
+cxx_binary(
+    name = "test",
+    srcs = ["main.cpp"],
+    deps = [":shared_lib", ":static_lib"],
+    link_style = None,
+)
+
+cxx_library(
+    name = "shared_lib",
+    srcs = ["shared_lib.cpp"],
+    link_style = "shared",
+)
 
-genrule(
-    name = "hello_world",
-    out = "out.txt",
-    cmd = "echo BUILT BY BUCK2> $OUT",
+cxx_library(
+    name = "static_lib",
+    srcs = ["static_lib.cpp"],
+    link_style = "static",
 )
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..d0b8ca7
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,8 @@
+void dynamic_lib_fn();
+void static_lib_fn();
+
+int main()
+{
+    dynamic_lib_fn();
+    static_lib_fn();
+}
diff --git a/shared_lib.cpp b/shared_lib.cpp
new file mode 100644
index 0000000..6451836
--- /dev/null
+++ b/shared_lib.cpp
@@ -0,0 +1,3 @@
+void dynamic_lib_fn()
+{
+}
diff --git a/static_lib.cpp b/static_lib.cpp
new file mode 100644
index 0000000..28ce184
--- /dev/null
+++ b/static_lib.cpp
@@ -0,0 +1,3 @@
+void static_lib_fn()
+{
+}

which I then check with readelf -d $(buck2 build :test --show-full-simple-output). In this case, both libraries are linked as dynamically:

 0x0000000000000001 (NEEDED)             Shared library: [lib_shared_lib.so]
 0x0000000000000001 (NEEDED)             Shared library: [lib_static_lib.so]

If I set the binary's link_style to either "static" or "shared", it overrides both libraries' link_style, which is not what I want. I've read the documentation for both cxx_binary and cxx_library and played with a few parameters, but got nowhere with that.

Is there something that I'm missing here/do you have any pointers for me?

from buck2.

cbarrete avatar cbarrete commented on April 28, 2024

I also forgot to mention, since the documentation states that:

link_style: Determines whether to build and link this rule's dependencies statically or dynamically. Can be either static, static_pic or shared.

(that is, the library itself might not be affected by the link_style, only its dependencies), I also tried adding an intermediate layer of wrappers and depending on those, but no dice:

cxx_library(
    name = "shared_lib_wrapper",
    exported_deps = [":shared_lib"],
    link_style = "shared",
)

cxx_library(
    name = "static_lib_wrapper",
    exported_deps = [":static_lib"],
    link_style = "static",
)

from buck2.

cbarrete avatar cbarrete commented on April 28, 2024

This is exactly what I needed and was missing, thanks a lot!
The transitive subtleties are a bit of a gotcha, it would be nice for them to be documented (I'll look into this when I have some time after work).

from buck2.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.