小编bgo*_*odr的帖子

使用CMake链接来自静态库的Windows DLL文件,而无需手工制作未解析的符号名称

情况

我正在使用Visual Studio 2008 SP1(专业版,适用于32位和64位版本).我正在寻找一种解决方法,我认为这是Visual Studio中一个非常无益的" 限制 ".

我觉得很奇怪,在Visual Studio连接器和编译器不以DLL文件的创建时间这一权利,自动扫描所有导出的符号所有指定的静态库中所示的相同的方式构建一个导入库和导出文件,并在一StackOverflow评论.我确认仅仅在组成静态库的文件中应用__declspec(dllexport)__declspec(dllimport)属性类,函数和数据声明是不够的 .

链接器不扫描导出符号的所有静态库,因此不会将它们拉入DLL文件(符号必须由.objDLL链接命令行上的文件或我在下面显示的其他方式引用).如果没有对每个导出符号的显式引用,仍可能会创建DLL文件,但不会创建其关联的导入库文件.

根据我的收集,Microsoft建议使用LIB.EXE 来创建DEF文件,但不幸的是,LIB.EXE页面应用了一个约束:

请注意,如果您在创建导入库之前创建导入库,则在构建导入库时,必须在构建导入库时.dll传递相同的目标文件集.dll.

鉴于我在新的构建环境中也使用了CMake,这是一个不幸的约束.CMake隐藏了实际传递给链接器的细节(我认为这在99%的时间里都是好事),但在这种情况下我需要在CMake执行时访问一些信息,而不是然后使用手工制作的脚本或其他脆弱的skulduggery.

问题:

如何强制DLL链接器解析构成DLL文件的所有静态库中的所有导出符号,这不会导致脆弱性和额外的构建逻辑维护工作?在这里考虑全自动化,并记住我需要多次为多个不同的DLL执行此操作.

我的问题是:

  1. 如何仅使用CMake语法获取最终DLL链接命令行上使用的目标文件和静态库集?

  2. LIB.EXE行(用于生成DEF文件的那个)上列出的文件的顺序是否必须与DLL链接行上使用的顺序完全匹配?

  3. 使用LIB.EXE方法生成DEF文件可能会遇到其他困难吗?

  4. 有没有更好的方法来解决这个问题,调用最终链接之前不需要调用单独的实用程序,例如LIB.EXE ?我担心LIB.EXE链接本身之外的额外构建开销会再次重新扫描所有静态库 ,即使它只是在单独的执行中写出来.

非答案:

以下是我现在无法考虑的解决方案:

  1. 在原始文件.h.cpp文件之外的任何地方手动指定未引用的符号,因为每次开发人员忘记更新列出(很可能是名称错位的)符号名称的文件时,这样做会中断.并且它将打破关于未解析符号的非用户友好链接器错误,这对于开发人员来说将是昂贵的调试.这个非答案包括以下方法:

    1. 明确地将.obj文件添加到DLL链接命令行中(其中的变体包括添加"假" .obj文件,这些文件具有对未引用但导出的符号的虚拟引用(并注意这是我的旧构建环境今天所做的,并且它很臭) ),和,

    2. 手工制作DEF文件以包含未引用但导出的符号,以及 …

linker cmake static-libraries visual-studio-2008-sp1

26
推荐指数
1
解决办法
6111
查看次数

在Visual Studio 2008速成版(VS2008EE)中配置64位编译

我试图在IDE和命令行中在Visual Studio 2008 Express Edition Service Pack 1(之后安装了一些相关的Windows SDK)下构建64位本机C++应用程序.这是在Windows XP Professional x64 Edition版本2003 Service Pack 2计算机上.

我知道专业版可能提供真正的VS IDE集成,但我特别希望在Visual Studio 2008 Express Edition中实现这一点.

但是,我在Visual Studio 2008 Express IDE的项目配置中遇到了一些麻烦,我希望有人可以回答可能出现的问题.关键目标是能够从IDE本身以及命令行中通过执行vcvarsall.bat类似批处理文件或类似批处理文件来构建64位本机应用程序.

这是我到目前为止尝试的内容:

我安装了带有SP1的Visual Studio 2008 Express Editions,它安装了某种类型的SDK,但我认为不是包含64位编译器的正确版本(但当时并不知道它).

我构建了一个hello world Win32 Console应用程序,并查看为可执行文件生成的清单文件.我在清单文件中找到了"x86",这不是64位AFAICT,所以我做了更多研究.

我发现Visual Studio 2008 Express Edition中什么"缺失"?.我看到了一些回复,其中一个回复中有一个缺少功能的列表,其中包含"64位Visual C++工具"作为缺少的功能之一.

但是,在维基百科条目中,我们看到:

可以将64位编译器真正集成到Visual C++ 2008 Express Edition中,但仍然很麻烦.9

