Set cargo linker for cross compilation only if necessary - rust

According to various guides on cross-compiling Rust I need to set something like this in .cargo/config:
[target.x86_64-unknown-linux-musl]
linker = "x86_64-linux-musl-gcc"
In my case I am cross compiling for Linux on Mac. This is fine, but I'd also like to be able to build the code natively on Linux (i.e. not cross-compiling). In that case surely the target is still x86_64-unknown-linux-musl, but I don't want to override linker then.
I guess you can probably do this using a custom build.rs, but is there any way to do this from .cargo/config? I thought you'd be able to do something like this:
[target.'cfg(all(host_os = "macos", target_os = "linux"))']
linker = "x86_64-linux-musl-gcc"
But there is no host_os.

I'm guessing that you've put .cargo/config inside of your Cargo workspace?
If this the case, you should consider moving host-specific configuration options (such as target.{target}.linker) into your user-specific ~/.cargo/config instead. That way, the linker is not tied to the workspace configuration, but instead to the user: different users on different hosts could have different linkers configured for different targets.

Related

Yocto Dunfell how to set Compiler Flags to '-Os' Globally

I have a working Linux system image being produced for my ARM board with Yocto ( Dunfell branch ).
Space occupied by the rootfs is a premium and I am working on shrinking the image.
I want to experiment with the GCC '-Os' flag, to optimize for space. I would like to set this globally for my experiment. I found the following information in a presentation ( https://pretalx.com/yocto-project-summit-2020/talk/AY37HF/ ):
I added the following to my image_0.1.bb file. However, I do not see the '-Os' optimization flag being used in any package.
# Disabled until the option works properly -feliminate-dwarf2-dups
FULL_OPTIMIZATION = "-Os -pipe ${DEBUG_FLAGS}"
DEBUG_OPTIMIZATION = "-Og ${DEBUG_FLAGS} -pipe"
SELECTED_OPTIMIZATION = "${#d.getVar(oe.utils.vartrue('DEBUG_BUILD', 'DEBUG_OPTIMIZATION', 'FULL_OPTIMIZATION', d))}"
Is the code correct and, if so, where should I put this code? If not correct, how can I globally add the '-Os' compiler optimization flag to my project?
Global options must be added to one of the global configuration files.
For testing things this would typically be conf/local.conf.
You only need to add the variables you actually change as bitbake uses lazy evaluation of variables values.
Variables in recipe files only affect the tasks for that recipe. This means that nothing you do in the image recipe can affect how tasks in other recipes are done.

Setting the include path with bindgen

I'm writing a Rust interface to a small C library, which has headers spread in a few locations. It's not a system library, and is normally used by some executables in the same package; I'm currently including it as a git submodule in my Cargo project.
Building the library seems to be pretty easy; I've opted to use the gcc crate from build.rs:
gcc::Config::new()
.file("external/foo/dir1/file1.c")
.file("external/foo/dir2/file2.c")
.include("external/foo/dir1/")
.include("external/foo/dir2/")
.include("external/foo/config_a/")
.compile("libfoo.a");
Now I was hoping to use the bindgen crate to generate the FFI interface without too much fuss, but it doesn't seem to have a way of setting include paths.
I can create a wrapper.h as suggested by this blog and include several headers, but if dir1/dir1.h includes conf.h directly, which works when building due to .include("external/foo/config_a/") it can't be found.
I can't find anything in bindgen's API to help here (essentially I want to pass the equivalent of gcc/clang's -I option). Am I missing anything?
The best option I can think of so far is to copy the various headers from the library source into some temporary directory in build.rs and run bindgen on that, but that seems somewhat messy if there's a nicer way.
With the API you can use Builder::clang_arg with arbitrary arguments:
let b = bindgen::builder().header("foo.h").clang_arg("-I/path");
From the command line you can do the same by appending arguments after --, like:
bindgen foo.h -- -I/path

How to check the compiler version in Qt .pro file?

I want to build a Qt project using either GCC or an ARM compiler. In either environment I have to link different libraries.
How I can check if the current compiler is Linux's g++ and CROSS_COMPILE is 'arm-cortexa9neont-linux-gnueabi-'?
You can use the Platform Scope built in to QMake to set up the build differently depending on platform.
It's based on the mkspec's shipped with Qt and can be found in
[Where Qt's installed]/mkspecs
So in your case I guess it'll look something like this:
linux-arm-gnueabi {
//ARM stuff here
}
Please note that I have not tested this. I've only read what's in the documentation I have linked to.
If you want to know only type of processor, you can use Q_PROCESSOR_ARM macro.

SCons: how to explicitly express the dependencies between envs?

I have a project build by scons.
In the project there are multiple components, including client, shell, engine and etc...
Each component uses different compile options so they are split into different env.
And both shell and engine are going to require client libraries built first.
In the environment settings, both shell and engine has something like "-lclient -L[installpath]/lib", and SConscriptClient is going to build the libclient.a in [installpath]/lib.
So I expect SConscriptClient is run before everything else.
so in the code I have something like:
clientbuild = clientEnv.SConscript ( 'SConscriptClient', variant_dir=clientDir )
if hasShell:
shellbuild = shellEnv.SConscript ( 'SConscriptShell', variant_dir=shellDir )
Depends ( shellbuild, clientbuild )
if hasEngine:
enginebuild = engineEnv.SConscript ( 'SConscriptEngine', variant_dir=engineDir )
Depends ( enginebuild, clientbuild )
However it seems scons is not smart enough to understand the dependencies between client/shell and engine ( that means the Depends call doesn't take effect ). It still try to run SConscriptShell before SConscriptClient
Is there anything i can do to set the dependeices between sconscript?
You shouldn't have to explicitly set these dependencies with Depends(). If the client library is a target built by SCons and both the shell and engine link that library, then SCons should be able to implicitly determine the dependencies and build the client first.
Basically, I see 2 issues here:
Why doesn't SCons implicitly figure out the dependencies?
Why isn't it working as is with the explicit calls to Depends()?
If we figure out number 1, then we wont have to figure out number 2. But just to be complete, I think number 2 isnt working because of what the call to SConscript() is returning. In the subsidiary SConscript scripts (SConscriptClient, SConscriptShell, and SConscriptEngine) are you returning the target? If not, I would imagine the clientbuild variable would be None. To return the target use the Return() SCons function and pass it the return value of the Library() builder.
As for why SCons cant figure out the dependencies implicitly, we would need to see the subsidiary SConscript build scripts. But I can imagine its because you are probably specifying the client library "by hand", so SCons doesnt see the dependency.
The way to build a program with a library so that SCons can see the dependency, you need to use the LIBS construction variable, as follows:
env.Append(LIBS='client')
env.Append(LIBPATH='path/to/client/lib')
env.Program(target='shell', source='shell.cc')
Notice I don't use the -l nor the -L flags above, SCons will add those in a platform independent manner. If you're specifying the library "by hand" by specifying it like this: '-lclient' then SCons wont see the dependency. This is by design, and is more interesting with include paths: if you have a lot of include paths with header files that will almost never change, then (for performance reasons) you don't want SCons to scan them for changes, and thus specify them "by hand".
One additional comment, normally the different environments are passed to the subsidiary SConscript build scripts differently, as follows:
clientEnv = Environment()
# set the clientEnv accordingly
SConscript ('SConscriptClient', variant_dir=clientDir, exports=['clientEnv'] )
SConscriptClient:
Import('clientEnv')
# You may want to clone the clientEnv here, if you want to make
# changes that you don't want seen in the rest of the build

Conditionally disable shared library build

I’ve written a C library that builds using Libtool, and I’d like to only build static libraries on Cygwin. To that end, I placed
if test "$target_os" = "cygwin"; then
AC_DISABLE_SHARED
fi
in my configure.ac.
This does indeed disable building shared libraries on Cygwin; however, it also disables building them everywhere else. I assume this is because expanding AC_DISABLE_SHARED causes some unfortunate side effects.
How can I use Libtool to avoid building shared libraries on Cygwin while still building them on other platforms?
I'm not sure $target_os is what you want. $host_os is the name for the system the code will run on. The 'target' triple is rarely used outside of building compilers / toolchains.
Even though the configure script might still say yes / enabled for shared libraries, you can override the result by setting the enable_shared|static variables.
AC_CANONICAL_HOST
...
LT_INIT
case $host_os in
cygwin*)
AC_MSG_RESULT([explicitly disabled shared libraries for $host])
enable_shared=no; enable_static=yes ;;
esac
These variables aren't documented, so it's technically a hack - but it's basically behaving like any other AC_ARG_ENABLE option. Your original idea might still work if it appears before LT_INIT, but this approach overrides any configure options.

Resources