cyndis / qmlrs

QtQuick interface for Rust
Apache License 2.0
437 stars 43 forks source link

Add /usr/local include and lib paths #29

Closed valpackett closed 8 years ago

valpackett commented 8 years ago

Makes the build work on FreeBSD

cyndis commented 8 years ago

This doesn't seem to be the right way to solve the issue -- the pkg-config invocations should already add the appropriate paths for your system.

valpackett commented 8 years ago

Build systems never do what they should ;-)

here's another example with CMake

florianjacob commented 8 years ago

What libraries can't be found on FreeBSD, could you please post the errors you get with the current qmlrs version?

If the Qt5 libraries can't be found, could you also post the output of e.g. pkg-config --libs --cflags Qt5Core? If pkg-config doesn't report the right paths you need on your system, this is not a problem to be fixed in qmlrs.

Note: Relevant pkg-config-rs code starts at https://github.com/alexcrichton/pkg-config-rs/blob/master/src/lib.rs#L137

valpackett commented 8 years ago

Yeah, it doesn't return -L for Qt5:

$ pkg-config --libs --cflags Qt5Core
-I/usr/local/include/qt5/QtCore -I/usr/local/include/qt5 -lQt5Core

$ pkg-config --libs --cflags libsodium
-I/usr/local/include -L/usr/local/lib -lsodium

The .pc file contains Libs: -lQt5Core. Other libraries' files usually have the -L: Libs: -L${libdir} -lgtk-3

Seems like every Qt app just has /usr/local/lib in the library path though.

P.S. I didn't get any CMake errors on my 11-CURRENT laptop

florianjacob commented 8 years ago

For reference, my /usr/lib/pkgconfig/Qt5Core.pc looks like this:

prefix=/usr
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/include/qt

host_bins=${prefix}/lib/qt/bin
qt_config=minimal-config small-config medium-config large-config full-config gtk2 gtkstyle fontconfig libudev evdev xkbcommon-evdev libinput xlib xrender xcb-plugin xcb-glx xcb-xlib xcb-sm accessibility-atspi-bridge linuxfb kms c++11 accessibility egl egl_x11 eglfs opengl shared qpa reduce_exports reduce_relocations clock-gettime clock-monotonic posix_fallocate mremap getaddrinfo ipv6ifname getifaddrs inotify eventfd system-jpeg system-png png system-freetype system-harfbuzz system-zlib mtdev nis cups iconv glib dbus dbus-linked openssl-linked xcb xinput2 pulseaudio gstreamer-1.0 icu concurrent audio-backend release

Name: Qt5 Core
Description: Qt Core module
Version: 5.5.1
Libs: -lQt5Core 
Libs.private: -lpthread -lz -licui18n -licuuc -licudata -lpcre16 -lm -ldl -lgthread-2.0 -pthread -lglib-2.0 -lrt -lsystemd  
Cflags: -I${includedir}/QtCore -I${includedir}

I assume the only thing different from yours is that your prefix is /usr/local instead of /usr. To work correctly, you'd need your libs line to say Libs: -L${libdir} -lQt5Core.

The code generating the .pc file seems to take into account whether the library dir is already, which might be related to why it is left out.

Sorry, but if FreeBSD ships with a broken Qt5Core.pc file, I don't see why each and every Qt project should include a workaround. This is a bug either in the FreeBSD downstream Qt package or the upstream Qt .pc file generator. In both cases, the preliminary solution would be to include a patch with the FreeBSD package that corrects the Libs: line.

I just created #34 to keep track of the issue in general. Could you please report a bug to the FreeBSD Qt package, add the link to the bugreport to #34 and report if this got fixed?

valpackett commented 8 years ago

Yeah your Libs doesn't include -L${libdir} either. This is not a bug in Qt/FreeBSD. If it was, it would've been fixed a long time ago.

The code you linked to:

if (!project->values("QMAKE_DEFAULT_LIBDIRS").contains(libDir))
            t << "-L${libdir} ";

Means that QMAKE_DEFAULT_LIBDIRS includes /usr/local/lib.

If qmake includes /usr/local/lib, you should do it too.