所以,我尝试了上面给出的9个链接中的指令.该链接实际上是指如何:将Visual C++项目配置为目标64位平台.我浏览了该页面上的各个步骤,但他们指示您执行以下操作:

单击"类型"或选择新平台下拉箭头,然后选择64位平台.

但下拉列表中没有条目.

我再次提到维基百科上的SDK页面,特别是64位开发部分,其中指出:

最近发布的适用于Windows Server 2008和.NET …

64-bit visual-studio-2008-sp1 visual-studio

14
推荐指数
1
解决办法
2万
查看次数

开源C++扫描库

理由:在我的日常C++代码开发中,我经常需要回答一些基本问题,例如谁在一个经常变化的非常大的C++代码库中调用了什么.但是,我还需要有一些自动方法来准确识别代码在特定代码区域内所做的工作.诸如Cscope之类的"grep"工具很有用(我已经大量使用它们),但不是C++ - 语言感知:它们没有任何方法来识别给定类型的词汇环境的类型和种类或者以一种有利于自动化的方式运行(即使所述自动化仅限于"只读"操作,例如代码浏览和导航,但我要求的不仅仅是下面的内容).

问题:是否已存在基于C/C++的开源库(本机,非托管,非Microsoft或Linux特定),可以静态扫描或分析大型C++代码树,并且可以生成可回答的结果集详细问题如:

  • 某些提供的函数调用了哪些函数?
  • 哪些功能使用这种提供的类型?
  • 如果涉及C++类或类模板,请同样考虑上述问题.

结果集应该提供某种"句柄".我应该能够将该句柄反馈给库以执行以下类型的内省:

  • 进行引用的文件中的字节偏移量是多少?
  • 对该引用的抽象语法树(AST)的引用是什么,以便我可以检查周围的代码构造?并且每个AST实体还具有与之关联的文件路径,字节偏移和类型信息数据,因此我可以递归地向上走调用者或引用者的图形以执行有用的操作.

答案应符合以下要求:

  • API:公开的API必须是以下之一:
    • C或C++,可能是"C句柄"或C++ - 基于类的实例(如果是,必须是通用的C o C++代码,而不是Microsoft或Linux特定的代码构造,除非它是满足给定的细节平台),或
    • 命令行标准输入和标准输出.
  • C++意识:不仅限于C代码,而是以细微的细节理解C++语言结构,包括对类间继承关系和C++模板的了解.
  • 快速:扫描大型代码库比从头开始编译整个代码库要快得多.这可能需要放宽,但只有在下面完全满足增量结果检索小型代码更改要求的弹性时.
  • 提供结果计数:我应该能够问"你会为一些请求提供多少结果(并且不会向我发送所有结果)?" 响应的次数少于3秒,而不必检索任何给定问题的所有结果.如果得到答案需要太长时间,那么就浪费了开发时间.这与下一个要求相结合.
  • 增量结果检索:我应该能够然后问"给我这个请求的下一个N个结果",然后是结果集的句柄,这样我就可以反复提出问题,从而逐步提取结果.这意味着在查看所有结果的某个子集之前,我不必等待整个结果集.如果我看到足够的结果,我可以安全地取消操作.原因:我需要回答这个问题:"更改某些特定功能签名会对构建或开发产生什么影响?"
  • 适应小代码更改:如果我更改标头或源文件,我不必等待重新扫描整个代码库,而只重新扫描该标头或源文件.重新扫描应该很快.例如,不要执行cscope要求您执行的操作,即重新扫描整个代码库以进行小的更改.可以理解,如果更改标题,则扫描可能需要更长时间,因为必须重新扫描包含该标题的其他文件.
  • IDE不可知:文本编辑器是不可知的(不要让我使用特定的文本编辑器;我已经做出了我的选择,谢谢!)
  • 平台不可知:与平台无关(不要让我只在Linux上使用它或仅在Windows上使用它,因为我必须在我的日常工作中使用这两个平台,但我需要这个工具对我们两个都有用两个平台上的代码沙箱).
  • 非二进制:除了下载和编译库及其所有依赖项的时间之外,我不应该花费任何其他成本.
  • 不是试用品.
  • 积极支持:向邮件列表或相关论坛发送帮助请求可能会在不到2天的时间内得到响应.
  • 网络不可知:库构建的数据库应该能够在32位和64位系统上直接在网络上使用,同时可以互换Linux和Windows,并且不会将硬编码路径嵌入文件系统,否则" root"数据库到特定网络.
  • 构建环境不可知:不需要对我的构建环境有深入了解,但可能需要了解编译器提供的CPP宏定义(例如-Dmacro = value).

c++ static automation analysis

10
推荐指数
1
解决办法
1553
查看次数

