How to properly organize multiple .c and .h files in different directories, so it is includable as <foo.h> elsewhere?

老子叫甜甜 提交于 2019-12-25 18:22:13

问题


I asked this question a while back: How to make C library installable with angle brackets as <mylib.h> on Mac. I am trying to do the same sort of thing, but don't exactly remember all the details / I'm not sure if I'm doing it right.

So I have a production example working, but it seems like things aren't organized right (even though it seems to be compiling and running properly). My question is, how can I clean this up and remove some duplication and remove anything unnecessary?

So here is my Makefile:

C_OPTS := -shared -fpic -O2 \
  -lssl -lcrypto -lboost_system \
  -lboost_thread-mt -lboost_chrono-mt \
  -std=c99 -lncurses

c/macos:
  @cp src/bundle.h \
    /usr/local/include/foo.h
  @mkdir -p /usr/local/include/foo
  @cp src/client.h \
    /usr/local/include/foo
  @cp src/cursor.h \
    /usr/local/include/foo
  @clang $(C_OPTS) \
    -install_name libfoo.dylib \
    -o build/libfoo.dylib \
    src/client.c \
    src/cursor.c \
    src/bundle.c
  @cp build/libfoo.dylib \
    /usr/local/lib
  @clang test/bundle.c \
    -lfoo -o build/foo.o
  @./build/foo.o
.PHONY: c/macos

What I do here is essentially, copy all of the header files from my local project to the global /usr/local/include/foo, so it ends up like this:

/usr/local/include
  /foo.h
  /foo
    /client.h
    /cursor.h

Notice how I am doing this file copying before doing the clang compilation step. I kept on getting errors of either Undefined symbols for architecture x86_64 or fatal error: 'client.h' file not found, depending on the small adjustments made to this system to try and get it to work. So the only thing I could do to get it to work was to actually copy all the header files to /usr/local/include. I don't feel like this is right.... Shouldn't I just be able to copy only the foo.h to /usr/local/include/foo.h, and somehow the other 2+ header files are just compiled into the dylib or something? I don't know how this is supposed to work, or if it's common practice to copy the multiple (nested) header files to the global path like this.

The reason I am doing this step is so I can include it like #include <foo.h>.

So after the file copying step, I compile the libfoo.dylib with clang. At one point in this process I was able to only have to pass it the "main" "top level" file src/bundle.c. But after figuring out that copying the headers works, I had to pass all of the files to the clang command as input. So instead of this:

@clang $(C_OPTS) \
  -install_name libfoo.dylib \
  -o build/libfoo.dylib \
  src/bundle.c

I have to do this:

@clang $(C_OPTS) \
  -install_name libfoo.dylib \
  -o build/libfoo.dylib \
  src/client.c \
  src/cursor.c \
  src/bundle.c

Is that the right way to be doing this? If not, how should it be? Is there a way to make it so I only have to pass it the top-level src/bundle.c?

So now, src/bundle.c looks like this:

#include "bundle.h"
#include "client.h"
#include "cursor.h"

And I had to do this seemingly hack in src/bundle.h to get it to work:

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "foo/client.h"
#include "foo/cursor.h"

That is presumably because it is actually loading the header files from the global folder I made just before doing the clang compilation step. But this smells, something is not right. I feel like it should be like this:

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "client.h"
#include "cursor.h"

Combine that with this, and it seems like it should work, but it doesn't....

  @clang $(C_OPTS) \
    -install_name libfoo.dylib \
    -o build/libfoo.dylib \
    src/bundle.c

Why isn't that working?

Finally, I have another file, test/bundle.c, which I use to verify things are working. I compile it in the last step:

@clang test/bundle.c \
  -lfoo -o build/foo.o

It works with this current setup. That test/bundle.c looks like this:

#include <foo.h>

int
main() {
  some_function();
  return 0;
}

In one configuration I had of all these files and headers and everything, I kept on getting the warning implicit declaration of function 'some_function' is invalid in C99, even though in foo.h and foo.c it was defined. I don't understand why it wasn't working before. I understand why it's working now, but again, my main concern is this #include architecture, and the way things are being compiled and link, smells bad. Something seems wrong. How do I clean it up and make the files better organized, while getting rid of all those errors?

来源:https://stackoverflow.com/questions/59021186/how-to-properly-organize-multiple-c-and-h-files-in-different-directories-so-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!