Skip to content

Cannot compile rustc on FreeBSD #23287

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

Closed
aidancully opened this issue Mar 11, 2015 · 5 comments · Fixed by #23324
Closed

Cannot compile rustc on FreeBSD #23287

aidancully opened this issue Mar 11, 2015 · 5 comments · Fixed by #23324

Comments

@aidancully
Copy link
Contributor

Problem was introduced in 95d9046.

Command line:

CFG_LLVM_LINKAGE_FILE=/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/rt/llvmdeps.rs \
LD_LIBRARY_PATH=/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib:$LD_LIBRARY_PATH   \
x86_64-unknown-freebsd/stage1/bin/rustc --cfg stage1  -O --cfg rtopt --cfg debug \
-C prefer-dynamic --target=x86_64-unknown-freebsd  -D warnings \
-L "x86_64-unknown-freebsd/rt" \
-L "/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/llvm/Release+Asserts/lib" \
-L ""  \
--out-dir x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib \
-C extra-filename=-4e7c5e5c /usr/home/aidan/rust/rust/src/libstd/lib.rs

Produces error:

error: linking with `cc` failed: exit code: 1
note: "cc" "-L/usr/local/lib" "-L/usr/local/lib/gcc46" "-L/usr/local/lib/gcc44" "-m64" \
"-L" "/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib" \
"-o" "x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/libstd-4e7c5e5c.so" \
"x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/std-4e7c5e5c.o" \
"-Wl,--whole-archive" "-lmorestack" "-Wl,--no-whole-archive" \
"x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/std-4e7c5e5c.metadata.o" \
"-nodefaultlibs" \
"/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/libcollections-4e7c5e5c.rlib" \
"/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/librand-4e7c5e5c.rlib" \
"/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/liballoc-4e7c5e5c.rlib" \
"/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/libunicode-4e7c5e5c.rlib" \
"/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/liblibc-4e7c5e5c.rlib" \
"/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/libcore-4e7c5e5c.rlib" \
"-L" "x86_64-unknown-freebsd/rt" \
"-L" "/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/llvm/Release+Asserts/lib" \
"-L" "" \
"-L" "/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib" \
"-L" "/usr/home/aidan/rust/rust/.rust/lib/x86_64-unknown-freebsd" \
"-L" "/usr/home/aidan/rust/rust/lib/x86_64-unknown-freebsd" \
"-Wl,--whole-archive" "-Wl,-Bstatic" "-lrust_builtin" "-lbacktrace" "-lrustrt_native" \
"-Wl,--no-whole-archive" "-Wl,-Bdynamic" "-lexecinfo" "-lpthread" "-lrt" "-lgcc_s" \
"-lpthread" "-lc" "-lm" "-shared" "-lcompiler-rt"
note: /usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib: file not recognized: File format not recognized

error: aborting due to previous error
/usr/home/aidan/rust/rust/mk/target.mk:166: recipe for target 'x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/stamp.std' failed
gmake: *** [x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/stamp.std] Error 101

The problem seems to be that the FreeBSD linker expects "-L" to be a single argument, while rustc is splitting it into two arguments, "-L" and "". Running the following command line by hand:

"cc" "-L/usr/local/lib" "-L/usr/local/lib/gcc46" "-L/usr/local/lib/gcc44" "-m64" \
"-L/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib" \
"-o" "x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/libstd-4e7c5e5c.so" \
"x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/std-4e7c5e5c.o" \
"-Wl,--whole-archive" "-lmorestack" "-Wl,--no-whole-archive" \
"x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/std-4e7c5e5c.metadata.o" \
"-nodefaultlibs" \
"/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/libcollections-4e7c5e5c.rlib" \
"/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/librand-4e7c5e5c.rlib" \
"/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/liballoc-4e7c5e5c.rlib" \
"/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/libunicode-4e7c5e5c.rlib" \
"/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/liblibc-4e7c5e5c.rlib" \
"/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib/libcore-4e7c5e5c.rlib" \
"-Lx86_64-unknown-freebsd/rt" \
"-L/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/llvm/Release+Asserts/lib" \
"-L" \
"-L/usr/home/aidan/rust/rust/x86_64-unknown-freebsd/stage1/lib/rustlib/x86_64-unknown-freebsd/lib" \
"-L/usr/home/aidan/rust/rust/.rust/lib/x86_64-unknown-freebsd" \
"-L/usr/home/aidan/rust/rust/lib/x86_64-unknown-freebsd" "-Wl,--whole-archive" \
"-Wl,-Bstatic" "-lrust_builtin" "-lbacktrace" "-lrustrt_native" "-Wl,--no-whole-archive" \
"-Wl,-Bdynamic" "-lexecinfo" "-lpthread" "-lrt" "-lgcc_s" "-lpthread" "-lc" "-lm" \
"-shared" "-lcompiler-rt"

(same as before, but with -L and <path> arguments merged into a single argument)

This allowed the link to succeed.

@rprichard
Copy link
Contributor

I suspect the problem stems from the curious -L "". That's passing two arguments, the second of which is blank.