使用CMake 2.8.x使用VS2008 SP1将多个静态.lib文件链接到一个单片.lib文件中

使用cmake将目标文件链接到lib.xxxx.a文件相关,但不完全相同,我使用CMake 2.8.x使用VS2008 SP1在Windows上构建了几个静态库.有没有办法通过CMake单独将所有现有静态库中的所有.obj文件重新链接到一个更大的单片库中,最好是通过add_libraryCMake函数或其他类似的构造?

我认为答案是"不",因此我考虑通过常规add_custom_command+ add_custom_target方法通过自定义命令滚动自己,通过在调用时提供所有其他库.obj文件,只需手动构建库LINK.EXE.但我发现这种方法存在一些问题:

  1. 我找不到一个CMake变量来指示LINK.EXE可执行文件的完全限定路径.然后,我必须以某种方式推导出LINK.EXE使用脆弱启发式的路径:在不同的Visual Studio版本可能将LINK.EXE文件定位在不同目录中的意义上它是脆弱的,我需要这个工作用于32位和64位位Windows编译器条件,并且能够抵御VS2008与未来编译器修订版之间的升级.
  2. 我必须找到一种方法来查找其他静态库的所有.obj文件,在构建时在CMake时,因为在CMake时,.obj文件当然不存在(总是).出于构建性能的原因,我希望不要从.lib文件中提取.obj文件LINK.EXE,以便将它们添加到命令行,因此FILE(GLOB...)在这种情况下,构造将是我最好的第二种选择.
  3. 也许可以简单地LINK.EXE通过:来调用LINK.EXE /OUT:monolithic.lib lib1.lib lib2.lib ...,但也许并不是所有的.obj都会被包括在内(编辑:我已经确认LINK.EXE省略了一些.obj文件lib1.lib lib2.lib ...而没有任何诊断消息解释原因,所以这种方法是非首发的); 关于LINK.EXE这一点,在线文档尚不清楚.有没有LINK.EXE以这种方式使用的经验?

谢谢,

黑雁

PS,我知道如何使用CMake创建DLL,但我特别不想在此时构建DLL.

linker cmake static-libraries

7
推荐指数
1
解决办法
5672
查看次数

如何使用 conda MatchSpec?

如何列出 conda 可用的软件包版本有一些有用的答案,其中之一在/sf/answers/3345709041/使用两个等号。 conda search -h没有完全说明 MatchSpec 语法允许的内容,只给出了一些简单的例子。

例如,我想查看最新版本的python 下存在哪些包,对于一个名为jedi. 我不得不求助于实验和猜测来找到正确的语法,因为上面缺少 MatchSpec 语法的详细文档。我结束了:

$ condaw search 'jedi[build=py37*]' --json | grep '"build"' 
      "build": "py37_1",
      "build": "py37_0",
      "build": "py37_0",
      "build": "py37_0",
      "build": "py37_0",
$ 
Run Code Online (Sandbox Code Playgroud)

使用上面的--json选项只是为了让我可以找出哪些关键字(例如)build可能是语法的一部分。

那么,MatchSpec 语法在哪里有正式和完整的文档,这样我就不必猜测了?我现在得出的结论是-h输出是唯一的。

conda

7
推荐指数
1
解决办法
468
查看次数

Emacs org-mode - 如何在不挂起Emacs的情况下使用后台进程运行shell脚本

将其添加到emacs .org文件中:

#+BEGIN_SRC sh :results verbatim
  #!/bin/bash

  exec 2>&1  # <-- Because Emacs treats stderr output as an error and doesn't show it in the RESULT

  echo before 

  # This nohup should just run in the background and continue to exit
  # the script, but emacs hangs and waits on it anyhow:
  nohup sleep 10 &

  # Failed attempts at working around the hang are:
  #   setsid nohup sleep 10 &
  #   nohup sleep 10 </dev/null & 

  # Do see …
Run Code Online (Sandbox Code Playgroud)

emacs hang background-process org-mode

6
推荐指数
1
解决办法
1506
查看次数

如何使用Bash运行前台子进程可靠地使用陷阱

我有一个Bash脚本,它在前台运行一个长时间运行的进程.当它收到SIGQUIT信号时,它应该执行各种清理操作,例如查杀自身及其所有子进程(通过杀死进程组等).应该捕获信号的最小脚本如下所示(称为test_trap.sh):

#!/bin/bash

trap 'echo "TRAP CAUGHT"; exit 1' QUIT  # other required signals are omitted for brevity

echo starting sleep
sleep 11666
echo ending sleep

echo done
Run Code Online (Sandbox Code Playgroud)

我想将SIGHUP信号发送到test_trap.sh脚本的进程.但是,向该SIGHUP发送test_trap.sh不会触发陷阱表达式,但只有当我将信号发送到子sleep 11666进程时才会触发陷阱.下面是一个bash会话,展示了这一点:

