我使用一些我不想构建的库作为每个使用它们的项目的一部分.一个非常容易理解的例子是LLVM,它有78个静态库.即使使用cmake代码在每个cmakefile中查找和导入这些代码也是过多的.
显而易见的解决方案似乎是使用"include"命令,并将相关的cmake脚本块分解为*.cmake文件,并设置CMAKE_MODULE_PATH环境变量.
除了它只是简单不起作用.Cmake找不到我在include命令中指定的文件.
在off-chance上,我甚至尝试用几种方式在环境变量中指定路径 - 一次使用反斜杠,一次使用正斜杠... - 每次我重新启动命令提示符并检查环境变量是否存在且正确.
在cmake手册中,它暗示"文件"与"模块"不同 - 只有模块才能获得自动添加 - 扩展和搜索路径处理.但没有解释差异是什么.我猜测缺少的扩展可能就足够了(与标准模块一样),但显然不是.
搜索手册中的"模块"并没有多大帮助,因为这个词似乎过载了.例如,模块也是使用LoadLibrary/dl_open加载的动态库.
任何人都可以解释在这个上下文中文件和模块之间的区别,以及我如何创建自己的模块,以便cmake include命令可以找到并使用它?
我在Windows上使用cmake 2.8.1.
编辑
我非常有信心这里的问题不是理解cmake应该如何工作.我认为我应该做的是写一些find_package
可以使用的东西.
事实上,我仍然可以回答我自己的问题.
如果我使用llvm-gcc构建一个静态库,然后将它与使用mingw gcc编译的程序链接,结果是否有效?
对于llvm-gcc,clang和普通gcc的其他组合也是如此.我对如何在Linux(当然使用普通的非mingw gcc)和其他平台上工作感兴趣,但重点是Windows.
我也对所有语言感兴趣,但强调C和C++ - 显然clang不支持Fortran等,但我相信llvm-gcc会这样做.
我假设它们都使用ELF文件格式,但是调用约定,虚拟表格布局等呢?
我目前正在使用cmake来构建一些项目,主要平台是Visual C++,MinGW GCC和Linux GCC.使用GCC构建时,我需要指定-Wno-invalid-offsetof
编译器选项.
我目前的修复方法如下......
if ( "${CMAKE_GENERATOR}" MATCHES "^Visual Studio"
OR "${CMAKE_GENERATOR}" MATCHES "^NMake"
)
set (CPPLIB_COMPILER_OPTS "")
else ()
set (CPPLIB_COMPILER_OPTS "-Wno-invalid-offsetof")
endif ()
...
set_target_properties(sh_core PROPERTIES COMPILE_FLAGS "${CPPLIB_COMPILER_OPTS}")
# repeated for all targets
Run Code Online (Sandbox Code Playgroud)
这是有效的,但假设除了视觉工作室之外的所有生成器都将使用gcc构建,这显然是不安全的.首先,Borland编译器有IIRC发生器.更重要的是,使用make并不总是意味着使用gcc.
我可能使用的其他编译器是llvm-gcc和clang.幸运的是,我认为即使是clang也支持gcc兼容的选项.但只要相关代码永远不会发布,这种逻辑才有用.
Cmake似乎检查了可用的编译器,并专门为该编译器生成一个makefile(提出问题 - 为什么不至少可以选择直接构建项目,而不需要像make这样的中间人?).
既然如此,我希望能够在我的CMakeLists.txt文件中直接测试gcc.但到目前为止,我找不到合适的变量来测试或任何其他明显的解决方案.
这可能吗?
gnu make,microsoft nmake和posix标准有多相似/不同?
显然有"哪个操作系统?","哪个编译器?" 和"哪个链接器?",但我具体指的是makefile本身的语法,语义和命令行选项.
如果我根据gnu make的手册编写makefile,那么我需要注意哪些最重要的可移植性问题?
我刚刚浏览并发现以下内容......
根据惯例,你应该只使用结构用于POD,没有方法等.
我一直认为某些类型是自然结构而不是类,但仍然可以有一些辅助函数作为成员.结构应该仍然是大多数通常规则的POD - 特别是使用memcpy复制必须是安全的.它必须公开所有成员数据.但是,将助手功能作为成员对我来说仍然有意义.我甚至不一定会反对私人方法,尽管我不记得曾经这样做过.虽然它打破了正常的POD规则,但我不反对具有构造函数的结构,只要它们只是初始化 - 少数字段构造函数(重写赋值或析构函数肯定会违反规则).
对我来说,结构直观地是字段的集合 - 数据结构节点或其他 - 而类是抽象.为字段集合提供辅助函数的逻辑位置可能在结构中.
我甚至认为我曾经沿着这些方向阅读过一些建议,尽管我不记得在哪里.
这是否违反公认的最佳做法?
编辑 - POD(普通旧数据)被这个问题误传.特别是,结构可以是非POD纯粹因为成员是非POD - 例如具有std :: string类型成员的聚合.不得使用memcpy复制该聚合.如果有困惑,请看这里.
我正在编译MinGW GCC 4.4.0中的一些c ++代码,并使用以下表单获取警告......
warning: invalid access to non-static data member '<membername>' of NULL object
warning: (perhaps the 'offsetof' macro was used incorrectly)
Run Code Online (Sandbox Code Playgroud)
这个问题似乎很熟悉 - 我想,之前我曾试图解决这个问题,但我想,但不久之前.代码在Visual C++中构建得很好,但我最近没有在任何其他编译器中构建这个特定的代码.
问题代码是以下模板......
template<typename T>
class c_Align_Of
{
private:
struct c_Test
{
char m_Char;
T m_Test;
};
public:
enum { e_Align = offsetof (c_Test, m_Test) };
};
Run Code Online (Sandbox Code Playgroud)
显然,我可以使用一些条件编译来为此使用特定于编译器的函数,我相信C++ 0x(最后)会使它变得多余.但无论如何,我看不出这种用法有什么不妥offsetof
.
非常迂腐,有可能因为T
参数类型有时是非POD,所以GCC类c_Test
作为非POD和抱怨(抱怨和抱怨 - 我得到近800行这些警告).
由于非POD类型可能会破坏,因此标准的严格措辞令人顽皮offsetof
.但是,这种非POD在实践中应该不是问题 - c_Test
不会有虚拟表,也不需要运行时技巧来查找偏移量m_Test
.
此外,即使c_Test
有一个虚拟表,GCC 也会使用内部函数实现offsetof宏,该内部函数总是在编译时根据该特定类型的静态布局进行求值.提供一个工具,然后每次使用时抱怨(抱歉,警告)似乎很愚蠢.
另外,我不是这里唯一一个做这种事的人......
我确实 …
到目前为止,我已经使用了一个简易的单元测试程序 - 基本上整个负载的单元测试程序由批处理文件自动运行.虽然其中很多都明确地检查了他们的结果,但更多的欺骗 - 他们将结果转储到版本化的文本文件.测试结果中的任何更改都会被subversion标记,我可以轻松识别出更改的内容.许多测试输出点文件或其他一些形式,允许我获得输出的直观表示.
麻烦的是我正在转向使用cmake.使用cmake流意味着使用源外构建,这意味着转储在共享源/构建文件夹中的便利性以及将它们与源一起版本化并不真正起作用.
作为替代,有什么我喜欢做的是告诉单元测试工具在哪里可以找到预期的结果(源树)的文件,并得到它做比较.失败时,它应该提供实际结果和差异列表.
这是可能的,还是应该采取完全不同的方法?
显然,我可以忽略ctest,只是调整我一直在做的源外构建.我可以对我的文件夹进行版本控制 - 例如,所有的构建 - 实时(当然,自由使用'忽略').这样理智吗?可能不是,因为每个构建最终会得到预期结果的单独副本.
此外,对cmake/ctest进行单元测试的推荐方法提出了任何建议.我浪费了很多时间与cmake,不是因为它很糟糕,而是因为我不明白如何最好地使用它.
编辑
最后,我决定让单元测试的cmake/ctest方面尽可能简单.为了测试实际的预期结果,我在我的库中找到了以下功能的主页......
bool Check_Results (std::ostream &p_Stream ,
const char *p_Title ,
const char **p_Expected,
const std::ostringstream &p_Actual )
{
std::ostringstream l_Expected_Stream;
while (*p_Expected != 0)
{
l_Expected_Stream << (*p_Expected) << std::endl;
p_Expected++;
}
std::string l_Expected (l_Expected_Stream.str ());
std::string l_Actual (p_Actual.str ());
bool l_Pass = (l_Actual == l_Expected);
p_Stream << "Test: " << p_Title << " : ";
if (l_Pass)
{
p_Stream << …
Run Code Online (Sandbox Code Playgroud) 我再一次质疑一个长期存在的信念.
直到今天,我相信以下结构的对齐通常为4,大小通常为5 ...
struct example
{
int m_Assume_32_Bits;
char m_Assume_8_Bit_Bytes;
};
Run Code Online (Sandbox Code Playgroud)
由于这个假设,我有数据结构代码使用offsetof来确定数组中两个相邻项之间的字节距离.今天,我发现了一些使用sizeof的旧代码,它本不应该,不明白为什么我没有错误,编写单元测试 - 测试让我感到惊讶.
一些调查显示我用于测试的类型的大小(类似于上面的结构)是对齐的精确倍数 - 即8个字节.它在最终成员之后有填充.这是一个为什么我从没想过这个的例子......
struct example2
{
example m_Example;
char m_Why_Cant_This_Be_At_Offset_6_Bytes;
};
Run Code Online (Sandbox Code Playgroud)
一些谷歌搜索显示的例子清楚表明允许最后一个成员之后的填充 - 例如http://en.wikipedia.org/wiki/Data_structure_alignment#Data_structure_padding("或结构的末尾"位) .
这有点令人尴尬,因为我最近发布了这条评论 - 使用struct padding(我对该答案的第一个评论).
我似乎无法确定的是,这个填充到对齐的精确倍数是否由C++标准保证,或者它是否只是允许的内容以及某些(但可能不是全部)编译器.
那么 - 根据C++标准,结构的大小是否需要是该结构对齐的精确倍数?
如果C标准有不同的保证,我也对此感兴趣,但重点是C++.
根据cppreference.com,std::shared_ptr
提供了一整套相对运算符(==,!=,<,...),但未指定比较的语义.我假设他们比较了引用对象的底层原始指针,并且std :: weak_ptr和std :: unique_ptr也是如此.
出于某些目的,我宁愿让相对运算符根据比较引用的对象(而不是指向它们的指针)来对智能指针进行排序.这已经是我做了很多事情,但是我自己的"哑指针"除了相对运算符之外,其行为大部分都像原始指针.我也想用标准的C++ 11智能指针做同样的事情.所以...
是否可以从C++ 11智能指针(shared_ptr,weak_ptr和unique_ptr)继承并覆盖相对运算符?
我需要注意哪些鬼鬼祟祟的问题?例如,我需要实现或使用任何其他方法using
来确保工作正常吗?
对于最终的懒惰,是否有可用的库模板自动执行此操作?
我希望这是"当然你可以做到这一点,白痴!" 有点事,但我有点不确定,因为标准库中有一些类(std::map
至少是容器)你不应该继承.