|
| 1 | +--- |
| 2 | +date: 2025-05-04 |
| 3 | +title: Building software from source |
| 4 | +--- |
| 5 | + |
| 6 | +This tutorial describes how to configure and build libraries from source for your unique system. |
| 7 | +This is often necessary when your software requirements are not met by the packages available in the repositories of |
| 8 | +your distribution (the version of the package you want is not available from `apt` for your version of Ubuntu, for |
| 9 | +example). |
| 10 | +This tutorial will cover the process for customizing and building packages from source as you need them. |
| 11 | +Along the way, common pitfalls and how to avoid them will be discussed. |
| 12 | +You will also discover how to avoid polluting your system environment to avoid conflicts between the packages you build |
| 13 | +and the ones installed by your package manager. |
| 14 | + |
| 15 | +## Why build your packages from source? |
| 16 | + |
| 17 | +There are several reasons you might want to build packages from source, a few of these are listed below: |
| 18 | + |
| 19 | +- The package (+ version) you want is not available from your system package manager. |
| 20 | +- You need a customized build of the package (building OpenCV with CUDA support for example). |
| 21 | +- For optimized builds that fully utilize all the features your hardware has to offer. |
| 22 | + |
| 23 | +## Process outline and key pieces |
| 24 | + |
| 25 | +To build software from source code, these are the broad steps that must be followed: |
| 26 | + |
| 27 | +- Obtain the source code: Usually `git clone` and `git checkout` and then apply patches if necessary. |
| 28 | +- Get dependencies: Use your system package manager or build the packages that this package depends on so they are |
| 29 | + available to this package. |
| 30 | +- Configure the build: Use `cmake` to set options for the build, including which features to compile with and the path |
| 31 | + where the package must be installed. |
| 32 | +- Build and install the package: Use `cmake` to build and install the package. |
| 33 | +- Linking against the built package: Set environment/cmake variables so that other packages can find the package |
| 34 | + that you just built. |
| 35 | + |
| 36 | +This tutorial will use the popular computer-vision library OpenCV as a guiding example due to its popularity and |
| 37 | +complexity, which will concretely demonstrate all steps. |
| 38 | + |
| 39 | +## Step 0: Prerequisites |
| 40 | + |
| 41 | +To build software, the system needs to have the following installed: |
| 42 | + |
| 43 | +- [CMake](https://cmake.org/) |
| 44 | +- [Ninja](https://ninja-build.org/) as a preferred build tool. |
| 45 | +- A C/C++ compiler, linker, and standard libraries/headers (usually preinstalled). |
| 46 | + |
| 47 | +This collection is called the "toolchain". |
| 48 | +On Ubuntu all of this can be installed with: |
| 49 | + |
| 50 | +```bash |
| 51 | +sudo apt install build-essential |
| 52 | +``` |
| 53 | + |
| 54 | +## Step 1: Getting the source code |
| 55 | + |
| 56 | +### Which version do I require |
| 57 | + |
| 58 | +If this package is being compiled to satisfy the dependency of other software that you need, you should check which |
| 59 | +exact version that dependent package needs. This can be done by analyzing the CMakeLists.txt file of the dependent ( |
| 60 | +final) package, and finding a line resembling: |
| 61 | + |
| 62 | +```cmake |
| 63 | +find_package(OpenCV 4 ...) |
| 64 | +``` |
| 65 | + |
| 66 | +This tells you that this package requires OpenCV 4 (Any 4.x.y version works). |
| 67 | + |
| 68 | +Get source code for this version. |
| 69 | + |
| 70 | +### Cloning source code |
| 71 | + |
| 72 | +Get the source code on your computer into a well-organized folder (in a separate directory, that directory is alongside |
| 73 | +directories that contain source-code for other packages). |
| 74 | + |
| 75 | +Instructions should be present on the package website. Usually, this involves: |
| 76 | + |
| 77 | +- `git clone` the package. |
| 78 | +- `git checkout` to the release that is desired, e.g. `git checkout 4.11.0` to get that version of OpenCV, obtained from |
| 79 | + the GitHub releases page. |
| 80 | + |
| 81 | +Here you would modify the source code (such as apply any quick fixes/patches as required). |
| 82 | + |
| 83 | +**Also follow any prescribed instructions as the package demands** |
| 84 | + |
| 85 | +To build OpenCV with the contrib feature set, we must also download and extract some more content. Follow instructions |
| 86 | +listed on the website. |
| 87 | + |
| 88 | +## Step 2: Get dependencies |
| 89 | + |
| 90 | +This library will depend on other software. Get that software, usually from your package manager, by running a command |
| 91 | +similar to (on ubuntu): |
| 92 | + |
| 93 | +```bash |
| 94 | +sudo apt install lib-<libname>-dev |
| 95 | +``` |
| 96 | + |
| 97 | +For example, to get the "png" dependency to allow OpenCV to read png images, just run: |
| 98 | + |
| 99 | +```bash |
| 100 | +sudo apt install libpng-dev |
| 101 | +``` |
| 102 | + |
| 103 | +You can proceed to the next step, and install these as CMake will complain that it did not find a dependency. |
| 104 | + |
| 105 | +## Step 3: Configure the build |
| 106 | + |
| 107 | +This is the crucial step. Here, you decide how the package needs to be compiled, this includes: |
| 108 | + |
| 109 | +- Which features you need: In OpenCV, for example, which image formats (png, jpg, etc.) you want to support |
| 110 | + reading/writing to? |
| 111 | +- Do you want OpenCV to support CUDA? |
| 112 | +- Do you want to build support for Python? |
| 113 | +- Disable/enable features (GUI support, for example). |
| 114 | + |
| 115 | +### Setting the environment |
| 116 | + |
| 117 | +Be in the environment under which you will run this package. |
| 118 | + |
| 119 | +Concretely, this means: If you want OpenCV to be built in a particular Python virtual environment, in your terminal, |
| 120 | +source this Python Environment. |
| 121 | + |
| 122 | +Also set `CMAKE_PREFIX_PATH` (explained later) to allow CMake to find other packages. |
| 123 | + |
| 124 | +### Set Options |
| 125 | + |
| 126 | +Now, create a well-organized build directory, where build time intermediates will be stored (these are temporary files |
| 127 | +emitted and |
| 128 | +consumed by the compiler and linker on the way to making the final binaries and libraries). |
| 129 | + |
| 130 | +Change into the build directory and configure the package as follows: |
| 131 | + |
| 132 | +```bash |
| 133 | +cmake -S <path_to_source_code> -DCMAKE_INSTALL_PREFIX=<path_to_install_directory> -DOPENCV_EXTRA_MODULES_PATH=../../src/OpenCV/opencv_contrib-4.x/modules -DWITH_TIFF=ON -DCMAKE_BUILD_TYPE=Release |
| 134 | +``` |
| 135 | + |
| 136 | +Let's break down this command: |
| 137 | + |
| 138 | +- `-S` is where the source code to be compiled it. This directory must contain the `CMakeLists.txt` file. |
| 139 | +- `-D<option>=<value>` The options being configured. Most are package-specific (such as `-DOPENCV_EXTRA_MODULES_PATH` |
| 140 | + and `-DWITH_TIFF=ON`). Some package-agnostic options (the `-DCMAKE_<option>=<value>`) are elaborated upon below: |
| 141 | + - `-DCMAKE_INSTALL_PREFIX=<install_directory>`: This option tells CMake the directory under which to place all the |
| 142 | + libraries, binaries, headers and auxiliary files. By default, CMake will try to install to your root system and |
| 143 | + this can cause conflicts with the package manager. **It is highly recommended to set this to a well-organized |
| 144 | + location.** |
| 145 | + - `-DCMAKE_BUILD_TYPE=Release`: This tells CMake to build the package in "Release" mode, i.e. enable optimizations |
| 146 | + and disable debug information. **Set this for optimal performance**. |
| 147 | + |
| 148 | +Upon running the above command, CMake will check your system to see if everything is available. |
| 149 | +If it complains about not finding something, either install it via the method described in the section above, or build |
| 150 | +it from source and include its install prefix in the `CMAKE_PREFIX_PATH` environment variable. |
| 151 | + |
| 152 | +If this step is successful, proceed to building and installing the package. |
| 153 | + |
| 154 | +## Step 4: Build and install the package |
| 155 | + |
| 156 | +To build and install the package, simply run the following from the build directory: |
| 157 | + |
| 158 | +```bash |
| 159 | +cmake --build . --target install |
| 160 | +``` |
| 161 | + |
| 162 | +This will start compilation and linking and install the library to the directory specified in the configuration step. |
| 163 | + |
| 164 | +Compiling is compute intensive and large packages can take a long time (5-6 hours to compile PyTorch on an Orin). |
| 165 | + |
| 166 | +Errors in this step can be dealt with by consulting GitHub issues and searching the internet. Common fixes include |
| 167 | +installing a more modern compiler, changing versions of dependencies or changing package source code. |
| 168 | + |
| 169 | +When this step completes, the install directory will contain: |
| 170 | + |
| 171 | +```text |
| 172 | +├── bin |
| 173 | +├── include |
| 174 | +├── lib |
| 175 | +├── lib64 |
| 176 | +└── share |
| 177 | +``` |
| 178 | + |
| 179 | +Note that multiple packages can install to the same install directory. |
| 180 | + |
| 181 | +## Step 5: Link against the built package |
| 182 | + |
| 183 | +You most likely built this package as a dependency to some other target package you need to build. |
| 184 | + |
| 185 | +While building your target package, you need to inform CMake where to find the dependency you just built. |
| 186 | + |
| 187 | +To achieve this, before configuring the target package, add the install directory of the package you just built to the |
| 188 | +`CMAKE_PREFIX_PATH` environment variable, like so in bash: |
| 189 | + |
| 190 | +```bash |
| 191 | +export CMAKE_PREFIX_PATH="<install_directory>:$CMAKE_PREFIX_PATH" |
| 192 | +``` |
| 193 | + |
| 194 | +Here, <install_directory> is the same as specified in the variable |
| 195 | +`-DCMAKE_INSTALL_PREFIX` during configuration, which has the structure mentioned above below it. |
| 196 | + |
| 197 | +After setting this environment variable, continue the configure process as usual, and CMake will pick up the dependency |
| 198 | +from where you installed it. |
| 199 | + |
| 200 | +While running the library, you might encounter errors about not finding a particular `.so` file. To fix these, simply |
| 201 | +add the `<install_directory>/lib/` or the `<install_directory>/lib64/` directory to the `LD_LIBRARY_PATH` environment |
| 202 | +variable to enable the Linux Dynamic Linker to find the dynamic libraries where you installed them. |
| 203 | +An example of this process is |
| 204 | + |
| 205 | +```bash |
| 206 | +export LD_LIBRARY_PATH="<install_directory>/lib:$LD_LIBRARY_PATH" |
| 207 | +``` |
| 208 | + |
| 209 | +## Summary |
| 210 | + |
| 211 | +This tutorial went over the exact process to build `cmake` enabled projects from source. |
| 212 | + |
| 213 | +The ability to do this reduces your reliance on the package manager and helps you get out of dependency issues. |
| 214 | + |
| 215 | +Moreover, using the above framework you can install and use multiple versions of the same library on your system. |
| 216 | + |
| 217 | +## See Also: |
| 218 | + |
| 219 | +- [A short guide on using CMake](/wiki/programming/cmake/) |
0 commit comments