1

我正在尝试构建一个我下载的应用程序,它使用 SCONS“make replacement”和 Fast Light Tool Kit Gui。

检测 fltk 存在的 SConstruct 代码是:

guienv = Environment(CPPFLAGS = '')
guiconf = Configure(guienv)

if not guiconf.CheckLibWithHeader('lo', 'lo/lo.h','c'):
    print 'Did not find liblo for OSC, exiting!'
    Exit(1)

if not guiconf.CheckLibWithHeader('fltk', 'FL/Fl.H','c++'):
    print 'Did not find FLTK for the gui, exiting!'
    Exit(1)

不幸的是,在我的(Gentoo Linux)系统和许多其他(Linux 发行版)上,如果包管理器允许同时安装 FLTK-1 和 FLTK-2,这可能会非常麻烦。

我试图通过像这样添加它们来修改 SConstruct 文件以使用fltk-config --cflagsfltk-config --ldflags(或fltk-config --libs可能比)更好:ldflags

guienv.Append(CPPPATH = os.popen('fltk-config --cflags').read())
guienv.Append(LIBPATH = os.popen('fltk-config --ldflags').read())

但这会导致 liblo 的测试失败!查看config.log显示它是如何失败的:

scons: Configure: Checking for C library lo...
gcc -o .sconf_temp/conftest_4.o -c "-I/usr/include/fltk-1.1 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_THREAD_SAFE -D_REENTRANT"
gcc: no input files
scons: Configure: no

这应该怎么做?

为了完成我的回答,我如何从结果中删除引号os.popen( 'command').read()

编辑这里真正的问题是为什么附加fltk-config导致 gcc 的输出不接收它应该编译的文件名参数?

4

2 回答 2

1

这是一个相当复杂的问题,没有快速的答案

我在http://www.scons.org/wiki/UsingPkgConfigpkg-config参考了使用scons的说明。以下问题也很有帮助 测试 Python 中是否存在可执行文件?.

但是我们需要在这些方面走得更远一些。

因此,经过大量调查,我发现os.popen('command').read()并没有修剪尾随换行符 '\n',这是导致发送给 GCC 的参数截断的原因。

我们可以使用 str.rstrip() 删除尾随的 '\n'。

其次,如图config.log所示,fltk-config提供的参数 SCONS 在将它们提供给 GCC 之前用双引号括起来。我不确定具体细节,但这是因为fltk-config(via os.popen) 的输出包含空格字符。

我们可以使用类似strarray = str.split(" ", str.count(" "))的方法将输出拆分为出现空格字符的子字符串。

还值得注意的是,我们试图将 附加fltk-config --ldflags到 GUI 环境中的错误变量,它们应该被添加到LINKFLAGS.

不幸的是,这只是解决方案的一半。

我们需要做的是:

  • 查找系统上可执行文件的完整路径
  • 将参数传递给可执行文件并捕获其输出
  • 将输出转换为合适的格式以附加到CPPFLAGSand LINKFLAGS

所以我定义了一些函数来帮助......

1)在系统上查找可执行文件的完整路径:( 参见:Test if executable exists in Python?

def ExecutablePath(program):
    def is_exe(fpath):
        return os.path.exists(fpath) and os.access(fpath, os.X_OK)
    fpath, fname = os.path.split(program)
    if fpath:
        if is_exe(program):
            return program
    else:
        for path in os.environ["PATH"].split(os.pathsep):
            exe_file = os.path.join(path, program)
            if is_exe(exe_file):
                return exe_file
    return None

1b)我们还需要测试可执行文件是否存在:

def CheckForExecutable(context, program):
    context.Message( 'Checking for program %s...' %program )
    if ExecutablePath(program):
        context.Result('yes')
    return program
    context.Result('no')

2)将参数传递给可执行文件并将输出放入数组中:

def ExecutableOutputAsArray(program, args):
    pth = ExecutablePath(program)
    pargs = shlex.split('%s %s' %(pth, args))
    progout = subprocess.Popen( pargs , stdout=subprocess.PIPE).communicate()[0]
    flags = progout.rstrip()
    return flags.split(' ', flags.count(" "))

一些用法:

guienv.Append(CPPFLAGS =  ExecutableOutputAsArray('fltk-config', '--cflags') )
guienv.Append(LINKFLAGS = ExecutableOutputAsArray('fltk-config', '--ldflags') )
guienv.Append(LINKFLAGS = ExecutableOutputAsArray('pkg-config', '--libs liblo') )
于 2010-05-31T21:16:30.333 回答
1

有两种类似的方法可以做到这一点:1)

conf = Configure(env)
status, _ = conf.TryAction("fltk-config --cflags")
if status:
  env.ParseConfig("fltk-config --cflags")
else:
  print "Failed fltk"

2)

  try:
    env.ParseConfig("fltk-config --cflags")
  except (OSError):
    print 'failed to run fltk-config you sure fltk is installed !?'
    sys.exit(1)
于 2010-06-04T18:16:30.343 回答