The buildtime of my cuda library is increasing and so I thought that separate compilation introduced in CUDA 5.0 might help me. I couldn't figure out how to achieve separate compilation with cmake. I looked into the NVCC documentation and found how to compile device object (using the -dc option) and how to link them (using the -dlink). My attempts to get it running using cmake failed. I'm using cmake 2.8.10.2 and the head of the trunk of the FindCUDA.cmake. I couldn't however find out how to specify which files should be compiled and how to link them into a library.
Especially the syntax of the function(CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS output_file_var cuda_target options object_files source_files)
is unclear to me because I don't know what the output_file_var and the cuda_target are.
Here the not working results of my attemps:
cuda_compile(DEVICEMANAGER_O devicemanager.cu OPTIONS -dc)
cuda_compile(BLUB_O blub.cu OPTIONS -dc)
CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS(TEST_O gpuacceleration
"" DEVICEMANGER_O BLUB_O)
set(LIB_TYPE SHARED)
#cuda_add_library(gpuacceleration ${LIB_TYPE}
#${gpuacc_SRCS}
#devicemanager.cu
# blub.cu
#DEVICEMANAGER_O
# TEST_O
#)
Does anyone know how to compile and link a cuda library using cmake?
Thanks in advance.
EDIT:
After a friend consulted the developer of the FindCUDA.cmake, a bug got fixed in the example provided with FindCUDA.cmake (https://gforge.sci.utah.edu/gf/project/findcuda/scmsvn/?action=browse&path=%2Fcheckout%2Ftrunk%2FFindCuda.html).
I'm now able to build the example.
In my project I can build the library as needed using the following (cmake 2.8.10 required):
set(LIB_TYPE SHARED)
set(CUDA_SEPARABLE_COMPILATION ON)
cuda_add_library(gpuacceleration ${LIB_TYPE}
blub.cu
blab.cu
)
BUT:
I cannot link against this library. When I builded the lib without separate compilation i was able to link against it.
Now getting the following error:
undefined reference to `__cudaRegisterLinkedBinary_53_tmpxft_00005ab4_00000000_6_blub_cpp1_ii_d07d5695'
for every file with a function used in the interface. Seems strange since it builds without any warning etc.
Any ideas how to get this working?
EDIT:
I finally figured out how to do this. See #PHD's and my answer for details.
I finally got it running ;)
In Addition to the answer of #PHD and my comment on it I modified: set(BUILD_SHARED_LIBS OFF) in my CMakeLists.txt since shared libs are not supported for separate compilation according to the nvcc manually v5.0 page 40.
In addition to that use the latest rev (1223) from the repository instead of rev 1221. I contacted the developer and he fixed some issue blocking this.
This revision doesn't set the nvcc -arch=sm_xx flag correctly, so I added this manually for my project and informed the developer of FindCUDA.cmake. So this might get fixed in the future.
Don't forget to get cmake > 2.8.10 for this to work.
Hope this helps anyone but me ;)
Here is my CMakeLists.txt:
#Required for CUDA-Check
cmake_minimum_required(VERSION 2.8.10)
project(gpulib)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake/cuda" ${CMAKE_MODULE_PATH})
# ============================================
# === Target
# ============================================
file(GLOB_RECURSE gpuacc_SRCS "*.cu")
include_directories(.)
# ---------------------------------------
# Find Cuda
find_package(CUDA REQUIRED)
set(CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE ON)
set(BUILD_SHARED_LIBS OFF)
set(CUDA_SEPARABLE_COMPILATION ON)
#list(APPEND CUDA_NVCC_FLAGS -arch=sm_20)
set(LIB_NAME "gpuacceleration")
cuda_add_library(${LIB_NAME}
${gpuacc_SRCS}
OPTIONS -DSTUFF="blah blah"
RELEASE -DNDEBUG
DEBUG -g -DDEBUG
)
set(PUBLIC_HEADERS "myheader1.h;myheader2.h")
INSTALL(FILES ${PUBLIC_HEADERS} DESTINATION include)
INSTALL(FILES "${CMAKE_BINARY_DIR}/src/lib${LIB_NAME}.a" DESTINATION lib)
EDIT: this is not working!
The problem is that there are undefined references to all cuda functions (eg. cudaMalloc) when linking the generated library when building a executable in the main project.
Still working on it
EDIT (2016-03-15): Yes, it is confirmed as a bug in FindCUDA: https://cmake.org/Bug/view.php?id=15157
TL;DR: This seems to be a bug in FindCUDA, which makes objects lose info on external definitions before the final linking.
The problem is that, even if separable compilation is enabled, a linking step is still performed for all the targets individually before the final linking.
For instance, I have module.cu with:
#include "module.h"
#include <cstdio>
double arr[10] = {1,2,3,4,5,6,7,8,9,10};
__constant__ double carr[10];
void init_carr() {
cudaMemcpyToSymbol(carr,arr,10*sizeof(double));
}
__global__ void pkernel() {
printf("(pkernel) carr[%d]=%g\n",threadIdx.x,carr[threadIdx.x]);
}
void print_carr() {
printf("in print_carr\n");
pkernel<<<1,10>>>();
}
and module.h with:
extern __constant__ double carr[10];
extern double arr[10];
void print_carr();
void init_carr();
and finally main.cu with:
#include "module.h"
#include <cstdio>
__global__ void kernel() {
printf("(kernel) carr[%d]=%g\n",threadIdx.x,carr[threadIdx.x]);
}
int main(int argc, char *argv[]) {
printf("arr: %g %g %g ..\n",arr[0],arr[1],arr[2]);
kernel<<<1,10>>>();
cudaDeviceSynchronize();
print_carr();
cudaDeviceSynchronize();
init_carr();
cudaDeviceSynchronize();
kernel<<<1,10>>>();
cudaDeviceSynchronize();
print_carr();
cudaDeviceSynchronize();
return 0;
}
This then works fine with the following Makefile:
NVCC=nvcc
NVCCFLAGS=-arch=sm_20
LIB=libmodule.a
OBJS=module.o main.o
PROG=extern
$(PROG): main.o libmodule.a
$(NVCC) $(NVCCFLAGS) -o $# $^
%.o: %.cu
$(NVCC) $(NVCCFLAGS) -dc -c -o $# $^
$(LIB): module.o
ar cr $# $^
clean:
$(RM) $(PROG) $(OBJS) $(LIB)
But then I try to use the following CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
PROJECT(extern)
FIND_PACKAGE(CUDA REQUIRED)
SET(CUDA_SEPARABLE_COMPILATION ON)
SITE_NAME(HOSTNAME)
SET(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -arch=sm_20)
cuda_add_library(module module.cu)
CUDA_ADD_EXECUTABLE(extern main.cu)
TARGET_LINK_LIBRARIES(extern module)
When then compiling, what then happens is that the following:
$ cmake ..
-- The C compiler identification is GNU 4.9.2
...
$ make VERBOSE=1
...
[ 25%] Building NVCC (Device) object CMakeFiles/module.dir//./module_generated_module.cu.o
...
-- Generating <...>/build/CMakeFiles/module.dir//./module_generated_module.cu.o
/usr/local/cuda/bin/nvcc <...>/module.cu -dc -o <...>/build/CMakeFiles/module.dir//./module_generated_module.cu.o -ccbin /usr/bin/cc -m64 -Xcompiler ,\"-g\" -arch=sm_20 -DNVCC -I/usr/local/cuda/include
[ 50%] Building NVCC intermediate link file CMakeFiles/module.dir/./module_intermediate_link.o
/usr/local/cuda/bin/nvcc -arch=sm_20 -m64 -ccbin "/usr/bin/cc" -dlink <...>/build/CMakeFiles/module.dir//./module_generated_module.cu.o -o <...>/build/CMakeFiles/module.dir/./module_intermediate_link.o
...
/usr/bin/ar cr libmodule.a CMakeFiles/module.dir/./module_generated_module.cu.o CMakeFiles/module.dir/./module_intermediate_link.o
/usr/bin/ranlib libmodule.a
...
[ 50%] Built target module
[ 75%] Building NVCC (Device) object CMakeFiles/extern.dir//./extern_generated_main.cu.o
...
-- Generating <...>/build/CMakeFiles/extern.dir//./extern_generated_main.cu.o
/usr/local/cuda/bin/nvcc <...>/main.cu -dc -o <...>/build/CMakeFiles/extern.dir//./extern_generated_main.cu.o -ccbin /usr/bin/cc -m64 -Xcompiler ,\"-g\" -arch=sm_20 -DNVCC -I/usr/local/cuda/include -I/usr/local/cuda/include
...
[100%] Building NVCC intermediate link file CMakeFiles/extern.dir/./extern_intermediate_link.o
/usr/local/cuda/bin/nvcc -arch=sm_20 -m64 -ccbin "/usr/bin/cc" -dlink <...>/build/CMakeFiles/extern.dir//./extern_generated_main.cu.o -o <...>/build/CMakeFiles/extern.dir/./extern_intermediate_link.o
nvlink error : Undefined reference to 'carr' in '<...>/build/CMakeFiles/extern.dir//./extern_generated_main.cu.o'
Clearly, the problem are the nvcc -dlink obj.o -o obj_intermediate_link.o lines. Then, I guess, the info on external definitions are lost. So, the question is, it is possible to make CMake/FindCUDA not do this extra linking step?
Otherwise, I would argue that this is a bug. Do you agree? I can file a bug report with CMake.
Tested it with nvcc version:
nvcc: NVIDIA (R) Cuda compiler driver Copyright (c) 2005-2012 NVIDIA
Corporation Built on Fri_Sep_21_17:28:58_PDT_2012 Cuda compilation
tools, release 5.0, V0.2.1221
and svn revision:
URL: https://gforge.sci.utah.edu/svn/findcuda/trunk
Repository Root: https://gforge.sci.utah.edu/svn/findcuda
Repository UUID: 81322f20-870f-0410-845c-a4cd4664c908
Revision: 1221
Node Kind: directory
Schedule: normal
Last Changed Rev: 1221
Last Changed Date: 2013-01-28 22:31:07 +0100 (Mon, 28 Jan 2013)
In this example includes following classes:
lib.h / lib.cu
kernel.h / kernel.cu
kernel.cu contains a simple CUDA kernel and a class with a public method to call the CUDA kernel. The class lib contains an instance of the class kernel and a method calling the public method of class kernel.
Following CMakeLists.txt works with this configuration:
cmake_minimum_required(VERSION 2.6.2)
project(Cuda-project)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake/cuda" ${CMAKE_MODULE_PATH})
find_package(CUDA QUIET REQUIRED)
set(CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE OFF)
set(BUILD_SHARED_LIBS ON)
list(APPEND CUDA_NVCC_FLAGS -DBLAH="he he" -DTEST1="this is a test")
CUDA_ADD_LIBRARY(test_lib
kernel.cu
lib.cu
# SHARED
# STATIC
OPTIONS -DSTUFF="blah blah"
RELEASE --use_fast_math -DNDEBUG
DEBUG -g -DDEBUG
)
INSTALL(FILES lib.h kernel.h
DESTINATION include)
INSTALL(FILES "${CMAKE_BINARY_DIR}/libtest_lib.so"
DESTINATION lib)
I couldn't make it works using CUDA_ADD_EXECUTABLE so I created a function that makes a custom target to do so.
function(add_cuda_exe_lib name files libraries is_lib)
set (obj_list)
foreach(file ${files})
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${file}.o
DEPENDS ${file}
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --blue "Building NVCC Device object ${CMAKE_CURRENT_SOURCE_DIR}/${file}"
COMMAND ${CUDA_NVCC_EXECUTABLE} ${CUDA_NVCC_FLAGS} -dc "${CMAKE_CURRENT_SOURCE_DIR}/${file}" -o "${CMAKE_CURRENT_BINARY_DIR}/${file}.o"
COMMENT "Building ${CMAKE_CURRENT_SOURCE_DIR}/${file}"
VERBATIM
)
LIST(APPEND obj_list ${CMAKE_CURRENT_BINARY_DIR}/${file}.o)
endforeach()
set (lib_list)
LIST(APPEND lib_list "-lcudadevrt")
foreach(library_name ${libraries})
LIST(APPEND lib_list "-l${library_name}")
endforeach()
set (flags ${CUDA_NVCC_FLAGS})
if (is_lib)
LIST(APPEND flags "-dlink")
set (obj_name "${CMAKE_CURRENT_BINARY_DIR}/${name}.so")
else()
set (obj_name "${CMAKE_CURRENT_BINARY_DIR}/${name}")
endif()
add_custom_target(${name} ALL
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red "Linking CXX executable ${name}"
COMMAND ${CUDA_NVCC_EXECUTABLE} ${flags} ${obj_list} ${lib_list} -o ${obj_name}
DEPENDS ${obj_list}
COMMENT "Linking ${name}"
)
endfunction()
function(add_cuda_exe name files libraries)
add_cuda_exe_lib(${name} "${files}" "${libraries}" OFF)
endfunction()
function(add_cuda_lib name files libraries)
add_cuda_exe_lib(${name} "${files}" "${libraries}" ON)
endfunction()
Now, to generate a lib, just use:
add_cuda_lib(testar "devicemanager.cu;blub.cu" "")
Or this to generate an executable:
add_cuda_exe(testar "devicemanager.cu;blub.cu" "")
The last param is a list of libs to be attached.
I hope it helps.
Related
When trying to run Repast HPC executables I get the following error:
./main.exe: error while loading shared libraries: libboost_mpi-mt.so.1.61.0: cannot open shared object file: No such file or directory ./main.exe: error while loading shared libraries: libboost_mpi-mt.so.1.61.0: cannot open shared object
In the make file I define the link to boost in an env file with the below:
BOOST_INCLUDE= -I$(HOME)/sfw/Boost/Boost_1.61/include/
BOOST_LIB_DIR= -L$(HOME)/sfw/Boost/Boost_1.61/lib/
This is linked to a make file with the following make file
include ./env
.PHONY: clean
clean:
rm -f *.o
rm -f *.exe
.PHONY: compile
compile:
$(MPICXX) $(BOOST_INCLUDE) -c Main.cpp -o Main.o
$(MPICXX) $(BOOST_LIB_DIR) -o main.exe Main.o $(BOOST_LIBS)
.PHONY: all
all: clean compile
Boost in tsnow#DESKTOP-IF7CEHL:~/sfw/Boost/Boost_1.61/lib$ so it should link well across.
Any help appreciated, just trying to get a tutorial running.
We typically don't link repast to boost, but rather use rpath to let the model executable know where the boost and repast libraries are. For example in your Makefile:
REPAST_LIB_DIR = $(REPAST_HOME)/lib
BOOST_LIB_DIR = $(HOME)/theta/sfw/boost-1.66.0/lib
RPATHS += -Wl,-rpath -Wl,$(REPAST_LIB_DIR) -Wl,-rpath -Wl,$(BOOST_LIB_DIR)
and then add $(RPATHS) after the list of libraries during linking.
model : $(EXEC_OBJECTS)
$(CXXLD) -fopenmp -dynamic $^ $(LIBS) $(RPATHS) -o $(NAME)
Some of those args might not be appropriate for WSL, but hopefully the RPATHS part makes sense.
So, if after your include directive, you add
RPATHS=-Wl,-rpath -Wl,$(BOOST_LIB_DIR)
and update the second line of your compile target with
$(MPICXX) $(BOOST_LIB_DIR) -o main.exe Main.o $(BOOST_LIBS) $(RPATHS)
The location of your boost libs is compiled into main.exe, and it should find it.
The command:
export LD_LIBRARY_PATH=/home/tsnow/sfw/Boost/Boost_1.61/lib/
allowed boost to be found.
I want to accomplish a c++ executable that links to another c++ library of my own without a libstdc++ dependency. I can create such a c++ executable without the library without difficulty. But as soon as I link it to my library, the executable now has a libstdc++ dependency. A requirement is to NOT need to copy libstdc++6.dll (or any other .dll) onto Windows.
I'm building on Linux (Centos 7) using the latest mingw64 (x86_64-w64-mingw32-gcc (GCC) 4.9.3), cross compiling to Windows. Building on MSYS2/MingW has the same unwanted result.
(BTW, I have both libstdc++-static and glibc-static installed)
In the example, two lines are marked "COMMENT ME OUT": one in hello_c/main.cpp and the other in hello_c/CMakeLists.txt. If you comment these out, the reference to the hello_lib library is removed; the project builds and the executable executes on Windows 10 without a libstdc++ dependency. If you uncomment the two lines, the function in the hello_lib library is linked in; the project builds, but won't execute on Windows 10 due to the libstdc++ dependency. (Note: in powershell it silently fails, in an old-school dos/cmd box it displays an error message.)
The example has this structure:
hello_lib/library.cpp
hello_lib/library.h
hello_lib/CMakeLists.txt
hello_c/main.cpp
hello_c/CMakeLists.xt
buildme.sh
toolchain.cmake
## hello_lib/library.h:
int hello();
// hello_lib/library.cpp:
#include "library.h"
int hello() {
return 666;
}
## hello_lib CMakeLists.txt:
cmake_minimum_required(VERSION 3.13)
project(hello_lib)
set(CMAKE_CXX_STANDARD 11)
if(MINGW)
# Including these flags on Linux on Linux build = "Missing ELF Interpreter" error
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static -static-libgcc -static-libstdc++")
endif()
add_library(hello_lib STATIC library.cpp)
## hello_c/main.cpp:
#include <iostream>
#include "../hello_lib/library.h"
int main() {
std::cout << "Hello, world" << std::endl;
//COMMENT ME OUT:
printf("x = %d\n", hello());
return 0;
}
## hello_c CMakeLists.txt:
cmake_minimum_required(VERSION 3.13)
project(hello_c)
set(CMAKE_CXX_STANDARD 11)
if(MINGW)
# Including these flags on Linux on Linux build = "Missing ELF Interpreter" error
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static -static-libgcc -static-libstdc++")
endif()
link_directories(../hello_lib/cmake-build-debug)
add_executable(hello_c main.cpp)
# COMMENT ME OUT:
target_link_libraries(hello_c -static-libgcc -static-libstdc++ libhello_lib.a)
## buildme.sh:
#!/bin/bash
set -e
for i in hello_lib hello_c
do
rm -rf $i/cmake-build-debug
mkdir $i/cmake-build-debug
pushd $i/cmake-build-debug
# For building Win64 on Linux (with MinW64):
cmake .. -DCMAKE_TOOLCHAIN_FILE="../toolchain.cmake" -DCMAKE_BUILD_TYPE=Debug
# For building Win64 on Win64/MSYS2/MinW64:
#cmake .. -G "MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug
# For building Linux on Linux
#cmake .. -DCMAKE_BUILD_TYPE=Debug
make
popd
done
## toolchain.cmake:
set(CMAKE_SYSTEM_NAME Windows)
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
With both MingW64 on Linux, and MingW64/MSYS2 on Windows 10, I get the libstdc++ dependency when I link with the 'hello_lib' library. In both cases if I comment out the reference to hello_lib, the libstdc++ dependency is eliminated.
I wrote some C++ files to create a shared library, and here is my Makefile
PYTHON_VERSION = 3.6
PYTHON_HOME_PATH = /Library/Frameworks/Python.framework/Versions
PYTHON_INCLUDE = $(PYTHON_HOME_PATH)/$(PYTHON_VERSION)
BOOST_INC = /usr/local/Cellar/boost/1.67.0_1/include
BOOST_LIB = /usr/local/Cellar/boost/1.67.0_1/lib
BOOST_PYTHON_LIB = /usr/local/Cellar/boost-python3/1.67.0_1/lib/
TARGET = main
EXTEND_FILE = main_ext
$(TARGET).so:$(TARGET).o
g++ -shared depend.o -L$(BOOST_LIB) -L$(BOOST_PYTHON_LIB) -lboost_python3 `python3.6m-config --libs --ldflags` -o depend_ext.so
g++ -shared depend.o $(TARGET).o -L$(BOOST_LIB) -L$(BOOST_PYTHON_LIB) -lboost_python3 `python3.6m-config --libs --ldflags` -o $(TARGET).so
mv $(TARGET).so $(EXTEND_FILE).so
depend.o:depend.cpp
g++ `python3.6m-config --include` -fPIC -c depend.cpp -O3 -std=c++11
$(TARGET).o:$(TARGET).cpp
g++ `python3.6m-config --include` -fPIC -c depend.cpp $(TARGET).cpp -O3 -std=c++11
clean:
rm *.so *.o
The Makefile can generate the .so file. And my CMakeLists.txt is
cmake_minimum_required(VERSION 3.8)
project(Simulator)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES depend.cpp depend.h main.cpp main.h)
add_executable(Simulator ${SOURCE_FILES})
set(Boost_INCLUDE_DIRS /usr/local/Cellar/boost/1.67.0_1/include)
set(Boost_LIBRARIES /usr/local/Cellar/boost/1.67.0_1/lib)
set(BOOST_PYTHON_LIB /usr/local/Cellar/boost-python3/1.67.0_1/lib/)
find_package(Boost COMPONENTS filesystem system date_time python REQUIRED)
message("--> Include dirs of boost: " ${Boost_INCLUDE_DIRS} )
message("--> Libs of boost: " ${Boost_LIBRARIES} )
find_package(PythonLibs 3.6 REQUIRED)
message("--> Include dirs of Python: " ${PYTHON_INCLUDE_DIRS} )
message("--> Libs of Python: " ${PYTHON_LIBRARIES} )
include_directories(
${Boost_INCLUDE_DIRS}
${PYTHON_INCLUDE_DIRS}
)
target_link_libraries(Simulator
${Boost_LIBRARIES}
${PYTHON_LIBRARIES}
${BOOST_PYTHON_LIB}
)
But running CMake gives the following errors
CMake Error at /usr/local/Cellar/cmake/3.10.2/share/cmake/Modules/FindBoost.cmake:1928 (message):
Unable to find the requested Boost libraries.
Boost version: 1.67.0
Boost include path: /usr/local/include
Could not find the following Boost libraries:
boost_python3
I want to build it with Python3 and I have already install boost.python3. How can I fix it?
I think the problem is that Homebrew installs boost_python under a separate directory (i.e. /usr/local/Cellar/boost-python3/1.67.0_1/) which is different from the rest of the Boost installation (i.e. /usr/local/Cellar/boost/1.67.0_1).
I'm not on a Mac, thus I'm not exactly certain of the actual directory structure and how much can be done with symlinks (symlinking the Boost Python component directories back into the main Boost installation dir).
So, I built and installed (on Ubuntu Linux) from source the latest Boost version (1.68) using
./bootstrap.sh --prefix=/bulk/workbench/boost/install --with-python=python3
All components ended up under the include and lib directories in /bulk/workbench/boost/install. Providing that during CMake configuration as in
cmake -DBoost_ROOT=/bulk/workbench/boost/install [path-to-my-project-source-dir]
and using this in my CMakeLists.txt
find_package(Boost COMPONENTS python REQUIRED)
it was able to find my boost_python module.
Basically, unless you're able to twist the Homebrew installation, it might be more straightforward to build your own Boost.
I'm trying to build a simple GTK+ app on Windows (64 bit) using CMake. I've installed everything according to the official guide.
Here's the contents of my CMakeLists.txt:
# Set project
project(gtk-test C)
cmake_minimum_required(VERSION 3.0)
# Configure project paths
set(PROJECT_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
# Find dependencies
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
include_directories(${GTK3_INCLUDE_DIRS})
link_directories(${GTK3_LIBRARY_DIRS})
add_definitions(${GTK3_CFLAGS_OTHER})
set(LIBRARIES ${LIBRARIES} ${GTK3_LIBRARIES})
# Compile
add_executable(main ${PROJECT_SOURCE_DIR}/main.c)
target_link_libraries(main ${LIBRARIES})
# Messages
message(STATUS "GTK include directories: ${GTK3_INCLUDE_DIRS}")
and then I'm building the source file with the following:
cmake -Bbuild -H.
cmake --build build
Everything seems to work fine on macOS, but on Windows I keep getting the following error:
fatal error: gtk/gtk.h: No such file or directory
#include <gtk/gtk.h>
I checked the directory included by CMake and the header file is there. Also, the following command from the tutorial successfully builds the application:
gcc `pkg-config --cflags gtk+-3.0` -o main.exe main.c `pkg-config --libs gtk+-3.0`
Still, I would really love to get it working with CMake. I've been searching for the solution for hours now with no result, so any help would be highly appreciated.
Thanks in advance!
Update
Apparently, the whole problem lies within included libraries. For some reason, the line:
include_directories(${GTK3_INCLUDE_DIRS})
does not include them. I managed to fix the problem including libraries myself with -I option:
# Set project
cmake_minimum_required(VERSION 3.0)
project(gtk-test C)
# Configure project paths
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
set(CMAKE_SOURCE_DIR ${CMAKE_SOURCE_DIR}/src)
# Find dependencies
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
link_directories(${GTK3_LIBRARY_DIRS})
add_compile_options(${GTK3_CFLAGS_OTHER})
set(LIBRARIES ${LIBRARIES} ${GTK3_LIBRARIES})
set(FLAGS "-I${GTK3_INCLUDE_DIRS}")
message(STATUS "Flags: ${FLAGS}")
string(REPLACE ";" " -I" FLAGS "${FLAGS}")
set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} ${GTK3_FLAGS} ${FLAGS})
# Compile
add_executable(main ${PROJECT_SOURCE_DIR}/main.c)
target_link_libraries(main ${LIBRARIES})
Although it seems to work, this does not look like a good solution to me.
I'm having an issue when compiling a program with CMake 2.8.9 and Boost 1.49, on Ubuntu 12.10 (libboost installed via repos). Currently, the program is just some shared libs and an executable (which doesn't use the libs yet). The executable uses boost::program_options to parse input.
It is laid out like this (there will be more directories, such as a shared library and includes, but they don't feature in the CMake yet):
src
|- tools
| |- CMakeLists.txt
| |- main.cpp <-- main executable
|- CMakeLists.txt
When I compile manually, it works, but when I CMake it, it corrupts some text and then segfaults at the end. The program code so far is simply exactly the "first" program from the program_options docs (you can see it here).
The manual compilation command I used is:
g++ -Wall -o myapp src/tools/main.cpp -lboost_program_options
which gives the correct output with myapp --help:
Allowed options:
--help produce help message
--compression arg set compression level
The CMake files look like this:
# src/CmakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(testApp CXX)
FIND_PACKAGE( Boost COMPONENTS program_options REQUIRED)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR})
ADD_DEFINITIONS(-g -O2
-fsigned-char -freg-struct-return
-Wall -W -Wshadow -Wpointer-arith -Wcast-qual -Winline -Werror)
ADD_SUBDIRECTORY(tools)
# src/tools/CmakeLists.txt
ADD_EXECUTABLE(main main.cpp)
TARGET_LINK_LIBRARIES(main
${Boost_LIBRARIES})
#rename to the final outut name
SET_TARGET_PROPERTIES(main
PROPERTIES OUTPUT_NAME myapp)
When I then run myapp --help, I get the following output:
,#:
--help produce help message
--compression arg set compression level
Segmentation fault (core dumped)
The "#" symbol often changes to other, such as "`", "�" and Unicode-codepoints-in-boxes, which implies it is printing junk memory to me.
What am I doing wrong in this CMake setup?
My guess. The usage of add_definitions is wrong. It is intended for pre-processor macros not compiler options. I am not sure how this will interfere with the final output, but it is a starting point.
Rewrite your cmakelists.txt file for your compiler options as given here.
This was caused by the use of the -freg-struct-return compiler flag. So nothing to do with CMake in the end, just careless code reuse. Thanks Bort for pointing me towards the compiler flags!