diff --git a/CMakeLists.txt b/CMakeLists.txt
index b08a739f1ebcb31a960b3dc1386db3756a5a04c1..be8d1decc0c6cc6f344edd8cfc201289ca0b0931 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -52,6 +52,11 @@ option(NMC_AUTO_RUN_MODCC_ON_CHANGES
 set(EXTERNAL_LIBRARIES "")
 set(EXTERNAL_INCLUDES "")
 
+#----------------------------------------------------------
+# list of libraries built inside NestMC
+#----------------------------------------------------------
+set(NESTMC_LIBRARIES "")
+
 #----------------------------------------------------------
 # Threading model selection
 #----------------------------------------------------------
diff --git a/miniapp/CMakeLists.txt b/miniapp/CMakeLists.txt
index 801a48d2fbd9272fd9f00c30bf9f2a1950259efb..c41f7c5137147ccc7724f05bdcfed29a75fccaef 100644
--- a/miniapp/CMakeLists.txt
+++ b/miniapp/CMakeLists.txt
@@ -13,14 +13,9 @@ set(MINIAPP_SOURCES_CUDA
     morphology_pool.cpp
 )
 
-if(NMC_WITH_CUDA)
-    cuda_add_executable(miniapp.exe ${MINIAPP_SOURCES_CUDA} ${HEADERS})
-    target_link_libraries(miniapp.exe LINK_PUBLIC gpu)
-else()
-    add_executable(miniapp.exe ${MINIAPP_SOURCES} ${HEADERS})
-endif()
+add_executable(miniapp.exe ${MINIAPP_SOURCES} ${HEADERS})
 
-target_link_libraries(miniapp.exe LINK_PUBLIC nestmc)
+target_link_libraries(miniapp.exe LINK_PUBLIC ${NESTMC_LIBRARIES})
 target_link_libraries(miniapp.exe LINK_PUBLIC ${EXTERNAL_LIBRARIES})
 
 if(NMC_WITH_MPI)
@@ -32,4 +27,3 @@ set_target_properties(miniapp.exe
    PROPERTIES
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/miniapp"
 )
-
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 469086ad5416ed518248b525178641e5395e0481..badd3733a2a0cf3d90b2b9bb6c19fb553fcae686 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,7 +1,7 @@
 set(BASE_SOURCES
     common_types_io.cpp
     cell.cpp
-    cell_group_factory.cpp
+    #cell_group_factory.cpp
     event_binner.cpp
     model.cpp
     morphology.cpp
@@ -25,13 +25,18 @@ set(CUDA_SOURCES
     memory/fill.cu
 )
 
+# The cell_group_factory acts like an interface between the
+# front end and back end.
+if(NMC_WITH_CUDA)
+    set(CUDA_SOURCES ${CUDA_SOURCES} cell_group_factory.cu)
+else()
+    set(BASE_SOURCES ${BASE_SOURCES} cell_group_factory.cpp)
+endif()
 
 if(NMC_WITH_MPI)
     set(BASE_SOURCES ${BASE_SOURCES} communication/mpi.cpp)
-
 elseif(NMC_WITH_DRYRUN)
     set(BASE_SOURCES ${BASE_SOURCES} communication/dryrun_global_policy.cpp)
-
 endif()
 
 if(NMC_WITH_CTHREAD)
@@ -39,14 +44,24 @@ if(NMC_WITH_CTHREAD)
 endif()
 
 add_library(nestmc ${BASE_SOURCES} ${HEADERS})
-
-if (NMC_AUTO_RUN_MODCC_ON_CHANGES)
-  add_dependencies(nestmc build_all_mods)
-endif()
+list(APPEND NESTMC_LIBRARIES nestmc)
 
 if(NMC_WITH_CUDA)
     cuda_add_library(gpu ${CUDA_SOURCES})
-    set(NESTMC_LIBRARIES ${NESTMC_LIBRARIES} gpu)
-    add_dependencies(gpu build_all_gpu_mods)
+    # FIXME
+    # The gpu library uses symbols fron nestmc, so we have to
+    # add nestmc to the end. This is a temporary hack that will
+    # go away when we have properly seperable front and back end
+    # compilation.
+    list(APPEND NESTMC_LIBRARIES gpu nestmc)
+endif()
+
+if (NMC_AUTO_RUN_MODCC_ON_CHANGES)
+    add_dependencies(nestmc build_all_mods)
+    if (NMC_WITH_CUDA)
+        add_dependencies(gpu build_all_gpu_mods)
+    endif()
 endif()
 
+# Make changes to the NMC_LIBRARIES visible to the parent scope.
+set(NESTMC_LIBRARIES "${NESTMC_LIBRARIES}" PARENT_SCOPE)
diff --git a/src/cell_group_factory.cu b/src/cell_group_factory.cu
new file mode 100644
index 0000000000000000000000000000000000000000..21d20e7b9f18c2c1028cfe4e5391f2b463d106a9
--- /dev/null
+++ b/src/cell_group_factory.cu
@@ -0,0 +1 @@
+#include "cell_group_factory.cpp"
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index 09935997242f8b1b6215a9f91bf4a7d00fd1c848..06899d2d9498959dbf44116ec2d75700c86d39bb 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -89,15 +89,13 @@ endif()
 target_include_directories(test.exe PRIVATE "${mech_proto_dir}/..")
 
 if(NMC_WITH_CUDA)
-    # Omit -DDATADIR for cuda target because of CMake 3.7/3.8 FindCUDA quoting bug.
-
     set(TARGETS ${TARGETS} test_cuda.exe)
     cuda_add_executable(test_cuda.exe ${TEST_CUDA_SOURCES} ${HEADERS})
-    target_link_libraries(test_cuda.exe LINK_PUBLIC gpu)
 endif()
 
 foreach(target ${TARGETS})
-    target_link_libraries(${target} LINK_PUBLIC gtest nestmc)
+    target_link_libraries(${target} LINK_PUBLIC gtest)
+    target_link_libraries(${target} LINK_PUBLIC ${NESTMC_LIBRARIES})
     target_link_libraries(${target} LINK_PUBLIC ${EXTERNAL_LIBRARIES})
 
     if(NMC_WITH_MPI)
diff --git a/tests/unit/test_matrix.cu b/tests/unit/test_matrix.cu
index dbf39f034fc42fd6243c5fa098648d6eb41ad54f..dac64cdf78e45b1bf0f53aaaf435e596f776c788 100644
--- a/tests/unit/test_matrix.cu
+++ b/tests/unit/test_matrix.cu
@@ -1,4 +1,5 @@
 #include <numeric>
+#include <random>
 #include <vector>
 
 #include "../gtest.h"
diff --git a/tests/validation/CMakeLists.txt b/tests/validation/CMakeLists.txt
index 5523c3d20058f0c18a71e9e211f76e9e2a2b7f2a..288f7ded6b51607a05d11d0258ae1fc08c76e922 100644
--- a/tests/validation/CMakeLists.txt
+++ b/tests/validation/CMakeLists.txt
@@ -48,8 +48,8 @@ endif()
 
 
 foreach(target ${TARGETS})
-    target_link_libraries(${target} LINK_PUBLIC nestmc gtest)
-
+    target_link_libraries(${target} LINK_PUBLIC gtest)
+    target_link_libraries(${target} LINK_PUBLIC ${NESTMC_LIBRARIES})
     target_link_libraries(${target} LINK_PUBLIC ${EXTERNAL_LIBRARIES})
 
     if(NMC_WITH_MPI)