Different compiler flags for different compilers? - gcc

I have a cc_library (tbb) that requires the compiler flag -mwaitpkg on some compilers (Clang) to compile successfully. At the same time, there are older versions of GCC (4.9) that do not know this flag, and therefore the compilation via GCC 4.9 leads to an error:
gcc: error: unrecognized command line option '-mwaitpkg'
In a more advanced Bazel setup, I guess one would work around this using hermetic toolchains. This way every toolchain could provide its own set of compiler flags. Nevertheless, I do not want to enforce any specific toolchain and I am not sure if this is the right way to go (move copts to toolchain?).
Also introducing a config would be a way to solve this problem. E.g. bazel build --config=waitpkg //.... But this would require that a user is aware of this config and also knows the details of using waitpkg.
What is a proper "Bazel-way" to handle different compiler flags for different compilers?

The flag '-mwaitpkg' is supported by GCC version 9.3, Clang* 12, and newer versions of those tools.
If you build Bazel with earlier versions of GCC, you should remove the flag otherwise it gives compilation errors.

Related

GCC built from source in different location is incorrectly using same shared libs as native GCC

I'm a student doing research involving extending the TM capabilities of gcc. My goal is to make changes to gcc source, build gcc from the modified source, and, use the new executable the same way I'd use my distro's vanilla gcc.
I built and installed gcc in a different location (not /usr/bin/gcc), specifically because the modified gcc will be unstable, and because our project goal is to compare transactional programs compiled with the two different versions.
Our changes to gcc source impact both /gcc and /libitm. This means we are making a change to libitm.so, one of the shared libraries that get built.
My expectation:
when compiling myprogram.cpp with /usr/bin/g++, the version of libitm.so that will get linked should be the one that came with my distro;
when compiling it with ~/project/install-dir/bin/g++, the version of libitm.so that will get linked should be the one that just got built when I built my modified gcc.
But in reality it seems both native gcc and mine are using the same libitm, /usr/lib/x86_64-linux-gnu/libitm.so.1.
I only have a rough grasp of gcc internals as they apply to our project, but this is my understanding:
Our changes tell one compiler pass to conditionally insert our own "function builtin" instead of one it would normally use, and this is / becomes a "symbol" which needs to link to libitm.
When I use the new gcc to compile my program, that pass detects those conditions and successfully inserts the symbol, but then at runtime my program gives a "relocation error" indicating the symbol is not defined in the file it is searching in: ./test: relocation error: ./test: symbol _ITM_S1RU4, version LIBITM_1.0 not defined in file libitm.so.1 with link time reference
readelf shows me that /usr/lib/x86_64-linux-gnu/libitm.so.1 does not contain our new symbols while ~/project/install-dir/lib64/libitm.so.1 does; if I re-run my program after simply copying the latter libitm over the former (backing it up first, of course), it does not produce the relocation error anymore. But naturally this is not a permanent solution.
So I want the gcc I built to use the shared libs that were built along with it when linking. And I don't want to have to tell it where they are every time - my feeling is that it should know where to look for them since I deliberately built it somewhere else to behave differently.
This sounds like the kind of problem any amateur gcc developer would have when trying to make a dev environment and still be able to use both versions of gcc, but I had difficulty finding similar questions. I am thinking this is a matter of lacking certain config options when I configure gcc before building it. What is the right configuration to do this?
My small understanding of the instructions for building and installing gcc led me to do the following:
cd ~/project/
mkdir objdir
cd objdir
../source-dir/configure --enable-languages=c,c++ --prefix=/home/myusername/project/install-dir
make -j2
make install
I only have those config options because they seemed like the ones closest related to "only building the parts I need" and "not overwriting native gcc", but I could be wrong. After the initial config step I just re-run make -j2 and make install every time I change the code. All these steps do complete without errors, and they produce the ~/project/install-dir/bin/ folder, containing the gcc and g++ which behave as described.
I use ~/project/install-dir/bin/g++ -fgnu-tm -o myprogram myprogram.cpp to compile a transactional program, possibly with other options for programs with threads.
(I am using Xubuntu 16.04.3 (64 bit), within VirtualBox on Windows. The installed /usr/bin/gcc is version 5.4.0. Our source at ~/project/source-dir/ is a modified version of 5.3.0.)
You’re running into build- versus run-time linking differences. When you build with -fgnu-tm, the compiler knows where the library it needs is found, and it tells the linker where to find it; you can see this by adding -v to your g++ command. However when you run the resulting program, the dynamic linker doesn’t know it should look somewhere special for the ITM library, so it uses the default library in /usr/lib/x86_64-linux-gnu.
Things get even more confusing with ITM on Ubuntu because the library is installed system-wide, but the link script is installed in a GCC-private directory. This doesn’t happen with the default GCC build, so your own GCC build doesn’t do this, and you’ll see libitm.so in ~/project/install-dir/lib64.
To fix this at run-time, you need to tell the dynamic linker where to find the right library. You can do this either by setting LD_LIBRARY_PATH (to /home/.../project/install-dir/lib64), or by storing the path in the binary using -Wl,-rpath=/home/.../project/install-dir/lib64 when you build it.

How to configure clang to use arm-none-eabi linker

I am trying to configure the last version of clang (6.0) to use the arm-none-eabi linker instead of the ld.lld but clang is always ignoring everything and keep asking for the ld.lld one. I am trying to build for cortex-m3 (lpx1769 board). How do I force clang to use the linker I want.
-fuse-ld=ld is also not working, so does clang no longer allow the use of any other linker?
So the answer was to use the flag:
-fuse-ld=path/to/linker-to-be-used
Remember that if you passing this flag to clang it will cause a warning that clang will not use this flag (only the linker stage will do). Thus if you compiling with -Werror, the warning will be turned into an error.
Moreover, because you are cross-compiling probably you will need to let the linker know where to find the target-specific libraries needed using the -L option. See this for more info:
https://clang.llvm.org/docs/CrossCompilation.html

Building cmake with non-default GCC uses system libstdc++

I'm trying to compile CMake using a non-default GCC installed in /usr/local/gcc530, on Solaris 2.11.
I have LD_LIBRARY_PATH=/usr/local/gcc530/lib/sparcv9
Bootstrap proceeds fine, bootstrapped cmake successfully compiles various object files, but when it tries to link the real cmake (and other executables), I get pages of "undefined reference" errors to various standard library functions, because, as running the link command manually with -Wl,-verbose shows, the linker links with /usr/lib/64/libstdc++.so of the system default, much older GCC.
This is because apparently CMake tries to find curses/ncurses libraries (even if I tell it BUILD_CursesDialog:BOOL=OFF), finds them in /usr/lib/64, and adds -L/usr/lib/64 to build/Source/CMakeFiles/cmake.dir/link.txt, which causes the linker to use libstdc++.so from there, and not my actual GCC's own.
I found a workaround: I can get the path to proper libraries from $CC -m64 -print-file-name=libstdc++.so then put it with -L into LDFLAGS when running ./configure, and all works well then.
Is there a less hacky way? It's really weird that I can't tell GCC to prioritize its own libraries.
Also, is there some way to have CMake explain where different parts of a resulting command line came from?

Let cmake with clang use c++11 (c++14)

My cmake project shall compile c++14 code. It also uses the CMakeLists.txts included from its external libraries (which are git submodules in my project). The build fails on macOS Sierra (cmake 3.6.2) because the default STL of clang is old and doesn't handle c++11. As far as I understand, there are two STLs shipped with clang: libstdc++ (from gcc) (default) or libc++. So if I add the -stdlib=libc++ option to cmake, the source compiles:
add_compile_options( "$<$<COMPILE_LANGUAGE:CXX>:-std=c++14>" )
add_compile_options( "$<$<COMPILE_LANGUAGE:CXX>:-stdlib=libc++>" )
But then it fails at link time because it tries to use libstdc++ for linking. How do I specify in cmake that the new STL libc++ shall be used for the whole build process?
PS: What is the rationale behind clang using the gcc STL by default if it is too old? Could I permanently specify which STL it shall use? Or am I doing something completely wrong (could some of my subprojects silently force gcc?)?
You should rely on CMake to handle compile options. Just specify the wanted standard version:
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
target_compile_features can also be used to require particular features of the standard (and implicitly ask CMake to set the adequate configuration). More information here.
EDIT
You figured out the solution, you also had to remove the following line in the CMakeLists of Ogred3D:
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7)
Removing it prevented CMake to add the flag mmacosx-version-min=10.7 causing the error.
I suppose, you also need to pass that flang to the linker in the clang case:
link_libraries("-stdlib=libc++")

gcc compiling error on Solaris 10

I want to compile a source code, but there are some compiling errors about __sync_xxx functions (__sync_bool_compare_and_swap etc.)
GCC version on machine is 3.4.3 (it must be gcc 4.1 or over for supporting atomic builtins), so I have downloaded GCC v4.6, copied it to another directory (I didn't remove v3.4.3) then change the $PATH path for GCC but it doesn't work (the same error occurs).
I want to ask that is only changing gcc path with export PATH=... enough for compiling with new GCC?
Use the following configure option when compiling gcc:
--program-prefix=foo --program-suffix=bar
and it will produce bin programs of the form "foo-gcc-bar", so that you may differentiate different builds of gcc.
Replace foo and/or bar with an appropriate "tag" for your build (eg "-4.6" for example).
This way if it doesn't find your toolchain correctly it will fail fast rather than using the 3.4 version.
It also means that different toolchain builds can coexist in the standard installation prefix directories.
We have to use -march=686 switch to get it to work on intel.
Try checking and updating LD_LIBRARY_PATH, to use the lib path for the new gcc installed.

Resources