g++ how to do partial link time optimization (-flto) - g++

I man g++ and read carefully about the lto part. Now I want to know how to do partial link time optimization just like -ipo-c in icpc compiler. For example:
g++ -O2 -flto -c a.cpp
g++ -O2 -flto -c b.cpp
Now it will generate a.o and b.o which contain GIMPLE (one of GCC's internal representations). I want to combine a.o and b.o to generate a real object c.o file. That means just lto over two cpp file not the whole program. Any idea?
The reason is that I need to combine fortran code and c++ code together, so the final link step is
ifort -nofor-main -cxxlib -fexceptions f.o a.o b.o
f.o is generated by ifort. Because ifort has no idea what GIMPLE is. So the final link step will fail.

Just use g++ to link it.
$ g++ --version
g++ (GCC) 4.8.3
Copyright (C) 2013 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.
$ gfortran --version
GNU Fortran (GCC) 4.8.3
Copyright (C) 2013 Free Software Foundation, Inc.
GNU Fortran comes with NO WARRANTY, to the extent permitted by law.
You may redistribute copies of GNU Fortran
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING
$ cat a.cpp
#include <stdio.h>
extern "C" void foo_() { puts("foo"); }
$ cat b.cpp
#include <stdio.h>
extern "C" void bar_() { puts("bar"); }
$ cat f.f90
program f
implicit none
external foo
external bar
call foo()
call bar()
end program
$ g++ -O2 -flto -c a.cpp
$ g++ -O2 -flto -c b.cpp
$ gfortran -O2 -flto -c f.f90
$ g++ -O2 -flto a.o b.o f.o -lgfortran
$ ./a
foo
bar

Related

Is -std=c++2a necessary at link stage as well?

If I compile in two stages, using a particular language standard:
g++ -std=c++2a -c file1.cpp #compile source files
g++ -std=c++2a -c file2.cpp
g++ -std=c++2a file1.o file2.o -o program #link 'em
...can I leave the -std=c++2a out of the link command, or is it sometimes needed?
Version is gcc 10.
I guess you are compiling on Linux with a recent GCC. Be sure to read more about C++ and about your particular compiler (i.e. GCC 9 is not the same as GCC 10). Check with g++ --version what it is.
In practice you want to compile with warnings and debug information (in DWARF for GDB inside your ELF object files and executables), so use
g++ -std=c++2a -Wall -Wextra -g -c file1.cpp
and likewise for file2.cpp
Later (once your program is correct enough, e.g. has few bugs) you could want to ask the compiler to optimize it. So you could use
g++ -std=c++2a -Wall -Wextra -O3 -g -c file1.cpp
Practically speaking, you'll configure your build automation tool (e.g. GNU make or ninja) to run your compilation commands.
In rare cases, you could want to use link time optimizations. Then you need to both compile and link with g++ -std=c++2a -Wall -Wextra -O3 -g -flto and perhaps other options.
Be aware that link time optimization could almost double your build time.
You could also be interested by static analysis options of GCC 10 (or even by writing your own static analysis using GCC plugins).

Can I use CMake to compile a program in stages?

I'm using the LLVM compiler to perform some analyses. I also have a test application I've written that I build using CMake. I'd like to compile the test application in stages:
Compile all source files of the test application to LLVM bitcode.
Link all of the bitcode files together using llvm-link.
Compile this linked bitcode file down into an actual binary (using an extra flag to run my analyses).
As an example, if I had a program test comprised of 3 files, foo.c, bar.c, and bar.h:
Normal compilation:
clang -I. -c foo.c // generates foo.o
clang -I. -c bar.c // generates bar.o
ld -lc -lgcc -o test foo.o bar.o // links foo.o and bar.o
Bitcode compilation & linking:
clang -I. -c -emit-llvm foo.c // generates foo.bc
clang -I. -c -emit-llvm bar.c // generates bar.bc
llvm-link -o test.bc foo.bc bar.bc // links foo.bc and bar.bc
clang -I. -o test test.bc // generates test
As I said, I've already written CMake files that build and compile the test application normally (i.e., in a single stage).
Is it possible, through some combination of adding custom commands and/or targets, to achieve such a thing? Or should I continue with my current approach of using bash/Python scripts to run this process?

Cross-platform static-linking SDL2

I'm building an SDL2/C++ program that needs to be portable to Windows, Mac, and Linux machines which may not have SDL installed.
I've read that static linking is the solution, but I'm not very good with compiling and don't know how to static link.
My program relies only on SDL2, GLU, and OpenGL. I'm compiling C++ with either MinGW (on Windows 8.1) or gcc (on Ubuntu 14.04) -- both of these OS's have SDL installed natively.
Here is my current makefile, derived from a sample makefile given to me by a professor of mine:
# Executable/file name
EXE=experiment
# MinGW
ifeq "$(OS)" "Windows_NT"
CFLG=-O3 -Wall -DUSEGLEW
LIBS= -lSDL2 -lglu32 -lopengl32
CLEAN=del *.exe *.o *.a
else
# OSX
ifeq "$(shell uname)" "Darwin"
CFLG=-O3 -Wall -Wno-deprecated-declarations
LIBS=-framework SDL2 -framework OpenGL
# Linux\Unix\Solaris
else
CFLG=-O3 -Wall
LIBS= `sdl2-config --cflags --libs` -lGLU -lGL -lm
endif
# OSX\Linux\Unix\Solaris
CLEAN=rm -f $(EXE) *.o *.a
endif
# Dependencies
$(EXE).o: $(EXE).cpp FORCE
.c.o:
gcc -c -o $# $(CFLG) $<
.cpp.o:
g++ -std=c++11 -c -o $# $(CFLG) $<
# Link
$(EXE):$(EXE).o
g++ -std=c++11 -O3 -o $# $^ $(LIBS)
# Clean
clean:
$(CLEAN)
# Force
FORCE:
To link with static library you either specify path to library file
gcc -o out_bin your_object_files.o path/to/lib.a -lfoo
or ask linker to use static version with -Bstatic linker flag. Usually you'll want to reset linking back to dynamic for the rest of the libraries, e.g. for static SDL2 and GLU but dynamic GL:
gcc -o out_bin your_object_files -Wl,-Bstatic -lSDL2 -lGLU -Wl,-Bdynamic -lGL
That of course implies that static versions of libraries are present in library search path list (.a libs for gcc on all specified platforms, although MSVC uses .lib for static libraries).
However you usually don't really want to do that at all. It is common practice for software to either depend on some libs (widespread on linux, with packages and dependendices lists) or bring required libraries with it. You can just distribute SDL dynamic library with your program and load it with LD_LIBRARY_PATH or relative rpath.
Please also note that newer SDL2 implements dynamic loading of functions which provides a way to override SDL with user-specified dynamic library, even if linked statically.
It wasn't related directly to static linking. When static linking, I had to include all of SDL's dependency libraries. Turns out, having -mwindows causes console communication to fail.

libtool picks up 64-bit library when I tries to build 32-bit program

I have a GNU build system with autoconf-2.69, automake-1.14.1, libtool-2.4.2. I've configured with --host=i686-linux on a x86_64 RHEL6 host OS to build a 32-bit program. The libtool command seems to be:
/bin/sh ../libtool --tag=CXX --mode=link g++ -I/home/STools/RLX/boost/include/boost-1_44 -m32 -g3 -Wall -static -o engine engine-main.o ../components/librlxvm.la /home/STools/RLX/boost/include/boost-1_44/../../lib/libboost_program_options-gcc42-mt-1_44.a -lz -lpthread -ldl -lrt -ldl -lz -lm
But the real command is to search the 64-bit libraries not the 32-bit libraries as shown below:
libtool: link: g++ -I/home/STools/RLX/boost/include/boost-1_44 -m32 -g3 -Wall -o engine engine-main.o -L/home/robert_bu/src/gcc/gcc-4.2.2/build-x86_64/x86_64-unknown-linux-gnu/libstdc++-v3/src -L/home/robert_bu/src/gcc/gcc-4.2.2/build-x86_64/x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs -L/home/robert_bu/src/gcc/gcc-4.2.2/build-x86_64/./gcc ../components/.libs/librlxvm.a /home/STools/RLX/boost/include/boost-1_44/../../lib/libboost_program_options-gcc42-mt-1_44.a /home/STools/RLX/gcc-4.2.2-x86_64/lib/../lib64/libstdc++.so -L/lib/../lib64 -L/usr/lib/../lib64 -lc -lgcc_s -lrt -ldl -lz -lm -pthread -Wl,-rpath -Wl,/home/STools/RLX/gcc-4.2.2-x86_64/lib/../lib64 -Wl,-rpath -Wl,/home/STools/RLX/gcc-4.2.2-x86_64/lib/../lib64
The --host config seems to have no effect. Is there anyway to tell libtool that 32-bit libraries are what we want?
It seems that libtool uses "CC", "CXX" to check the library search path. After I set CC to "gcc -m32", and CXX to "g++ -m32", it works. So libtool does not add "-m32" automatically even if I try to build a 32-bit program on a 64-bit system.
You're being hit by the problem of libtool .la files expansion. In particular libstdc++.la is being expanded for you to a full path rather than a simple -lstdc++.
My suggestion is to remove .la file from the SDK you're using (/home/STools). This way libtool can't assume things for you. Usually the ones you have in the system are fine, because the libraries are already in the search path, so it does not need to use -rpath or the full path to the .so file.
Depending on how well the SDK was crafted, this might or might not work correctly, so take it with a grain of salt.

g++ and gcc differences

I am trying to compile CPP code on an Ubuntu machine. I read somewhere that g++ is included in gcc. so in CodeBlocks I included the GNU GCC compiler. Codeblocks returned an error saying that g++ was not found. Is g++ another seperate compiler?
g++ is for compiling C++, gcc is for compiling C. Two different compilers for two different languages!
I'm not very familiar with g++ but g++ is a C++ compiler and C++ is an extension of the C language so all C code can be compiled with a C++ compiler. So you could say that g++ contains a C compiler but saying that g++ contains gcc isn't correct I think.
Both g++ and gcc programs are from the same free software project, GCC. However, on Ubuntu you have several different packages for them, so install the g++-4.6 or the g++ package with gcc-4.6 or gcc one. (if you don't install both, you won't be able to compile both C & C++).
Both programs can compile C and C++ files, assuming the C files are suffixed with .c and the C++ ones with .cc or .cpp (etc..).
But they won't do exactly the same things, in particular, they won't link the same default libraries.
To understand what they do, you can run
gcc -v -Wall -g myprog.cc -o myprog
and
g++ -v -Wall -g myprog.cc -o myprog
and you'll see the differences. The -v flag often means "verbose".