Correct way to use compiled spirv shaders in vulkan - c++
TL;DR:
Compiled spirv shaders crash where inline runtime-compiled spirvs work, tested with modified sample. Crash happens deep in vulkan code. What gives?
Details:
I am having trouble using compiled spirv shaders. I took the "draw-textured-cube" sample, extracted it to a standalone environment with paired-down cmake and a minimal edit to util.cpp to adjust the path to the data dir. It compiled and worked as expected.
I then extracted the shader codes from the static const cstrings at the beginning of the file and moved them to their own files. I replaced the call to init_shaders with one that just reads the file and builds the shader modules with the same options as init_shaders. I compiled the glsl into spirv with options taken from an unused function in the original sample CMakeLists.txt.
It now crashes with an access violation on the creation of the pipeline (full error text below). Same result in both Debug and Release builds, with or without the validation layer. Stepping through the assembly in visual studio reveals the error is happening at least 16 layers deep into the create pipeline call (where a call or non-local jmp constitutes a layer, as these are most likely function barriers).
Unhandled exception at 0x000000006894A525 (nvoglv64.dll) in main.exe: 0xC0000005: Access violation writing location 0x00000080A3CAA530. occurred
(With the exact addresses varying as one would expect.)
Any of the samples included with the SDK use inline glsl compiled at runtime into spirv, but all have a comment similar to this one (from the textured cube sample):
/* For this sample, we'll start with GLSL so the shader function is plain */
/* and then use the glslang GLSLtoSPV utility to convert it to SPIR-V for */
/* the driver. We do this for clarity rather than using pre-compiled */
/* SPIR-V */
This would seem to indicate that the "correct" way to do shaders is to use precompiled, and yet we are not given a working sample/example on how to accomplish this. I have looked other places but cannot find a reasonably simple (<10,000 lines) example of how to compile read and display spv shaders.
My best guesses at what the problem is are: 1) glslValidator is compiling them wrong; 2) I'm reading them wrong; 3) using them requires different options (say, to the shader module creation info) then runtime-compiled shaders. In any case, I'm already starting to wish that vulkan had better error trapping.
Obviously using inline glsl everywhere would be a workaround, and if that's what it takes I can just make a bunch of .cpp files with just one big cstring per shader, at the cost of runtime initial load, but there really should be a better solution.
Host system is windows 7 (x64) with excessive resources compared to what should be required by the program. I'm targetting windows linux and (if possible) mac, so any solutions that rule out android, ios, consoles etc. are fine with me.
Main.cpp:
/*
* Vulkan Samples
*
* Copyright (C) 2015-2016 Valve Corporation
* Copyright (C) 2015-2016 LunarG, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
VULKAN_SAMPLE_SHORT_DESCRIPTION
Draw Textured Cube
*/
/* This is part of the draw cube progression */
#include <util_init.hpp>
#include <assert.h>
#include <string.h>
#include <cstdlib>
#include "cube_data.h"
FILE* logfile;
#define FAIL {line = __LINE__; goto fail;}
unsigned int * loadSprv(const char* filename, size_t* codelen) {
struct stat fstat;
size_t len, offset = 0, read;
if (stat(filename, &fstat))
return NULL;
*codelen = len = fstat.st_size;
union {
unsigned int * ret;
unsigned char * bytes;
};
bytes = (unsigned char *)malloc((1 + len / 4) * 4 + 1);//padded to 32 bit barrier to accomodate unsigned int type
if (!ret) return NULL;
FILE* src = fopen(filename, "r");
if (!src) {
free(ret);
return NULL;
}
read = fread(bytes, 1, len, src);
while (read > 0 && len >= 0) {
len -= read;
offset += read;
read = fread(bytes + offset, 1, len, src);
}
bytes[offset] = 0;//null term, probably unneeded
fclose(src);
return ret;
}
int sample_main(int argc, char *argv[]) {
VkResult U_ASSERT_ONLY res = VK_SUCCESS;
struct sample_info info = {};
char sample_title[] = "Draw Textured Cube";
const bool depthPresent = true;
logfile = fopen("runtime.log", "w");
uint64_t line = 0;
process_command_line_args(info, argc, argv);
init_global_layer_properties(info);
init_instance_extension_names(info);
init_device_extension_names(info);
init_instance(info, sample_title);
init_enumerate_device(info);
init_window_size(info, 500, 500);
init_connection(info);
init_window(info);
init_swapchain_extension(info);
init_device(info);
init_command_pool(info);
init_command_buffer(info);
execute_begin_command_buffer(info);
init_device_queue(info);
init_swap_chain(info);
init_depth_buffer(info);
init_texture(info);
init_uniform_buffer(info);
init_descriptor_and_pipeline_layouts(info, true);
init_renderpass(info, depthPresent);
//init_shaders(info, vertShaderText, fragShaderText);
{
//|-X init_glslang (empty function on everything that's not android)
info.shaderStages[0] = {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, NULL, 0,
VK_SHADER_STAGE_VERTEX_BIT, VK_NULL_HANDLE, "main", NULL};
VkShaderModuleCreateInfo moduleCreateInfo = {VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, NULL, 0,
0, NULL};
moduleCreateInfo.pCode = loadSprv("shaders\\sample.vert.spv", &moduleCreateInfo.codeSize);
if(!moduleCreateInfo.pCode) FAIL;
res = vkCreateShaderModule(info.device, &moduleCreateInfo, NULL, &info.shaderStages[0].module);
free((void*)moduleCreateInfo.pCode);
if (res) FAIL;
info.shaderStages[1] = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, NULL, 0,
VK_SHADER_STAGE_FRAGMENT_BIT, VK_NULL_HANDLE, "main", NULL };
moduleCreateInfo.pCode = loadSprv("shaders\\sample.frag.spv", &moduleCreateInfo.codeSize);
res = vkCreateShaderModule(info.device, &moduleCreateInfo, NULL, &info.shaderStages[1].module);
free((void*)moduleCreateInfo.pCode);
if (res) FAIL;
}
init_framebuffers(info, depthPresent);
init_vertex_buffer(info, g_vb_texture_Data, sizeof(g_vb_texture_Data), sizeof(g_vb_texture_Data[0]), true);
init_descriptor_pool(info, true);
init_descriptor_set(info, true);
init_pipeline_cache(info);
init_pipeline(info, depthPresent);
/* VULKAN_KEY_START */
VkClearValue clear_values[2];
clear_values[0].color.float32[0] = 0.2f;
clear_values[0].color.float32[1] = 0.2f;
clear_values[0].color.float32[2] = 0.2f;
clear_values[0].color.float32[3] = 0.2f;
clear_values[1].depthStencil.depth = 1.0f;
clear_values[1].depthStencil.stencil = 0;
VkSemaphore imageAcquiredSemaphore;
VkSemaphoreCreateInfo imageAcquiredSemaphoreCreateInfo;
imageAcquiredSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
imageAcquiredSemaphoreCreateInfo.pNext = NULL;
imageAcquiredSemaphoreCreateInfo.flags = 0;
res = vkCreateSemaphore(info.device, &imageAcquiredSemaphoreCreateInfo, NULL, &imageAcquiredSemaphore);
assert(res == VK_SUCCESS);
// Get the index of the next available swapchain image:
res = vkAcquireNextImageKHR(info.device, info.swap_chain, UINT64_MAX, imageAcquiredSemaphore, VK_NULL_HANDLE,
&info.current_buffer);
// TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
// return codes
assert(res == VK_SUCCESS);
VkRenderPassBeginInfo rp_begin;
rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
rp_begin.pNext = NULL;
rp_begin.renderPass = info.render_pass;
rp_begin.framebuffer = info.framebuffers[info.current_buffer];
rp_begin.renderArea.offset.x = 0;
rp_begin.renderArea.offset.y = 0;
rp_begin.renderArea.extent.width = info.width;
rp_begin.renderArea.extent.height = info.height;
rp_begin.clearValueCount = 2;
rp_begin.pClearValues = clear_values;
vkCmdBeginRenderPass(info.cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline);
vkCmdBindDescriptorSets(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline_layout, 0, NUM_DESCRIPTOR_SETS,
info.desc_set.data(), 0, NULL);
const VkDeviceSize offsets[1] = { 0 };
vkCmdBindVertexBuffers(info.cmd, 0, 1, &info.vertex_buffer.buf, offsets);
init_viewports(info);
init_scissors(info);
vkCmdDraw(info.cmd, 12 * 3, 1, 0, 0);
vkCmdEndRenderPass(info.cmd);
res = vkEndCommandBuffer(info.cmd);
assert(res == VK_SUCCESS);
const VkCommandBuffer cmd_bufs[] = { info.cmd };
VkFenceCreateInfo fenceInfo;
VkFence drawFence;
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.pNext = NULL;
fenceInfo.flags = 0;
vkCreateFence(info.device, &fenceInfo, NULL, &drawFence);
VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo submit_info[1] = {};
submit_info[0].pNext = NULL;
submit_info[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info[0].waitSemaphoreCount = 1;
submit_info[0].pWaitSemaphores = &imageAcquiredSemaphore;
submit_info[0].pWaitDstStageMask = &pipe_stage_flags;
submit_info[0].commandBufferCount = 1;
submit_info[0].pCommandBuffers = cmd_bufs;
submit_info[0].signalSemaphoreCount = 0;
submit_info[0].pSignalSemaphores = NULL;
/* Queue the command buffer for execution */
res = vkQueueSubmit(info.graphics_queue, 1, submit_info, drawFence);
assert(res == VK_SUCCESS);
/* Now present the image in the window */
VkPresentInfoKHR present;
present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
present.pNext = NULL;
present.swapchainCount = 1;
present.pSwapchains = &info.swap_chain;
present.pImageIndices = &info.current_buffer;
present.pWaitSemaphores = NULL;
present.waitSemaphoreCount = 0;
present.pResults = NULL;
/* Make sure command buffer is finished before presenting */
do {
res = vkWaitForFences(info.device, 1, &drawFence, VK_TRUE, FENCE_TIMEOUT);
} while (res == VK_TIMEOUT);
assert(res == VK_SUCCESS);
res = vkQueuePresentKHR(info.present_queue, &present);
assert(res == VK_SUCCESS);
wait_seconds(1);
/* VULKAN_KEY_END */
if (info.save_images) write_ppm(info, "draw_textured_cube");
vkDestroyFence(info.device, drawFence, NULL);
vkDestroySemaphore(info.device, imageAcquiredSemaphore, NULL);
destroy_pipeline(info);
destroy_pipeline_cache(info);
destroy_textures(info);
destroy_descriptor_pool(info);
destroy_vertex_buffer(info);
destroy_framebuffers(info);
destroy_shaders(info);
destroy_renderpass(info);
destroy_descriptor_and_pipeline_layouts(info);
destroy_uniform_buffer(info);
destroy_depth_buffer(info);
destroy_swap_chain(info);
destroy_command_buffer(info);
destroy_command_pool(info);
destroy_device(info);
destroy_window(info);
destroy_instance(info);
return 0;
fail:
fprintf(logfile, "Fail. Res: %d. Line: %u\n", res, line);
return 1;
}
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.11)
project (STUPID_CUBE)
# set (CMAKE_VERBOSE_MAKEFILE 1)
set(API_NAME "Vulkan" CACHE STRING "API name to use when building")
string(TOLOWER ${API_NAME} API_LOWERCASE)
include(GNUInstallDirs)
file(TO_CMAKE_PATH $ENV{VULKAN_SDK} VULKAN)
add_definitions("-DVULKAN_SAMPLES_BASE_DIR=\"${CMAKE_SOURCE_DIR}\"")
# The MAJOR number of the version we're building, used in naming
# vulkan-<major>.dll (and other files).
set(MAJOR "1")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
set (CMAKE_INSTALL_PREFIX "")
set (UTILS_NAME vsamputils)
if(NOT WIN32)
include(FindPkgConfig)
option(BUILD_WSI_XCB_SUPPORT "Build XCB WSI support" ON)
option(BUILD_WSI_WAYLAND_SUPPORT "Build Wayland WSI support" OFF)
set(DEMOS_WSI_SELECTION "XCB" CACHE STRING "Select WSI target for demos (XCB, XLIB, WAYLAND, DISPLAY)")
set(SAMPLES_WSI_SELECTION "XCB" CACHE STRING "Select WSI target for api-samples (XCB, WAYLAND, DISPLAY)")
if (BUILD_WSI_XCB_SUPPORT)
find_package(XCB REQUIRED)
endif()
if (BUILD_WSI_WAYLAND_SUPPORT)
find_package(Wayland REQUIRED)
endif()
set (BUILDTGT_DIR build)
set (BINDATA_DIR x86_64/bin)
set (LIBSOURCE_DIR Lib)
else()
# For Windows, since 32-bit and 64-bit items can co-exist, we build each in its own build directory.
# 32-bit target data goes in build32, and 64-bit target data goes into build. So, include/link the
# appropriate data at build time.
if (CMAKE_CL_64)
set (BUILDTGT_DIR build)
set (BINDATA_DIR Bin)
set (LIBSOURCE_DIR Lib)
else()
set (BUILDTGT_DIR build32)
set (BINDATA_DIR Bin32)
set (LIBSOURCE_DIR Lib32)
endif()
endif()
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
set(COMMON_COMPILE_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers")
set(COMMON_COMPILE_FLAGS "${COMMON_COMPILE_FLAGS} -fno-strict-aliasing -fno-builtin-memcmp")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 ${COMMON_COMPILE_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMMON_COMPILE_FLAGS} -std=c++11")
if (UNIX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
endif()
endif()
find_program(GLSLANG_VALIDATOR NAMES glslangValidator
HINTS "${VULKAN}/glslang/${BUILDTGT_DIR}/install/bin"
"${VULKAN}/${BINDATA_DIR}" )
find_path(GLSLANG_SPIRV_INCLUDE_DIR SPIRV/spirv.hpp HINTS "${VULKAN}/source/glslang/"
"${VULKAN}/glslang"
DOC "Path to SPIRV/spirv.hpp")
find_path(SPIRV_TOOLS_INCLUDE_DIR spirv-tools/libspirv.h HINTS "${VULKAN}/spirv-tools/include"
"${VULKAN}/source/spirv-tools/include"
"${VULKAN}/spirv-tools/external/include"
"${VULKAN}/source/spirv-tools/external/include"
DOC "Path to spirv-tools/libspirv.h")
find_path(Vulkan_INCLUDE_DIR vulkan/vulkan.h HINTS "${VULKAN}"
"${VULKAN}/Include" )
if (WIN32)
set (GLSLANG_SEARCH_PATH "${VULKAN}/glslang/${BUILDTGT_DIR}/glslang/Release"
"${VULKAN}/glslang/${BUILDTGT_DIR}/glslang/OSDependent/Windows/Release"
"${VULKAN}/glslang/${BUILDTGT_DIR}/hlsl/Release"
"${VULKAN}/glslang/${BUILDTGT_DIR}/OGLCompilersDLL/Release"
"${VULKAN}/glslang/${BUILDTGT_DIR}/SPIRV/Release" )
set (SPIRV_TOOLS_SEARCH_PATH "${VULKAN}/spirv-tools/${BUILDTGT_DIR}/source/Release")
set (SPIRV_TOOLS_OPT_SEARCH_PATH "${VULKAN}/spirv-tools/${BUILDTGT_DIR}/source/opt/Release")
else()
set (GLSLANG_SEARCH_PATH "${VULKAN}/glslang/build/install/lib" "${VULKAN}/x86_64/lib/glslang" )
set (SPIRV_TOOLS_SEARCH_PATH "${VULKAN}/spirv-tools/build" "${VULKAN}/x86_64/lib/spirv-tools" )
set (SPIRV_TOOLS_OPT_SEARCH_PATH "${SPIRV_TOOLS_SEARCH_PATH}")
endif()
find_library(GLSLANG_LIB NAMES glslang
HINTS ${GLSLANG_SEARCH_PATH} )
find_library(OGLCompiler_LIB NAMES OGLCompiler
HINTS ${GLSLANG_SEARCH_PATH} )
find_library(OSDependent_LIB NAMES OSDependent
HINTS ${GLSLANG_SEARCH_PATH} )
find_library(HLSL_LIB NAMES HLSL
HINTS ${GLSLANG_SEARCH_PATH} )
find_library(SPIRV_LIB NAMES SPIRV
HINTS ${GLSLANG_SEARCH_PATH} )
find_library(SPIRV_TOOLS_LIB NAMES SPIRV-Tools
HINTS ${SPIRV_TOOLS_SEARCH_PATH} )
find_library(SPIRV_TOOLS_OPT_LIB NAMES SPIRV-Tools-opt
HINTS ${SPIRV_TOOLS_OPT_SEARCH_PATH} )
find_library(SPIRV_REMAPPER_LIB NAMES SPVRemapper
HINTS ${GLSLANG_SEARCH_PATH} )
# On Windows, we must pair Debug and Release appropriately
if (WIN32)
set (GLSLANG_DEBUG_SEARCH_PATH "${VULKAN}/glslang/${BUILDTGT_DIR}/glslang/Debug"
"${VULKAN}/glslang/${BUILDTGT_DIR}/glslang/OSDependent/Windows/Debug"
"${VULKAN}/glslang/${BUILDTGT_DIR}/hlsl/Debug"
"${VULKAN}/glslang/${BUILDTGT_DIR}/OGLCompilersDLL/Debug"
"${VULKAN}/glslang/${BUILDTGT_DIR}/SPIRV/Debug")
set (SPIRV_TOOLS_DEBUG_SEARCH_PATH "${VULKAN}/spirv-tools/${BUILDTGT_DIR}/source/Debug")
set (SPIRV_TOOLS_OPT_DEBUG_SEARCH_PATH "${VULKAN}/spirv-tools/${BUILDTGT_DIR}/source/opt/Debug")
add_library(glslang STATIC IMPORTED)
add_library(OGLCompiler STATIC IMPORTED)
add_library(OSDependent STATIC IMPORTED)
add_library(HLSL STATIC IMPORTED)
add_library(SPIRV STATIC IMPORTED)
add_library(Loader STATIC IMPORTED)
add_library(SPIRV-Tools STATIC IMPORTED)
add_library(SPIRV-Tools-opt STATIC IMPORTED)
add_library(SPVRemapper STATIC IMPORTED)
find_library(GLSLANG_DLIB NAMES glslangd
HINTS ${GLSLANG_DEBUG_SEARCH_PATH} )
find_library(OGLCompiler_DLIB NAMES OGLCompilerd
HINTS ${GLSLANG_DEBUG_SEARCH_PATH} )
find_library(OSDependent_DLIB NAMES OSDependentd
HINTS ${GLSLANG_DEBUG_SEARCH_PATH} )
find_library(HLSL_DLIB NAMES HLSLd
HINTS ${GLSLANG_DEBUG_SEARCH_PATH} )
find_library(SPIRV_DLIB NAMES SPIRVd
HINTS ${GLSLANG_DEBUG_SEARCH_PATH} )
find_library(SPIRV_TOOLS_DLIB NAMES SPIRV-Tools
HINTS ${SPIRV_TOOLS_DEBUG_SEARCH_PATH} )
find_library(SPIRV_TOOLS_OPT_DLIB NAMES SPIRV-Tools-opt
HINTS ${SPIRV_TOOLS_OPT_DEBUG_SEARCH_PATH} )
find_library(SPIRV_REMAPPER_DLIB NAMES SPVRemapperd
HINTS ${GLSLANG_DEBUG_SEARCH_PATH} )
set_target_properties(glslang PROPERTIES
IMPORTED_LOCATION "${GLSLANG_LIB}"
IMPORTED_LOCATION_DEBUG "${GLSLANG_DLIB}")
set_target_properties(OGLCompiler PROPERTIES
IMPORTED_LOCATION "${OGLCompiler_LIB}"
IMPORTED_LOCATION_DEBUG "${OGLCompiler_DLIB}")
set_target_properties(OSDependent PROPERTIES
IMPORTED_LOCATION "${OSDependent_LIB}"
IMPORTED_LOCATION_DEBUG "${OSDependent_DLIB}")
set_target_properties(HLSL PROPERTIES
IMPORTED_LOCATION "${HLSL_LIB}"
IMPORTED_LOCATION_DEBUG "${HLSL_DLIB}")
set_target_properties(SPIRV PROPERTIES
IMPORTED_LOCATION "${SPIRV_LIB}"
IMPORTED_LOCATION_DEBUG "${SPIRV_DLIB}")
set_target_properties(SPIRV-Tools PROPERTIES
IMPORTED_LOCATION "${SPIRV_TOOLS_LIB}"
IMPORTED_LOCATION_DEBUG "${SPIRV_TOOLS_DLIB}")
set_target_properties(SPIRV-Tools-opt PROPERTIES
IMPORTED_LOCATION "${SPIRV_TOOLS_OPT_LIB}"
IMPORTED_LOCATION_DEBUG "${SPIRV_TOOLS_OPT_DLIB}")
set_target_properties(SPVRemapper PROPERTIES
IMPORTED_LOCATION "${SPIRV_REMAPPER_LIB}"
IMPORTED_LOCATION_DEBUG "${SPIRV_REMAPPER_DLIB}")
set (SPIRV_TOOLS_LIBRARIES SPIRV-Tools-opt SPIRV-Tools)
set (GLSLANG_LIBRARIES glslang OGLCompiler OSDependent HLSL SPIRV SPVRemapper ${SPIRV_TOOLS_LIBRARIES})
else ()
set (SPIRV_TOOLS_LIBRARIES ${SPIRV_TOOLS_OPT_LIB} ${SPIRV_TOOLS_LIB})
set (GLSLANG_LIBRARIES ${GLSLANG_LIB} ${OGLCompiler_LIB} ${OSDependent_LIB} ${HLSL_LIB} ${SPIRV_LIB} ${SPIRV_REMAPPER_LIB} ${SPIRV_TOOLS_LIBRARIES})
endif()
set (GLMINCLUDES "${CMAKE_SOURCE_DIR}/utils")
# to run with source glslang libs/headers
if(UNIX)
add_definitions(-DVK_USE_PLATFORM_XCB_KHR)
if (EXISTS "${VULKAN}/glslang")
set (GLSLANGDIR "${VULKAN}/glslang")
else()
set (GLSLANGDIR "${VULKAN}/source/glslang")
endif()
else()
set (GLSLANGDIR "${VULKAN}/glslang")
endif()
get_filename_component(GLMINC_PREFIX "${GLMINCLUDES}" ABSOLUTE)
if(NOT EXISTS ${GLMINC_PREFIX})
message(FATAL_ERROR "Necessary glm headers do not exist: " ${GLMINC_PREFIX})
endif()
get_filename_component(GLSLANG_PREFIX "${GLSLANGDIR}" ABSOLUTE)
if(NOT EXISTS ${GLSLANG_PREFIX})
message(FATAL_ERROR "Necessary glslang components do not exist: " ${GLSLANG_PREFIX})
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/utils)
if(WIN32)
set (MOVE_CMD "move")
set (VULKAN_LOADER_NAME "${API_LOWERCASE}-${MAJOR}")
else()
set (MOVE_CMD "mv")
set (PTHREAD "pthread")
set (VULKAN_LOADER_NAME "${API_LOWERCASE}")
endif()
if(EXISTS "${CMAKE_SOURCE_DIR}/layers")
set (VULKAN_LOADER ${VULKAN_LOADER_NAME})
else()
find_library(VULKAN_LOADER NAMES ${VULKAN_LOADER_NAME}
HINTS "${VULKAN}/${LIBSOURCE_DIR}" "${VULKAN}/x86_64/lib" )
endif()
add_definitions(-DAPI_NAME="${API_NAME}")
# If ANDROID is ON, turn on cross-compiling for it
if(ANDROID)
set(CMAKE_SYSTEM_NAME "Android")
set(CMAKE_SYSTEM_VERSION "7")
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
add_definitions(-DVK_USE_PLATFORM_WIN32_KHR -DWIN32_LEAN_AND_MEAN)
set(DisplayServer Win32)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
add_definitions(-DVK_USE_PLATFORM_ANDROID_KHR)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
if (SAMPLES_WSI_SELECTION STREQUAL "XCB")
if (NOT BUILD_WSI_XCB_SUPPORT)
message( FATAL_ERROR "Selected XCB for samples build but not building Xcb support" )
endif()
add_definitions(-DVK_USE_PLATFORM_XCB_KHR)
elseif (SAMPLES_WSI_SELECTION STREQUAL "XLIB")
if (NOT BUILD_WSI_XLIB_SUPPORT)
message( FATAL_ERROR "Selected XLIB for samples build but not building Xlib support" )
endif()
add_definitions(-DVK_USE_PLATFORM_XLIB_KHR)
elseif (SAMPLES_WSI_SELECTION STREQUAL "WAYLAND")
if (NOT BUILD_WSI_WAYLAND_SUPPORT)
message( FATAL_ERROR "Selected Wayland for samples build but not building Wayland support" )
endif()
add_definitions(-DVK_USE_PLATFORM_WAYLAND_KHR)
endif()
else()
message(FATAL_ERROR "Unsupported Platform!")
endif()
set(SAMPLES_DATA_DIR ${SAMPLES_DATA_DIR} "${CMAKE_SOURCE_DIR}/data")
set(SHADER_FILES ${SHADER_FILES} "")
include_directories( ${SAMPLES_DATA_DIR} ${GLSLANG_SPIRV_INCLUDE_DIR} ${GLMINC_PREFIX} ${Vulkan_INCLUDE_DIR})
# Additional includes for spirv-tools
include_directories(${SPIRV_TOOLS_INCLUDE_DIR})
if(WIN32)
set (MOVE_CMD "move")
set (VULKAN_LOADER_NAME "${API_LOWERCASE}-${MAJOR}")
else()
set (MOVE_CMD "mv")
set (PTHREAD "pthread")
set (VULKAN_LOADER_NAME "${API_LOWERCASE}")
endif()
if(EXISTS "${PROJECT_SOURCE_DIR}/${V_LVL_RELATIVE_LOCATION}/loader")
set (VULKAN_LOADER ${VULKAN_LOADER_NAME})
else()
find_library(VULKAN_LOADER NAMES ${VULKAN_LOADER_NAME}
HINTS "${V_LVL_RELATIVE_LOCATION}/${LIBSOURCE_DIR}" "${V_LVL_RELATIVE_LOCATION}/x86_64/lib" )
endif()
set (LIBGLM_INCLUDE_DIR ${V_LVL_RELATIVE_LOCATION}/libs)
if(NOT WIN32 AND NOT ANDROID)
if(SDK_INCLUDE_PATH)
include_directories(${SDK_INCLUDE_PATH})
endif()
if (BUILD_WSI_XCB_SUPPORT)
include_directories(${XCB_INCLUDE_DIRS})
link_libraries(${XCB_LIBRARIES} m )
endif()
if (BUILD_WSI_WAYLAND_SUPPORT)
include_directories(${WAYLAND_CLIENT_INCLUDE_DIR})
link_libraries(${WAYLAND_CLIENT_LIBRARIES})
endif()
link_libraries(${VULKAN_LOADER} m )
endif()
if(WIN32)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS -D_USE_MATH_DEFINES")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS -D_USE_MATH_DEFINES")
# If MSVC, disable some signed/unsigned mismatch warnings.
if (MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4267")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267")
endif()
else()
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-compare")
endif()
if (NOT WIN32)
# extra setup for out-of-tree builds
if (NOT (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR))
add_custom_target(samples-binary-dir-symlinks ALL
COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/get-short-descripts.sh
VERBATIM
)
endif()
else()
if (NOT (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR))
FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lunarg.ppm LUNARG)
endif()
endif()
#
# START BUILDING SAMPLES HERE
#
# Generate Android project.
option(ANDROID OFF)
# simple one file sample targets, no additional files
file(GLOB SHADERS RELATIVE "${CMAKE_SOURCE_DIR}" CONFIGURE_DEPENDS shaders/*.frag shaders/*.vert)
foreach(SFILE ${SHADERS})
add_custom_command (OUTPUT ${SFILE}.spv COMMAND ${GLSLANG_VALIDATOR} -s -V "${CMAKE_SOURCE_DIR}/${SFILE}" -o ${SFILE}.spv DEPENDS ${SFILE} )
endforeach(SFILE)
add_executable( main WIN32 main.cpp shaders/sample.frag.spv shaders/sample.vert.spv )
target_link_libraries(main ${UTILS_NAME} ${GLSLANG_LIBRARIES} ${VULKAN_LOADER} ${WINLIBS} ${SPIRV_TOOLS_LIBRARIES})
if (NOT ANDROID)
foreach (sample ${S_TARGETS})
install(TARGETS ${sample} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endforeach(sample)
add_subdirectory(utils)
endif()
diff original util.cpp vs mine:
< return std::string(VULKAN_SAMPLES_BASE_DIR) + "/API-Samples/data/";
---
> return std::string(VULKAN_SAMPLES_BASE_DIR) + "/data/";
sample.vert:
#version 400
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
layout (std140, binding = 0) uniform buf {
mat4 mvp;
} ubuf;
layout (location = 0) in vec4 pos;
layout (location = 1) in vec2 inTexCoords;
layout (location = 0) out vec2 texcoord;
void main() {
texcoord = inTexCoords;
gl_Position = ubuf.mvp * pos;
}
sample.frag:
#version 400
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
layout (binding = 1) uniform sampler2D tex;
layout (location = 0) in vec2 texcoord;
layout (location = 0) out vec4 outColor;
void main() {
outColor = textureLod(tex, texcoord, 0.0);
}
On Windows, you'll need to open the binary SPIR-V file in binary mode by specifying the fopen mode flags as "rb". SPIR-V code is a sequence of 32-bit unsigned integers and on Windows you need to suppress any line-ending translations with the "binary" mode flag. The "b" flag is ignored on POSIX conforming systems like Linux and so you can leave it in your code if it is to be compiled on multiple platforms.
Related
Moving from QT 5.12.8 to 5.15.2 MOC fails
We try to mov to the latest Qt 5 LTSB (5.15.2) from our working base Qt 5.12.8 but ran into MOC errors: The moc process failed to compile "SRC:GenericForm.h" into "SRC:moc_GenericForm.cpp" Output SRC:/workspace/NBCI2/src/base/base_language.(9): Parse error at "{" The problem occours whith every Qt build greater 5.12.x what do we missing? What is changed on moc between 5.12.x and later? Build system is cmake base_language is include by some of the include headers. GenericForm.h: #pragma once #include "host.h" #include "qt_type_defines.h" #include <qwidget.h> #include "qt_in_scheduler.h" #include "qt_out_scheduler.h" #include "GenericBaseForm.h" namespace qt { using namespace nbc; class GenericForm : public GenericBaseForm { Q_OBJECT public: GenericForm(host::ihost * h, const GenericFormConfig & cfg, safe_bool & Shutdown, rmutex & form_creation_mtx); virtual ~GenericForm(); virtual void SetTitleError(bool on); virtual void SetTitle(str_cref title_str); virtual void SetHintText(str_cref hint_str); virtual bool AllowHide(); virtual void OnLanguageChange(lang_t) }; } base_language: #ifndef BASE_LANGAUAGE_H #define BASE_LANGAUAGE_H #include "base.h" namespace base { enum struct lang_t : char { default = -1, english = 0, german = 1, french = 2, }; base::str_t to_string(lang_t); lang_t from_string(base::str_cref); } #endif CMake.txt: CMAKE_MINIMUM_REQUIRED(VERSION 3.17.0 FATAL_ERROR) SET(VERSION_MAJOR 1) SET(VERSION_MINOR 0) SET(VERSION_PATCH 0) SET(PROJECT_NAME "lib_GenericForms") # find Qt5 and required components FIND_PACKAGE(Qt5 COMPONENTS REQUIRED Core Gui Widgets ) #need this to include the auto generated ui_mainwindow.h #file from the qt5_wrap_ui call below. IF(CMAKE_VERSION VERSION_LESS "3.7.0") SET(CMAKE_INCLUDE_CURRENT_DIR ON) ENDIF() INCLUDE_DIRECTORIES( ) ADD_DEFINITIONS( -DBUILD_STATIC -DQT_SUPPORT_LIB ) SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) SET(CMAKE_AUTORCC ON) SET(ENVIRONMENT_EXTENSION_DEBUG ${ENVIRONMENT_EXTENSION} ) SET(ENVIRONMENT_EXTENSION_RELEASE ${ENVIRONMENT_EXTENSION} ) #set project sources SET(PROJECT_SOURCES ${CMAKE_CURRENT_LIST_DIR}/GenericBaseForm.h ${CMAKE_CURRENT_LIST_DIR}/GenericBaseForm.cpp ${CMAKE_CURRENT_LIST_DIR}/GenericForm.h ${CMAKE_CURRENT_LIST_DIR}/GenericForm.cpp ${CMAKE_CURRENT_LIST_DIR}/GenericSensorForm.h ${CMAKE_CURRENT_LIST_DIR}/GenericSensorForm.cpp ) SET(PROJECT_RESOURCES ) #set project sources SET(PROJECT_UI ) # setup project ADD_LIBRARY(${PROJECT_NAME} STATIC ${PROJECT_SOURCES} ${UI_WRAP} ${MOC_SOURCES} ) TARGET_LINK_LIBRARIES( ${PROJECT_NAME} PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets ) GenerateVSUserFile( "${ENVIRONMENT_EXTENSION_DEBUG}" "${ENVIRONMENT_EXTENSION_RELEASE}" "$(TargetDir)" "$(TargetDir)" "$(TargetPath)" "$(TargetPath)" "" "" "${PROJECT_NAME}" ) GenerateVersionInfo( 1 0 0 "${PROJECT_NAME}" "${PROJECT_NAME}" "${PROJECT_NAME}.lib" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.rc" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_version.h" ) # Executables fail to build with Qt 5 in the default configuration # without -fPIE. We add that here. set(CMAKE_CXX_FLAGS "${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") #Set the target link subsystem SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS") #set compiler flasgs SET(COMPILER_FLAGS "${COMPILER_FLAGS} /MP") SET(COMPILER_FLAGS "${COMPILER_FLAGS} /EHsc") SET(COMPILER_FLAGS "${COMPILER_FLAGS} /Zc:wchar_t") SET(COMPILER_FLAGS "${COMPILER_FLAGS} /wd4290") SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${COMPILER_FLAGS}") SET(PROJECT_NAME_INCLUDES ${CMAKE_CURRENT_LIST_DIR} PARENT_SCOPE) SET(PROJECT_NAME_PROJECTNAME "${PROJECT_NAME}" PARENT_SCOPE)
C++: How to properly link compiled object using CMake in VSCode
OS Windows 10 CMake: 3.16.3 Editor VSCode: 1.48.1 Extensions CMake Tools: 1.4.1 C/C++ 0.30.0-insiders3 Kit Visual Studio Community 2019 Release - amd64 Project Repo https://gitlab.com/NumeralRocket/kepler Removed, insufficient for minimal reproducible example Tutorial Introduction to Google Test and CMake https://www.youtube.com/watch?v=Lp1ifh9TuFI I'm attempting to build unit tests for one of my personal projects using CMake, and while I wholly admit I am quite new to CMake and a novice at C++, I am stumped on how to resolve this problem. When I go to build my project I get the following Linker error: [main] Building folder: kepler [build] Starting build [proc] Executing command: "C:\Program Files\CMake\bin\cmake.EXE" --build n:/Unreal_Engine/Magellan/kepler/build-vscode --config Debug --target ALL_BUILD -- /maxcpucount:14 [build] Microsoft (R) Build Engine version 16.6.0+5ff7b0c9e for .NET Framework [build] Copyright (C) Microsoft Corporation. All rights reserved. [build] [build] gmock.vcxproj -> N:\Unreal_Engine\Magellan\kepler\build-vscode\lib\Debug\gmockd.lib [build] gmock_main.vcxproj -> N:\Unreal_Engine\Magellan\kepler\build-vscode\lib\Debug\gmock_maind.lib [build] kepler.vcxproj -> N:\Unreal_Engine\Magellan\kepler\build-vscode\Debug\kepler.lib [build] gtest.vcxproj -> N:\Unreal_Engine\Magellan\kepler\build-vscode\lib\Debug\gtestd.lib [build] gtest_main.vcxproj -> N:\Unreal_Engine\Magellan\kepler\build-vscode\lib\Debug\gtest_maind.lib [build] LINK : fatal error LNK1104: cannot open file 'Quaternion.lib' [N:\Unreal_Engine\Magellan\kepler\build-vscode\test\QuaternionTests.vcxproj] [cmakefileapi-parser] Code model version (2.1) of cmake-file-api is unexpected. Expecting (2.0). IntelliSense configuration may be incorrect. [cmakefileapi-parser] Code model version (2.1) of cmake-file-api is unexpected. Expecting (2.0). IntelliSense configuration may be incorrect. [build] Build finished with exit code 1 For context, the project is structured as follows: ${ProjectRoot} ├── CMakeLists.txt ├── Quaternion.cpp ├── Quaternion.hpp ├── googletest └── test ├── CMakeLists.txt └── QuaternionTest.cpp ${ProjectRoot}/CMakeLists.txt cmake_minimum_required(VERSION 3.16) # version can be different set(CMAKE_VERBOSE_MAKEFILE ON) set(This kepler) get_filename_component(CODE_ROOT ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) project(${This}) #name of your project project(${This} C CXX) set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 11) set(CMAKE_POSITION_INDEPENDENT_CODE ON) enable_testing() add_subdirectory(googletest) add_subdirectory(test) set(Headers Quaternion.hpp ) set(Sources Quaternion.cpp ) add_library(${This} STATIC ${Sources} ${Headers}) ${ProjectRoot}/Quaternion.cpp #include <iostream> #include "Quaternion.hpp" // Default Constructor Quaternion::Quaternion() {} // Specified Value Constructor Quaternion::Quaternion(double qs, double qi, double qj, double qk) : q0(qs), q1(qi), q2(qj), q3(qk) {} Quaternion operator + (Quaternion const &quatA, Quaternion const &quatB) // 1) § 5.3 { Quaternion quatC; quatC.q0 = quatA.q0 + quatB.q0; quatC.q1 = quatA.q1 + quatB.q1; quatC.q2 = quatA.q2 + quatB.q2; quatC.q3 = quatA.q3 + quatB.q3; return quatC; } Quaternion operator - (Quaternion const &quatA, Quaternion const &quatB) // 1) § 5.3 { Quaternion quatC; quatC.q0 = quatA.q0 - quatB.q0; quatC.q1 = quatA.q1 - quatB.q1; quatC.q2 = quatA.q2 - quatB.q2; quatC.q3 = quatA.q3 - quatB.q3; return quatC; } void QuaternionLog(Quaternion quat2log) { std::cout << "q0: " << quat2log.q0 << std::endl; std::cout << "q1: " << quat2log.q1 << std::endl; std::cout << "q2: " << quat2log.q2 << std::endl; std::cout << "q3: " << quat2log.q3 << std::endl; } int main() { Quaternion quat1; Quaternion quat2(1, 2, 3, 4); Quaternion quat3 = quat1 + quat2; Quaternion quat4 = quat1 - quat2; QuaternionLog(quat1); QuaternionLog(quat2); QuaternionLog(quat3); QuaternionLog(quat4); } ${ProjectRoot}/Quaternion.hpp #ifndef QUATERNION_H #define QUATERNION_H class Quaternion { public: double q0{ 1.0 }; double q1{ 0.0 }; double q2{ 0.0 }; double q3{ 0.0 }; Quaternion(); Quaternion(double qs, double qi, double qj, double qk); friend Quaternion operator + (Quaternion const &quatA, Quaternion const &quatB); friend Quaternion operator - (Quaternion const &quatA, Quaternion const &quatB); }; #endif /* QUATERNION_H */ ${ProjectRoot}/test/CMakeLists.txt cmake_minimum_required(VERSION 3.16) set(This QuaternionTests) set(Sources QuaternionTest.cpp ) add_executable(${This} ${Sources}) target_link_libraries(${This} PUBLIC gtest_main Quaternion ) add_test( NAME ${This} COMMAND ${This} ) ${ProjectRoot}/test/QuaternionTest.cpp #include <gtest/gtest.h> #include "../Quaternion.hpp" TEST(Quaternion, QuaternionConstructors) { Quaternion test_quat_1; ASSERT_EQ(test_quat_1.q0, 1); ASSERT_EQ(test_quat_1.q1, 0); ASSERT_EQ(test_quat_1.q2, 0); ASSERT_EQ(test_quat_1.q3, 0); ASSERT_EQ(1,1); }; int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }; How can I: Ensure and Inspect that objects are being built appropriately? Properly instruct CMake such that the linker can find my Quaternion (source code) object? Any insight would be appreciated.
My mistake was in adding my library incorrectly: ${ProjectRoot}/CMakeLists.txt cmake_minimum_required(VERSION 3.16) # version can be different set(CMAKE_VERBOSE_MAKEFILE ON) set(This kepler) get_filename_component(CODE_ROOT ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) project(${This}) #name of your project project(${This} C CXX) set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 11) set(CMAKE_POSITION_INDEPENDENT_CODE ON) enable_testing() add_subdirectory(googletest) add_subdirectory(test) set(Headers Quaternion.hpp ) set(Sources Quaternion.cpp ) add_library(${This} STATIC ${Sources} ${Headers}) I was adding a library named ${THIS} which was "kepler" instead of the expected "Quaternion", so: add_library(Quaternion STATIC ${Sources} ${Headers}) correctly tells the linker what/where to expect my library AND Leaving a main function in Quaternion.cpp, which was removed Solution Source: vector-of-bool
Adapting CMakeList.txt to run with CUDA
I'm working with a slam system, i've install dso, which the code can be seen here:: https://github.com/JakobEngel/dso Everything works fine, I manage to compile and run without errors. But know I want to parallelize the code, using CUDA. I'm having lot's of trouble adapting it's CMakeLists.txt in order to be able to use CUDA. The original CMakeLists from dso is available here: dso CMakeLists.txt I'm trying to adapt it basing my changes on this implementation of another author on another SLAM system: ORB SLAM 2 CMakeLists.txt using CUDA Right now my CMakeLists, with my changes (not working), is like this: SET(PROJECT_NAME DSO) PROJECT(${PROJECT_NAME}) CMAKE_MINIMUM_REQUIRED(VERSION 2.6) #set(CMAKE_VERBOSE_MAKEFILE ON) set(BUILD_TYPE Release) #set(BUILD_TYPE RelWithDebInfo) set(EXECUTABLE_OUTPUT_PATH bin) set(LIBRARY_OUTPUT_PATH lib) set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) # required libraries #SET(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "/usr/include") find_package(SuiteParse REQUIRED) find_package(Eigen3 REQUIRED) find_package(Boost) # optional libraries find_package(LibZip QUIET) find_package(Pangolin 0.2 QUIET) find_package(OpenCV QUIET) #find_package(OpenACC) # flags add_definitions("-DENABLE_SSE") set(CMAKE_CXX_FLAGS "${SSE_FLAGS} -O3 -g -std=c++11" ) set(CMAKE_C_FLAGS "${SSE_FLAGS} -O3 -g -std=c++11" ) #LIST(APPEND CMAKE_C_FLAGS "-Wall -Wextra -DUSE_NVTX") <<<< Error: doesn't recognize -Wall -Wextra #LIST(APPEND CMAKE_CXX_FLAGS "-Wall -Wextra -DUSE_NVTX") << Error: doesn't recognize -Wall -Wextra find_package(CUDA REQUIRED) set(CUDA_PROPAGATE_HOST_FLAGS OFF) SET(CUDA_HOST_COMPILER /usr/bin/g++) LIST(APPEND CUDA_NVCC_FLAGS "--compiler-options -fno-strict-aliasing -use_fast_math -ccbin gcc-5") set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -std=c++11") if (MSVC) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") endif (MSVC) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY lib) cuda_include_directories( ${CUDA_TOOLKIT_ROOT_DIR}/samples/common/inc ) # Sources files set(dso_SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/FullSystem/FullSystem.cpp ${PROJECT_SOURCE_DIR}/src/FullSystem/FullSystemOptimize.cpp ${PROJECT_SOURCE_DIR}/src/FullSystem/FullSystemOptPoint.cpp ${PROJECT_SOURCE_DIR}/src/FullSystem/FullSystemDebugStuff.cpp ${PROJECT_SOURCE_DIR}/src/FullSystem/FullSystemMarginalize.cpp ${PROJECT_SOURCE_DIR}/src/FullSystem/Residuals.cpp ${PROJECT_SOURCE_DIR}/src/FullSystem/CoarseTracker.cpp ${PROJECT_SOURCE_DIR}/src/FullSystem/CoarseInitializer.cpp ${PROJECT_SOURCE_DIR}/src/FullSystem/ImmaturePoint.cpp ${PROJECT_SOURCE_DIR}/src/FullSystem/HessianBlocks.cpp ${PROJECT_SOURCE_DIR}/src/FullSystem/PixelSelector2.cpp ${PROJECT_SOURCE_DIR}/src/OptimizationBackend/EnergyFunctional.cpp ${PROJECT_SOURCE_DIR}/src/OptimizationBackend/AccumulatedTopHessian.cpp ${PROJECT_SOURCE_DIR}/src/OptimizationBackend/AccumulatedSCHessian.cpp ${PROJECT_SOURCE_DIR}/src/OptimizationBackend/EnergyFunctionalStructs.cpp ${PROJECT_SOURCE_DIR}/src/util/settings.cpp ${PROJECT_SOURCE_DIR}/src/util/Undistort.cpp ${PROJECT_SOURCE_DIR}/src/util/globalCalib.cpp ) include_directories( ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/thirdparty/Sophus ${PROJECT_SOURCE_DIR}/thirdparty/sse2neon ${EIGEN3_INCLUDE_DIR} ) # decide if we have pangolin if (Pangolin_FOUND) message("--- found PANGOLIN, compiling dso_pangolin library.") include_directories( ${Pangolin_INCLUDE_DIRS} ) set(dso_pangolin_SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/IOWrapper/Pangolin/KeyFrameDisplay.cpp ${PROJECT_SOURCE_DIR}/src/IOWrapper/Pangolin/PangolinDSOViewer.cpp) set(HAS_PANGOLIN 1) else () message("--- could not find PANGOLIN, not compiling dso_pangolin library.") message(" this means there will be no 3D display / GUI available for dso_dataset.") set(dso_pangolin_SOURCE_FILES ) set(HAS_PANGOLIN 0) endif () # decide if we have openCV if (OpenCV_FOUND) message("--- found OpenCV, compiling dso_opencv library.") include_directories( ${OpenCV_INCLUDE_DIRS} ) set(dso_opencv_SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/IOWrapper/OpenCV/ImageDisplay_OpenCV.cpp ${PROJECT_SOURCE_DIR}/src/IOWrapper/OpenCV/ImageRW_OpenCV.cpp) set(HAS_OPENCV 1) else () message("--- could not find OpenCV, not compiling dso_opencv library.") message(" this means there will be no image display, and image read / load functionality.") set(dso_opencv_SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/IOWrapper/ImageDisplay_dummy.cpp ${PROJECT_SOURCE_DIR}/src/IOWrapper/ImageRW_dummy.cpp) set(HAS_OPENCV 0) endif () # decide if we have ziplib. if (LIBZIP_LIBRARY) message("--- found ziplib (${LIBZIP_VERSION}), compiling with zip capability.") add_definitions(-DHAS_ZIPLIB=1) include_directories( ${LIBZIP_INCLUDE_DIR_ZIP} ${LIBZIP_INCLUDE_DIR_ZIPCONF} ) else() message("--- not found ziplib (${LIBZIP_LIBRARY}), compiling without zip capability.") set(LIBZIP_LIBRARY "") endif() # compile main library. include_directories( ${CSPARSE_INCLUDE_DIR} ${CHOLMOD_INCLUDE_DIR}) cuda_add_library(dso SHARED ${dso_SOURCE_FILES} ${dso_opencv_SOURCE_FILES} ${dso_pangolin_SOURCE_FILES} ${PROJECT_SOURCE_DIR}/src/teste.cu ) #set_property( TARGET dso APPEND_STRING PROPERTY COMPILE_FLAGS -Wall ) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # OSX set(BOOST_THREAD_LIBRARY boost_thread-mt) else() set(BOOST_THREAD_LIBRARY boost_thread) endif() # build main executable (only if we have both OpenCV and Pangolin) if (OpenCV_FOUND AND Pangolin_FOUND) message("--- compiling dso_dataset.") add_executable(dso_dataset ${PROJECT_SOURCE_DIR}/src/main_dso_pangolin.cpp) target_link_libraries(dso_dataset dso boost_system cxsparse ${BOOST_THREAD_LIBRARY} ${LIBZIP_LIBRARY} ${Pangolin_LIBRARIES} ${OpenCV_LIBS}) else() message("--- not building dso_dataset, since either don't have openCV or Pangolin.") endif() unset(CMAKE_RUNTIME_OUTPUT_DIRECTORY) So, 'main_dso_pangolin.cpp' is my main file. At this point, with only this changes the code compiles. But i wanted to try if i was able to make some CUDA code. In order to do this I created a 'teste.cu' file, that has the same code as one of the cuda samples, like this: #include <stdlib.h> #include <stdio.h> #include <assert.h> // CUDA runtime #include </usr/local/cuda-9.0/include/cuda_runtime.h> #include <cuda.h> // helper functions and utilities to work with CUDA #include </usr/local/cuda-9.0/samples/common/inc/helper_functions.h> #include </usr/local/cuda-9.0/samples/common/inc/helper_cuda.h> __global__ static void timedReduction(const float *input, float *output, clock_t *timer) { // __shared__ float shared[2 * blockDim.x]; extern __shared__ float shared[]; const int tid = threadIdx.x; const int bid = blockIdx.x; if (tid == 0) timer[bid] = clock(); // Copy input. shared[tid] = input[tid]; shared[tid + blockDim.x] = input[tid + blockDim.x]; // Perform reduction to find minimum. for (int d = blockDim.x; d > 0; d /= 2) { __syncthreads(); if (tid < d) { float f0 = shared[tid]; float f1 = shared[tid + d]; if (f1 < f0) { shared[tid] = f1; } } } // Write result. if (tid == 0) output[bid] = shared[0]; __syncthreads(); if (tid == 0) timer[bid+gridDim.x] = clock(); } #define NUM_BLOCKS 64 #define NUM_THREADS 256 void xx(int argc, char** argv){ printf("CUDA Clock sample\n"); // This will pick the best possible CUDA capable device int dev = findCudaDevice(argc, (const char **)argv); float *dinput = NULL; float *doutput = NULL; clock_t *dtimer = NULL; clock_t timer[NUM_BLOCKS * 2]; float input[NUM_THREADS * 2]; for (int i = 0; i < NUM_THREADS * 2; i++) { input[i] = (float)i; } checkCudaErrors(cudaMalloc((void **)&dinput, sizeof(float) * NUM_THREADS * 2)); checkCudaErrors(cudaMalloc((void **)&doutput, sizeof(float) * NUM_BLOCKS)); checkCudaErrors(cudaMalloc((void **)&dtimer, sizeof(clock_t) * NUM_BLOCKS * 2)); checkCudaErrors(cudaMemcpy(dinput, input, sizeof(float) * NUM_THREADS * 2, cudaMemcpyHostToDevice)); timedReduction<<<NUM_BLOCKS, NUM_THREADS, sizeof(float) * 2 *NUM_THREADS>>>(dinput, doutput, dtimer); checkCudaErrors(cudaMemcpy(timer, dtimer, sizeof(clock_t) * NUM_BLOCKS * 2, cudaMemcpyDeviceToHost)); checkCudaErrors(cudaFree(dinput)); checkCudaErrors(cudaFree(doutput)); checkCudaErrors(cudaFree(dtimer)); long double avgElapsedClocks = 0; for (int i = 0; i < NUM_BLOCKS; i++) { avgElapsedClocks += (long double) (timer[i + NUM_BLOCKS] - timer[i]); } avgElapsedClocks = avgElapsedClocks/NUM_BLOCKS; printf("Average clocks/block = %Lf\n", avgElapsedClocks); } And in my main, the first thing i do is to call this function. This time, when i do 'cmake' and 'make i get errors like: /home/cesar/Documents/dso/src/teste.cu:18:21: error: ‘threadIdx’ was not declared in this scope const int tid = threadIdx.x; /home/cesar/Documents/dso/src/teste.cu:19:21: error: ‘blockIdx’ was not declared in this scope const int bid = blockIdx.x; I've install CUDA Toolkit correctly, but here is the version: cesar#cesar-X550JX:/usr/local/cuda/bin$ /usr/local/cuda/bin/nvcc --version nvcc: NVIDIA (R) Cuda compiler driver Copyright (c) 2005-2017 NVIDIA Corporation Built on Fri_Sep__1_21:08:03_CDT_2017 Cuda compilation tools, release 9.0, V9.0.176 What do you think i'm doing wrong or i'm missing? I'm having many difficulties adapting CMakeLists.txt due to its complexity and well defined structure. --- EDIT --- Running with make -j VERBOSE=1 i get this messages which tells me that a regular c++ compiler is being used: /usr/bin/c++ -fPIC -O3 -g -std=c++11 -D_FORCE_INLINES -shared -Wl,-soname,libdso.so -o lib/libdso.so CMakeFiles/dso.dir/src/FullSystem/FullSystem.cpp.o CMakeFiles/dso.dir/src/FullSystem/FullSystemOptimize.cpp.o CMakeFiles/dso.dir/src/FullSystem/FullSystemOptPoint.cpp.o CMakeFiles/dso.dir/src/FullSystem/FullSystemDebugStuff.cpp.o CMakeFiles/dso.dir/src/FullSystem/FullSystemMarginalize.cpp.o CMakeFiles/dso.dir/src/FullSystem/Residuals.cpp.o CMakeFiles/dso.dir/src/FullSystem/CoarseTracker.cpp.o CMakeFiles/dso.dir/src/FullSystem/CoarseInitializer.cpp.o CMakeFiles/dso.dir/src/FullSystem/ImmaturePoint.cpp.o CMakeFiles/dso.dir/src/FullSystem/HessianBlocks.cpp.o CMakeFiles/dso.dir/src/FullSystem/PixelSelector2.cpp.o CMakeFiles/dso.dir/src/OptimizationBackend/EnergyFunctional.cpp.o CMakeFiles/dso.dir/src/OptimizationBackend/AccumulatedTopHessian.cpp.o CMakeFiles/dso.dir/src/OptimizationBackend/AccumulatedSCHessian.cpp.o CMakeFiles/dso.dir/src/OptimizationBackend/EnergyFunctionalStructs.cpp.o CMakeFiles/dso.dir/src/util/settings.cpp.o CMakeFiles/dso.dir/src/util/Undistort.cpp.o CMakeFiles/dso.dir/src/util/globalCalib.cpp.o CMakeFiles/dso.dir/src/IOWrapper/OpenCV/ImageDisplay_OpenCV.cpp.o CMakeFiles/dso.dir/src/IOWrapper/OpenCV/ImageRW_OpenCV.cpp.o CMakeFiles/dso.dir/src/IOWrapper/Pangolin/KeyFrameDisplay.cpp.o CMakeFiles/dso.dir/src/IOWrapper/Pangolin/PangolinDSOViewer.cpp.o CMakeFiles/dso.dir/src/dso_generated_teste.cu.o /usr/local/cuda/lib64/libcudart_static.a -lpthread -ldl -lrt [ 96%] Building CXX object CMakeFiles/dso_dataset.dir/src/main_dso_pangolin.cpp.o /usr/bin/c++ -DENABLE_SSE -DHAS_ZIPLIB=1 -I/usr/include/opencv -I/home/cesar/Documents/dso/src -I/home/cesar/Documents/dso/thirdparty/Sophus -I/home/cesar/Documents/dso/thirdparty/sse2neon -I/usr/include/eigen3 -I/home/cesar/Documents/Pangolin/include -I/home/cesar/Documents/Pangolin/build/src/include -I/usr/local/include -I/usr/include/suitesparse -I/usr/local/cuda/include -O3 -g -std=c++11 -D_FORCE_INLINES -o CMakeFiles/dso_dataset.dir/src/main_dso_pangolin.cpp.o -c /home/cesar/Documents/dso/src/main_dso_pangolin.cpp I also tried to separate .cpp files from .cu files, used add_library for .cpp and cuda_add_library for .cu files, like this: add_library(dso ${dso_SOURCE_FILES} ${dso_opencv_SOURCE_FILES} ${dso_pangolin_SOURCE_FILES}) cuda_add_library(my_cuda_lib ${PROJECT_SOURCE_DIR}/src/teste.cu) And then use my_cuda_lib in target_link_libraries, like this: target_link_libraries(dso_dataset dso boost_system cxsparse ${BOOST_THREAD_LIBRARY} ${LIBZIP_LIBRARY} ${Pangolin_LIBRARIES} ${OpenCV_LIBS} ${CUDA_LIBRARIES} my_cuda_lib) But still got the same errors. -- EDIT: MCVE --- To demonstrate my error i created a simple example. I have 2 simple files, my main which is a .cpp and my cuda file .cu. My main just calls the function on the other file, looks like this: #include <iostream> #include "hello_world.cu" using namespace std; int main() { teste(); return 0; } And my .cu file looks like this: #include <stdio.h> #include <iostream> // CUDA runtime #include </usr/local/cuda-9.0/include/cuda_runtime.h> // helper functions and utilities to work with CUDA #include </usr/local/cuda-9.0/samples/common/inc/helper_functions.h> #include </usr/local/cuda-9.0/samples/common/inc/helper_cuda.h> __global__ void kernel (void){ extern __shared__ float shared[]; const int tid = threadIdx.x; const int bid = blockIdx.x; } int teste( void ) { kernel<<<1,1>>>(); printf( "Hello, World!\n" ); return 0; } My CMakeLists.txt that i made to compile this looks like this: cmake_minimum_required(VERSION 2.8) set(CUDA_HOST_COMPILER /usr/bin/g++-5) find_package(CUDA QUIET REQUIRED) # Pass options to NVCC set( CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS}; -O3 ) # For compilation ... # Specify target & source files to compile it from cuda_add_executable( helloworld hello_world.cu teste.cpp ) After making cmake and running with "cmake --build ." (i don't know why it has to be this command, normally i just do make -j, but in this example only this works) i get the same errors as in my project, ‘threadIdx’ was not declared in this scope, same for 'blockIdx' etc..
Since you are including hello_world.cu file in your main code, then you want to have it compiled with nvcc compiler. To achieve this change name of teste.cpp file to teste.cu (otherwise g++ will be used). Also remove 'hello_world.cu' from CMakeLists.txt (it is included already in teste file) to have something like this: cuda_add_executable( helloworld teste.cu ) Then it should work. -- EDIT: Additional question -- If you want to keep your .cpp file then you need kind of separation between what g++ can do for you and what nvcc should. So you can introduce to your project additional hello_world.h file: #ifndef HELLO_WORLD_H #define HELLO_WORLD_H int teste(); #endif include it in your teste.cpp: #include <iostream> #include "hello_world.h" using namespace std; int main() { teste(); return 0; } and then your CMakeLists.txt looks like in your original example: ... cuda_add_executable( helloworld teste.cpp hello_world.cu ) In such a case hello_world.cu will be compiled with nvcc, and then compilling and linking of teste.cpp will be done by g++ (which will be possible in that case since there is no CUDA code in teste.cpp).
Cannot connect mpg123 and ao in project with cmakelists
I am using the cmakelists.txt below, that exists in the top folder of my project, and I am trying to connect mpg123 and ao to my project. In one .cpp file of the source folder I added a code with mpg123 and ao to play a song. This code can be compiled with this line: g++ mpg.cpp -lmpg123 -lao -o mpg I also added this line: target_link_libraries(emotime ${LIBAO_LIBRARIES} ${MPG123_LIBRARIES}) in the cmakelists that exists in my source folder. When I am running make I get errors like "undefined reference to ao_initialize'" and "undefined reference tompg123_init'" in this piece of code: int playaudio(int trackid) { char * traklink=""; int tid=trackid; if (tid==1){ traklink= "/home/mixa/tutti_frutti.wav"; } else if (tid==2){ traklink= "/home/mixa/karavi.wav"; } else if (tid==3){ traklink= "/home/mixa/timon.wav"; } else if (tid==4){ traklink= "/home/mixa/hippo.wav"; } else{ traklink= "/home/mixa/nanourisma.wav"; } mpg123_handle *mh; unsigned char *buffer; size_t buffer_size; size_t done; int err; int driver; ao_device *dev; ao_sample_format format; int channels, encoding; long rate; /* if(argc < 2) exit(0); */ /* initializations */ ao_initialize(); driver = ao_default_driver_id(); mpg123_init(); mh = mpg123_new(NULL, &err); buffer_size = mpg123_outblock(mh); buffer = (unsigned char*) malloc(buffer_size * sizeof(unsigned char)); /* open the file and get the decoding format */ //mpg123_open(mh,traklink); mpg123_open(mh,traklink); mpg123_getformat(mh, &rate, &channels, &encoding); /* set the output format and open the output device */ format.bits = mpg123_encsize(encoding) * BITS; format.rate = rate; format.channels = channels; format.byte_format = AO_FMT_NATIVE; format.matrix = 0; dev = ao_open_live(driver, &format, NULL); /* decode and play */ while (mpg123_read(mh, buffer, buffer_size, &done) == MPG123_OK) //ao_play(dev, buffer, done); ao_play(dev, (char*)buffer, done); /* clean up */ free(buffer); ao_close(dev); mpg123_close(mh); mpg123_delete(mh); mpg123_exit(); ao_shutdown(); //system("mpg123 -q traklink"); // return 0; } void *threading (void *trackid) { long tid=(long)trackid; cout<<"sound plays on:Thread id, "<<tid<<endl; playaudio(tid); pthread_exit(NULL); } cmakelists: cmake_minimum_required(VERSION 2.8) project(emotime) find_package(OpenCV REQUIRED) include_directories(${OpenCV_INCLUDE_DIRS}) FIND_PATH( MPG123_INCLUDE_DIR1 NAMES mpg123.h PATH_SUFFIXES include PATHS ~/Library/Frameworks /Library/Frameworks /usr/local /usr /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave /opt extern/mpg123/ports/MSVC++ extern/mpg123/ports/Xcode ) IF( MPG123_INCLUDE_DIR1 ) SET( MPG123_INCLUDE_DIRS ${MPG123_INCLUDE_DIRS} ${MPG123_INCLUDE_DIR1} ) ENDIF( MPG123_INCLUDE_DIR1 ) # Include dir (May not be necessary on all platforms) FIND_PATH( MPG123_INCLUDE_DIR2 NAMES mpg123.h.in PATHS ~/Library/Frameworks /Library/Frameworks /usr/local /usr /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave /opt extern/mpg123/src/libmpg123 ) IF( MPG123_INCLUDE_DIR2 ) SET( MPG123_INCLUDE_DIRS ${MPG123_INCLUDE_DIRS} ${MPG123_INCLUDE_DIR2} ) ENDIF( MPG123_INCLUDE_DIR2 ) #MESSAGE( "MPG123_INCLUDE_DIR1: " ${MPG123_INCLUDE_DIR1} ) #MESSAGE( "MPG123_INCLUDE_DIR2: " ${MPG123_INCLUDE_DIR2} ) #MESSAGE( "MPG123_INCLUDE_DIRS: " ${MPG123_INCLUDE_DIRS} ) FIND_LIBRARY( MPG123_LIBRARIES NAMES mpg123 libmpg123.lib HINTS PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 Release Debug PATHS ~/Library/Frameworks /Library/Frameworks /usr/local /usr /sw /opt/local /opt/csw /opt extern/mpg123/ports/MSVC++/2005 extern/mpg123/ports/MSVC++/2008 extern/mpg123/ports/MSVC++/2008clr extern/mpg123/ports/MSVC++/2010 ) SET( MPG123_FOUND 0 ) IF( MPG123_LIBRARIES AND MPG123_INCLUDE_DIRS ) SET( MPG123_FOUND 1 ) MESSAGE( STATUS "mpg123 found!" ) ELSE( MPG123_LIBRARIES AND MPG123_INCLUDE_DIRS ) MESSAGE( STATUS "mpg123 not found..." ) ENDIF( MPG123_LIBRARIES AND MPG123_INCLUDE_DIRS ) FIND_PATH(LIBAO_INCLUDE_DIR ao.h /usr/include/ao /usr/local/include/ao) FIND_LIBRARY(LIBAO_LIBRARIES NAMES ao PATH /usr/lib /usr/local/lib) IF (LIBAO_INCLUDE_DIR AND LIBAO_LIBRARIES) SET(LIBAO_FOUND TRUE) ENDIF (LIBAO_INCLUDE_DIR AND LIBAO_LIBRARIES) IF (LIBAO_FOUND) IF (NOT LIBAO_FIND_QUIETLY) MESSAGE(STATUS "Found libao: ${LIBAO_LIBRARIES}") ENDIF (NOT LIBAO_FIND_QUIETLY) ELSE (LIBAO_FOUND) IF (LIBAO_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find libao") ENDIF (LIBAO_FIND_REQUIRED) ENDIF (LIBAO_FOUND) include_directories(${LIBAO_INCLUDE_DIR} ${MPG123_INCLUDE_DIRS}) set(ASSETDIR "${emotime_SOURCE_DIR}/assets" ) set(HEADERDIR "${emotime_SOURCE_DIR}/include" ) set(SRCDIR "${emotime_SOURCE_DIR}/src" ) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") add_subdirectory(src )
In CMake you achieve linking to those libraries using the following commands (don't add the libraries to CXX_FLAGS!): include_directories(${LIBAO_INCLUDE_DIR} ${MPG123_INCLUDE_DIRS}) target_link_libraries(target_name ${LIBAO_LIBRARIES} ${MPG123_LIBRARIES}) were target_name needs to be replaced by your actual target's name.
Undefined reference to "function name from external library"
I'm using Ubuntu 12 64 bit, installed fftw library version 2.1.5. I have a c++ project with use CMake to build the make file. This is my cmakelist.text: project(MP) cmake_minimum_required(VERSION 2.8) if(TYPE STREQUAL "Debug") set(CMAKE_BUILD_TYPE "Debug") else() set(CMAKE_BUILD_TYPE "Release") endif() if(CMAKE_COMPILER_IS_GNUCXX) add_definitions( -std=c++11 ) endif() find_package(GLUT REQUIRED) find_package(OpenGL REQUIRED) find_library(GLUI libglui.a ./vendor/lib) include_directories(${OPENGL_INCLUDE_DIR} ./vendor/include) LINK_DIRECTORIES(/usr/local/lib) LINK_DIRECTORIES(/usr/lib) LINK_DIRECTORIES(/usr/bin) aux_source_directory(. SRC_LIST) add_executable(${PROJECT_NAME} ${SRC_LIST}) target_link_libraries(${PROJECT_NAME} GL GLU glut ${GLUI}) When I tried running the make file create by Cmake, i got this problem: CMakeFiles/SciVis.dir/Simulation.cc.o: In function `Simulation::init_simulation(unsigned long)': Simulation.cc:(.text+0x2d5): undefined reference to `rfftw2d_create_plan' Simulation.cc:(.text+0x2ee): undefined reference to `rfftw2d_create_plan' CMakeFiles/SciVis.dir/Simulation.cc.o: In function `Simulation::solve()': Simulation.cc:(.text+0x881): undefined reference to `rfftwnd_one_real_to_complex' Simulation.cc:(.text+0x891): undefined reference to `rfftwnd_one_real_to_complex' Simulation.cc:(.text+0xa7f): undefined reference to `rfftwnd_one_complex_to_real' Simulation.cc:(.text+0xa8f): undefined reference to `rfftwnd_one_complex_to_real' CMakeFiles/SciVis.dir/Simulation.cc.o: In function `Simulation::FFT(int, void*)': Simulation.cc:(.text+0x390): undefined reference to `rfftwnd_one_complex_to_real' Simulation.cc:(.text+0x3a0): undefined reference to `rfftwnd_one_real_to_complex' collect2: error: ld returned 1 exit status make[2]: *** [SciVis] Error 1 make[1]: *** [CMakeFiles/SciVis.dir/all] Error 2 make: *** [all] Error 2 In my Simulation.cc file: #include <fftw.h> void Simulation::init_simulation(size_t n) { //Allocate data structures size_t dim = n * 2 * (n / 2 + 1); vx = new fftw_real[dim]; vy = new fftw_real[dim]; vx0 = new fftw_real[dim]; vy0 = new fftw_real[dim]; fx = new fftw_real[n * n]; fy = new fftw_real[n * n]; rho = new fftw_real[n * n]; rho0 = new fftw_real[n * n]; plan_rc = rfftw2d_create_plan(n, n, FFTW_REAL_TO_COMPLEX, FFTW_IN_PLACE); plan_cr = rfftw2d_create_plan(n, n, FFTW_COMPLEX_TO_REAL, FFTW_IN_PLACE); // Initialize data structures to 0 for (size_t i = 0; i < n * n; i++) { vx[i] = vy[i] = vx0[i] = vy0[i] = fx[i] = fy[i] = rho[i] = rho0[i] = 0.0f; } } void Simulation::FFT(int direction,void* vx) { if(direction==1) rfftwnd_one_real_to_complex(plan_rc,(fftw_real*)vx,(fftw_complex*)vx); else rfftwnd_one_complex_to_real(plan_cr,(fftw_complex*)vx,(fftw_real*)vx); } I dont know where I were wrong, can someone please help me ? Thank you very much.
You're not linking against FFTW, you need to make CMake find the library and link against it first, put this file in your project's directory under a new folder "CMakeModules". FindFFTW.cmake # - Find FFTW # Find the native FFTW includes and library # # FFTW_INCLUDES - where to find fftw3.h # FFTW_LIBRARIES - List of libraries when using FFTW. # FFTW_FOUND - True if FFTW found. if (FFTW_INCLUDES) # Already in cache, be silent set (FFTW_FIND_QUIETLY TRUE) endif (FFTW_INCLUDES) find_path (FFTW_INCLUDES fftw3.h) find_library (FFTW_LIBRARIES NAMES fftw3) # handle the QUIETLY and REQUIRED arguments and set FFTW_FOUND to TRUE if # all listed variables are TRUE include (FindPackageHandleStandardArgs) find_package_handle_standard_args (FFTW DEFAULT_MSG FFTW_LIBRARIES FFTW_INCLUDES) mark_as_advanced (FFTW_LIBRARIES FFTW_INCLUDES) Next, add this line to the top of your CMakeLists.txt: project(MP) cmake_minimum_required(VERSION 2.8) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules" ${CMAKE_MODULE_PATH}) Now try this: find_package(FFTW REQUIRED) include_directories(${OPENGL_INCLUDE_DIR} ${FFTW_INCLUDES} ./vendor/include) ... target_link_libraries(${PROJECT_NAME} GL GLU glut ${GLUI} ${FFTW_LIBRARIES})