0

I'm trying to create a library with CMake that uses libcurl but GCC is consistently failing to find certain structs and defines even though they were included. I have curl, libssl-dev, and libcurl4-openssl-dev installed. I was able to compile a standalone example program generated by curl http://example.com --libcurl libcurl-out.c with gcc libcurl-out.c -lcurl.

Here is my project structure:

OpenDropC/
├── include/
│   ├── browser.h
│   ├── client.h
│   ├── config.h
│   └── server.h
├── src/
│   ├── browser.c
│   ├── client.c
│   ├── config_private.h
│   ├── config.c
│   ├── server.c
│   ├── utils.c
│   └── utils.h
└── CMakeLists.txt

config.c includes config_private.h which includes <curl/curl.h>. Putting the curl include directly in config.c doesn't fix the problem.

Here is my CMakeLists.txt:

cmake_minimum_required(VERSION 3.18)

project(OpenDropC VERSION 0.0.1 DESCRIPTION "Implementation of OpenDrop in C for Linux")

include(CTest)
enable_testing()

add_library(OpenDropC SHARED
    src/browser.c
    src/client.c
    src/server.c
    src/config.c
    src/utils.c
)

# set_target_properties(OpenDropC PROPERTIES PUBLIC_HEADER include/browser.h)
target_link_libraries(OpenDropC PRIVATE avahi-common avahi-client curl ssl)

Here is the compiler error that I get:

