|
| 1 | +## Compile |
| 2 | +[Compiling with g++](https://www.geeksforgeeks.org/compiling-with-g-plus-plus/) |
| 3 | + |
| 4 | +### Check g++ default c++ standard version |
| 5 | +[Which C++ standard is the default when compiling with g++?](https://stackoverflow.com/questions/44734397/which-c-standard-is-the-default-when-compiling-with-g) |
| 6 | +```sh |
| 7 | +g++ -dM -E -x c++ /dev/null | grep -F __cplusplus |
| 8 | +``` |
| 9 | +Sample output: |
| 10 | +``` |
| 11 | +#define __cplusplus 199711L |
| 12 | +``` |
| 13 | + |
| 14 | +### Compile, specify c++ version |
| 15 | +[to_string is not a member of std, says g++ (mingw)](https://stackoverflow.com/questions/12975341/to-string-is-not-a-member-of-std-says-g-mingw) |
| 16 | +```sh |
| 17 | +g++ xxx.cpp -std=c++11 |
| 18 | +``` |
| 19 | + |
| 20 | +This solves the error: |
| 21 | +``` |
| 22 | +/usr/include/c++/5/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options. |
| 23 | + #error This file requires compiler and library support \ |
| 24 | +``` |
| 25 | + |
| 26 | +### specify include directory |
| 27 | +```sh |
| 28 | +g++ xxx.cpp -I /usr/local/include |
| 29 | +``` |
| 30 | + |
| 31 | +### make |
| 32 | +Dry run: |
| 33 | + |
| 34 | +[How do I force make/GCC to show me the commands?](https://stackoverflow.com/questions/5820303/how-do-i-force-make-gcc-to-show-me-the-commands) |
| 35 | +```sh |
| 36 | +make -n |
| 37 | +``` |
| 38 | + |
| 39 | +### CMakeLists.txt |
| 40 | +#### fundamental |
| 41 | + |
| 42 | +``` |
| 43 | +cmake_minimum_required(VERSION 3.5) |
| 44 | +project(name) |
| 45 | +# specify the c++ version to use |
| 46 | +set(CMAKE_CXX_STANDARD 14) |
| 47 | +
|
| 48 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused-result -Wno-unknown-pragmas -Wfatal-errors -fPIC -std=c++11") |
| 49 | +# the compiler flags for compiling C sources |
| 50 | +message(STATUS "CMAKE_C_FLAGS: " ${CMAKE_C_FLAGS}) |
| 51 | +# the compiler flags for compiling C++ sources |
| 52 | +message(STATUS "CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS}) |
| 53 | +
|
| 54 | +find_package(OpenCV REQUIRED) |
| 55 | +set(SOURCE_FILES ./src/file1.cpp ./src/file2.cpp) |
| 56 | +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) |
| 57 | +link_directories(${CMAKE_SOURCE_DIR}/libs) |
| 58 | +
|
| 59 | +# create a executable file |
| 60 | +add_executable(<executable_file_name> ./src/main.cpp) |
| 61 | +target_link_libraries(<executable_file_name> ${OpenCV_LIBS}) |
| 62 | +
|
| 63 | +# create a shared object |
| 64 | +add_library(<library_name> SHARED ${SOURCE_FILES}) |
| 65 | +target_link_libraries(<library_name> ${OpenCV_LIBS}) |
| 66 | +``` |
| 67 | + |
| 68 | +Ref: [Configuring an c++ OpenCV project with Cmake](https://stackoverflow.com/questions/13970377/configuring-an-c-opencv-project-with-cmake) |
| 69 | + |
| 70 | +#### set variable and print |
| 71 | +[CMake: Output a list with delimiters](https://stackoverflow.com/questions/17666003/cmake-output-a-list-with-delimiters) |
| 72 | +``` |
| 73 | +set(VAR1 hello) |
| 74 | +set(LIST1 a b c d) |
| 75 | +message("the variable VAR1 is " ${VAR1}) |
| 76 | +message("the list LIST1 is " "${LIST1}") |
| 77 | +``` |
| 78 | + |
| 79 | +Other types of variable: [What's the CMake syntax to set and use variables?](https://stackoverflow.com/questions/31037882/whats-the-cmake-syntax-to-set-and-use-variables) |
| 80 | + |
| 81 | +#### add definition |
| 82 | +This equals to add `#define MYVAR` in `.cpp` or `.h` files. |
| 83 | +``` |
| 84 | +add_definitions(-D MYVAR) |
| 85 | +``` |
| 86 | + |
| 87 | +#### CMAKE_SOURCE_DIR v.s. PROJECT_SOURCE_DIR |
| 88 | +[Are CMAKE_SOURCE_DIR and PROJECT_SOURCE_DIR the same in CMake?](https://stackoverflow.com/questions/32028667/are-cmake-source-dir-and-project-source-dir-the-same-in-cmake) |
| 89 | + |
| 90 | +`CMAKE_SOURCE_DIR`: the folder containing the top-level CMakeLists.txt |
| 91 | + |
| 92 | +`PROJECT_SOURCE_DIR`: the inner-most folder containing CMakeLists.txt with `project()` command |
| 93 | + |
| 94 | +#### project structure |
| 95 | +[CMake with include and source paths - basic setup](https://stackoverflow.com/questions/8304190/cmake-with-include-and-source-paths-basic-setup) |
| 96 | + |
| 97 | +### make, specify number of jobs as the number of processing units available |
| 98 | +```sh |
| 99 | +make -j $(nproc) |
| 100 | +``` |
| 101 | + |
| 102 | +### cmake in debug mode and make in verbose mode |
| 103 | +[Using CMake with GNU Make: How can I see the exact commands?](https://stackoverflow.com/questions/2670121/using-cmake-with-gnu-make-how-can-i-see-the-exact-commands) |
| 104 | +```sh |
| 105 | +cmake -DCMAKE_BUILD_TYPE=DEBUG .. |
| 106 | +make VERBOSE=1 2>../log.txt |
| 107 | +``` |
| 108 | + |
| 109 | +The `2>../log.txt` redirect error message into a log file. |
| 110 | + |
| 111 | +## list the .so dependencies of a executable file |
| 112 | +```sh |
| 113 | +ldd <executable> |
| 114 | +``` |
| 115 | +Sample output: |
| 116 | +``` |
| 117 | + libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007fc3364fd000) |
| 118 | + libsoxr.so.0 => /usr/lib/x86_64-linux-gnu/libsoxr.so.0 (0x00007fc336297000) |
| 119 | + libnuma.so.1 => /usr/lib/x86_64-linux-gnu/libnuma.so.1 (0x00007fc33608c000) |
| 120 | +``` |
| 121 | + |
| 122 | +## list symbols from xxx.so |
| 123 | +```sh |
| 124 | +nm -D <xxx.so> # -D will list dynamic symbols |
| 125 | +``` |
| 126 | +Sample output: |
| 127 | +``` |
| 128 | +0000000000092030 T YoloPluginCtxInit |
| 129 | + U rename |
| 130 | +0000000000104d8f V _ZTS4Yolo |
| 131 | +000000000007c425 W _ZSt10_ConstructI7DsImageIEEvPT_DpOT0_ |
| 132 | +``` |
| 133 | +`T` for symbol defined in code section, `U` for undefined, `V` and `W` for weak object. |
| 134 | + |
| 135 | +This is helpful for solving the following error: |
| 136 | +``` |
| 137 | +/home/ubuntu/catkin_ws/devel/lib/ros_trans/OpenTrans: symbol lookup error: /home/ubuntu/catkin_ws/devel/lib/libproduct.so: undefined symbol: YoloPluginGetVersion |
| 138 | +``` |
| 139 | + |
| 140 | +## show the unmangled name of a symbol |
| 141 | +```sh |
| 142 | +c++filt <symbol(mangled name)> |
| 143 | +``` |
| 144 | + |
| 145 | +## /usr/bin/ld: cannot find -l\<xxx> |
| 146 | +Error message while linking: |
| 147 | +``` |
| 148 | +/usr/bin/ld: cannot find -lcudnn |
| 149 | +collect2: error: ld returned 1 exit status |
| 150 | +``` |
| 151 | +Solution: |
| 152 | +[https://stackoverflow.com/questions/51451746/cmake-command-line-ld-library-path-and-c-include-dirs](https://stackoverflow.com/questions/51451746/cmake-command-line-ld-library-path-and-c-include-dirs) |
| 153 | + |
| 154 | +First set `LD_LIBRARY_PATH` to the path of that `.so` file, and then add: |
| 155 | +``` |
| 156 | +link_directories( $ENV{LD_LIBRARY_PATH} ) |
| 157 | +``` |
| 158 | +into `CMakeLists.txt`. |
| 159 | + |
| 160 | +## ./a.out: error while loading shared libraries: xxx.so: cannot open shared object file: No such file or directory |
| 161 | +[g++ executable cannot find shared library](https://stackoverflow.com/questions/12000990/g-executable-cannot-find-shared-library) |
| 162 | +```sh |
| 163 | +LD_LIBRARY_PATH=/usr/local/lib ./a.out |
| 164 | +``` |
| 165 | +or |
| 166 | +```sh |
| 167 | +export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH |
| 168 | +``` |
| 169 | + |
| 170 | +## stack smashing detected |
| 171 | +From [StackOverflow - Stack smashing detected](https://stackoverflow.com/questions/1345670/stack-smashing-detected/50690687), add the following in `CMakeLists` to temporarily get rid of this error: |
| 172 | +``` |
| 173 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-stack-protector -std=c++11") |
| 174 | +``` |
| 175 | + |
| 176 | +## c++: internal compiler error: Killed (program cc1plus) |
| 177 | +[make -j 8 g++: internal compiler error: Killed (program cc1plus)](https://stackoverflow.com/questions/30887143/make-j-8-g-internal-compiler-error-killed-program-cc1plus) |
| 178 | + |
| 179 | +That's probably `make -j4` uses to much memory, so it's killed by system, try using `make -j1` instead. |
| 180 | + |
| 181 | +Another method is to tell kswapd0 to only move stuff to SWAP when you are completely out of RAM([kswapd0 is taking a lot of cpu](https://askubuntu.com/questions/259739/kswapd0-is-taking-a-lot-of-cpu/530661)): |
| 182 | +```sh |
| 183 | +echo vm.swappiness=0 | sudo tee -a /etc/sysctl.conf |
| 184 | +``` |
| 185 | + |
| 186 | +## specify CUDA path while cmake |
| 187 | +[How to let cmake find CUDA](https://stackoverflow.com/questions/19980412/how-to-let-cmake-find-cuda) |
| 188 | + |
| 189 | +Method 1, use `-D` flag while `cmake`: |
| 190 | +```sh |
| 191 | +cmake -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda .. |
| 192 | +``` |
| 193 | + |
| 194 | +Method 2, revise `CMakeLists.txt`, before `FIND_PACKAGE(CUDA)`, add one line, this becomes: |
| 195 | +``` |
| 196 | +set(CUDA_TOOLKIT_ROOT_DIR /usr/local/cuda) |
| 197 | +FIND_PACKAGE(CUDA) |
| 198 | +``` |
| 199 | + |
| 200 | +## specify OpenCV path while cmake |
| 201 | +``` |
| 202 | +set(OpenCV_DIR /usr/local/lib/cmake/opencv4) # set to system installation directory |
| 203 | +set(OpenCV_DIR ~/installation/opencv-4.1.2/build) # set to opencv build directory |
| 204 | +FIND_PACKAGE(OpenCV REQUIRED) |
| 205 | +``` |
| 206 | + |
| 207 | +Another method: [cmake find_package specify path](https://stackoverflow.com/questions/49816206/cmake-find-package-specify-path) |
| 208 | + |
| 209 | +## ccmake |
| 210 | +Its usage: [A ccmake walk-through for the impatients](https://graal.ens-lyon.fr/diet/UsersManualDIET2.4/node22.html). |
| 211 | + |
| 212 | +## Conventions |
| 213 | +[Separating class code into a header and cpp file](https://stackoverflow.com/questions/9579930/separating-class-code-into-a-header-and-cpp-file) |
| 214 | + |
| 215 | +## Macros |
| 216 | +### #define, #if, #elif, #else, #end |
| 217 | +[Preprocessor check if multiple defines are not defined](https://stackoverflow.com/questions/17237545/preprocessor-check-if-multiple-defines-are-not-defined) |
| 218 | +```cpp |
| 219 | +#define <MACRO_A> |
| 220 | + |
| 221 | +#ifdef <MACRO_A> |
| 222 | +#elif defined(<MACRO_B>) |
| 223 | +#elif !define(<MACRO_C>) && !define(<MACRO_D>) |
| 224 | +#elif !define(<MACRO_E>) || !define(<MACRO_F>) |
| 225 | +#else |
| 226 | +#end |
| 227 | +``` |
| 228 | +
|
| 229 | +### include guard |
| 230 | +Naming convention for include guard: [How to properly name include guards in c++ [closed]](https://stackoverflow.com/questions/49688518/how-to-properly-name-include-guards-in-c) |
| 231 | +
|
| 232 | +``` |
| 233 | +For a file named "baz.h" in a project named "foo", in submodule "bar", I'd name the guard FOO_BAR_BAZ_H. |
| 234 | +``` |
| 235 | +
|
| 236 | +### #pragma once |
| 237 | +```cpp |
| 238 | +#ifndef __SOMEFILE_H__ |
| 239 | +#define __SOMEFILE_H__ |
| 240 | +// ... |
| 241 | +#endif |
| 242 | +``` |
| 243 | +can be replaced with: |
| 244 | +```cpp |
| 245 | +#pragma once |
| 246 | +// ... |
| 247 | +``` |
| 248 | + |
| 249 | +## mimic of python if __name__ == '__main__': |
| 250 | + |
| 251 | +In Python, say we have `foo.py` and `bar.py`, and they both have `if __name__ == '__main__':`(we can think this as `main` function in C++). We can easily `import foo` from `bar.py` or `import bar` from `foo.py` without any problem. |
| 252 | + |
| 253 | +But in C++, if `foo.cpp` and `bar.cpp` both have `main` fucntion, then when they are compiled together(`g++ foo.cpp bar.cpp`), there will be the linker error: |
| 254 | + |
| 255 | +``` |
| 256 | +multiple definition of `main' |
| 257 | +``` |
| 258 | + |
| 259 | +Indicating that there are multiple functions named `main` are being linked together. |
| 260 | + |
| 261 | +So how to only enable one `main` function when compiling multiple `.cpp` files together? |
| 262 | + |
| 263 | +Following is a workaround: |
| 264 | + |
| 265 | +In `foo.cpp`: |
| 266 | + |
| 267 | +```cpp |
| 268 | +#include "foo.h" |
| 269 | +#include "bar.h" |
| 270 | + |
| 271 | +int foo(){ |
| 272 | + return 0; |
| 273 | +} |
| 274 | + |
| 275 | +#ifdef FOO |
| 276 | +int main(){ |
| 277 | + return 0; |
| 278 | +}; |
| 279 | +#endif |
| 280 | +``` |
| 281 | + |
| 282 | +And in `bar.cpp`: |
| 283 | + |
| 284 | +```cpp |
| 285 | +int bar(){ |
| 286 | + return 0; |
| 287 | +} |
| 288 | + |
| 289 | +#ifdef BAR |
| 290 | +int main(){ |
| 291 | + return 0; |
| 292 | +}; |
| 293 | +#endif |
| 294 | +``` |
| 295 | + |
| 296 | +Wrap their `main` function with the macro `ifdef-endif`, and when compiling them, use: |
| 297 | + |
| 298 | +```sh |
| 299 | +g++ -DFOO foo.cpp bar.cpp |
| 300 | +``` |
| 301 | + |
| 302 | +to only activate `foo.cpp`'s `main` function! |
0 commit comments