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

add "Compile and link dynamically to an external C library" example #294

Open
budziq opened this Issue Sep 25, 2017 · 8 comments

Comments

Projects
None yet
3 participants
@budziq
Collaborator

budziq commented Sep 25, 2017

Crates cc
Section 8.3 Build Time Tooling

Use cc crate to compile and link dynamically to an external/system C library from a build.rs file.

Please note that it will be important to mention that this is a build time crate.
Most likely we will dedicate a separate (last) chapter like "build_time.md"

cc #236

@brson brson referenced this issue Sep 25, 2017

Open

Cookbook ideas for "cc" crate #236

3 of 5 tasks complete

@budziq budziq added this to the impl period milestone Oct 4, 2017

@j-haj

This comment has been minimized.

Show comment
Hide comment
@j-haj

j-haj Oct 8, 2017

Contributor

I have a minimal working example here. I am currently verifying that the library produced is indeed dynamic.

Contributor

j-haj commented Oct 8, 2017

I have a minimal working example here. I am currently verifying that the library produced is indeed dynamic.

@budziq budziq added the claimed label Oct 8, 2017

@j-haj

This comment has been minimized.

Show comment
Hide comment
@j-haj

j-haj Oct 10, 2017

Contributor

I'm starting to get into the weeds on this and before I go too deep I thought I should get some clarification here... What is the overall goal of this issue? Are we trying to create library that is dynamically linked to or are we simply creating a dynamic object which is then statically compiled into the executable? Specifically, there is a subtle difference between a shared object and a shared library -- the former can be statically linked into an executable, while the latter is linked at runtime.

To expand upon this, the example from the cc crate docs would lead one to come up with the following code example:

cc::Build::new()
        .file("src/foo.c")
        .shared_flag(true)
        .pic(true)
        .compiler("gcc")
        .compile("foo.so");

However, as far as I can tell, this does not actually produce a shared library. Instead, it produces foo.so.a, which does not appear to be a shared library. I'm guessing the object foo.o is created using the -shared flag, but a shared library is not actually created. Additionally, on macOS, where gcc is an alias for clang, the -shared flag is actually ignored.

To return to the original question, what do we want to do with this recipe? It seems we have two options. The more complex option:

  • Create libfoo.so
  • Link libfoo.so with our executable
  • It would be great if we could verify libfoo.so is a shared library. I am trying to get _init() and _fini() to work with a standalone C shared lib but no luck so far...

The alternative:

  • Create libfoo.a as we have in prior examples, the only difference being we use .shared(true) and .pic(true) options

As an aside, is there an easy way to create an executable binary in rust? Cargo does not seem to offer this functionality so I imagine this is done via rustc -- I'll read the docs. Ideally I'd like to get option 1 working with a compiled binary, then delete the shared lib and watch the binary give me an error when it is subsequently run.

Contributor

j-haj commented Oct 10, 2017

I'm starting to get into the weeds on this and before I go too deep I thought I should get some clarification here... What is the overall goal of this issue? Are we trying to create library that is dynamically linked to or are we simply creating a dynamic object which is then statically compiled into the executable? Specifically, there is a subtle difference between a shared object and a shared library -- the former can be statically linked into an executable, while the latter is linked at runtime.

To expand upon this, the example from the cc crate docs would lead one to come up with the following code example:

cc::Build::new()
        .file("src/foo.c")
        .shared_flag(true)
        .pic(true)
        .compiler("gcc")
        .compile("foo.so");

However, as far as I can tell, this does not actually produce a shared library. Instead, it produces foo.so.a, which does not appear to be a shared library. I'm guessing the object foo.o is created using the -shared flag, but a shared library is not actually created. Additionally, on macOS, where gcc is an alias for clang, the -shared flag is actually ignored.

To return to the original question, what do we want to do with this recipe? It seems we have two options. The more complex option:

  • Create libfoo.so
  • Link libfoo.so with our executable
  • It would be great if we could verify libfoo.so is a shared library. I am trying to get _init() and _fini() to work with a standalone C shared lib but no luck so far...

The alternative:

  • Create libfoo.a as we have in prior examples, the only difference being we use .shared(true) and .pic(true) options

As an aside, is there an easy way to create an executable binary in rust? Cargo does not seem to offer this functionality so I imagine this is done via rustc -- I'll read the docs. Ideally I'd like to get option 1 working with a compiled binary, then delete the shared lib and watch the binary give me an error when it is subsequently run.

@budziq

This comment has been minimized.

Show comment
Hide comment
@budziq

budziq Oct 11, 2017

Collaborator

What is the overall goal of this issue? Are we trying to create library that is dynamically linked to or are we simply creating a dynamic object which is then statically compiled into the executable?

