在子目录中构建共享库 [英] Building shared libraries in subdirectories

查看:65
本文介绍了在子目录中构建共享库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to build an R package that uses some C code. I have a C library that is compiled into an executable, that can be called from the command line. There is a Makefile associated with it.

我正尝试在此处,上面写着

如果要创建然后链接到库,请说 子目录,使用类似

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) 

小心创建所有必要的依赖项,因为没有 保证所有的依赖 将以特定的顺序运行(以及某些CRAN构建机器 使用多个CPU和并行制造商.)

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导出的共享库?

If I create a new subdirectory of the src folder in my package, called someLibrary, with the code and Makefile unchanged, and in turn, in the original Makevars file for my package I add the above code unchanged, then I will be able to build that shared library to be exported using useDynLib?

以下信息

Following information here, I changed the Makefile to create a shared library by adding

CFLAG = -fPIC -g -O3 
LDFLAGS= -shared

但是,这导致.so文件没有直接导出到程序包的libs目录的问题.如果我将路径硬编码到目标中,则文件将发送到程序包的libs目录(全部通过对R CMD INSTALL myPackage的调用).

However, this leads to the problem that the .so file is not exported directly to the libs directory of the package. If I hard code the path into the target, then the file is sent to the libs directory of the package (this is all by the way of calls to R CMD INSTALL myPackage).

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

Lastly, I would like to know how to make calls to the shared library, given that it has a main() method that I could call from the command line executable.

将其公开给R NAMESPACE以便可以通过.Call进行调用的过程是什么?

What is the procedure to expose this to the R NAMESPACE, so that it can be called via .Call?

PS.请让我知道是否最后一个问题.

PS. Please let me know if I should make the last bit a separate question.

推荐答案

原始问题的作者在对该问题的评论中要求使用 Automake Libtool 的示例strong>和LDADD链接在一个目录中编译的程序与在第二个目录中编译的共享库. 这是一个完整的,独立的,完全有效的示例,说明如何使用GNU Autotools在同一源代码树的单独目录中编译库和程序.

The original question author asked, in the comments on the question, for an example of using Automake, Libtool and LDADD to link a program compiled in one directory with a shared library compiled in a second directory. This is a complete, standalone, fully worked example of how to compile a library and program in separate directories of the same source tree using GNU Autotools.

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

We need to set up a directory structure as follows:

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

共享库将在目录A/中进行编译,而使用该共享库的程序将在目录B/中进行编译.

The shared library will be compiled in directory A/, and the program that uses it in directory B/.

有三个源文件.

A/helloworld.c是该库的源代码.它导出一个过程say_hello(),该过程显示消息"Hello world!".到标准输出.

A/helloworld.c is the source code of the library. It exports one procedure, say_hello(), which prints the message "Hello world!" to standard output.

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

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

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

A/helloworld.h is the header file that contains the declaration of the say_hello() function. It only has one line:

void say_hello (void);

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

Finally, B/foo.c is the source code of the program that uses the shared library. It includes the library's header file, and calls say_hello().

#include <helloworld.h>

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

编译库

我们将使用Automake和Libtool来编译共享库.这两个工具都非常强大,并且实际上有充分的文档记录.手册( Automake

Compiling the library

We will use Automake and Libtool to compile the shared library. Both of these tools are very powerful, and actually remarkably well-documented. The manuals (Automake, Libtool) are definitely worth reading.

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

The A/Makefile.am file is used by automake to control the compilation of the library.

# 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链接到我们之前编译的库.

Compiling the program

The B/Makefile.am file controls compilation of the library. We need to use the LDADD variable to tell automake to link against the library we compiled earlier.

# 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如何找到所需的工具.

Controlling the build

Finally, we need a top level Makefile.am to tell Automake how to build the project, and a configure.ac file to tell Autoconf how to find the required tools.

顶级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脚本.

Finally, the configure.ac file tells Autoconf how to create the configure script.

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!"

You should see the required output: "Hello world!"

这篇关于在子目录中构建共享库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