草庐IT

关于项目目录下的 c:scons 可执行共享库

codeneng 2023-03-28 原文

scons executable + shared library in project directory

这是一个示例 SConscript 文件:

1
2
3
4
5
6
7
8
env = Environment()
hello_lib = env.SharedLibrary('hello', ['libhello.c'])
exe = env.Program('main', ['main.c'], LIBS=hello_lib)

env.Install('/usr/lib', hello_lib)
env.Install('/usr/bin', exe)
env.Alias('install', '/usr/bin')
env.Alias('install', '/usr/lib')

它构建一个共享库,以及一个链接到该库的可执行文件:

1
2
3
4
5
6
7
8
9
$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o libhello.os -c -fPIC libhello.c
gcc -o libhello.so -shared libhello.os
gcc -o main.o -c main.c
gcc -o main main.o libhello.so
scons: done building targets.

现在,问题是创建的可执行文件在从项目目录运行时找不到共享库,
这是很自然的,因为没有设置 LD_LIBRARY_PATH 环境变量,或者
在可执行文件中设置了任何 RPATH:

1
2
[fedora 00:07:10 2 ~] $ ./main
./main: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory

我总是可以在开发时设置 LD_LIBRARY_PATH 变量,但是如果项目的目录层次结构在 sub_directories 中有多个共享库,这将变得很麻烦。

GNU autotools/libtool 通过自动将可执行文件的 RPATH 设置到项目目录中构建共享库的任何位置来解决这个问题,这样可以在开发时轻松运行/测试可执行文件。并且它在安装时重新链接可执行文件以省略那些不再需要的 RPATH。

是否有任何类似于 autotools 的功能可以使用 scons 来简化开发时的可执行文件测试?

有没有推荐的方法来使用共享库和 scons 构建应用程序,这样可以很容易地从构建目录运行可执行文件?


您可以修改每个生成库的 SConscript 文件,如下所示:

1
hello_lib = env.SharedLibrary('#/lib/hello', ['libhello.c'])

您的所有共享库现在都位于一个目录中。

生成可执行文件的 SConscript 变为:

1
exe = env.Program('main', ['main.c'], LIBPATH='#/lib', LIBS=hello_lib)

然后您就可以将 LD_LIBRARY_PATH 设置为 $PWD/lib


看起来您正在寻找 scons 中的 RPATH 选项。

在 wiki 页面中,RPATH 被描述为 scons,如下所示。

A list of paths to search for shared libraries when running programs.
Currently only used in the GNU linker (gnulink) and IRIX linker
(sgilink). Ignored on platforms and toolchains that don't support it.
Note that the paths added to RPATH are not transformed by scons in any
way: if you want an absolute path, you must make it absolute yourself.

  • 是的,我正在寻找有关如何最好地使用 SCons 执行此操作的建议,方法与 automake/libtool 处理它的方式类似。或者您是说我必须手动为项目中的每个潜在共享库设置 RPATH,并以某种方式确保在安装目标运行时未设置 RPATH?
  • @user964970,RPATH 通常用于与应用程序捆绑在一起的共享库,wiki 解释了如何在 RPATH 内指定相对路径,以便构建的应用程序在开发环境和目标环境中都可以工作.
  • @user964970,当然,这要求您的开发环境构建输出中的相对目录结构与部署的相对目录结构相匹配,但我认为这是一个合理的要求。
  • 嗯,这对我来说是一个很不合理的要求。例如,我在 libA 和 libB 源文件夹下有 2 个共享库,这需要我将 RPATH 设置为 libA 和 libB,在安装项目时,库进入 /usr/lib(并且不需要 RPATH)。
  • @user964970,我当然不是要求您更改源目录结构,只是要求您的二进制分发结构应该与部署的结构相匹配。构建 libAlibB 时,将输出放在名为 lib 的本地目录中。
  • 除了手动复制文件之外,有关如何使用 scons 执行此操作的任何提示? variant_dir 不会有太大帮助,因为它还将中间文件放在变体目录中(这当然可能与文件名冲突)。

有关关于项目目录下的 c:scons 可执行共享库的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  4. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  5. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  6. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  7. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

    我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

  8. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  9. Ruby 从大范围中获取第 n 个项目 - 2

    假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit

  10. ruby - 检查是否通过 require 执行或导入了 Ruby 程序 - 2

    如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby​​文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否

随机推荐