I am trying to run swig using CMake and I am getting
java.i:9: Error: Unable to find 'api.h'
java.i:10:Error: Unable to find 'TestStruct.h'
I have tried setting USE_LIBRARY_INCLUDE_DIRECTORIES, SWIG_USE_TARGET_INCLUDE_DIRECTORIES, SWIG_USE_LIBRARY_INCLUDE_DIRECTORIES, without any luck. I am probably failing to understand something that is going on. My understanding was that I am linking to the api target so those include directories should be visible.
Note: That it works if I copy those headers into the build directory where swig is getting called.
Any information will be helpful. Thanks.
java.i
%module example
%include "std_string.i"
%{
/* Put header files here or function declarations like below */
#include "api.h"
extern TestStruct TestFunc();
%}
%include "api.h"
%include "TestStruct.h"
extern TestStruct TestFunc();
CMakeLists.txt for the swig target
find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})
find_package(Java REQUIRED)
find_package(JNI REQUIRED)
set_property(SOURCE java.i PROPERTY CPLUSPLUS ON)
swig_add_library(javaExample
TYPE SHARED
LANGUAGE java
SOURCES java.i)
target_include_directories(javaExample PRIVATE ${JNI_INCLUDE_DIRS})
target_link_libraries(javaExample PRIVATE api)
CMakeLists.txt for the api target
add_library( api SHARED
inc/api.h
src/api.cpp
)
target_include_directories( api
PUBLIC
inc
)
target_link_libraries( api
PUBLIC
FooTypes
PRIVATE
FooBar
)
add_subdirectory(src/FooBar)
Found the problem. I was unfortunately using cmake 3.10 instead of latest (The default apt repo for cmake is old?). Upgraded to 3.17 and there was no issue.
All that is required is:
set_property(TARGET javaExample PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE)
Related
Like the heading says I don't wanna use the find_package(Boost) to locate Boost and then the Asio component in it rather I want to do by creating a target library, and then link the target to my executable like this
cmake_minimum_required(VERSION 3.0)
project(final_exe_proj VERSION 1.0)
add_executable(final_exe main.cpp)
find_package(Threads REQUIRED)
add_library(boost_asio INTERFACE)
target_include_directories(boost_asio INTERFACE /usr/local/include/boost/asio.hpp)
target_link_libraries(boost_asio INTERFACE Threads::Threads)
target_link_libraries(final_exe PRIVATE boost_asio)
I have tried doing #include <asio.hpp> but still no luck. What is the right way to do it? Really would appreciate any help. Thanks!
Happy New Year!
Thanks Alan! The issue was in the line target_include_directories
On changing that too
target_include_directories(boost_asio INTERFACE /usr/local/include)
In a way this adds to the path for this project, so now the compiler will be able to find #include <boost/asio.hpp>
Answer is found. To save your time from reading alot:
Useful Document Here:
https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/Exporting-and-Importing-Targets
The working CMakeLists.txt is like this:
cmake_minimum_required(VERSION 3.10)
project(Test VERSION 1.0)
add_library(Lib SHARED IMPORTED)
set_property(TARGET Lib PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/lib.dll")
set_property(TARGET Lib PROPERTY IMPORTED_IMPLIB "${PROJECT_SOURCE_DIR}/lib.dll.a") //Notice: lib.lib here if you are using VS building system.
add_executable(App app.cxx)
target_link_libraries(App Lib)
Most tutorial online will assume you are using MS VS build system. Thus they will keep talking about importing a "*.lib" file.
If you use GCC(MinGW) like me, the actually file you are looking for is "*.dll.a"
Edit in Sep.17
No it's not right. We are using a DLL. And a DLL should not affect the compiling.
DLL should be whenever you want to place them into the folder which the .exe required instead of compiling check for header.
But we are trying to unpack a header from a dll.
There must be something wrong with this workflow.
CMake and GCC
I cannot use any IDE nor VS Build Tool due to the lack of license in my company.
Thus I'll have to learn about CMake + GCC for an open-sourced compile environment.
I could compile app and static library correctly now. But stuck in dll linkage.
This should be a simple one but since I can't find any sample on Google thus I need your help to correction the CMake workflow in this DLL linking job. Thanks.
Or maybe any hyperlink where could find a right direction.
As I know, I could simply add the dll library in IDE like VisualStudio and it will do all the magic to exchange it into something containing a header file.
I must missed this part in CMake.
My Step:
Compile a dll
Compile an legacy app without dll
Recreate the app with function linked from dll (BOOM!)
Detailed codes below:
Step 1: Compile a dll
Code in Test.h:
#pragma once
#ifdef TEST_EXPORTS
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif
extern "C" TEST_API int helloworld();
Code in Test.cxx:
#include <iostream>
#include "Test.h"
int helloworld() {
std::cout << "I hate HelloWorld\n";
return 0;
}
Code in CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(Test)
include(GenerateExportHeader)
add_library(Test SHARED Test.cxx)
generate_export_header(Test)
Compile it. Get a "libTest.dll". Good.
Step 2: Compile a legacy app without a dll
Let's skip it. Just a hello world console app. Nothing special.
Compile finished. Good to go.
Step 3: Recreate the app with linked dll
I've tried so many sample from google but no luck till now.
I've tried the library's name both "Test" and "libTest".
I've tried to put the dll directly in both ${PROJECT_BINARY_DIR}, ${PROJECT_SOURCE_DIR}, and make an add_subdirectory(libStore).
I've tried to use find_package(Test/libTest).
Thus I think there should be something incorrect in my cmake and source code.
Code in App.cxx:
#include <iostream>
#include "Test.h" //Also tried "libTest.h"
int main() {
std::cout << helloworld();
getchar();
return 0;
}
Attempt 1:
Put libTest.dll under sub directory "/Lib"
Code in root CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(App VERSION 1.0)
include_directories("${PROJECT_SOURCE_DIR}/Lib")
add_subdirecotry(Lib)
add_executable(App App.cxx)
target_link_libraries(App libTest) //Tried both Test and libTest
Code in /Lib CMakeLists.txt:
add_library(libTest libTest.dll)
set_target_properties(libTest PROPERTIES LINKER_LANGUAGE C)
Build result:
Fatal Error: Test.h(libTest.h): No such file or directory.
Attempt 2:
Put libTest.dll directly in source directory (${PROJECT_SOURCE_DIR})
Code in CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(App VERSION 1.0)
include_directories("${PROJECT_SOURCE_DIR}")
add_executable(App App.cxx)
target_link_libraries(App libTest) //Tried both Test and libTest
Build Result:
Fatal Error: Test.h(libTest.h): No such file or directory.
Attempt 3:
Same with Attempt 2 but add a find_package(libTest) function.
cmake_minimum_required(VERSION 3.10)
project(App VERSION 1.0)
include_directories("${PROJECT_SOURCE_DIR}")
find_package(libTest)
add_executable(App App.cxx)
target_link_libraries(App libTest) //Tried both Test and libTest
CMake Warning:
Could not find a package configuration file provided by "libTest" with any of the following names:
libTestConfig.cmake
libTest-config.cmake
Created an empty file names libTestConfig.cmake in source directory.
Build Result:
Fatal Error: Test.h(libTest.h): No such file or directory.
BOOM!
At last, I found the answer here:
https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/Exporting-and-Importing-Targets
First:
All of the code in my old attempts are assuming you have your source code in your project folder.
If you want to import a DLL you get from outside, the actually CMakeLists.txt should look like this:
cmake_minimum_required(VERSION 3.10)
project(Test VERSION 1.0)
add_library(Lib SHARED IMPORTED)
set_property(TARGET Lib PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/lib.dll")
set_property(TARGET Lib PROPERTY IMPORTED_IMPLIB "${PROJECT_SOURCE_DIR}/lib.dll.a") //Notice: lib.lib here if you are using VS building system.
add_executable(App app.cxx)
target_link_libraries(App Lib)
Second:
Almost all the tutorial online will assume you are using MS VS build system. Thus they will keep talking about importing a "*.lib" file.
Which will be a big mislead and makes you meaninglessly tracing the non-exist lib file and confuse it with the dll file itself.
If you use GCC(MinGW) like me, the actually file you are looking for is "lib.dll.a"
I think the problem may be here:
include_directories("${PROJECT_SOURCE_DIR}")
Rather than having an issue finding the DLL itself, it seems like cmake is simply having an issue finding the Test.h (or libTest.h) header file. Try putting the DLL's header file in a path that's specified via cmake's "include_directories".
I work on C++ project, i use CMake to build my file. My build fail cause
undefined reference to `Software::Software()'
, but I do not see the problem. If you have an idea, do not hesitate, thank you
Files architecture:
CMake :
# cmake_minimum_required(VERSION <specify CMake version here>)
project(untitled)
cmake_minimum_required(VERSION 2.8.9)
set(CMAKE_CXX_STANDARD 11)
include_directories(include)
file(GLOB SOURCES "src/*.cpp")
add_executable(untitled ${SOURCES})
Software.h :
#include <string>
class Software{
private :
std::string name;
public :
Software();
}
Software.cpp :
#include "Software.h"
Software::Software() {
this->name = "defaultName";
}
SoftwaresConfigurations.h (who call the contructor of Software) :
#include "Software.h"
class SoftwaresConfigurations {
public:
SoftwaresConfigurations();
}
SoftwaresConfiguration.cpp :
#include "SoftwaresConfigurations.h"
SoftwaresConfigurations::SoftwaresConfigurations(){
Software software = Software();
}
You have fallen into the trap that is FILE(GLOB ...).
Re-running CMake should fix this, but you should probably move away from using GLOB to collect your source files. For example, you can list them explicitly as follows:
set(SOURCES src/main.cpp src/Softwares.cpp src/SoftwaresConfigurations.cpp)
I will explain what happened below.
The official documentation says the following:
We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.
So what probably happened is that you created the project with just one source file. CMake ran the GLOB at configuration-time and found only the one .cpp file.
Then, you added two files (which CMake did not know about) and added the #include to your SoftwaresConfiguration.cpp. This triggers a rebuild. However, since CMake does not know about Softwares.cpp, it does not build that file and the linker produces an unreferenced symbol.
I am on Windows 10, Visual Studio 2015. Suppose I am building library A with CMakeLists looking like
cmake_minimum_required(VERSION 3.7)
project(A)
set(DLLIMPORT "__declspec(dllimport)")
set(DLLEXPORT "__declspec(dllexport)")
set(PROJECT_SRCS
${PROJECT_SOURCE_DIR}/src/TestA.cpp)
set(PROJECT_INCS
${PROJECT_SOURCE_DIR}/include/TestA.h)
add_library(${PROJECT_NAME} SHARED ${PROJECT_SRCS} ${PROJECT_INCS})
target_compile_definitions(${PROJECT_NAME} INTERFACE
WINDOWS_DLL_API=${DLLIMPORT})
target_compile_definitions(${PROJECT_NAME} PRIVATE
WINDOWS_DLL_API=${DLLEXPORT})
target_include_directories(${PROJECT_NAME} PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include>)
I am defining the macro WINDOWS_DLL_API as dllexport when it's building library A, and defining WINDOWS_DLL_API as dllimport for external applications that is linking library A. The problem is when I have another library B that is also linking A, I don't know how to overwrite WINDOWS_DLL_API back to dllexport. Below is my attempt of my CMakeLists for library B,
cmake_minimum_required(VERSION 3.7)
project(B)
set(DLLEXPORT "__declspec(dllexport)")
set(PROJECT_SRCS
${PROJECT_SOURCE_DIR}/src/TestB.cpp)
set(PROJECT_INCS
${PROJECT_SOURCE_DIR}/include/TestB.h)
add_library(${PROJECT_NAME} SHARED ${PROJECT_SRCS} ${PROJECT_INCS})
target_include_directories(${PROJECT_NAME} PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include>)
target_link_libraries(${PROJECT_NAME} A)
# does not work
target_compile_definitions(${PROJECT_NAME} PRIVATE
WINDOWS_DLL_API=${DLLEXPORT})
What is the right way to do it?
Concept of INTERFACE option for command target_compile_definitions (and for other target_* CMake commands) is to enforce something for all users of the library, both executables and libraries.
Intention to clear enforcement for at least single library's user means that the conception is used in a wrong way. And other approaches should be used instead.
In given case, you need to use different macro names for libraries A and B. And it is better to remove INTERFACE option completely, so even non-CMake users of your library will be happy.
TestA.h:
#ifdef BUILD_A
#define WINDOWS_DLL_API_A __declspec(dllexport)
#else
#define WINDOWS_DLL_API_A __declspec(dllimport)
#endif
...
WINDOWS_DLL_API_A void foo(void);
...
TestB.h:
#ifdef BUILD_B
#define WINDOWS_DLL_API_B __declspec(dllexport)
#else
#define WINDOWS_DLL_API_B __declspec(dllimport)
#endif
// Assume usage of A is here.
#include <TestA.h>
...
WINDOWS_DLL_API_B void bar(void);
A/CMakeLists.txt:
cmake_minimum_required(VERSION 3.7)
project(A)
...
add_library(${PROJECT_NAME} SHARED ...)
target_compile_definitions(${PROJECT_NAME} PRIVATE "BUILD_${PROJECT_NAME}=1")
B/CMakeLists.txt:
cmake_minimum_required(VERSION 3.7)
project(B)
...
add_library(${PROJECT_NAME} SHARED ...)
target_compile_definitions(${PROJECT_NAME} PRIVATE "BUILD_${PROJECT_NAME}=1")
target_link_libraries(${PROJECT_NAME} A)
See also this answer, which provides more detailed header, which works on Windows platforms too.
Note, that when the library B includes header from A, it treats foo() as imported, and this is correct: the function is defined in A, not in B. With your approach (even if you would manage to redefine WINDOWS_DLL_API for B), library B would incorrectly treat foo() as exported.
This is an advantage of the conception: intention to overcome a conception signals that you do something wrong.
Just wanted to add my piece of code I'm using (compatible with CMake versions prior to 2.8.12).
In my root CMakeLists.txt file I have:
if (MSVC)
add_definitions(-DWINDOWS_DLL_API=__declspec\(dllexport\))
else()
add_definitions(-DWINDOWS_DLL_API=)
endif()
In the (sub-)project's CMakeLists.txt using the DLL I've put:
if (MSVC)
remove_definitions(-DWINDOWS_DLL_API=__declspec\(dllexport\))
add_definitions(-DWINDOWS_DLL_API=__declspec\(dllimport\))
endif()
The MSVC checks are necessary in my case because I also cross-compile.
Reference
CMake - override compile flags for single files
I'm trying to migrate from Visual Studio towards Jetbrains' (awesome) CLion IDE which uses CMake to organize the projects.
Until now, the transition has been smooth: creating CMake projects and importing them into CLion is easy, and I can begin coding on one plateform then continue on another one without problems.
However, one aspect of Visual Studio that I couldn't find an equivalent to in CMake is property sheets: I use them mainly for holding the include directories' paths and the linking libs for libraries (i.e. one .vsprops file for each library, e.g. OpenCV.vsprops, Boost.vsprops, etc.).
This way, in VS, I could share a library's .vsprops file between different projects without having to configure the paths/libs each time.
Does CMake have a similar mechanism to Visual Studio's property sheets ? How is it possible to store a library's includes/libs in a CMake-parsable file then "import" it in CMakeLists.txt in order to link against the library ?
Basically, what I want to do is:
Create a "cmake property sheet" (for lack of a better name) for a given library.
Then, in CMakeLists.txt, write something like link_target_to_libs(myTarget "path/to/propertySheet1" "path/to/propertySheet2" ...) .
In CMake, libraries can export a package with IMPORTED targets which other buildsystems import using find_package:
http://www.cmake.org/cmake/help/v3.1/manual/cmake-packages.7.html
http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html
http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html#imported-targets
Instead of 'linking to property sheets', you link to the IMPORTED targets.
target_link_libraries(myTarget Dep1::Dep1 Dep2::Dep2)
Not all libraries create IMPORTED targets, and not all provide cmake config-file packages. In those cases (including OpenCV and Boost), CMake provides find modules:
http://www.cmake.org/cmake/help/v3.0/manual/cmake-developer.7.html#find-modules
which you use with find_package and link to the contents of variables.
Since I really want to make the libraries' inclusion/linking into a one-line command, and as far as my (basic) knowledge of CMake goes, I think that some compromise should be made -- mainly sharing the target name's variable between CMakeLists.txt and the "property sheets". So this is my solution... until someone proposes a simpler/cleaner one:
A CMake property sheet is a .cmake text file,
A well-known variable name --TARGET-- designates the target (i.e. the first argument of add_executable()),
Aside from library-specific commands, a .cmake file contains a call to target_include_directories(${TARGET} PRIVATE ${PATH_TO_INCLUDE_DIR}) and target_link_libraries(${TARGET} ${LIST_OF_LIBS}),
In order to use/link against a library, call include("path/to/.cmake") in CMakeLists.txt.
I have successfully built and executed a simple program that uses X11 and OpenCV with the following files:
x11.cmake
target_include_directories(${TARGET} PRIVATE "/usr/include/X11")
target_link_libraries(${TARGET} "/usr/lib/x86_64-linux-gnu/libX11.so")
opencv.cmake
# OpenCV-specific stuff
set(OpenCV_DIR "/PATH/TO/OPENCV/INSTALL/DIR/share/OpenCV") # path to OpenCVConfig.cmake
find_package(OpenCV REQUIRED)
# include path
target_include_directories(${TARGET} PRIVATE ${OpenCV_INCLUDE_DIRS})
# linking libs
target_link_libraries(${TARGET} opencv_world opencv_ts)
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.4)
project(hello_clion)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
## hello-clion ##############################
# make a new target name
set(TARGET hello-clion)
# find sources
file(GLOB_RECURSE SOURCE_FILES "src/*.cpp" "src/*.hpp")
# declare a target
add_executable(${TARGET} ${SOURCE_FILES})
# link the libraries (to the last-declared ${TARGET}, which should be the last-added executable)
include("x11.cmake")
include("opencv.cmake")
#############################################
main.cpp
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <thread>
#include <opencv2/opencv.hpp>
#include <Xlib.h>
int main_x11()
{
// adapted from: http://rosettacode.org/wiki/Window_creation/X11#Xlib
}
int main_ocv()
{
// adapted from: http://docs.opencv.org/doc/tutorials/introduction/display_image/display_image.html#source-code
}
int main()
{
using namespace std;
thread tocv(main_ocv);
thread tx11(main_x11);
tocv.join();
tx11.join();
return 0;
}
Now, each time I want to use OpenCV in a project/program, I just have to put include("opencv.cmake") in the corresponding CMakeLists.txt.
This seems to work great, but there could certainly be problems I haven't discovered. (I was worried multiple macros adding the same target_link_libraries would cause "already defined" linking errors , but at least g++ 5.1.0 handles being given the same library name multiple times without error.)
In root CMakeLists.txt, BEFORE add_subdirectory() calls or globs, include:
macro(USES_WX)
include_directories(SYSTEM /usr/local/include/wx-3.0)
include_directories(SYSTEM /usr/local/lib/wx/include/gtk3-unicode-3.0)
link_directories(/usr/local/lib)
add_definitions(-D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXGTK__ -pthread)
target_link_libraries(${TARGET} pthread wx_gtk3u_xrc-3.0 wx_gtk3u_html-3.0 wx_gtk3u_qa-3.0 wx_gtk3u_adv-3.0 wx_gtk3u_core-3.0 wx_baseu_xml-3.0 wx_baseu_net-3.0 wx_baseu-3.0)
endmacro()
(You can make the macro more fancy, like checking for if CMAKE_BUILD_TYPE is "Debug" or "Release" to link to the appropriate libraries, vary preprocessor definitions, etc. See http://www.cmake.org/cmake/help/v3.0/command/if.html)
And have your project's CMakeLists.txt be like this:
set(TARGET myProgramName)
add_executable(${TARGET} myProgramName.cpp)
USES_WX()
^^ The macro call MUST be after add_executable()
And, if you want multiple target support, modify the line in the root CMakeLists.txt section shown above to:
...
target_link_libraries(${ARGV0} pthread wx_gtk3u_xrc-3.0 ...)
...
And have your project's CMakeLists.txt be like this (less lines, but more chance for error):
add_executable(myProgramName myProgramName.cpp)
USES_WX(myProgramName)