We would be interested in linking to a full blown external shared library (probably the title could be more descriptive). So we just assume existence of some *.so file with given symbols.

As you have noticed the cc crate does not seam to provide a way to create a *.so file (although we might drop a note about it in their bugtracker as the feature would be desirable and their docs are not perfectly clear on it imho)

As an aside, is there an easy way to create an executable binary in rust? Cargo does not seem to offer this functionality

Please see information under "Configuring a target" you are probably looking for [[bin]] clause. If you need more control (very unlikely) you can look into "The profile.* section"

Collaborator

budziq commented Oct 11, 2017

What is the overall goal of this issue? Are we trying to create library that is dynamically linked to or are we simply creating a dynamic object which is then statically compiled into the executable?

We would be interested in linking to a full blown external shared library (probably the title could be more descriptive). So we just assume existence of some *.so file with given symbols.

As you have noticed the cc crate does not seam to provide a way to create a *.so file (although we might drop a note about it in their bugtracker as the feature would be desirable and their docs are not perfectly clear on it imho)

As an aside, is there an easy way to create an executable binary in rust? Cargo does not seem to offer this functionality

Please see information under "Configuring a target" you are probably looking for [[bin]] clause. If you need more control (very unlikely) you can look into "The profile.* section"

@j-haj

This comment has been minimized.

Show comment
Hide comment
@j-haj

j-haj Oct 11, 2017

Contributor

Thanks for the links @budziq ! Very useful info. I'll follow-up with the cc team.

Contributor

j-haj commented Oct 11, 2017

Thanks for the links @budziq ! Very useful info. I'll follow-up with the cc team.

@j-haj

This comment has been minimized.

Show comment
Hide comment
@j-haj

j-haj Oct 11, 2017

Contributor

See this issue from the cc crate. Alex mentions it wasn't the intention of the cc crate to build shared libraries. Given this info, it seems we should close this issue and remove this as a recipe for the cookbook. What are your thoughts @budziq ?

Contributor

j-haj commented Oct 11, 2017

See this issue from the cc crate. Alex mentions it wasn't the intention of the cc crate to build shared libraries. Given this info, it seems we should close this issue and remove this as a recipe for the cookbook. What are your thoughts @budziq ?

@budziq

This comment has been minimized.

Show comment
Hide comment
@budziq

budziq Oct 11, 2017

Collaborator

Given this info, it seems we should close this issue and remove this as a recipe for the cookbook.

Not necessarily. We can still:

  • build a static library whose only contents are link against *.so using object - it might be a little contrived
  • link directly with *.so without cc crate, using only the facilities given by cargo cargo:rustc-link-lib=dylib=foo

Then it still might an interesting example.

Collaborator

budziq commented Oct 11, 2017

Given this info, it seems we should close this issue and remove this as a recipe for the cookbook.

Not necessarily. We can still:

  • build a static library whose only contents are link against *.so using object - it might be a little contrived
  • link directly with *.so without cc crate, using only the facilities given by cargo cargo:rustc-link-lib=dylib=foo

Then it still might an interesting example.

@j-haj

This comment has been minimized.

Show comment
Hide comment
@j-haj

j-haj Oct 12, 2017

Contributor

Great points. I think the latter might be more interesting. To that end, it might be worth having a separate section for cargo with various recipes that show what you can do with cargo (e.g., linking to a shared lib). The main takeaways I got from the book with regards to cargo were creating binary and library projects, and the commands cargo run, cargo build, and cargo test. Looking through the docs you linked there is obviously a lot more tooling available 😄

Contributor

j-haj commented Oct 12, 2017

Great points. I think the latter might be more interesting. To that end, it might be worth having a separate section for cargo with various recipes that show what you can do with cargo (e.g., linking to a shared lib). The main takeaways I got from the book with regards to cargo were creating binary and library projects, and the commands cargo run, cargo build, and cargo test. Looking through the docs you linked there is obviously a lot more tooling available 😄

@budziq

This comment has been minimized.

Show comment
Hide comment
@budziq

budziq Oct 12, 2017

Collaborator

@j-haj I feel that this example is stepping (possibly neck deep) into a FFI territory that is quite scattered in the rust landscape. For now I've marked this as "needs clarification" and created an issue to gather some opinions here before we proceed here.

Collaborator

budziq commented Oct 12, 2017

@j-haj I feel that this example is stepping (possibly neck deep) into a FFI territory that is quite scattered in the rust landscape. For now I've marked this as "needs clarification" and created an issue to gather some opinions here before we proceed here.

@budziq budziq removed the hacktoberfest label Nov 3, 2017

@budziq budziq removed this from the impl period milestone May 16, 2018

@AndyGauge AndyGauge removed the easy label Jul 18, 2018

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