bash-4.1$ test_trap.sh &
[1] 19633
bash-4.1$ starting sleep

bash-4.1$ kill -s SIGQUIT 19633
bash-4.1$ jobs
[1]+  Running                 test_trap.sh &
bash-4.1$ ps -ef --forest --cols=10000 | grep '11666\|test_trap.sh' | grep -v grep
theuser   19633 12227  0 07:40 pts/4    00:00:00              \_ /bin/bash ./test_trap.sh
theuser   19634 …
Run Code Online (Sandbox Code Playgroud)

bash

6
推荐指数
1
解决办法
1292
查看次数

强制GCC 4.x将-Wreturn-type视为错误而不启用-Werror?

假设我们有以下代码:

#if !defined(__cplusplus)
#  error This file should be compiled as C++
#endif

#include <stdio.h>
#include <string>

//#define USE_CXX_CLASS
#ifdef USE_CXX_CLASS
class SomeClass
{
public:
    SomeClass() {}
    ~SomeClass() {}
    std::string GetSomeString()
    {
        // case #1
    }
};
#endif // USE_CXX_CLASS

int foo()
{
    // case #2
}

int
main (int argc, char *argv[])
{
    (void)argc;
    (void)argv;
#ifdef USE_CXX_CLASS
    SomeClass someInstance;
    someInstance.GetSomeString();
#endif // USE_CXX_CLASS
    foo();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

并且假设它是使用选项从GCC版本4.2.1编译C++编译器(而不是C编译器)-Wreturn-type -Werror=return-type.如果上面的代码是按原样编译而没有先取消//#define USE_CXX_CLASS上面的行,那么你会看到一个警告但没有错误:

.../gcc-4.2.1/bin/g++   -g    -fPIC …
Run Code Online (Sandbox Code Playgroud)

c++ gcc return-value gcc-warning gcc4

5
推荐指数
1
解决办法
1771
查看次数

将双重类型传递给ceil会导致GCC中不同优化级别的值不同

下面,result1和result2变量值报告不同的值,具体取决于您是使用-g还是使用-O在GCC 4.2.1和GCC 3.2.0上编译代码(我还没有尝试过更新的GCC版本) :

double double_identity(double in_double)
{
    return in_double;
}

...

double result1 = ceil(log(32.0) / log(2.0));
std::cout << __FILE__ << ":" << __LINE__ << ":" << "result1==" << result1 << std::endl;

double result2 = ceil(double_identity(log(32.0) / log(2.0)));
std::cout << __FILE__ << ":" << __LINE__ << ":" << "result2==" << result2 << std::endl;
Run Code Online (Sandbox Code Playgroud)

result1和result2 == 5仅在使用-g进行编译时,但如果使用-OI进行编译,则得到result1 == 6和result2 == 5.

这似乎与编译器完成优化的方式不同,或者内部与IEEE浮点表示有关,但我很好奇这种差异究竟是如何发生的.我希望尽可能避免看汇编程序.

以上是用C++编译的,但我认为如果使用printfs将其转换为ANSI-C代码,则会保持相同.

上述差异发生在32位Linux上,但不适用于64位Linux.

谢谢bg

c c++ math logarithm compiler-optimization

3
推荐指数
1
解决办法
250
查看次数

为什么 Rust 要求宏名称末尾有感叹号?

为什么 Rust 编程语言的设计者要求宏名称必须以感叹号结尾?

请注意,我并不是说这种设计选择是错误的。我只是好奇。

rust

2
推荐指数
1
解决办法
608
查看次数

如何在不编写额外代码的情况下使用 Python 将“-”(破折号)作为标准输入读取?

使用 Python 3.5.x,没有比这更高的版本。

/sf/answers/2117818601/是正确的答案,但没有提供内置于 Python 的解决方案,而是需要从头开始编写代码:

我需要一个值为“-”的字符串来表示标准输入,或者它的值是我想要读取的文本文件的路径。我想使用with运算符打开这些文件中的任何一种,而不使用条件逻辑来检查脚本中的“-”。我有一些有用的东西,但它似乎应该是内置在 Python 核心中的东西,而不需要我推出自己的上下文管理器,如下所示:

from contextlib import contextmanager

@contextmanager
def read_text_file_or_stdin(path):
    """Return a file object from stdin if path is '-', else read from path as a text file."""
    if path == '-':
        with open(0) as f:
            yield f
    else:
        with open(path, 'r') as f:
            yield f


# path = '-'  # Means read from stdin
path = '/tmp/paths'  # Means read from a text file given by this value
with read_text_file_or_stdin(path) …
Run Code Online (Sandbox Code Playgroud)

python stdin contextmanager

1
推荐指数
1
解决办法
855
查看次数