summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authoronqtam <vik.kirilov@gmail.com>2016-09-10 01:37:53 +0300
committeronqtam <vik.kirilov@gmail.com>2016-09-21 15:46:12 +0300
commita0e28467f9c87333ac5b0b4f13b9999ea6903605 (patch)
treedb729776cbd22e710894a430b4a221534cad93ef /examples
parentf516977e0c966925abe215b22f83ded03d9c11e3 (diff)
Using a CMake function called "doctest_force_link_static_lib_in_target" located in "doctest_force_link_static_lib_in_target.cmake" users of CMake can force the linking of every object file from a static library to an executable/shared target. Not intrusive - using generated dummy headers in the build folder of the target, CMake target properties and compiler flags for including the headers to the appropriate sources.
fixes #21
Diffstat (limited to 'examples')
-rw-r--r--examples/exe_with_static_libs/CMakeLists.txt23
-rw-r--r--examples/exe_with_static_libs/doctest_force_link_static_lib_in_target.cmake107
-rw-r--r--examples/exe_with_static_libs/lib_1_src1.cpp4
-rw-r--r--examples/exe_with_static_libs/lib_1_src2.cpp4
-rw-r--r--examples/exe_with_static_libs/lib_2_src.cpp4
-rw-r--r--examples/exe_with_static_libs/main.cpp4
-rw-r--r--examples/exe_with_static_libs/test_output/exe_with_static_libs.txt9
7 files changed, 155 insertions, 0 deletions
diff --git a/examples/exe_with_static_libs/CMakeLists.txt b/examples/exe_with_static_libs/CMakeLists.txt
new file mode 100644
index 0000000..bd3d32a
--- /dev/null
+++ b/examples/exe_with_static_libs/CMakeLists.txt
@@ -0,0 +1,23 @@
+cmake_minimum_required(VERSION 2.8)
+
+get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
+project(${PROJECT_NAME})
+
+include(../../scripts/common.cmake)
+
+include_directories("../../doctest/")
+
+add_library(lib_1 STATIC lib_1_src1.cpp lib_1_src2.cpp)
+add_library(lib_2 STATIC lib_2_src.cpp)
+
+add_executable(${PROJECT_NAME} main.cpp)
+target_link_libraries(${PROJECT_NAME} lib_1)
+target_link_libraries(${PROJECT_NAME} lib_2)
+
+add_test(NAME ${PROJECT_NAME} COMMAND $<TARGET_FILE:${PROJECT_NAME}>)
+
+# pulls the force linking functionality
+include(doctest_force_link_static_lib_in_target.cmake)
+
+doctest_force_link_static_lib_in_target(${PROJECT_NAME} lib_1)
+doctest_force_link_static_lib_in_target(${PROJECT_NAME} lib_2)
diff --git a/examples/exe_with_static_libs/doctest_force_link_static_lib_in_target.cmake b/examples/exe_with_static_libs/doctest_force_link_static_lib_in_target.cmake
new file mode 100644
index 0000000..b937aec
--- /dev/null
+++ b/examples/exe_with_static_libs/doctest_force_link_static_lib_in_target.cmake
@@ -0,0 +1,107 @@
+if(doctest_force_link_static_lib_in_target_included)
+ return()
+endif()
+set(doctest_force_link_static_lib_in_target_included true)
+
+# includes the file to the source with compiler flags
+function(doctest_include_file_in_sources header sources)
+ foreach(src ${sources})
+ if(${src} MATCHES \\.\(cc|cp|cpp|CPP|c\\+\\+|cxx\)$)
+ # get old flags
+ get_source_file_property(old_compile_flags ${src} COMPILE_FLAGS)
+ if(old_compile_flags STREQUAL "NOTFOUND")
+ set(old_compile_flags "")
+ endif()
+
+ # update flags
+ if(MSVC)
+ set_source_files_properties(${src} PROPERTIES COMPILE_FLAGS
+ "${old_compile_flags} /FI\"${header}\"")
+ else()
+ set_source_files_properties(${src} PROPERTIES COMPILE_FLAGS
+ "${old_compile_flags} -include \"${header}\"")
+ endif()
+ endif()
+ endforeach()
+endfunction()
+
+# this is the magic function - forces every object file from the library to be linked into the target (dll or executable)
+function(doctest_force_link_static_lib_in_target target lib)
+ # check if the library has generated dummy headers
+ get_target_property(DDH ${lib} DOCTEST_DUMMY_HEADER)
+ get_target_property(LIB_NAME ${lib} NAME)
+ if(${DDH} STREQUAL "DDH-NOTFOUND")
+ # figure out the paths and names of the dummy headers - should be in the build folder for the target
+ get_target_property(BD ${lib} BINARY_DIR)
+ set(dummy_dir ${BD}/${LIB_NAME}_DOCTEST_STATIC_LIB_FORCE_LINK_DUMMIES/)
+ set(dummy_header ${dummy_dir}/all_dummies.h)
+ file(MAKE_DIRECTORY ${dummy_dir})
+
+ # create a dummy header for each source file, include a dummy function in it and include it in the source file
+ set(curr_dummy "0")
+ set(DLL_PRIVATE "#ifndef _WIN32\n#define DLL_PRIVATE __attribute__ ((visibility (\"hidden\")))\n#else\n#define DLL_PRIVATE\n#endif\n\n")
+ get_target_property(lib_sources ${lib} SOURCES)
+ foreach(src ${lib_sources})
+ if(${src} MATCHES \\.\(cc|cp|cpp|CPP|c\\+\\+|cxx\)$)
+ math(EXPR curr_dummy "${curr_dummy} + 1")
+
+ set(curr_dummy_header ${dummy_dir}/dummy_${curr_dummy}.h)
+ file(WRITE ${curr_dummy_header} "${DLL_PRIVATE}namespace doctest { namespace detail { DLL_PRIVATE int dummy_for_${LIB_NAME}_${curr_dummy}(); DLL_PRIVATE int dummy_for_${LIB_NAME}_${curr_dummy}() { return ${curr_dummy}; } } }")
+ doctest_include_file_in_sources(${curr_dummy_header} ${src})
+ endif()
+ endforeach()
+ set(total_dummies ${curr_dummy})
+
+ # create the master dummy header
+ file(WRITE ${dummy_header} "${DLL_PRIVATE}namespace doctest { namespace detail {\n\n")
+
+ # forward declare the dummy functions in the master dummy header
+ foreach(curr_dummy RANGE 1 ${total_dummies})
+ file(APPEND ${dummy_header} "DLL_PRIVATE int dummy_for_${LIB_NAME}_${curr_dummy}();\n")
+ endforeach()
+
+ # call the dummy functions in the master dummy header
+ file(APPEND ${dummy_header} "\nDLL_PRIVATE int dummies_for_${LIB_NAME}();\nDLL_PRIVATE int dummies_for_${LIB_NAME}() {\n int res = 0;\n")
+ foreach(curr_dummy RANGE 1 ${total_dummies})
+ file(APPEND ${dummy_header} " res += dummy_for_${LIB_NAME}_${curr_dummy}();\n")
+ endforeach()
+ file(APPEND ${dummy_header} " return res;\n}\n\n} } // namespaces")
+
+ # set the dummy header property so we don't recreate the dummy headers the next time this macro is called for this library
+ set_target_properties(${lib} PROPERTIES DOCTEST_DUMMY_HEADER ${dummy_header})
+ set(DDH ${dummy_header})
+ endif()
+
+ get_target_property(DFLLTD ${target} DOCTEST_FORCE_LINKED_LIBRARIES_THROUGH_DUMMIES)
+ get_target_property(target_sources ${target} SOURCES)
+
+ if("${DFLLTD}" STREQUAL "DFLLTD-NOTFOUND")
+ # if no library has been force linked to this target
+ foreach(src ${target_sources})
+ if(${src} MATCHES \\.\(cc|cp|cpp|CPP|c\\+\\+|cxx\)$)
+ doctest_include_file_in_sources(${DDH} ${src})
+ break()
+ endif()
+ endforeach()
+
+ # add the library as force linked to this target
+ set_target_properties(${target} PROPERTIES DOCTEST_FORCE_LINKED_LIBRARIES_THROUGH_DUMMIES ${LIB_NAME})
+ else()
+ # if this particular library hasn't been force linked to this target
+ list(FIND DFLLTD ${LIB_NAME} lib_forced_in_target)
+ if(${lib_forced_in_target} EQUAL -1)
+ foreach(src ${target_sources})
+ if(${src} MATCHES \\.\(cc|cp|cpp|CPP|c\\+\\+|cxx\)$)
+ doctest_include_file_in_sources(${DDH} ${src})
+ break()
+ endif()
+ endforeach()
+
+ # add this library to the list of force linked libraries for this target
+ list(APPEND DFLLTD ${LIB_NAME})
+ set_target_properties(${target} PROPERTIES DOCTEST_FORCE_LINKED_LIBRARIES_THROUGH_DUMMIES "${DFLLTD}")
+ else()
+ message(AUTHOR_WARNING "LIBRARY \"${lib}\" ALREADY FORCE-LINKED TO TARGET \"${target}\"!")
+ endif()
+ endif()
+endfunction()
diff --git a/examples/exe_with_static_libs/lib_1_src1.cpp b/examples/exe_with_static_libs/lib_1_src1.cpp
new file mode 100644
index 0000000..0ce2690
--- /dev/null
+++ b/examples/exe_with_static_libs/lib_1_src1.cpp
@@ -0,0 +1,4 @@
+#include "doctest.h"
+#include <cstdio>
+
+TEST_CASE("asd") { printf("hello from <lib_1_src1.cpp>\n"); }
diff --git a/examples/exe_with_static_libs/lib_1_src2.cpp b/examples/exe_with_static_libs/lib_1_src2.cpp
new file mode 100644
index 0000000..13ed390
--- /dev/null
+++ b/examples/exe_with_static_libs/lib_1_src2.cpp
@@ -0,0 +1,4 @@
+#include "doctest.h"
+#include <cstdio>
+
+TEST_CASE("asd") { printf("hello from <lib_1_src2.cpp>\n"); }
diff --git a/examples/exe_with_static_libs/lib_2_src.cpp b/examples/exe_with_static_libs/lib_2_src.cpp
new file mode 100644
index 0000000..68c3dad
--- /dev/null
+++ b/examples/exe_with_static_libs/lib_2_src.cpp
@@ -0,0 +1,4 @@
+#include "doctest.h"
+#include <cstdio>
+
+TEST_CASE("asd") { printf("hello from <lib_2_src.cpp>\n"); }
diff --git a/examples/exe_with_static_libs/main.cpp b/examples/exe_with_static_libs/main.cpp
new file mode 100644
index 0000000..427d25f
--- /dev/null
+++ b/examples/exe_with_static_libs/main.cpp
@@ -0,0 +1,4 @@
+#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+#include "doctest.h"
+
+TEST_CASE("main") { printf("hello from <main.cpp>\n"); }
diff --git a/examples/exe_with_static_libs/test_output/exe_with_static_libs.txt b/examples/exe_with_static_libs/test_output/exe_with_static_libs.txt
new file mode 100644
index 0000000..fa25c1b
--- /dev/null
+++ b/examples/exe_with_static_libs/test_output/exe_with_static_libs.txt
@@ -0,0 +1,9 @@
+[doctest] doctest version is "1.0.0"
+[doctest] run with "--help" for options
+hello from <lib_1_src1.cpp>
+hello from <lib_1_src2.cpp>
+hello from <lib_2_src.cpp>
+hello from <main.cpp>
+===============================================================================
+[doctest] test cases: 4 | 4 passed | 0 failed | 0 skipped
+[doctest] assertions: 0 | 0 passed | 0 failed |