From my testing so far (on Linux), neither rustc nor clang/gcc treat -L "" as a synonym for -L., so I'm not sure what it actually accomplishes, if anything. rustc passes both arguments to cc. The compiler drivers merge the two-argument form into a single-argument form for passing to ld.

However, Linux's ld actually accepts both the single-argument and two-argument forms. When the command-line has -L "" on it, it corrupts the subsequent argument:

mkdir subdir
echo "void dummy(void){}" > subdir/dummy.c
gcc -shared subdir/dummy.c -o subdir/libdummy.so
echo  >main.rs '#[link(name = "dummy", kind = "dylib")]'
echo >>main.rs 'extern { fn dummy(); }'
echo >>main.rs 'fn main() { unsafe { dummy(); } }'
rustc main.rs -L "" -Lsubdir

Produces:

error: linking with `cc` failed: exit code: 1
note: "cc" "-Wl,--as-needed" "-m64" "-L" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "./main" "./main.o" "-Wl,--whole-archive" "-lmorestack" "-Wl,--no-whole-archive" "-Wl,--gc-sections" "-pie" "-nodefaultlibs" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-4e7c5e5c.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcollections-4e7c5e5c.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunicode-4e7c5e5c.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/librand-4e7c5e5c.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-4e7c5e5c.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-4e7c5e5c.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-4e7c5e5c.rlib" "-L" "" "-L" "subdir" "-L" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-L" "/home/rprichard/mess/dyncrate/.rust/lib/x86_64-unknown-linux-gnu" "-L" "/home/rprichard/mess/dyncrate/lib/x86_64-unknown-linux-gnu" "-Wl,--whole-archive" "-Wl,-Bstatic" "-Wl,--no-whole-archive" "-Wl,-Bdynamic" "-ldummy" "-ldl" "-lpthread" "-lrt" "-lgcc_s" "-lpthread" "-lc" "-lm" "-lcompiler-rt"
note: /usr/bin/ld: cannot find -ldummy
collect2: error: ld returned 1 exit status

Remove the -L "", or move it to the end of the command-line, and it works. ld is seeing -L -Lsubdir, so it adds the non-existent -Lsubdir directory to the search path, and it doesn't search inside subdir.

@rprichard
Copy link
Contributor

@aidancully What versions of tools are you using? e.g.:

uname -a
cc --version
ld --version
rustc --version --verbose

@rprichard
Copy link
Contributor

I think the -L "" is coming from here in mk/target.mk:

    $(Q)CFG_LLVM_LINKAGE_FILE=$$(LLVM_LINKAGE_PATH_$(3)) \
        $$(subst @,,$$(STAGE$(1)_T_$(2)_H_$(3))) \
        $$(RUST_LIB_FLAGS_ST$(1)) \
        -L "$$(RT_OUTPUT_DIR_$(2))" \
        -L "$$(LLVM_LIBDIR_$(2))" \
        -L "$$(dir $$(LLVM_STDCPP_LOCATION_$(2)))" \
        $$(RUSTFLAGS_$(4)) \
        --out-dir $$(@D) \
        -C extra-filename=-$$(CFG_FILENAME_EXTRA) \
        $$<

I suspect LLVM_STDCPP_LOCATION_$(2) is normally blank (mk/llvm.mk):

ifeq ($$(CFG_ENABLE_LLVM_STATIC_STDCPP),1)
LLVM_STDCPP_LOCATION_$(1) = $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \
                    -print-file-name=libstdc++.a)
else
LLVM_STDCPP_LOCATION_$(1) =
endif

@rprichard
Copy link
Contributor

I was able to reproduce the problem on FreeBSD 9.2. Doing so required compiling and installing libcxxrt and libc++ from the FreeBSD source tree.

The important thing is that cc is cc (GCC) 4.2.1 20070831 patched [FreeBSD] on FreeBSD 9.2. Rather than converting two-argument -L to single-argument -L, this driver propagates both forms to ld unmodified, except that the "" argument in -L "" is dropped. We see something like -L -L <path> on the ld command-line, so of course ld thinks <path> is an input file.

I'm inclined to say that gcc and clang are both buggy, but even if they're fixed, it would take too long to propagate fixes. I'll see how hard this is to fix in the Rust makefile. We may want to fix rustc to either ignore -L "" or reject it.

rprichard added a commit to rprichard/rust that referenced this issue Mar 12, 2015
Currently, target.mk passes -L "" when LLVM_STDCPP_LOCATION_$(2) is empty.

This fixes rust-lang#23287.
@aidancully
Copy link
Contributor Author

@rprichard I think you're right about the problem being the odd -L "". I am building on FreeBSD 9.2 with a re-installed libcxxrt and libc++ (long story). To answer your questions:

$ cc --version
cc (GCC) 4.2.1 20070831 patched [FreeBSD]
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ld --version
GNU ld 2.17.50 [FreeBSD] 2007-07-03
Copyright 2007 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License.  This program has absolutely no warranty.

Rustc was the stage1 rustc compiled from 95d9046.

Thanks!

Manishearth added a commit to Manishearth/rust that referenced this issue Mar 13, 2015
 Currently, target.mk passes -L \"\" when LLVM_STDCPP_LOCATION_$(2) is empty.

This fixes rust-lang#23287.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants