Page MenuHomeFreeBSD

Fix GCC 4.2.1 to honor --sysroot for includes.
ClosedPublic

Authored by jhb on Apr 18 2018, 6:50 PM.

Details

Summary
  • Remove a FreeBSD-specific hack from 'find_a_file()' that hardcodes a single directory for includes.
  • Change the C++ directory entries to honor --sysroot if it is set.
  • Don't define CROSS_INCLUDE_DIR for the cross compiler. Instead, set TARGET_SYSTEM_ROOT to point to WORLDTMP and always define STANDARD_INCLUDE_DIR.
  • Change STANDARD_INCLUDE_DIR and the C++ include directories to just start with "/usr" always. The compiler will prepend the sysroot when doing cross-builds. GCC_INCLUDE_DIR (which contains headers that ship with the compiler such as intrinsincs rather than OS-supplied headers) remains hardcoded to look in TOOLS_PREFIX.
Test Plan
  • make tinderbox with only --sysroot in cflags
  • compiling a standalone hello.c for sparc64 using sparc64 cross-compiler and WORLDTMP as --sysroot
  • manually inspecting output of -print-search-dirs and include paths from -v when using different values of --sysroot for sparc64 cross-compiler
  • This along with the already-approved D14780 fix GCC 4.2.1 to work with just --sysroot. I believe the native compiler should also DTRT but still need to test that.

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

Makefile.inc1

.if ${WANT_COMPILER_TYPE} == gcc || \
    (defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc)
# GCC requires -isystem and -L when using a cross-compiler.  --sysroot
# won't set header path and -L is used to ensure the base library path
# is added before the port PREFIX library path.
XCFLAGS+=       -isystem ${WORLDTMP}/usr/include -L${WORLDTMP}/usr/lib
# GCC requires -B to find /usr/lib/crti.o when using a cross-compiler
# combined with --sysroot.
XCFLAGS+=       -B${WORLDTMP}/usr/lib
# Force using libc++ for external GCC.
.if defined(X_COMPILER_TYPE) && \
    ${X_COMPILER_TYPE} == gcc && ${X_COMPILER_VERSION} >= 40800
XCXXFLAGS+=     -isystem ${WORLDTMP}/usr/include/c++/v1 -std=c++11 \
                -nostdinc++
.endif

We may need to keep some of this like the -L usage if your port work didn't change the ordering or the -B usage... Did you test without the 2 -isystem uses here? I think the C++ one will need to remain looking at the freebsd-native.h change.

There's 2 tests that are needed:

  • Cross-build
  • Native-build with WITH_SYSTEM_COMPILER activated. You can probably cheat this one by doing a normal cross-build but removing TOOLS_PREFIX in gnu/usr.bin/cc/Makefile.inc:
CFLAGS+=        -DPREFIX=\"${TOOLS_PREFIX}/usr\"

Change TOOLS_PREFIX to blank there and it should then still build the cross-compiler but then require that --sysroot works properly.

contrib/gcc/gcc.c
2699 ↗(On Diff #41632)

Looks like this code was added in rS231336 for -print-file-name=include. Is it directly relevant for --sysroot?

gnu/usr.bin/cc/cc_tools/freebsd-native.h
18 ↗(On Diff #41632)

Hm this looks in /usr/include/c++/4.2 but our -isystem is adding in /usr/include/c++/v1, so I think we'll still need the -isystem for C++ in Makefile.inc1. In which case the --sysroot fixes in contrib/gcc/cppdefault.c may not be needed.

21 ↗(On Diff #41632)

This change for STANDARD_INCLUDE_DIR and CROSS_INCLUDE_DIR seems like the primary fix to me.

Makefile.inc1

.if ${WANT_COMPILER_TYPE} == gcc || \
    (defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc)
# GCC requires -isystem and -L when using a cross-compiler.  --sysroot
# won't set header path and -L is used to ensure the base library path
# is added before the port PREFIX library path.
XCFLAGS+=       -isystem ${WORLDTMP}/usr/include -L${WORLDTMP}/usr/lib
# GCC requires -B to find /usr/lib/crti.o when using a cross-compiler
# combined with --sysroot.
XCFLAGS+=       -B${WORLDTMP}/usr/lib
# Force using libc++ for external GCC.
.if defined(X_COMPILER_TYPE) && \
    ${X_COMPILER_TYPE} == gcc && ${X_COMPILER_VERSION} >= 40800
XCXXFLAGS+=     -isystem ${WORLDTMP}/usr/include/c++/v1 -std=c++11 \
                -nostdinc++
.endif

We may need to keep some of this like the -L usage if your port work didn't change the ordering or the -B usage... Did you test without the 2 -isystem uses here? I think the C++ one will need to remain looking at the freebsd-native.h change.

All of this is gone in my testing. The port versions now look in the right place when using --sysroot. The earlier commit in this git branch that I've been using for all my tests is here: https://github.com/freebsd/freebsd/commit/d68a00bbb3c0844020ba89c69fa0b13c27b561ff

I sill need to do a native build under qemu to test the system_compiler case (I thought I had done that already but I can't recall for certain). I can't quite break PREFIX as you suggested as the compiler still needs to find things like 'cc1' which are always under TOOLS_PREFIX and it uses PREFIX to find those.

contrib/gcc/gcc.c
2699 ↗(On Diff #41632)

Hmm, I can try removing it and/or testing --print-file-name=include.

gnu/usr.bin/cc/cc_tools/freebsd-native.h
18 ↗(On Diff #41632)

No. We don't use libc++ when using GCC 4.2.1 because 4.2.1 can't compile C++11. When using 4.2.1 we still use libstdc++ from contrib and this preserves that behavior.

In D15127#324326, @jhb wrote:

Makefile.inc1

.if ${WANT_COMPILER_TYPE} == gcc || \
    (defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc)
# GCC requires -isystem and -L when using a cross-compiler.  --sysroot
# won't set header path and -L is used to ensure the base library path
# is added before the port PREFIX library path.
XCFLAGS+=       -isystem ${WORLDTMP}/usr/include -L${WORLDTMP}/usr/lib
# GCC requires -B to find /usr/lib/crti.o when using a cross-compiler
# combined with --sysroot.
XCFLAGS+=       -B${WORLDTMP}/usr/lib
# Force using libc++ for external GCC.
.if defined(X_COMPILER_TYPE) && \
    ${X_COMPILER_TYPE} == gcc && ${X_COMPILER_VERSION} >= 40800
XCXXFLAGS+=     -isystem ${WORLDTMP}/usr/include/c++/v1 -std=c++11 \
                -nostdinc++
.endif

We may need to keep some of this like the -L usage if your port work didn't change the ordering or the -B usage... Did you test without the 2 -isystem uses here? I think the C++ one will need to remain looking at the freebsd-native.h change.

All of this is gone in my testing. The port versions now look in the right place when using --sysroot. The earlier commit in this git branch that I've been using for all my tests is here: https://github.com/freebsd/freebsd/commit/d68a00bbb3c0844020ba89c69fa0b13c27b561ff

I think the -isystem ${WORLDTMP}/usr/include/c++/v1 -std=c++11 needs to remain. It's for extenal (newer) GCC to use libc++.

I sill need to do a native build under qemu to test the system_compiler case (I thought I had done that already but I can't recall for certain). I can't quite break PREFIX as you suggested as the compiler still needs to find things like 'cc1' which are always under TOOLS_PREFIX and it uses PREFIX to find those.

gnu/usr.bin/cc/cc_tools/freebsd-native.h
18 ↗(On Diff #41632)

Funny enough I realized this while falling asleep the other night and almost got up to remove the comment.

In D15127#324326, @jhb wrote:

Makefile.inc1

.if ${WANT_COMPILER_TYPE} == gcc || \
    (defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc)
# GCC requires -isystem and -L when using a cross-compiler.  --sysroot
# won't set header path and -L is used to ensure the base library path
# is added before the port PREFIX library path.
XCFLAGS+=       -isystem ${WORLDTMP}/usr/include -L${WORLDTMP}/usr/lib
# GCC requires -B to find /usr/lib/crti.o when using a cross-compiler
# combined with --sysroot.
XCFLAGS+=       -B${WORLDTMP}/usr/lib
# Force using libc++ for external GCC.
.if defined(X_COMPILER_TYPE) && \
    ${X_COMPILER_TYPE} == gcc && ${X_COMPILER_VERSION} >= 40800
XCXXFLAGS+=     -isystem ${WORLDTMP}/usr/include/c++/v1 -std=c++11 \
                -nostdinc++
.endif

We may need to keep some of this like the -L usage if your port work didn't change the ordering or the -B usage... Did you test without the 2 -isystem uses here? I think the C++ one will need to remain looking at the freebsd-native.h change.

All of this is gone in my testing. The port versions now look in the right place when using --sysroot. The earlier commit in this git branch that I've been using for all my tests is here: https://github.com/freebsd/freebsd/commit/d68a00bbb3c0844020ba89c69fa0b13c27b561ff

I think the -isystem ${WORLDTMP}/usr/include/c++/v1 -std=c++11 needs to remain. It's for extenal (newer) GCC to use libc++.

No, we do fixups in the devel/powerpc64-gcc and base/gcc ports to make them use libc++:

CONFIGURE_ARGS+=--target=${GCC_TARGET} --disable-nls --enable-languages=c,c++ \
		...
		--with-gxx-include-dir=/usr/include/c++/v1/ \
...

post-patch:
	@${REINPLACE_CMD} -e '/LIBSTDCXX/ s/stdc\+\+/c\+\+/g ' \
		${WRKSRC}//gcc/cp/g++spec.c

The first one removes the need for the -isystem. The second one makes gcc use -lc++ instead of -lstdc++.

This revision is now accepted and ready to land.Jun 19 2018, 6:09 PM
jhb marked 2 inline comments as done.Jun 27 2018, 3:47 PM
jhb added inline comments.
contrib/gcc/gcc.c
2699 ↗(On Diff #41632)

I finally did a test tinderbox yesterday with this hunk removed and it still builds fine, so I'm going to drop it. Without this change '--print-file-name=include' outputs 'include'. With this change left in it prints out '/usr/include' (always, doesn't honor sys root, but it's also not clear to me what might possibly use it)

This revision was automatically updated to reflect the committed changes.
jhb marked an inline comment as done.