链接命令行太长:在Windows上的scons中链接时如何使用响应文件

时间:2013-03-06 08:17:55

标签: windows linker scons googletest

others类似,我的链接行超出了Windows cmd行限制。对于大多数情况,我们通过使用目标文件的子集构建中间存档(也称为静态库)并使用这些存档执行最终链接来解决问题。但是,在Google Test中使用此策略会导致无法找到测试,特别是在归档的目标文件中定义的测试。

更新:This is why。我可能会使用这种解决方法,但我仍然想了解如何使响应文件在scons下工作。

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

似乎有一个更简单(并且我认为合适)的解决方案:response files,它们也是supported by 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以某种方式导致查找文件的问题

我尝试使用absolute(@C:\ blah \ soft_test.rsp),relative(@。\ 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规则不同,足以引起悲伤。

1 个答案:

答案 0 :(得分:1)

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

最初,我使用了这个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.htestClass.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()函数。 / p>