# Shared library in CMake

**URL:** https://discourse.cmake.org/t/shared-library-in-cmake/8773
**Category:** Code
**Tags:** os:linux
**Created:** [August 18, 2023, 3:13pm UTC](https://discourse.cmake.org/t/shared-library-in-cmake/8773 "2023-08-18T15:13:07Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Matheus\_Diogenes\_And](https://discourse.cmake.org/user_avatar/discourse.cmake.org/matheus_diogenes_and/32/3738_2.png) [@Matheus\_Diogenes\_And](https://discourse.cmake.org/u/Matheus_Diogenes_And)
#### Post date: [August 18, 2023, 3:13pm UTC](https://discourse.cmake.org/t/shared-library-in-cmake/8773/1 "2023-08-18T15:13:08Z")

</div>

Hello everyone.

**Summary**

I am working in a C++20 project that makes use of a shared library. So far, I successfully managed to call the shared library when compiling and running the script, however, when using CMake to do the job, the things are not going that well.

**Pre-CMake**

I have a code `main.cpp` with a structure similar to the one below:

```cpp
extern "C"
{
void c_custom(char *param);
}

int main() {

    char *param = ...

    c_custom(param);

    return 0;
}

```

The above script has no imports or includes whatsoever.

For compiling, I simply type:

```sh
g++ -O3 main.cpp -L/opt/custom/lib -std=c++20 -lcustom -lgfortran -lm -o main

```

Where the folder `/opt/custom/lib` contains a file named `libcustom.a`.

The compilation and execution work perfectly well.

**Pos-CMake**

For the CMake project, I created the following folder structure:

- includes
- src
- build

With the following `CMakeLists.txt`:

```cmake
cmake_minimum_required(VERSION 3.16)
project(Main)

##### Include Dirs

include_directories(SYSTEM includes "${PROJECT_BINARY_DIR}")

##### Compile options

add_compile_options(
    -std=c++20
    # CUSTOM Lib
    -L/opt/custom/lib
    -lcustom
    -lgfortran
    -lm
    )

file(GLOB_RECURSE SOURCES "src/*.cpp")

add_executable(main ${SOURCES})

target_link_libraries(main)

```

With the following codes:

- `includes/main.hpp`:

```cpp
#ifndef MAIN_HPP

    #define MAIN_HPP

    #ifdef __cplusplus
        extern "C" {
    #endif

            void c_custom(char *param);

    #ifdef __cplusplus
        }
    #endif

#endif

```

- `src/main.cpp`:

```cpp
#include "main.hpp"

int main() {
    char *param = ...
    c_custom(param);
    return 0;
}

```

When running the commands:

```sh
cd build
cmake ..

```

I obtain the following output:

```sh
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: project/build

```

Which seems to be fine. However, when running `make`, we obtain these:

```sh
[50%] Building CXX object CMakeFiles/main.dir/src/main.cpp.o
[100%] Linking CXX executable main
/usr/bin/ld: CMakeFiles/main.dir/src/main.cpp.o: in the function `main':
main.cpp:(.text+0x812): reference to `c_custom' not defined
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/main.dir/build.make:97: main] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/main.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

```

I took some hours to play with the commands `add_library`, `set_target_properties`, `target_include_directories`, and even setting the `LANGUAGE` to `C CXX Fortran` in the `project` statement, but none worked.

I would like to know if someone ever did something similar before.

Thanks and regards.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [August 18, 2023, 3:36pm UTC](https://discourse.cmake.org/t/shared-library-in-cmake/8773/2 "2023-08-18T15:36:35Z")

</div>

> [@Matheus\_Diogenes\_And](#):
>
> ```auto
> add_compile_options(
> -std=c++20
> # CUSTOM Lib
> -L/opt/custom/lib
> -lcustom
> -lgfortran
> -lm
> )
> 
> ```

You’re giving linker options as compile options. You should use `add_link_options()` for those. Better would be to use `IMPORTED` targets, but this should at least get you _a_ working build.

---

<div class="post-metadata">

### Author: ![Matheus\_Diogenes\_And](https://discourse.cmake.org/user_avatar/discourse.cmake.org/matheus_diogenes_and/32/3738_2.png) [@Matheus\_Diogenes\_And](https://discourse.cmake.org/u/Matheus_Diogenes_And)
#### Post date: [August 18, 2023, 3:57pm UTC](https://discourse.cmake.org/t/shared-library-in-cmake/8773/3 "2023-08-18T15:57:50Z")

</div>

> [@ben.boeckel](#):
>
> add\_link\_options

Thank you very much. I tried to follow the recommendation, ending-up with the following script:

```cmake
cmake_minimum_required(VERSION 3.16)
project(Main)

##### Include Dirs

include_directories(SYSTEM includes "${PROJECT_BINARY_DIR}")

##### Compile options

# CUSTOM Lib
add_link_options(-L/opt/custom/lib)

add_compile_options(
    -std=c++20
    # CUSTOM Lib
    -lcustom
    -lgfortran
    -lm
    )

file(GLOB_RECURSE SOURCES "src/*.cpp")

add_executable(main ${SOURCES})

target_link_libraries(main)

```

But the same error persists. What do you mean by `IMPORTED` targets? I am sorry, but could you post some code snippet? I am newbie in CMake.

Regards.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [August 18, 2023, 5:17pm UTC](https://discourse.cmake.org/t/shared-library-in-cmake/8773/4 "2023-08-18T17:17:35Z")

</div>

The `-l` flags are also linker options.

For an `IMPORTED` target, it’s something like:

```cmake
add_library(custom STATIC IMPORTED)
set_target_properties(custom PROPERTIES
  INTERFACE_INCLUDE_DIRECTORIES "/abs/path/to/custom/includes/dir"
  IMPORTED_LOCATION "/opt/custom/lib/libcustom.a"
  INTERFACE_LINK_LIBRARIES "gfortran;m"
  )

```

You then use it by `target_link_libraries(main PRIVATE custom)`.

---

<div class="post-metadata">

### Author: ![Matheus\_Diogenes\_And](https://discourse.cmake.org/user_avatar/discourse.cmake.org/matheus_diogenes_and/32/3738_2.png) [@Matheus\_Diogenes\_And](https://discourse.cmake.org/u/Matheus_Diogenes_And)
#### Post date: [August 18, 2023, 7:02pm UTC](https://discourse.cmake.org/t/shared-library-in-cmake/8773/5 "2023-08-18T19:02:49Z")

</div>

> [@ben.boeckel](#):
>
> ```auto
> add_library(custom STATIC IMPORTED)
> set_target_properties(custom PROPERTIES
> INTERFACE_INCLUDE_DIRECTORIES "/abs/path/to/custom/includes/dir"
> IMPORTED_LOCATION "/opt/custom/lib/libcustom.a"
> INTERFACE_LINK_LIBRARIES "gfortran;m"
> )
> 
> ```

Thank you very much, it works prefectly well.
