gpt4 book ai didi

c - 在子目录中构建共享库

转载 作者:太空狗 更新时间:2023-10-29 16:32:28 26 4
gpt4 key购买 nike

我正在尝试构建一个使用一些 C 代码的 R 包。我有一个编译成可执行文件的 C 库,可以从命令行调用它。有一个与之关联的 Makefile。

我正在努力寻找信息 here ,它说

If you want to create and then link to a library, say using code in a subdirectory, use something like

 .PHONY: all mylibs

all: $(SHLIB)
$(SHLIB): mylibs

mylibs:
(cd subdir; make)

Be careful to create all the necessary dependencies, as there is a no guarantee that the dependencies of all will be run in a particular order (and some of the CRAN build machines use multiple CPUs and parallel makes).

如果我在我的包中的 src 文件夹中创建一个新的子目录,名为 someLibrary,代码和 Makefile 不变,然后在原始 我的包的 Makevars 文件 我添加上面的代码不变,然后我将能够构建要使用 useDynLib 导出的共享库?


编辑 1:

以下信息here ,我更改了 Makefile 以通过添加

创建共享库
CFLAG = -fPIC -g -O3 
LDFLAGS= -shared

但是这样会导致.so文件没有直接导出到包的libs目录下。如果我将路径硬编码到目标中,则文件将发送到包的 libs 目录(这都是通过调用 R CMD INSTALL myPackage ).


编辑2:

最后,我想知道如何调用共享库,因为它有一个我可以从命令行可执行文件调用的 main() 方法。

将此暴露给 R NAMESPACE 的过程是什么,以便可以通过 .Call 调用它?

附言。请让我知道我是否应该将最后一点作为一个单独的问题。

最佳答案

原问题作者在问题的评论中询问了使用AutomakeLibtoolLDADD 链接a 的示例在一个目录中编译的程序与在第二个目录中编译的共享库。 这是一个完整、独立、完整的示例,说明如何使用 GNU Autotools 在同一源代码树的不同目录中编译库和程序。

目录结构

我们需要建立一个目录结构如下:

├ A/
│ ├ Makefile.am
│ ├ helloworld.c
│ └ helloworld.h
├ B/
│ ├ Makefile.am
│ └ foo.c
├ configure.ac
└ Makefile.am

共享库将在目录A/ 中编译,而使用它的程序在目录B/ 中。

编写源代码

共有三个源文件。

A/helloworld.c 是库的源代码。它导出一个过程,say_hello(),打印消息“Hello world!”到标准输出。

#include <stdio.h>
#include "helloworld.h"

void
say_hello (void)
{
printf ("Hello world!\n");
}

A/helloworld.h 是包含 say_hello() 函数声明的头文件。它只有一行:

void say_hello (void);

最后,B/foo.c是使用共享库的程序的源代码。它包含库的头文件,并调用 say_hello()

#include <helloworld.h>

int
main (int argc, char **argv)
{
say_hello ();
return 0;
}

编译库

我们将使用 Automake 和 Libtool 来编译共享库。这两个工具都非常强大,而且实际上有非常详细的文档记录。手册( AutomakeLibtool )绝对值得一读。

A/Makefile.am文件被automake用来控制库的编译。

# We're going to compile one libtool library, installed to ${libdir},
# and named libhelloworld.
lib_LTLIBRARIES = libhelloworld.la

# List the source files used by libhelloworld.
libhelloworld_la_SOURCES = helloworld.c

# We install a single header file to ${includedir}
include_HEADERS = helloworld.h

编译程序

B/Makefile.am 文件控制库的编译。我们需要使用 LDADD变量告诉 automake 链接我们之前编译的库。

# Compile one program, called foo, and installed to ${bindir}, with a single C
# source file.
bin_PROGRAMS = foo
foo_SOURCES = foo.c

# Link against our uninstalled copy of libhelloworld.
LDADD = $(top_builddir)/A/libhelloworld.la

# Make sure we can find the uninstalled header file.
AM_CPPFLAGS = -I$(top_srcdir)/A

控制构建

最后,我们需要一个顶级的Makefile.am来告诉Automake如何构建项目,以及一个configure.ac文件来告诉Autoconf如何找到所需的工具。

顶级 Makefile.am 非常简单:

# Compile two subdirectories.  We need to compile A/ first so the shared library is
# available to link against.
SUBDIRS = A B

# libtool requires some M4 scripts to be added to the source tree. Make sure that
# Autoconf knows where to find them.
ACLOCAL_AMFLAGS = -I m4

最后,configure.ac 文件告诉 Autoconf 如何创建 configure 脚本。

AC_INIT([libhelloworld], 1, peter@peter-b.co.uk)

# This is used to help configure check whether the source code is actually present, and
# that it isn't being run from some random directory.
AC_CONFIG_SRCDIR([A/helloworld.c])

# Put M4 macros in the m4/ subdirectory.
AC_CONFIG_MACRO_DIR([m4])

# We're using automake, but we want to turn off complaints about missing README files
# etc., so we need the "foreign" option.
AM_INIT_AUTOMAKE([foreign])

# We need a C compiler
AC_PROG_CC

# Find the tools etc. needed by libtool
AC_PROG_LIBTOOL

# configure needs to generate three Makefiles.
AC_CONFIG_FILES([A/Makefile
B/Makefile
Makefile])
AC_OUTPUT

测试一下

运行:

$ autoreconf -i
$ ./configure
$ make
$ B/foo

您应该看到所需的输出:“Hello world!”

关于c - 在子目录中构建共享库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17133550/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com