Previously, header files were installed uniformly under the include directory, ignoring the specified paths.
This change ensures header files are installed in the appropriate directories under `CMAKE_INSTALL_INCLUDEDIR`.
Issue
When `CMAKE_INSTALL_LIBDIR` and `CMAKE_INSTALL_INCLUDEDIR` are set to absolute paths, the `msgpack-c.pc` file generated by CMake improperly configures `libdir` and `includedir`. This leads to incorrect paths that prevent the compiler from locating necessary header and library files.
How to reproduce
Build and install `msgpack-c`.
```console
% cmake -S . -B ../msgpack-c.build -DCMAKE_INSTALL_LIBDIR=/tmp/local/lib -DCMAKE_INSTALL_INCLUDEDIR=/tmp/local/include
% cmake --build ../msgpack-c.build
% sudo cmake --install ../msgpack-c.build
```
Compile `example/simple_c.c` using installed msgpack-c. The following error happens because the linker cannot find paths provided by pkg-config.
```console
% export PKG_CONFIG_PATH=/tmp/local/lib/pkgconfig:$PKG_CONFIG_PATH
% gcc -o simple_c example/simple_c.c $(pkg-config --cflags --libs msgpack-c)
/usr/bin/ld: cannot find -lmsgpack-c: No such file or directory
collect2: error: ld returned 1 exit status
```
Expected
Successfully compile `example/simple_c.c` using installed msgpack-c. We can execute `simple_c` like the following.
```console
% gcc -o simple_c example/simple_c.c $(pkg-config --cflags --libs msgpack-c)
% ./simple_c
93 01 c3 a7 65 78 61 6d 70 6c 65
[1, true, "example"]
```
Explain the problem in detail
The generated `msgpack-c.pc` file does not handle absolute paths correctly. Here is the result of the incorrect configuration in `How to reproduce` section. In the following `msgpack-c.pc` file, `libdir` and `includedir` are showing unrecognized paths, leading to incorrect paths.
```console
% cat /tmp/local/lib/pkgconfig/msgpack-c.pc
prefix=/usr/local
exec_prefix=/usr/local
libdir=${prefix}//tmp/local/lib <- Here the path is wrong. We expected `/tmp/local/lib`
includedir=${prefix}//tmp/local/include <- Here the path is wrong. We expected `/tmp/local/include`
Name: MessagePack
Description: Binary-based efficient object serialization library
Version: 6.0.1
Libs: -L${libdir} -lmsgpack-c
Cflags: -I${includedir}
```
Solution
Modify the `CMakeLists.txt` file to ensure that `libdir` and `includedir` use absolute paths. This change addresses the issue by providing correct paths to the compiler and linker.
When `CMAKE_INSTALL_LIBDIR` and `CMAKE_INSTALL_INCLUDEDIR` are set to relative paths, the `msgpack-c.pc` file generated by CMake improperly configures `libdir` and `includedir`. This leads to incorrect paths that prevent the compiler from locating necessary header and library files.
Build and install `msgpack-c`.
```console
% git switch -c c_master
% cmake -S . -B ../msgpack-c.build -DCMAKE_INSTALL_PREFIX=/tmp/local -DCMAKE_INSTALL_LIBDIR=lib-relative -DCMAKE_INSTALL_INCLUDEDIR=include-relative
% cmake --build ../msgpack-c.build
% cmake --install ../msgpack-c.build/
```
Compile `example/simple_c.c` using installed msgpack-c.
The following error happens because the linker cannot find paths provided by pkg-config.
```console
% export PKG_CONFIG_PATH=/usr/local/lib-relative/pkgconfig:$PKG_CONFIG_PATH
% gcc -o simple_c example/simple_c.c $(pkg-config --cflags --libs msgpack-c)
/usr/bin/ld: cannot find -lmsgpack-c: No such file or directory
collect2: error: ld returned 1 exit status
```
Successly compile `example/simple_c.c` using install msgpack-c.
We can execute `simple_c.c` like the following.
```console
% gcc -o simple_c example/simple_c.c $(pkg-config --cflags --libs msgpack-c)
% ./simple_c
93 01 c3 a7 65 78 61 6d 70 6c 65
[1, true, "example"]
```
The generated `msgpack-c.pc` file does not handle relative paths correctly. Here is the result of the incorrect configuration in How to reproduce section.
In the following `msgpack-c.pc` file, `libdir` and `includedir` are relative to the current directory, leading to incorrect paths.
```console
cat ../msgpack-c.build/msgpack-c.pc
prefix=/tmp/local
exec_prefix=/tmp/local
libdir=lib-relative
includedir=include-relative
Name: MessagePack
Description: Binary-based efficient object serialization library
Version: 6.0.1
Libs: -L${libdir} -lmsgpack-c
Cflags: -I${includedir}
```
Modify the `msgpack-c.pc.in` file to ensure that `libdir` and `includedir` use absolute paths by prefixing them with ${prefix}/. This change addresses the issue by providing correct paths to the compiler and linker.
Building msgpack gives currently gives the following warning:
"CMake Deprecation Warning at CMakeLists.txt:1 (CMAKE_MINIMUM_REQUIRED):
Compatibility with CMake < 3.5 will be removed from a future version of
CMake.
Update the VERSION argument <min> value or use a ...<max> suffix to tell
CMake that the project does not need compatibility with older versions."
Reuse same solution as fc18087cdfaadec0b905643f93950387e797da08 as the
policy CMP0060 introduced in cmake 3.3 causes problems with when linking
for 32-bit otherwise.
Removing CMAKE_INSTALL_PREFIX allows for `cmake --install <build-dir>
--prefix=<installation-prefix>` to install headers at
`<installation-prefix>/include` at install time.
When CMAKE_INSTALL_PREFIX is present in `INSTALL()`, it is hard-coded
during configuration (e.g., `cmake -S .`), which disallows it from being
set at install time.
Ubuntu 18.04 is deprecated on GitHub Actions. Additionally:
- Install 'clang' to get the latest clang toolchain.
- Use -gdwarf-4 so Valgrind understands the debug information.
- Install latest version of gtest (v1.13.0).
- Show compile and link commands when building.
- `cat` Valgrind output on error.
CMake assumes the default project uses both C and C++, and therefore
will fail if both a C and a C++ compiler isn't found. This essentially
blocks pure C projects from using msgpack-c if they also don't have a
C++ compiler.
Just specifying that the project is "C" isn't possible though, as the
test themselves use C++. The workaround here is that we specify the
project needs both a C and C++ compiler if tests are used, but only a C
compiler if the tests aren't used.