3

其他人一样,我有一个超过 Windows cmd 行限制的链接行。对于大多数情况,我们通过使用目标文件的子集构建中间档案(又名静态库)并执行与这些档案的最终链接来解决问题。但是,在 Google Test 中使用此策略会导致无法找到测试,特别是在已归档的目标文件中定义的测试。

更新:这就是为什么. 我可能会使用这种解决方法,但我仍然想了解如何使响应文件在 scons 下工作。

LongCmdLinesOnWin32修复存在问题。我们有一个 cygwin 环境和包含空格的路径名,因此一些编译器绝对路径包含引号。LongCmdLinesOnWin32 中的脚本首先需要扩展以处理嵌入的引号和空格(否则它会创建单个路径名的单独标记)。更严重的是,当使用 MS Visual Studio 时,编译器命令只是“cl”,即不包括路径名。这在 PATH 环境中不可用 - 它似乎是动态设置的(以某种方式)并且在构造 LongCmdLinesOnWin32 脚本的 cmdline 参数时不可见。但我离题了......

似乎有一个更简单(在我看来也很合适)的解决方案:response files,它也受 gcc 支持

我写了一个小函数来获取对象名称列表并将它们打印到一个文本文件,一个到一行,例如:

"""
  In place for generating response files
"""
def gen_response_file(filename,file_list):
    with open(filename,"w") as f:
        for obj_name in file_list:
            f.write ('%s\n' %os.path.abspath(str(obj_name)).replace('\\','/'))
    return filename

然后我尝试在文件名前添加“@”字符并将其添加到选项列表中。

回显的命令行是:

link /nologo /MACHINE:x86 /DEBUG @E:\dev\pcoip_view_client\soft_test.rsp /OUT:blah_client\blah_client_tests.exe /LIBPATH:\\sterbkp03\qt\4.8.2\lib ....

如果我只是将文件命名为“soft_test”,那么 scons 会添加后缀“.obj”而链接器找不到它,所以我尝试添加后缀“.rsp”。现在,链接器抱怨它找不到文件,但它存在。我捕获了 scons 的输出并将其粘贴到 bat 文件中。当我运行 bat 文件(来自 VS 2008 命令行环境)时,链接就像一个魅力,所以看起来 scons 以某种方式导致了查找文件的问题

我尝试使用绝对 (@C:\blah\soft_test.rsp)、相对 (@.\soft_test.rsp) 和 @soft_test.rsp 更改路径,但它们都不起作用。

LINK : fatal error LNK1104: cannot open file '@E:\dev\swift.dev\blah_client\soft_test.rsp'
scons: *** [blah_client\blah_client_tests.exe] Error 1104

我在 Windows 7-64 下使用 scons v2.1.0.r5357、VS 2008 和 python 2.7

我的 scons 文件如下所示:

test_objects = tenv.Object(test_sources)
xx = gen_response_file('soft_test.rsp',test_objects)
tenv.Append( LINKFLAGS = [ '@%s' % os.path.abspath(xx)]) # 
test_exe = tenv.Program(target = 'blah_client_tests', source = objects + moc_objects + qrc_objects )

任何建议都非常感谢。

更新:我用 gcc 试过,没有问题。我的猜测是,与 Visual Studio 工具相关的 scons 规则以某种方式不同,足以引起悲伤。

4

1 回答 1

1

我尝试使用 gcc 在 Linux 中重现此问题,但遇到了一个不同的问题,其解决方案可能会有所帮助。

最初,我使用了这个 SConscript:

import os

"""
  In place for generating response files
"""
def gen_response_file(filename,file_list):
    with open(filename,"w") as f:
        for obj_name in file_list:
            f.write ('%s\n' %os.path.abspath(str(obj_name)).replace('\\','/'))
    return filename

env = Environment()

test_objects = env.Object(target = 'testClass', source = 'testClass.cc')

resp_file = gen_response_file('response_file.rsp', test_objects)

env.Append(LINKFLAGS = [ '@%s' % os.path.abspath(resp_file)])
env.Program(target = 'helloWorld', source = 'helloWorld.cc')

以下是我使用的相关源文件:

# tree .
.
|-- SConstruct
|-- helloWorld.cc
|-- testClass.cc
`-- testClass.h

helloWorld.cc主程序在哪里。helloWorld.cc包含testClass.h和链接testClass.o当我尝试编译它时,响应文件已正确生成(仅包含/some/path/testClass.o)并由编译器读取。我遇到的问题testClass.o是没有编译,因为 SCons 似乎无法识别响应文件中列出的对象的依赖关系。结果如下:

# scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o helloWorld.o -c helloWorld.cc
g++ -o helloWorld @/some/path/response_file.rsp helloWorld.o
g++: /some/path/testClass.o: No such file or directory
scons: *** [helloWorld] Error 1
scons: building terminated because of errors.

这似乎是 SCons 的失败,因为它不分析响应文件。为了解决这个问题,我不得不使用Depends()以下摘录中的函数:

...
bin = env.Program(target = 'helloWorld', source = 'helloWorld.cc')
env.Depends(bin, test_objects)

这有效并给了我以下信息:

# scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o helloWorld.o -c helloWorld.cc
g++ -o testClass.o -c testClass.cc
g++ -o helloWorld @/some/path/response_file.rsp helloWorld.o
scons: done building targets.

我知道这并不能回答关于为什么找不到响应文件的原始问题,但是一旦你解决了这个问题,你很可能会遇到上面提到的问题,并且必须使用该Depends()功能。

于 2013-03-07T07:36:58.987 回答