gcc 如何确保静态库和应用程序被编译为相同的?

hmmo2u0o  于 2022-11-13  发布在  其他
关注(0)|答案(2)|浏览(129)

我正在将一个第三方项目集成到我的应用程序中(确切地说是LittleFS)。我试图将该项目编译为一个静态库,然后将其链接到我的应用程序中。我对链接和正确获取包含路径没有问题,我的问题是如何处理编译时的配置。
例如,项目在其标题中有一行,如下所示:

struct lfs_config {
    ...
    #ifdef LFS_THREADSAFE
    int (*lock)(const struct lfs_config *c);
    int (*unlock)(const struct lfs_config *c);
    #endif
    ...
};

我将使用以下标志编译第三方项目/静态库以启用此功能:

gcc ... -DLFS_THREADSAFE

但是,当我将这个库链接到我的应用程序中时,为了使其正常工作,我还需要****确保我的应用程序设置了-DLFS_THREADSAFE标志。
这意味着我必须跟踪哪些定义设置在两个不同的地方,这似乎会变得有点容易出错和麻烦后,一段时间。
我的问题是,如何确保静态库和应用程序共享相同的配置?

46qrfjad

46qrfjad1#

There is no definitive and portable way to do this. In fact, most coding standards I've worked with will not permit any structure that is defined differently based on macros, particularly if that structure is used as part of an API. This would be considered an API design flaw if an interface structure is not consistently defined.
Rather than having the structure contents actually change based on the compile time configuration, it is better to keep it consistent but rather simply set the values to something to indicate they are not used. That is, in your example, keep the function pointers unconditionally, without any "ifdef":

struct lfs_config {
    ...
    int (*lock)(const struct lfs_config *c);
    int (*unlock)(const struct lfs_config *c);
    ...
};

In the event that LFS_THREADSAFE is undefined, these pointers can be set NULL. Assuming you use c99 style initializers, this can just work, i.e.

const struct lfs_config MY_CONFIG = {
    .other_option_1 = <value>
#ifdef LFS_THREADSAFE
    .lock = my_lock
    .unlock = my_unlock
#endif
    .other_option_2 = <value>
};

In this case, if LFS_THREADSAFE is defined, the lock and unlock items will be set accordingly. But if LFS_THREADSAFE is undefined, these initializers will be omitted, and per the C99 standard, the unspecified members will be assigned value 0 (NULL, in the case of a pointer). Inside the library, it can be made to simply skip the lock/unlock call if the function pointer value is NULL.
Alternatively, one could also always set the pointer to a valid function, but have it be a no-op if the LFS_THREADSAFE is undefined. That is:

int my_lock(struct lfs_config *c)
{
#ifdef LFS_THREADSAFE
    <do_something>
#endif
    return 0;
}

And similar for unlock.
To summarize, its always wise to keep API structures as consistent as possible, and not make them dependent on macros. Hope this helps!!

e4yzc0pl

e4yzc0pl2#

我已经查看了littlefs的源代码。
LFS_THREADSAFE是 * 唯一 * 的(即,您不需要设置LFS_MIGRATE)。
只需删除lfs.h中的#ifdef/#endif即可。
但是,要回答你的问题一般来说:只需通过一个“顶级”makefile来构建您项目和littlefs:

MYPROJ = myproj
LITTLEFS = littlefs

CFLAGS += -DLFS_THREADSAFE
CFLAGS += -DLFS_NAME_MAX=367
CFLAGS := $(addprefix CFLAGS+=,$(CFLAGS))

all: lfs_mk myp_mk

myp_mk: lfs_mk
    $(MAKE) -C $(MYPROJ) $(CFLAGS) $(MAKECMDGOALS)

lfs_mk:
    $(MAKE) -C $(LITTLEFS) $(CFLAGS) $(MAKECMDGOALS)

相关问题