florianjacob commented 8 years ago

Seems like I'm learning alout about pkg-config today. :smile:

The intended behaviour for library searching of qmlrs is the following:

  1. Ask the OS wether there's a specific library directory we need to link to when depending on the library. This is done by evaluating -L flags in the .pc file
  2. If there is nothing specified, assume that all required library directories are searched by the operating system's linker by default.

Which I'd say is correct behaviour, right? Look at where the OS is telling you to look for QtCore in specific, and if there's nothing specified, assume it's in the linker's default directories.

Your proposal could be translated to an additional step:

  1. Preemptively look in /usr/local/lib because FreeBSD keeps stuff there without telling us via -L or the linker's default directory.

On Linux, Qt is installed to /usr/lib, which is included in the default linker directories.

The default linker directories are not configured by us, they're set by the OS. They can be displayed with:

> sudo ldconfig -v 2>/dev/null | grep -v ^$'\t'
/usr/lib/libfakeroot:
/usr/lib32:
/usr/lib/R/lib:
/usr/lib:

Which is why on Linux, you don't need the -L in your .pc file.

Means that QMAKE_DEFAULT_LIBDIRS includes /usr/local/lib. If qmake includes /usr/local/lib, you should do it too.

Qt's default DEFAULT_LIBDIR doesn't include /usr/local/lib: its only print "DEFAULT_LIBDIRS=\"/lib\n/usr/lib\"\n";.

I found out it's a FreeBSD change to include /usr/local/lib in DEFAULT_LIBDIR, which is why the -L is not generated on your system, too. I don't understand why, though, as I don't know enough about FreeBSD internals.

If FreeBSD tells Qt “hey Qt, you don't need to generate -L for libraries in /usr/local/lib, we link to that by default.“, why don't they link to it by default?

valpackett commented 8 years ago

The default linker directories are hardcoded in the linker.

ld installed from binutils:

$ /usr/local/bin/ld --verbose | grep SEARCH
SEARCH_DIR("=/usr/local/x86_64-portbld-freebsd11.0/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/local/lib");

Base system ld:

$ /usr/bin/ld --verbose | grep SEARCH
SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");

Rust calls the system cc to link, which calls the system ld.

Why doesn't the base system ld search /usr/local/lib? Because /usr/local is not used by the base system. It's used by all packages, but they have to do it manually.

With Qt, because of the DEFAULT_LIBDIRS change, qmake searches /usr/local/lib, and any qmake projects are built like that. Non-qmake projects have to add /usr/local/lib manually.

florianjacob commented 8 years ago

I found https://wiki.freebsd.org/WarnerLosh/UsrLocal which shed some light for me on what / how the situation with FreeBSD currently is.

Did / could you experiment with something like this?:

CMAKE_PREFIX_PATH=${LOCALBASE} cargo run --example factorial

If this works, CMAKE_PREFIX_PATH would resolve both the include and the library issue at once on systems where it is still present, while also being able to depend on the ${LOCALBASE} variable, as this seems to be something the user can actually change.

Also, this would use the same means as a similar problem on MacOS needed, fixed here: e550be0d676e6a49fd442ba9b06aedb4faddd688

If you know which BSD variants except FreeBSD this also applies to, we could then enable that for all of them with something like

#[cfg(any(target_os = "freebsd", target_os="openbsd", target_os="dragonfly"))]
valpackett commented 8 years ago
  1. cmake doesn't return errors (it did on my other machine…)
  2. the error is from cargo, cargo doesn't care about CMAKE_PREFIX_PATH
  3. LOCALBASE is not set anywhere except for ports makefiles, it's not set when you just build a rust package with cargo!
  4. all BSD systems use /usr/local as the prefix for user packages, of course… I'm not sure about what Qt installs into pkg-config there though
florianjacob commented 8 years ago

Ok, so no ${LOCALBASE}.

Could you take a look at #37? I only used the native lib search code as you said the cmake include error doesn't occur on 11-current, and tried to capture what's going on there. Also, I added every BSD variant available as target_os, because as you say it'll probably work, and if not, they should come here and tell us. :sweat_smile: