g++ -O1 a.cpp -O2 b.cpp How cpp file optimized? - g++

I attended a exam, one question is:
g++ -O1 a.cpp -O2 b.cpp
How the a.cpp and b.cpp optimized?
A.O1 on a.cpp and O2 on b.cpp
B.O1 on a.cpp and b.cpp
C.O2 on a.cpp and b.cpp
The problem seems silly and may be useless in practice...
Is there any standard discuss this problem?
By the way, is there any way that we can obtain compile options based on object files?

Related

Cmake, How to add link option like '-rdynamic' in debug build

I added -rdynamic option in debug build in CMakeLists.txt like following.
Is there a better or simple way to this?
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_link_libraries(${PROJECT_NAME}
-rdynamic -lm -lpthread -lboost_system
)
else()
target_link_libraries(${PROJECT_NAME}
-lm -lpthread -lboost_system
)
endif()
There is an similar question at What is the modern method for setting general compile flags in CMake? And that answer is a general solution.
But I need a more specific answer for this question.

add extern cmake directory without building it

I have a cmake project somewhere that I want to use in several other projects. Let's call it projA located at path /projA. I have built it in /projA/build. In this build folder there is some library /projA/build/lib.a.
Now if I want to create a new project B using project A in the folder /projB I know two options for the CMakeLists:
Solution A
cmake_minimum_required(VERSION 3.0)
project(projB)
add_executable(${PROJECT_NAME} projB.cpp)
add_subdirectory(/projA /projA/build)
target_link_libraries(${PROJECT_NAME} projA)
The problem is that this solution will create new make files in /projA/build and the project A will be built again. Furthermore each time I will switch to a new project using projA, projA will be built again. So that's not a good solution. I would like to not overwrite all the build folder each time I switch between two project using projA.
Solution B
cmake_minimum_required(VERSION 3.0)
project(projB)
add_executable(${PROJECT_NAME} projB.cpp)
link_libraries(${PROJECT_NAME} /projA/build/lib.a)
target_include_directories(${PROJECT_NAME} PRIVATE /projA/include)
# Include directories
target_include_directories(${PROJECT_NAME} PRIVATE /projA/deps/depA/include)
target_include_directories(${PROJECT_NAME} PRIVATE /projA/deps/depB/include)
...
This solution works, but it's not very beautiful. I have to add a line for each include directory of all dependencies of project A.
So my question is: Is there a way to do it properly?
If you want to build them entirely separately, you will need to go through the find_package infrastructure. Here's a complete example:
Project A
lib.h
#ifndef LIB_H
#define LIB_H
int lib();
#endif
lib.c
#include "lib.h"
int lib() { return 42; }
CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
project(projA)
add_library(lib lib.c)
target_include_directories(lib PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
# Export the target named lib for use in other projects
# from the build tree of this project.
export(TARGETS lib FILE projA-config.cmake)
Project B
main.c
#include <stdio.h>
#include <lib.h>
int main () {
printf("%d\n", lib());
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
project(projB)
# Import the targets defined by projA
find_package(projA REQUIRED)
add_executable(projB main.c)
target_link_libraries(projB PRIVATE lib)
Compilation steps:
I'm imagining the two directories are next to each other, like so:
$ tree
.
├── projA
│   ├── CMakeLists.txt
│   ├── lib.c
│   └── lib.h
└── projB
├── CMakeLists.txt
└── main.c
Now we can build project A:
$ cmake -S projA -B projA/build -DCMAKE_BUILD_TYPE=Release
...
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/projA/build
$ cmake --build projA/build/ -- -v
[1/2] /usr/bin/cc -I/path/to/projA -O3 -DNDEBUG -MD -MT CMakeFiles/lib.dir/lib.c.o -MF CMakeFiles/lib.dir/lib.c.o.d -o CMakeFiles/lib.dir/lib.c.o -c /path/to/projA/lib.c
[2/2] : && /usr/bin/cmake -E rm -f liblib.a && /usr/bin/ar qc liblib.a CMakeFiles/lib.dir/lib.c.o && /usr/bin/ranlib liblib.a && :
And now we'll build project B, and set the projA_ROOT variable to /path/to/projA/build so that find_package(projA) will succeed.
$ cmake -S projB -B projB/build -DCMAKE_BUILD_TYPE=Release -DprojA_ROOT=$PWD/projA/build
...
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/projB/build
$ cmake --build projB/build
$ cmake --build projB/build/ -- -v
[1/2] /usr/bin/cc -isystem /path/to/projA -O3 -DNDEBUG -MD -MT CMakeFiles/projB.dir/main.c.o -MF CMakeFiles/projB.dir/main.c.o.d -o CMakeFiles/projB.dir/main.c.o -c /path/to/projB/main.c
[2/2] : && /usr/bin/cc -O3 -DNDEBUG CMakeFiles/projB.dir/main.c.o -o projB /path/to/projA/build/liblib.a && :
Clearly, this is non-obvious, and it's also sort of minimal. To build your own packages correctly, you should carefully read these CMake documentation pages:
https://cmake.org/cmake/help/latest/guide/importing-exporting/index.html
https://cmake.org/cmake/help/latest/command/install.html
https://cmake.org/cmake/help/latest/command/export.html
I would also suggest watching Craig Scott's talk "Deep CMake for Library Authors", here: https://youtu.be/m0DwB4OvDXk

Use SWIG for .cpp which depends on another .cpp

I have a .cpp file which calls another .cpp file. I want to use SWIG to create a Python wrapper for this.
How do I make this using SWIG.
When I had a single .cpp file I was able to create a .so in the following manner:
//app.cpp
#include "app.hpp"
int p(int a)
{
std::cout<<"hello...SWIG runs fine!"<<std::endl;
return a;
}
//app.hpp
#include <iostream>
int p(int a);
//app.i
%module app
%{
#include "app.hpp"
%}
%include "app.hpp"
Commands run were:
swig -c++ -python app.i
g++ -Isrc -fPIC -I/../../../../usr/include/python3.6m
-I/../../../../usr/include/x86_64-linux-gnu/python3.6m -lpython3.6m -c app.cpp app_wrap.cxx
g++ -shared -fPIC -o _app.so app.o app_wrap.o
I was successful in generating a .so file with this method. However, now my app.cpp needs to use a function defined in another .cpp file (a function called int fn1(int x) in hello.cpp). How do I generate .so now? If anyone could provide a small example it'd be great!
EDIT:: Someone suggested I would have to use SWIG and CMAKE together. Is this true? If yes, how can I do so?
Solved it!
swig -c++ -python file1.i
g++ -Isrc -fPIC -I/../../../../usr/include/python3.6m
-I/../../../../usr/include/x86_64-linux-gnu/python3.6m -lpython3.6m -c file1.cpp file2.cpp file1_wrap.cxx
g++ -shared -fPIC -o _file1.pyd file1.o file2.o file1_wrap.o
Turns out we can use CMake to define dependencies and do this process automatically.
Also, SWIG can be used with CMake as mentioned on SWIG documentation Introduction_build_system

CMake, static library and link time optimization

I'm trying to create static library with link time optimization using cmake and g++.
set(
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wall -Werror -Wextra -pedantic -std=c++11"
)
if (CMAKE_COMPILER_IS_GNUCXX)
set(
CMAKE_STATIC_LINKER_FLAGS_RELEASE
"${CMAKE_STATIC_LINKER_FLAGS_RELEASE} -flto -fwhole-program"
)
endif()
add_library(
mylib STATIC
mylib.cpp
)
But when running typical
cmake -DCMAKE_BUILD_TYPE=Release ..
make
I'm getting following error:
/usr/bin/ar: two different operation options specified
link.txt file contains following commands:
/usr/bin/ar cq libmylib.a -flto -fwhole-program CMakeFiles/mylib.cpp.o
/usr/bin/ranlib libmylib.a
From what I understand from running ar --help the -flto -fwhole-program should be before libmylib.a in the first line. But I have no idea how to force CMake to put it there.
Is my assumption correct? And how can I resolve this?
EDIT: I'd like to add that I'm completely new to using LTO so if it doesn't make sense to use it for static libraries, please do tell me so.
-flto isn't a valid option for ar. You should instead use these flags for CMAKE_EXE_LINKER_FLAGS.

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

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