Rust fails to compile after adding geo crate - rust

I am using alpine-3.16 and rust-1.56 with the following packages to compile my program.
expat libbz2 libcrypto1.1 libffi libpq libssl1.1 libtirpc libuuid musl \
ncurses-libs readline xz-libs zlib libc6-compat rust cargo bash
I was able to compile my program before adding the following two dependencies:
geo = "0.22.1"
geo-types = "0.7.6"
Following are the full contents of cargo.toml:
[package]
name = "math-helpers"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies.cpython]
version = "0.7.0"
[features]
default = ["python3"]
python3 = ["cpython/python3-sys", "cpython/extension-module"]
[dependencies]
libm = {version = "0.2.0"}
geo = "0.22.1"
geo-types = "0.7.6"
The errors that I am getting are as following:
/math-helpers # cargo build
Compiling geo v0.22.1
error: there is no argument named `pt`
--> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/geo-0.22.1/src/algorithm/sweep/line_or_point.rs:248:59
|
248 | "line intersection before first line: {pt:?}\n\tLine({lp1:?} - {lp2:?}) X Line({lp3:?} - {lp4:?})",
| ^^^^^^
error: there is no argument named `pt`
--> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/geo-0.22.1/src/algorithm/sweep/line_or_point.rs:256:60
|
256 | "line intersection before second line: {pt:?}\n\tLine({lp1:?} - {lp2:?}) X Line({lp3:?} - {lp4:?})",
| ^^^^^^
error: there is no argument named `r`
--> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/geo-0.22.1/src/algorithm/sweep/segment.rs:51:79
|
51 | "intersection point was not ordered within the line: {p:?} <= {r:?} <=> {q:?}",
| ^^^^^
error: there is no argument named `q`
--> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/geo-0.22.1/src/algorithm/sweep/segment.rs:51:89
|
51 | "intersection point was not ordered within the line: {p:?} <= {r:?} <=> {q:?}",
| ^^^^^
It works fine on Ubuntu, though. It's highly likely that I am missing a platform dependency that needs to be installed on Alpine.

Related

Patch a transient git dependency to a specific rev

I depend on crates a and b, where I patched b to a git dependency on ref foo:
# Cargo.toml of my crate
[dependencies]
a = "1.0.0"
b = "1.0.0"
[patch.crates-io]
b = { git = "https://github.com/user/example", rev = "foo" }
a also depends on b as a git dependency, but on no specific ref:
# Cargo.toml of a
[dependencies]
b = { git = "https://github.com/user/example" }
I want to force a to use the same ref for b as I do, which I thought I could do like this:
# The ideal Cargo.toml of my crate
[dependencies]
a = "1.0.0"
b = "1.0.0"
# patch local dependency
[patch.crates-io]
b = { git = "https://github.com/user/example", rev = "foo" }
# patch transient dependency
[patch.'https://github.com/user/example']
b = { git = "https://github.com/user/example", rev = "foo" }
This does not work however, since the source I'm patching still points to the same source, just in a different rev:
error: failed to resolve patches for `https://github.com/user/example`
Caused by:
patch for `b` in `https://github.com/user/example` points to the same source, but patches must point to different sources
[Finished running. Exit status: 101]
My workaround so far is to fork b and patch like this:
# Cargo.toml of my crate using a work around
[dependencies]
a = "1.0.0"
b = "1.0.0"
[patch.crates-io]
b = { git = "https://github.com/me/example", rev = "foo" } # Using my fork
[patch.'https://github.com/user/example']
b = { git = "https://github.com/me/example", rev = "foo" } # Using my fork
This works, but the fork is essentially useless. Is there a better way to do this?
I tried this hack, but it does not work either since it just ignores the rev. The whole GitHub issue makes it look like what I'm trying is not supported at the moment, but it's hard to tell, since it's not exactly the same feature.
Per this GitHub issue, this feature is currently not supported, since git dependencies are differentiated exclusively via URL, not revision. Some URLs are treated as the same, e.g. the .git ending always being stripped, but cargo is still just comparing URLs and nothing else.
We can however use this "feature" to our advantage: Adding a ?ref=foo to the end of the URL will make it look like a new source:
# Fixed Cargo.toml
[dependencies]
a = "1.0.0"
b = "1.0.0"
# patch local dependency
[patch.crates-io]
b = { git = "https://github.com/user/example?rev=foo" }
# patch transient dependency
[patch.'https://github.com/user/example']
b = { git = "https://github.com/user/example?rev=foo" }
Be careful to use the URL hack in both patches, otherwise you will create a corrupt Cargo.lock with two definitions of b:
# Corrupt Cargo.toml
[dependencies]
a = "1.0.0"
b = "1.0.0"
# patch local dependency
[patch.crates-io]
b = { git = "https://github.com/user/example", rev = "foo" } # mistake!
# patch transient dependency
[patch.'https://github.com/user/example']
b = { git = "https://github.com/user/example?rev=foo" }
While I did not test it, this approach should in principle also work with patches on branches by appending /tree/<branch> to the URL.

