每个 CTest 可执行文件有几 MB - 我如何使它们更小?
Each CTest executable is several MB - how do I make them smaller?
我有一堆单元测试想从 Visual Studio 的测试框架迁移到更容易访问的东西。我开始将一些移动到 ctest,其中(据我了解)每个测试都需要编译为单独的可执行文件。
我的 cmakelists.txt 看起来像:
cmake_minimum_required(VERSION 3.10)
project(UnitTests)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_MACOSX_RPATH 1)
include(CTest)
enable_testing()
add_executable(Test1 Test1.cpp)
add_executable(Test2 Test2.cpp)
add_test(First Test1)
add_test(Second Test2)
问题是 Test1 和 Test2 分别编译为 2.7 和 2.6 MB 的文件。这是因为每个人都必须有 #include "BigClass.h"
,其中 BigClass
是我真正想要测试的庞大而庞大的项目。
我可能有几十个测试要迁移,所以编译 运行 所有这些测试可能 运行 成数百兆字节的可执行文件,其中大部分 space 只是重复 BigClass
!
中的所有代码
我试图将此 class 作为一个库包括在内:
add_library(BigClass SHARED ../path/to/BigClass.cpp)
然后在文件末尾:
target_link_libraries(Test1 PUBLIC BigClass)
但这并没有影响space。
我想我想要的是一种动态 link 到 BigClass
的方法(反正已经编译好了),所以所有的测试都可以共享代码。但我不确定如何执行此操作,也不太确定如何搜索它(例如,动态搜索 linked #include
表明这实际上是不可能的)。
无论如何都可以帮我找到:
- 一个避免所有这些问题的跨平台 C++ 测试框架?
- 一种在 ctest 中编译单元测试以共享大量相同代码的方法?
- 有关如何 link C++ class 动态执行的说明?
- a cross-platform C++ testing framework that avoids all these problems?
忽略代码建议 off-topic…
我们正在使用 catch2,对此我很满意。
- a way to compile unit tests in ctest to share a lot of the same code?
测试还有其他应用。所以,下一个问题的答案应该包括这个。
- directions on how to link C++ classes dynamically?
我制作了一篇 MCVE,试图涵盖整个故事。做好准备……
当代码被写入成为 DLL 的一部分时,它必须导出所有符号,这些符号将在其他 DLL 或可执行文件中可见。其他 DLL 和可执行文件必须依次导入这些符号。微软提供了这个主题的一般介绍:dllexport, dllimport.
有一个常用的宏技巧来确保可以在 DLL 内部(需要 dllexport
)和 DLL 外部(需要 dllimport
)使用相同的 headers需要)。
这在 BigClass.h
中得到了证明:
#ifndef BIG_CLASS_H
#define BIG_CLASS_H
/* A macro trickery to provide export and import prefixes
* platform dependent for Windows and Linux.
*/
#ifdef _WIN32
// for Windows, Visual C++
#define DLL_EXPORT __declspec(dllexport)
#define DLL_IMPORT __declspec(dllimport)
#else // (not) _WIN32
// for gcc
#define DLL_EXPORT __attribute__((visibility("default")))
#define DLL_IMPORT __attribute__((visibility("default")))
#endif // _WIN32
/* The macro trickery to define how exported symbols shall
* be included.
*/
#ifdef BIG_CLASS_STATIC
#define BIG_CLASS_API
#else // (not) BIG_CLASS_STATIC
#ifdef BUILD_BIG_CLASS
#define BIG_CLASS_API DLL_EXPORT
#else // (not) BUILD_BIG_CLASS
#define BIG_CLASS_API DLL_IMPORT
#endif // BUILD_BIG_CLASS
#endif // BIG_CLASS_STATIC
// the library interface
#include <iostream>
struct BigClass {
const int id = 0;
// inline constructors doesn't need an export guard
BigClass() = default;
// non-inline constructors need an export guard
BIG_CLASS_API BigClass(int id);
// non-inline functins as well
BIG_CLASS_API void print() const;
// no export guard for inline member functions
void printLn() const
{
print();
std::cout << std::endl;
}
};
// functions need to be exported
extern BIG_CLASS_API void print(const BigClass&);
// inline functions don't need to be exported
inline void printLn(const BigClass& big)
{
big.printLn();
}
#endif // BIG_CLASS_H
从而引入第一个宏DLL_EXPORT
和DLL_IMPORT
来隐藏Windows(Visual Studio)和Linux(g++ ).
这些定义可以在多个库中共享。
第二组宏是特定于库的——因此,所有宏中的前缀 BIG_CLASS_
。
BIG_CLASS_STATIC
是一个宏,当(且仅当)库被构建为静态库时,它应该被定义为编译器的参数。如果必须将静态库 link 编辑为可执行文件,也必须对其进行定义。
BUILD_BIG_CLASS
是一个宏,如果(且仅当)库被构建并且 link 编辑为 DLL(或共享 object 在 Linux).
这两个宏都被认为是准备第三个宏BIG_CLASS_API
,扩展为
- 没有静态库
DLL_EXPORT
如果构建了DLL
DLL_IMPORT
如果构建了任何其他旨在使用和 link DLL 的内容。
对应BigClass.cc
:
#include "BigClass.h"
BigClass::BigClass(int id): id(id) { }
void BigClass::print() const
{
std::cout << "BigClass::print(): *this: BigClass { id: " << id << " }";
}
void print(const BigClass& big)
{
std::cout << "print(): "; big.print();
}
没什么特别的。
BigClass.h
和 BigClass.cc
将用于构建示例 BigClass.dll
。
此外,两个测试应用程序 Test1
和 Test2
应 link 编辑 BigClass.dll
。
Test1.cc
:
#include <iostream>
#include <BigClass.h>
#define TEST(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
std::cout
<< "Test1:\n"
<< "======\n";
TEST(BigClass big);
TEST(big.print());
std::cout << '\n';
TEST(big.printLn());
TEST(BigClass big1(1));
TEST(big1.print());
std::cout << '\n';
TEST(big1.printLn());
std::cout << "Done." << std::endl;
}
Test2.cc
:
#include <iostream>
#include <BigClass.h>
#define TEST(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
std::cout
<< "Test2:\n"
<< "======\n";
TEST(BigClass big);
TEST(print(big));
std::cout << '\n';
TEST(printLn(big));
TEST(BigClass big2(2));
TEST(print(big2));
std::cout << '\n';
TEST(printLn(big2));
std::cout << "Done." << std::endl;
}
同样,它们没有什么特别之处。
免责声明:宏TEST()
与单元测试无关。这只是一种演示摆弄。
最后,CMakeLists.txt
将所有内容放在一起(例如在 VS 解决方案中 BigClassDLL.sln
):
project (BigClassDLL)
cmake_minimum_required(VERSION 3.10.0)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if (MSVC)
# Unfortunately neither
# CMAKE_CXX_STANDARD_REQUIRED ON
# nor
# CMAKE_CXX_EXTENSIONS OFF
# force the /permissive- option
# which makes MSVC standard conform.
add_compile_options(/permissive-)
endif()
# enable shared libraries (aka. DLLs)
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
include_directories("${CMAKE_SOURCE_DIR}")
# build the library
add_library(BigClass
BigClass.cc BigClass.h)
set_target_properties(BigClass
PROPERTIES
PROJECT_LABEL "Big Class DLL"
DEFINE_SYMBOL BUILD_BIG_CLASS)
if (NOT BUILD_SHARED_LIBS)
target_compile_definitions(BigClass PUBLIC BIG_CLASS_STATIC)
endif()
# build the tests
add_executable(Test1 Test1.cc)
target_link_libraries(Test1 BigClass)
add_executable(Test2 Test2.cc)
target_link_libraries(Test2 BigClass)
关于动态 linking:
有一些具体的事情
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
这在 CMake: Step 9: Selecting Static or Shared Libraries.
中有解释
set_target_properties(BigClass PROPERTIES DEFINE_SYMBOL BUILD_BIG_CLASS)
这确保宏 BUILD_BIG_CLASS
将在构建库 BigClass
时在编译器的命令行中专门定义。
-
if (NOT BUILD_SHARED_LIBS)
target_compile_definitions(BigClass PUBLIC BIG_CLASS_STATIC)
endif()
宏 BIG_CLASS_STATIC
将在构建或使用库 BigClass
的每个编译器命令行中定义。
免责声明: 我知道 CMakeLists.txt
用于多个项目被认为是糟糕的风格。对于一个严肃的项目,库当然应该驻留在自己的目录中,并带有自己的 CMakeLists.txt
文件。我把它放在一起是为了尽可能地减少它(也是因为我可以)。
2019 年 Visual Studio 的情况:
2019 年 Visual Studio 的构建工件:
运行 Test1.exe
:
Test1:
======
BigClass big;
big.print();
BigClass::print(): *this: BigClass { id: 0 }
big.printLn();
BigClass::print(): *this: BigClass { id: 0 }
BigClass big1(1);
big1.print();
BigClass::print(): *this: BigClass { id: 1 }
big1.printLn();
BigClass::print(): *this: BigClass { id: 1 }
Done.
运行 Test2.exe
:
Test2:
======
BigClass big;
print(big);
print(): BigClass::print(): *this: BigClass { id: 0 }
printLn(big);
BigClass::print(): *this: BigClass { id: 0 }
BigClass big2(2);
print(big2);
print(): BigClass::print(): *this: BigClass { id: 2 }
printLn(big2);
BigClass::print(): *this: BigClass { id: 2 }
Done.
最后(为了解决可移植性问题),我在 Linux:
中构建了相同的 CMake 项目
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll$ mkdir build-Linux
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll$ cd build-Linux
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll/build-Linux$ ccmake ..
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll/build-Linux$ cmake --build .
Scanning dependencies of target BigClass
[ 16%] Building CXX object CMakeFiles/BigClass.dir/BigClass.cc.o
[ 33%] Linking CXX shared library libBigClass.so
[ 33%] Built target BigClass
Scanning dependencies of target Test2
[ 50%] Building CXX object CMakeFiles/Test2.dir/Test2.cc.o
[ 66%] Linking CXX executable Test2
[ 66%] Built target Test2
Scanning dependencies of target Test1
[ 83%] Building CXX object CMakeFiles/Test1.dir/Test1.cc.o
[100%] Linking CXX executable Test1
[100%] Built target Test1
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll/build-Linux$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake libBigClass.so Makefile Test1 Test2
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll/build-Linux$ ./Test1
Test1:
======
BigClass big;
big.print();
BigClass::print(): *this: BigClass { id: 0 }
big.printLn();
BigClass::print(): *this: BigClass { id: 0 }
BigClass big1(1);
big1.print();
BigClass::print(): *this: BigClass { id: 1 }
big1.printLn();
BigClass::print(): *this: BigClass { id: 1 }
Done.
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll/build-Linux$ ./Test2
Test2:
======
BigClass big;
print(big);
print(): BigClass::print(): *this: BigClass { id: 0 }
printLn(big);
BigClass::print(): *this: BigClass { id: 0 }
BigClass big2(2);
print(big2);
print(): BigClass::print(): *this: BigClass { id: 2 }
printLn(big2);
BigClass::print(): *this: BigClass { id: 2 }
Done.
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll/build-Linux$
我有一堆单元测试想从 Visual Studio 的测试框架迁移到更容易访问的东西。我开始将一些移动到 ctest,其中(据我了解)每个测试都需要编译为单独的可执行文件。
我的 cmakelists.txt 看起来像:
cmake_minimum_required(VERSION 3.10)
project(UnitTests)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_MACOSX_RPATH 1)
include(CTest)
enable_testing()
add_executable(Test1 Test1.cpp)
add_executable(Test2 Test2.cpp)
add_test(First Test1)
add_test(Second Test2)
问题是 Test1 和 Test2 分别编译为 2.7 和 2.6 MB 的文件。这是因为每个人都必须有 #include "BigClass.h"
,其中 BigClass
是我真正想要测试的庞大而庞大的项目。
我可能有几十个测试要迁移,所以编译 运行 所有这些测试可能 运行 成数百兆字节的可执行文件,其中大部分 space 只是重复 BigClass
!
我试图将此 class 作为一个库包括在内:
add_library(BigClass SHARED ../path/to/BigClass.cpp)
然后在文件末尾:
target_link_libraries(Test1 PUBLIC BigClass)
但这并没有影响space。
我想我想要的是一种动态 link 到 BigClass
的方法(反正已经编译好了),所以所有的测试都可以共享代码。但我不确定如何执行此操作,也不太确定如何搜索它(例如,动态搜索 linked #include
表明这实际上是不可能的)。
无论如何都可以帮我找到:
- 一个避免所有这些问题的跨平台 C++ 测试框架?
- 一种在 ctest 中编译单元测试以共享大量相同代码的方法?
- 有关如何 link C++ class 动态执行的说明?
- a cross-platform C++ testing framework that avoids all these problems?
忽略代码建议 off-topic…
我们正在使用 catch2,对此我很满意。
- a way to compile unit tests in ctest to share a lot of the same code?
测试还有其他应用。所以,下一个问题的答案应该包括这个。
- directions on how to link C++ classes dynamically?
我制作了一篇 MCVE,试图涵盖整个故事。做好准备……
当代码被写入成为 DLL 的一部分时,它必须导出所有符号,这些符号将在其他 DLL 或可执行文件中可见。其他 DLL 和可执行文件必须依次导入这些符号。微软提供了这个主题的一般介绍:dllexport, dllimport.
有一个常用的宏技巧来确保可以在 DLL 内部(需要 dllexport
)和 DLL 外部(需要 dllimport
)使用相同的 headers需要)。
这在 BigClass.h
中得到了证明:
#ifndef BIG_CLASS_H
#define BIG_CLASS_H
/* A macro trickery to provide export and import prefixes
* platform dependent for Windows and Linux.
*/
#ifdef _WIN32
// for Windows, Visual C++
#define DLL_EXPORT __declspec(dllexport)
#define DLL_IMPORT __declspec(dllimport)
#else // (not) _WIN32
// for gcc
#define DLL_EXPORT __attribute__((visibility("default")))
#define DLL_IMPORT __attribute__((visibility("default")))
#endif // _WIN32
/* The macro trickery to define how exported symbols shall
* be included.
*/
#ifdef BIG_CLASS_STATIC
#define BIG_CLASS_API
#else // (not) BIG_CLASS_STATIC
#ifdef BUILD_BIG_CLASS
#define BIG_CLASS_API DLL_EXPORT
#else // (not) BUILD_BIG_CLASS
#define BIG_CLASS_API DLL_IMPORT
#endif // BUILD_BIG_CLASS
#endif // BIG_CLASS_STATIC
// the library interface
#include <iostream>
struct BigClass {
const int id = 0;
// inline constructors doesn't need an export guard
BigClass() = default;
// non-inline constructors need an export guard
BIG_CLASS_API BigClass(int id);
// non-inline functins as well
BIG_CLASS_API void print() const;
// no export guard for inline member functions
void printLn() const
{
print();
std::cout << std::endl;
}
};
// functions need to be exported
extern BIG_CLASS_API void print(const BigClass&);
// inline functions don't need to be exported
inline void printLn(const BigClass& big)
{
big.printLn();
}
#endif // BIG_CLASS_H
从而引入第一个宏DLL_EXPORT
和DLL_IMPORT
来隐藏Windows(Visual Studio)和Linux(g++ ).
这些定义可以在多个库中共享。
第二组宏是特定于库的——因此,所有宏中的前缀 BIG_CLASS_
。
BIG_CLASS_STATIC
是一个宏,当(且仅当)库被构建为静态库时,它应该被定义为编译器的参数。如果必须将静态库 link 编辑为可执行文件,也必须对其进行定义。
BUILD_BIG_CLASS
是一个宏,如果(且仅当)库被构建并且 link 编辑为 DLL(或共享 object 在 Linux).
这两个宏都被认为是准备第三个宏BIG_CLASS_API
,扩展为
- 没有静态库
DLL_EXPORT
如果构建了DLLDLL_IMPORT
如果构建了任何其他旨在使用和 link DLL 的内容。
对应BigClass.cc
:
#include "BigClass.h"
BigClass::BigClass(int id): id(id) { }
void BigClass::print() const
{
std::cout << "BigClass::print(): *this: BigClass { id: " << id << " }";
}
void print(const BigClass& big)
{
std::cout << "print(): "; big.print();
}
没什么特别的。
BigClass.h
和 BigClass.cc
将用于构建示例 BigClass.dll
。
此外,两个测试应用程序 Test1
和 Test2
应 link 编辑 BigClass.dll
。
Test1.cc
:
#include <iostream>
#include <BigClass.h>
#define TEST(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
std::cout
<< "Test1:\n"
<< "======\n";
TEST(BigClass big);
TEST(big.print());
std::cout << '\n';
TEST(big.printLn());
TEST(BigClass big1(1));
TEST(big1.print());
std::cout << '\n';
TEST(big1.printLn());
std::cout << "Done." << std::endl;
}
Test2.cc
:
#include <iostream>
#include <BigClass.h>
#define TEST(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
std::cout
<< "Test2:\n"
<< "======\n";
TEST(BigClass big);
TEST(print(big));
std::cout << '\n';
TEST(printLn(big));
TEST(BigClass big2(2));
TEST(print(big2));
std::cout << '\n';
TEST(printLn(big2));
std::cout << "Done." << std::endl;
}
同样,它们没有什么特别之处。
免责声明:宏TEST()
与单元测试无关。这只是一种演示摆弄。
最后,CMakeLists.txt
将所有内容放在一起(例如在 VS 解决方案中 BigClassDLL.sln
):
project (BigClassDLL)
cmake_minimum_required(VERSION 3.10.0)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if (MSVC)
# Unfortunately neither
# CMAKE_CXX_STANDARD_REQUIRED ON
# nor
# CMAKE_CXX_EXTENSIONS OFF
# force the /permissive- option
# which makes MSVC standard conform.
add_compile_options(/permissive-)
endif()
# enable shared libraries (aka. DLLs)
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
include_directories("${CMAKE_SOURCE_DIR}")
# build the library
add_library(BigClass
BigClass.cc BigClass.h)
set_target_properties(BigClass
PROPERTIES
PROJECT_LABEL "Big Class DLL"
DEFINE_SYMBOL BUILD_BIG_CLASS)
if (NOT BUILD_SHARED_LIBS)
target_compile_definitions(BigClass PUBLIC BIG_CLASS_STATIC)
endif()
# build the tests
add_executable(Test1 Test1.cc)
target_link_libraries(Test1 BigClass)
add_executable(Test2 Test2.cc)
target_link_libraries(Test2 BigClass)
关于动态 linking:
有一些具体的事情
中有解释option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
这在 CMake: Step 9: Selecting Static or Shared Libraries.set_target_properties(BigClass PROPERTIES DEFINE_SYMBOL BUILD_BIG_CLASS)
这确保宏BUILD_BIG_CLASS
将在构建库BigClass
时在编译器的命令行中专门定义。-
if (NOT BUILD_SHARED_LIBS) target_compile_definitions(BigClass PUBLIC BIG_CLASS_STATIC) endif()
宏
BIG_CLASS_STATIC
将在构建或使用库BigClass
的每个编译器命令行中定义。
免责声明: 我知道 CMakeLists.txt
用于多个项目被认为是糟糕的风格。对于一个严肃的项目,库当然应该驻留在自己的目录中,并带有自己的 CMakeLists.txt
文件。我把它放在一起是为了尽可能地减少它(也是因为我可以)。
2019 年 Visual Studio 的情况:
2019 年 Visual Studio 的构建工件:
运行 Test1.exe
:
Test1:
======
BigClass big;
big.print();
BigClass::print(): *this: BigClass { id: 0 }
big.printLn();
BigClass::print(): *this: BigClass { id: 0 }
BigClass big1(1);
big1.print();
BigClass::print(): *this: BigClass { id: 1 }
big1.printLn();
BigClass::print(): *this: BigClass { id: 1 }
Done.
运行 Test2.exe
:
Test2:
======
BigClass big;
print(big);
print(): BigClass::print(): *this: BigClass { id: 0 }
printLn(big);
BigClass::print(): *this: BigClass { id: 0 }
BigClass big2(2);
print(big2);
print(): BigClass::print(): *this: BigClass { id: 2 }
printLn(big2);
BigClass::print(): *this: BigClass { id: 2 }
Done.
最后(为了解决可移植性问题),我在 Linux:
中构建了相同的 CMake 项目Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll$ mkdir build-Linux
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll$ cd build-Linux
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll/build-Linux$ ccmake ..
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll/build-Linux$ cmake --build .
Scanning dependencies of target BigClass
[ 16%] Building CXX object CMakeFiles/BigClass.dir/BigClass.cc.o
[ 33%] Linking CXX shared library libBigClass.so
[ 33%] Built target BigClass
Scanning dependencies of target Test2
[ 50%] Building CXX object CMakeFiles/Test2.dir/Test2.cc.o
[ 66%] Linking CXX executable Test2
[ 66%] Built target Test2
Scanning dependencies of target Test1
[ 83%] Building CXX object CMakeFiles/Test1.dir/Test1.cc.o
[100%] Linking CXX executable Test1
[100%] Built target Test1
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll/build-Linux$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake libBigClass.so Makefile Test1 Test2
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll/build-Linux$ ./Test1
Test1:
======
BigClass big;
big.print();
BigClass::print(): *this: BigClass { id: 0 }
big.printLn();
BigClass::print(): *this: BigClass { id: 0 }
BigClass big1(1);
big1.print();
BigClass::print(): *this: BigClass { id: 1 }
big1.printLn();
BigClass::print(): *this: BigClass { id: 1 }
Done.
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll/build-Linux$ ./Test2
Test2:
======
BigClass big;
print(big);
print(): BigClass::print(): *this: BigClass { id: 0 }
printLn(big);
BigClass::print(): *this: BigClass { id: 0 }
BigClass big2(2);
print(big2);
print(): BigClass::print(): *this: BigClass { id: 2 }
printLn(big2);
BigClass::print(): *this: BigClass { id: 2 }
Done.
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C++/dll/build-Linux$