Closed Bug 1624973 Opened 5 years ago Closed 4 years ago

Enable RUST_PROGRAMS to statically link C++ code

Categories

(Firefox Build System :: General, enhancement)

enhancement
Not set
normal

Tracking

(Not tracked)

RESOLVED WONTFIX

People

(Reporter: bytesized, Unassigned)

References

Details

I'm currently trying to call a function from this file from a program compiled with RUST_PROGRAMS += ....

I've tried adding this to the moz.build:

SOURCES += [
  '/toolkit/mozapps/update/common/commonupdatedir.cpp',
]

But I get: AttributeError: 'RustProgram' object has no attribute 'sources'

Since that file is also built into the "updatecommon" library, I also tried:

USE_LIBS += [
    'updatecommon',
]

But that doesn't seem to work either (linking fails when it can't find the symbol for the function I'm trying to call).

As far as I know, my only other option is to write a build script. But to build the file I'm building has several includes which, as far as I can tell, need to be manually specified. And then the includes of those includes need to be specified, and so on and so forth. Even if I listed all of them out, this solution seems extremely brittle.

There's no real support for calling C++ from Rust programs; I don't think anybody's asked for that feature before.

We could probably add something akin to USE_LIBS for Rust programs, so you'd have to compile all the code into a separate library in a different directory and then the build system would take care of linking that code into your Rust program. Would that work OK?

The only thing (well, one of the things) I'm not sure about is that we have an assumption that all C++ code is getting compiled as "Mozilla-style" C++ code -- no exceptions, infallible memory allocation, etc. -- and we've tweaked our Rust code to conform to that model. I don't know if shoving C++ code into a Rust program will necessarily work as well.

We could probably add something akin to USE_LIBS for Rust programs, so you'd have to compile all the code into a separate library in a different directory and then the build system would take care of linking that code into your Rust program. Would that work OK?

Quick implementation question, is this something we can actually do? I am not terribly knowledgeable about Rust, but from what I have seen, the typical way to link external libraries into your Rust projects is by tagging FFI stuff with the #[link] attribute or by adding a compiler directive in your build script. Neither of these are things the build system can do, to my knowledge. Is there something I'm missing?

The "updatecommon" library is already being compiled separately, so I think that solution sounds fine. In Rust, that would end up linking statically, right?

I'm not really sure what you mean by the "Mozilla-style" code issue. My understanding was that the C++ compiled code would use its own allocate and free functions and things like that, so that this wouldn't be an issue. Is the concern over what happens if an allocation fails in C++ code called from Rust?

The problem is that with rust programs, rust is doing the linking, so there's no way for the build system to do something about USE_LIBS. The best the build system could do is resolve USE_LIBS to the set of object files it corresponds to (since we don't actually build static libraries), and get the rust build.rs to link them in a library and the crate defining the right #[link].

I tried my best to get it to link as-is by adding #[link(name = "updatecommon")] to the function declaration and adding the correct directory to the library search path with a cargo:rustc-link-search=... in a build script, but it complained about there not being an updatecommon.lib. Indeed that file seems not to exist. Is it looking for the static library that we don't build?

Blocks: 1627805

I've written some code (attached to Bug 1627805) that almost works. But it is missing the build system component that causes them to build in the right order.

On a full build, I typically see the update agent build before the updatecommon library. This causes linking to fail. But when things build in the correct order, the build completes successfully.

(In reply to Kirk Steuber (he/him) [:bytesized] from comment #6)

I've written some code (attached to Bug 1627805) that almost works. But it is missing the build system component that causes them to build in the right order.

On a full build, I typically see the update agent build before the updatecommon library. This causes linking to fail. But when things build in the correct order, the build completes successfully.

You can force some ordering in recurse.mk although for obvious reasons we try to tell the build system what the actual dependencies are and have it figure out how to order things. Maybe see if you can achieve what you need that way to inform whether there are further issues?

With the updated approach for the background update agent I don't think this is relevant anymore. Please re-open if I am mistaken.

No longer blocks: update-agent
Status: NEW → RESOLVED
Closed: 4 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.