Python3.10.4 cross compilation for HP-UX

Trying to cross compile python3.10.4 on a Linux machine with gcc-9.3.0 for HP-UX IA64 and running into following errors. Did not find the setenv/unsetenv in stdlib.h for HP-UX.
*Python/pylifecycle.c: In function '_coerce_default_locale_settings':
Python/pylifecycle.c:319:9: error: implicit declaration of function 'setenv'; did you mean 'getenv'? [-Werror=implicit-function-declaration]
319 | if (setenv("LC_CTYPE", newloc, 1)) {
| ^~~~~~
| getenv
cc1: some warnings being treated as errors
./Modules/posixmodule.c: In function 'os_putenv_impl':
./Modules/posixmodule.c:10969:9: error: implicit declaration of function 'setenv'; did you mean 'getenv'? [-Werror=implicit-function-declaration]
10969 | if (setenv(name_string, value_string, 1)) {
| ^~~~~~
| getenv
./Modules/posixmodule.c: In function 'os_unsetenv_impl':
./Modules/posixmodule.c:11014:15: error: implicit declaration of function 'unsetenv'; did you mean 'getenv'? [-Werror=implicit-function-declaration]
11014 | int err = unsetenv(PyBytes_AS_STRING(name));
| ^~~~~~~~
| getenv*
Looks like this is implemented in 3.9 and does not have any config to skip this. Need help addressing this issue.

Include long options without short options for help and version

I would like to include --help and --version long options without the -h and -V short options. Is this possible?
I'm using clap with yaml. The closest I've been able to come up with is to use hidden (unused) args that mask the short options.
# main.rs
use clap::{load_yaml, App};
fn main() {
let y = load_yaml!("cli.yaml");
let m = App::from_yaml(y).get_matches();
println!("_help {}", m.is_present("_help"));
println!("_version {}", m.is_present("_version"));
}
# Cargo.toml
[package]
name = "app"
version = "0.0.1"
edition = "2018"
[dependencies]
clap = {version = "~2.33.0", features = ["yaml"]}
# cli.yaml
name: app
version: 0.0.1
args:
- opt: { short: "o", long: "opt" }
- _help: { short: "h", hidden: true }
- _version: { short: "V", hidden: true }
$ cargo -q run -- --help
app 0.0.1
USAGE:
app [FLAGS]
FLAGS:
--help Prints help information
-o, --opt
--version Prints version information
$ cargo -q run -- -h
_help true
_version false
$ cargo -q run -- -o
_help false
_version false
$ cargo -q run -- -V
_help false
_version true
$ cargo -q run -- -x
error: Found argument '-x' which wasn't expected, or isn't valid in this context
USAGE:
app [FLAGS]
For more information try --help
This doesn't feel like a very clean approach. Is there another/better way?
Clap is designed more towards creating an args parser. So there aren't really that much functionality for getting and removing existing arguments.
If you simply want to rename "-h" to e.g. "-?", then you can do that with help_short("-?") (see also version_short().)
However, there are ways to work around it.
Assuming you're using e.g. clap = "2.33". Then similarly to what you're already doing, you can override/replace the help and version args, and in that way "remove" the short versions. (For brevity, I'll only include examples for help.)
You can of course keep it in cli.yaml if you want, but I'll add it to main.rs. In short, you want to add a new "help" arg and only give it a long version. It's important that you include help("Prints help information") as this is replacing the existing help arg, so if you don't it won't have the default help message for --help.
The downside to overring "help" is that you'd need to handle print_help() yourself.
use clap::{load_yaml, App, Arg};
fn main() {
let y = load_yaml!("cli.yaml");
let mut app = App::from_yaml(y)
.arg(
Arg::with_name("help")
.long("help")
.help("Prints help information"),
);
let m = app.clone().get_matches();
if m.is_present("help") {
app.print_help().unwrap();
// std::process::exit(0);
// or just
return;
}
}
However, if you're using clap = "3.0.0-beta.2" then that simplifies things, with the introduction of mut_arg(). Because that allows us to mutate the argument. Thereby, we no longer need to call print_help() ourselves.
use clap::{load_yaml, App, Arg};
fn main() {
let y = load_yaml!("cli.yaml");
let m = App::from(y)
.mut_arg("help", |h| {
Arg::new("help")
.long("help")
.about("Prints help information")
})
.get_matches();
}
Note that App::from_yaml() is now App::from(), while Arg::with_name() has become Arg::new(), and help() is now about().

Why do Rust programs use so much more memory than the C, Haskell and OCaml versions?

I looked at how much RAM was used by Rust programs (RES column from top command) and I wonder why they use so much memory.
Here is an example:
use std::io;
fn main() {
println!("What's your name?");
let mut input = String::new();
io::stdin().read_line(&mut input).unwrap();
println!("Hello {}!", input);
}
I saw that 6 MB of memory was used before I input something.
Here is how I compiled and executed the program:
cargo build --release
./target/release/main
The equivalent C program:
#include <stdio.h>
int main(void) {
printf("What's your name?\n");
char input[100] = {0};
scanf("%s", input);
printf("Hello %s!\n", input);
return 0;
}
only uses 0.6 MB. In this case, the Rust program uses 10 times more memory. In other cases, I saw that the Rust program uses 5 times more memory.
I also tested with other languages to compare.
The OCaml version:
let () =
print_endline "What's your name?";
let line = read_line () in
print_string "Hello ";
print_endline line
uses 1 MB.
The Haskell version:
main = do
putStrLn "What's your name?"
name <- getLine
putStrLn ("Hello " ++ name ++ "!")
uses 3 MB.
The Python version:
print("What's your name?")
name = input()
print("Hello", name, "!")
uses 7 MB, almost the same as the Rust version!
Update
I'm running Linux (ArchLinux) with Rust 1.3 (I also tried the nightly with similar results).
Update 2
Here is more data from the htop command:
VIRT RES SHR MEM% Command
15572 2936 804 0.1 ocaml
21728 2732 2528 0.1 haskell
22540 7480 4308 0.2 python
4056 668 600 0.0 c
24180 6164 1928 0.2 rust
Update 3
I did more tests with massif to see the memory usage.
For every program, I ran massif twice, as following:
valgrind --tool=massif --time-unit=B ./program
valgrind --tool=massif --pages-as-heap=yes --time-unit=B ./program
Here are the results with all the programs (as shown by ms_print):
C versions:
https://framabin.org/?dd243f8ec99155bc#Af5cPrcHnz3DsWiOStfwgW8Qq6BTVhogz/46L+sMuSs=
https://framabin.org/?261b9366c3749469#1ztDBkgVly9CanrrWWrJdh3yBFL5PEIW3OI5OLnze/Q=
Rust versions:
https://framabin.org/?0f1bac1c750e97bf#AXwlFYYPHeazq9LfsTOpRBaUTTkb1NfN9ExPorDJud0=
https://framabin.org/?c24b21b01af36782#OLFWdwLjVG2t7eoLqLFhe0Pp8Q8pA2S/oq4jdRRWPzI=
OCaml versions:
https://framabin.org/?060f05bea318109c#/OJQ8reHCU3CzzJ5NCOCLOYJQFnA1VgxqAIVjgQWX9I=
https://framabin.org/?8ff1ffb6d03cb37a#GN8bq3Wrm6tNWaINIhMAr4ieltLtOPjuZ4Ynof9bV4w=
Haskell versions:
https://framabin.org/?b204bd978b8c1fd8#DyQH862AM8NEPTKlzEcZgoapPaZLdlF9W3dRn47K5yU=
https://framabin.org/?ac1aa89fcaeb782c#TQ+uAiqerjHuuEEIhehVitjm63nc3wu5wfivAeBH5uI=
Python versions:
https://framabin.org/?197e8b90df5373ec#aOi0+tEj32Na5jW66Kl97q2lsjSZ2x7Cwl/pOt0lYIM=
https://framabin.org/?397efa22484e3992#1ylOrmjKaA9Hg7gw7H7rKGM0MyxuvKwPNN1J/jLEMrk=
Summary (ram usage):
|------------|----------|----------|----------|----------|----------|
| | C | Haskell | OCaml | Rust | Python |
|------------|----------|----------|----------|----------|----------|
| First run | 1 B | 63.12 KB | 5.993 MB | 816 B | 1.321 MB |
|------------|----------|----------|----------|----------|----------|
| Second run | 6.031 MB | 24.20 MB | 17.14 MB | 25.60 MB | 27.43 MB |
|------------|----------|----------|----------|----------|----------|
The first run is without the --pages-as-heap=yes parameter.
I also ran massif with the --stacks=yes option for C and Rust.
C version:
https://framabin.org/?b3009d198ccfdee1#HxR6LPPAzt15K+wIFdaqlfSJjBrJvhV2ZHWdElg3ezc=
(3.141 KB)
Rust version:
https://framabin.org/?b446d8d76c279007#tHnGiOnRstTA2krhz6cgfvTjI+FclcZS3rqyZvquWdQ=
(8.602 KB)
What does explain such a huge difference between heap block allocation and page allocation in Rust?
Because the standard library is statically linked.
You can overcome this by compiling with the -C prefer-dynamic option.
As to the reason behind having the standard library statically linked: it increases executable portability (ie: no need for the standard library to be installed in target system).
Since this question is on top results from google, I would like to give an update for anybody looking at this in 2022. I ran the exact same program and measured rust RSS from htop. It shows 924KB. That is 0.92MB. Apparently rust has improved a lot in these years.
This article has a very good discussion of the topic. Some of the largest and most common culprits are cargo's default to debug builds (not relevant in your case) and statically including libraries by default.

Nimrod Beginner - Fizzbuzz - Compiling and Running

I tried writing compiling and running my first nimrod program a fizzbuzz.
Nimrod is installed from git and version is.
[sayth nimrod]$ nimrod --version
Nimrod Compiler Version 0.9.4 (2014-04-28) [Linux: amd64]
Copyright (c) 2006-2014 by Andreas Rumpf
So here is a fizzbuzz
proc fizzBuzz(x, y: int) =
for i in x .. y:
if i mod 15 == 0:
echo("FizzBuzz")
elif i mod 3 == 0:
echo("Fizz")
elif i mod 5 == 0:
echo("Buzz")
else:
echo(i)
I compiled to c (is there a better option?) and it appeared ok to me.
[sayth nimrod]$ nimrod c fizzbuzz.nim
config/nimrod.cfg(37, 2) Hint: added path: '/home/sayth/.babel/pkgs/' [Path]
Hint: used config file '/home/sayth/Nimrod/config/nimrod.cfg' [Conf]
Hint: system [Processing]
Hint: fizzbuzz [Processing]
fizzbuzz.nim(1, 5) Hint: 'fizzbuzz.fizzBuzz(x: int, y: int)' is declared but not used [XDeclaredButNotUsed]
gcc -c -w -I/home/sayth/Nimrod/lib -o /home/sayth/Scripts/nimrod/nimcache/fizzbuzz.o /home/sayth/Scripts/nimrod/nimcache/fizzbuzz.c
gcc -c -w -I/home/sayth/Nimrod/lib -o /home/sayth/Scripts/nimrod/nimcache/stdlib_system.o /home/sayth/Scripts/nimrod/nimcache/stdlib_system.c
gcc -o /home/sayth/Scripts/nimrod/fizzbuzz /home/sayth/Scripts/nimrod/nimcache/stdlib_system.o /home/sayth/Scripts/nimrod/nimcache/fizzbuzz.o -ldl
Hint: operation successful (8181 lines compiled; 1.065 sec total; 13.138MB) [SuccessX]
But running it produces no output. Is there something I am doing wrong?
[sayth nimrod]$ ./fizzbuzz
[sayth nimrod]$
You simply forgot to call it. Note the compiler hint:
fizzbuzz.nim(1, 5) Hint: 'fizzbuzz.fizzBuzz(x: int, y: int)' is declared but not used [XDeclaredButNotUsed]
And no, your best option is compiling to C. There may be an LLVM backend in the future, but the general opinion is that it is more trouble than it is worth. Intermediate C output is more portable (gcc runs in many more plataforms than LLVM) and you can chose the compiler that can best optimize your code.

Resources