[main] Building folder: OpenDropC 
[build] Starting build
[proc] Executing command: /usr/local/bin/cmake --build /home/parallels/Code/OpenDropC/build --config Debug --target all -j 4 --
[build] [4/8  12% :: 0.043] Building C object CMakeFiles/OpenDropC.dir/src/server.c.o
[build] [5/8  25% :: 0.063] Building C object CMakeFiles/OpenDropC.dir/src/browser.c.o
[build] [6/8  37% :: 0.072] Building C object CMakeFiles/OpenDropC.dir/src/client.c.o
[build] [6/8  50% :: 0.080] Building C object CMakeFiles/OpenDropC.dir/src/utils.c.o
[build] [6/8  62% :: 0.088] Building C object CMakeFiles/OpenDropC.dir/src/config.c.o
[build] FAILED: CMakeFiles/OpenDropC.dir/src/config.c.o 
[build] /bin/gcc-9 -DOpenDropC_EXPORTS  -g -fPIC -MD -MT CMakeFiles/OpenDropC.dir/src/config.c.o -MF CMakeFiles/OpenDropC.dir/src/config.c.o.d -o CMakeFiles/OpenDropC.dir/src/config.c.o -c /home/parallels/Code/OpenDropC/src/config.c
[build] /home/parallels/Code/OpenDropC/src/config.c: In function ‘opendrop_config_new’:
[build] /home/parallels/Code/OpenDropC/src/config.c:42:70: error: invalid application of ‘sizeof’ to incomplete type ‘struct curl_blob’
[build]    42 |     if (!(config_unwrap->root_ca = (struct curl_blob*) malloc(sizeof(struct curl_blob)))) {
[build]       |                                                                      ^~~~~~
[build] /home/parallels/Code/OpenDropC/src/config.c:48:33: error: dereferencing pointer to incomplete type ‘struct curl_blob’
[build]    48 |     if (!(config_unwrap->root_ca->data = malloc(root_ca_len))) {
[build]       |                                 ^~
[build] /home/parallels/Code/OpenDropC/src/config.c:56:37: error: ‘CURL_BLOB_NOCOPY’ undeclared (first use in this function)
[build]    56 |     config_unwrap->root_ca->flags = CURL_BLOB_NOCOPY;
[build]       |                                     ^~~~~~~~~~~~~~~~
[build] /home/parallels/Code/OpenDropC/src/config.c:56:37: note: each undeclared identifier is reported only once for each function it appears in
[build] /home/parallels/Code/OpenDropC/src/config.c: In function ‘opendrop_config_set_record_data’:
[build] /home/parallels/Code/OpenDropC/src/config.c:280:71: error: invalid application of ‘sizeof’ to incomplete type ‘struct curl_blob’
[build]   280 |         if (!(config->record_data = (struct curl_blob*) malloc(sizeof(struct curl_blob)))) {
[build]       |                                                                       ^~~~~~
[build] /home/parallels/Code/OpenDropC/src/config.c:284:38: error: ‘CURL_BLOB_NOCOPY’ undeclared (first use in this function)
[build]   284 |         config->record_data->flags = CURL_BLOB_NOCOPY;
[build]       |                                      ^~~~~~~~~~~~~~~~
[build] [6/8  75% :: 0.097] Building C object CMakeFiles/OpenDropCTest.dir/test/main.c.o
[build] ninja: build stopped: subcommand failed.
[build] Build finished with exit code 1

Running curl-config --cflags returns a blank string, but I tried explicitly including the directory with the curl files and nothing changed. I also tried this answer with no change. Other libraries compile perfectly fine, so this seems to be a libcurl issue. Attempting to use VCPKG for curl specifically did work, but using that would make my project too bloated.

ImTheSquid
  • 365
  • 6
  • 15
  • It seems you don't get any errors on finding `curl/easy.h` where `struct curl_blob` is defined. Just as an experiment, could you try including that file explicitly? – Ted Lyngmo Jan 21 '22 at 01:36
  • No luck on putting an include in either `config.c` or `config_private.h`. `curl.h` also explicitly includes `easy.h` in its definition. – ImTheSquid Jan 21 '22 at 01:58
  • So, even if you put `#include ` as the absolutly first line in `config.c`, you get `incomplete type ‘struct curl_blob'` when you compile? You don't get an error that it can't find the file, but it can't find the definition of `strcut curl_blob`? Clear the cmake cache and rebuild fresh... it seems like something has gone wrong... If you write a separate program, include **only** `curl/easy.h` and try to `sizeof(struct curl_blob)`, does that also fail? – Ted Lyngmo Jan 21 '22 at 02:04
  • Putting `easy.h` before `curl.h` gives me a ton of errors because stuff in `easy.h` is defined in `curl.h`, but even after adding `curl.h` before `easy.h` it shows the original error. Not sure if it matters but I do also define types as `struct curl_blob` in `config_private.h`. – ImTheSquid Jan 21 '22 at 02:07
  • ... as a separate program. `#include ` `#include ` `int main() { size_t x = sizeof(struct curl_blob); }` what's the error? – Ted Lyngmo Jan 21 '22 at 02:09
  • Got the incomplete type error, even after adding `easy.h` explicitly. I used the same gcc command as in the first part of my question. – ImTheSquid Jan 21 '22 at 02:16
  • 1
    It sounds like your curl installation is broken. Can you compile so that you see what's actually gets included and look in those files? – Ted Lyngmo Jan 21 '22 at 02:17
  • 1
    That fixed the problem! It seems that the curl version on Ubuntu 20.04.2 is broken. – ImTheSquid Jan 21 '22 at 02:27
  • Lovely! :-) Great that you found it! – Ted Lyngmo Jan 21 '22 at 02:29
  • *I have `curl`, `libssl-dev`, and `libcurl4-openssl-dev` installed.* Haven't you `libcurl-dev` installed? – 273K Jan 23 '22 at 17:17
  • `libcurl-dev` is a meta-package that redirects to packages such as `libcurl4-openssl-dev`. – ImTheSquid Jan 23 '22 at 21:51
  • You can't install a meta-package, you need to install one of the packages it redirects to. I installed the openssl variant and it would not compile correctly with code I wrote. Building curl with openssl from source fixed the problem, therefore I would assume that there is something wrong with the apt package. – ImTheSquid Jan 24 '22 at 14:18

1 Answers1

2

I fixed the problem by installing the latest version of libcurl from source. Ubuntu 20.04 seems to have a broken version of libcurl.

ImTheSquid
  • 365
  • 6
  • 15