I have followed the opencv doc for creating my own bindings.
I run the file gen2.py which generated some header files:
./
../
pyopencv_generated_enums.h
pyopencv_generated_funcs.h
pyopencv_generated_include.h
pyopencv_generated_modules_content.h
pyopencv_generated_modules.h
pyopencv_generated_types_content.h
pyopencv_generated_types.h
pyopencv_signatures.json
How should I build this?
I tried running cmake CMakeLists.txt directly in /opencv/modules/python but some defines were not found.
and I tried on re-building running cmake CMakeLists.txt in /opencv/ , where I got:
FATAL: In-source builds are not allowed.
You should create a separate directory for build files.
I think both approaches were quite wrong, but I haven't found any doc explaining how to build using the generated headers.
I'm using opencv 4.5.5 which I cloned and built.
EDIT
I found this in /source/opencv/modules/python/bindings/CMakeLists.txt:
string(REPLACE ";" "\n" opencv_hdrs_ "${opencv_hdrs}")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${opencv_hdrs_}")
add_custom_command(
OUTPUT ${cv2_generated_files}
COMMAND "${PYTHON_DEFAULT_EXECUTABLE}" "${PYTHON_SOURCE_DIR}/src2/gen2.py" "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/headers.txt"
DEPENDS "${PYTHON_SOURCE_DIR}/src2/gen2.py"
"${PYTHON_SOURCE_DIR}/src2/hdr_parser.py"
# not a real build dependency (file(WRITE) result): ${CMAKE_CURRENT_BINARY_DIR}/headers.txt
${opencv_hdrs}
COMMENT "Generate files for Python bindings and documentation"
)
I guess I have to add the path to my headers in ${CMAKE_CURRENT_BINARY_DIR}/headers.txt just not sure how to get the value of CMAKE_CURRENT_BINARY_DIR
EDIT 2
As proposed by #berak, I tried CMAKE_EXTRA_MODULES_PATH=my/path
this seems to get me really close to what I need.
It compiles my sources and generates the .so files as libopencv_xxx.so and saves them in my /usr/local/lib
(when running nm on it I see my class and method)
BUT! when I import cv2 in a script I don't achieve to load my module.
I tried print(cv2.__dict__) and greped on it, but it's not there.
Any clue on how to add the compiled modules into my python-opencv installation?
There's not much documentation on how to create a bind (at least I only found this, which is very helpful but doesn't have all the information).
First, your module must use the following tree structure (I did everything with cmake):
.
src
└── modules
└── your_module
├── CMakeLists.txt
├── include
│ └── opencv2
│ └── your_module_bind_lib.hpp
└── src
└── your_module_bind_lib.cpp
An example of my CMakeLists.txt (this of course may change according to your project):
set(the_description "yourModule LIB")
ocv_define_module(your_module opencv_imgproc WRAP python)
include_directories(${OpenCV_INCLUDE_DIRS})
Then I cloned OpenCV with
git clone https://github.com/opencv/opencv.git
Make a build folder
mkdir wherever/build
And run the following command for cmake
cd wherever/build
cmake -DOPENCV_EXTRA_MODULES_PATH=/project_from_previous_tree/src/modules/ -D BUILD_EXAMPLES=OFF -D BUILD_opencv_apps=OFF -D BUILD_DOCS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_TESTS=OFF -D CMAKE_INSTALL_PREFIX=/usr/local/ your_opencv_location/opencv/
make -j8
make install
In that command the only "special" thing was DOPENCV_EXTRA_MODULES_PATH (thanks to #berak for the idea).
And then? what happens in python level?
Make sure your python installation actually points to the built opencv, or use something like:
import sys
sys.path.append('/usr/local/lib/python3.8/site-packages/cv2/python-3.8')
import cv2
where /usr/local/lib/python3.8/site-packages/cv2/python-3.8' is where the generated .so is located in my PC.
With this you will be able to use things like
cv2.my_cpp_function()
cv2.my_cpp_class.some_method()
...
Where my_cpp stuff was declared and defined in the module project following the doc and can "easily" have OpenCV typed objects as parameters.
Et voila, now you can use your c++ functions in python.
Notice that this solution does not do any modification to the opencv directory cloned from Git.
You're not supposed to run gen2.py manually, cmake will do this for you at some stage, internally.
since you seem to be on some linux, rather follow the build steps here, this will also generate python bindings, the gist of it is:
make a special "build folder" and cd into it (dont try to build in the src folder, you'll never be able to clean anything up)
run cmake <some args> path_to_src_folder (or better even - cmake-gui) , check if python3 shows up in the "To be build" section of the output
run make install
Related
I'm trying to compile a libpng library. The thing is that I need a specific version of this library - 1.2.37 - because the project I'm using it in is written with this version.
I've found the source code of this version here (GnuWin32 project).
But the folder structure looks something like this:
libpng-1.2.37-src/
contrib/
projects/
scripts/
CMakeLists.txt
png.h
pngread.c
pngwrite.c
...
See, the CMakeLists.txt is one level deeper than the source files.
I've tried:
source directory libpng-1.2.37-src/ -> resulted in error: The source directory does not appear to contain CMakeLists.txt
source directory libpng-1.2.37-src/scripts -> resulted in multiple errors: File libpng-1.2.37-src/scripts/scripts/libpng.pc.in does not exist.
copy CMakeLists.txt from /scripts to /libpng-1.2.37-src and set source directory to /libpng-1.2.37-src -> resulted in error: The source "/libpng-1.2.37-src/CMakeLists.txt" does not match the source "/libpng-1.2.37-src/scripts/CMakeLists.txt" used to generate cache.
What should I do to make it work? I don't know why the CMakeLists.txt file would be included if it can't be used.
The INSTALL file explicitely says:
If you want to use "cmake" (see www.cmake.org), copy CMakeLists.txt
from the "scripts" directory to this directory and type
cmake . [-DPNG_MMX=YES] -DCMAKE_INSTALL_PREFIX=/path
make
make install
And as a side note, before this it says that the classic way to install it is:
On Unix/Linux and similar systems, you can simply type
./configure [--prefix=/path]
make check
make install
It sounds like you did right with 3), however you forgot to cleanup the build dir before trying again.
If it's library which you use in your project you can build it automatically via technique called 'superbuild' (use ExternalProject_Add).
By specifying SOURCE_SUBDIR as is described here to subdirectory with CMakeLists.txt you can do something like this
ExternalProject_Add(libpng
GIT_REPOSITORY url-to-your-repository.git
GIT_TAG v1.2.37
SOURCE_SUBDIR "scripts"
I've been trying to use clang-modernize with CMAKE_EXPORT_COMPILE_COMMANDS as recommended in the help of this tool.
With this option cmake generates a JSON file containing compile info like include paths (see also).
This variable is accepted on the command line of cmake,
but cmake --help-variable CMAKE_EXPORT_COMPILE_COMMANDS doesn't work (which is coherent with this mailing list posting).
Has someone any idea on how to use it?
I could also use it with cppcheck.
Some more info
I've discovered on a clang developer forum that this cmake feature is not available on all generators. This might change in the future, in the mean time my question remains and I will try too see what happen if I use other generators than Visual Studio.
I suggest setting
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
in the CMakeList.txt
As of CMake 3.5 the CMAKE_EXPORT_COMPILE_COMMANDS option is supported by the Ninja and Makefiles generators.
That means to generate a JSON compile database one has to select a generator that supports it.
For example on UNIX just:
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 /path/to/src
(as it uses the makefile generator there, by default)
Otherwise you can explicitly specify a generator like this:
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 /path/to/src -G Ninja
Or:
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 /path/to/src -G 'Unix Makefiles'
Or another makefiles variant that your cmake supports - a list of supported generators is included in the output of cmake --help.
Note that the compile database JSON file is generated at cmake execution time - not at compile time. Also, with recent clang versions (e.g. clang >= 3.8), clang-modernize was merged into clang-tidy.
I too was not able to get to work on the Visual Studio generator.
It did, however, work using the "NMake Makefiles" generator.
C:\work\build>cmake -G "NMake Makefiles" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
The first one you use CMAKE_EXPORT_COMPILE_COMMANDS ON in your CMakelists.txt
Or run CMake with following parameters:
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..
1.Option:
Here is a simple source and build tree to make it clear.
.
├── build
├── cars
│ ├── car.cpp
│ ├── car.h
│ └── CMakeLists.txt
├── CMakeLists.txt
└── main.cpp
main.cpp
#include <iostream>
#include "car.h"
int main (int argc, char *argv[])
{
std::cout << "car - main function" << std::endl;
showCarName();
return 0;
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.20)
project(Cars
VERSION 0.1
HOMEPAGE_URL "github/alitokur"
LANGUAGES CXX
)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_executable(carApp main.cpp)
add_subdirectory(cars)
target_link_libraries(carApp PRIVATE cars)
cars/CMakeLists.txt
add_library(cars OBJECT
car.cpp
)
target_include_directories(cars PUBLIC .)
And that's all, target link directories allow main.cpp to include the cars.h file without providing a relative path. You should use set(CMAKE_EXPORT_COMPILE_COMMANDS ON) after the project() definition because sometimes other tools override this setting and that's why you can't see compile_commands.json.
CMake 3.17
As of CMake 3.17 you can now set CMAKE_EXPORT_COMPILE_COMMANDS as an environment variable.
The default value for CMAKE_EXPORT_COMPILE_COMMANDS when there is no explicit configuration given on the first run while creating a new build tree. On later runs in an existing build tree the value persists in the cache as CMAKE_EXPORT_COMPILE_COMMANDS.
This is the best approach since you don't have to pollute project code or remember to set it individually for each project.
# Set this in your .bashrc or whatever environment you choose to set env variables
export CMAKE_EXPORT_COMPILE_COMMANDS=1
CMake 3.5
The second best approach is to pass CMAKE_EXPORT_COMPILE_COMMANDS as a cache variable when configuring the project.
cmake -S . -B build -D CMAKE_EXPORT_COMPILE_COMMANDS=1
I prefer the new CMake 3.17 approach, since the 3.5 approach is easy to forget.
There is some CMake magic I don't understand. How should a CMakeLists.txt file look like for a small C++ project with directories like this:
.
├── bin
└── src
├── src
└── test
bin — directory for built program
src/src — directory for source
src/test — directory for tests
The tests will need to include files from src/src.
I'd like to manage all the operations from cmake, however at this moment I even can't cause cmake to compile file in src/c.cpp.
Any help, links are welcome.
Your CMake files should reside in the main source directory and its sub-directories. The easiest approach is to have one CMakeLists.txt in the src directory, which includes all files from src/src and src/test. A very minimalistic example could look like the following:
# CMakeLists.txt in src
project(myExample)
set(myExample_SOURCES
src/file1.cpp
src/main.cpp)
add_executable(myExecutable ${myExample_SOURCES})
set(myExample_test_SOURCES
src/file1.cpp
test/test_file2.cpp
test/test_main.cpp)
add_executable(myTestSuite ${myExample_test_SOURCES})
The output directory is normally not specified, because you can have different active
builds in parallel with
different options, e.g. you can have one build in debug mode -O0 -g, another one in release mode with -O2 -g flags and a third one in release mode with heavy optimization flags -O3. Every build resides in its own directory (e.g. build-debug, build-rel,
build-opt).
You should create the output directory (bin in your case) manually and call the cmake command inside this directory. As an argument you have to supply the path to the main CMakeLists.txt. In other words, just execute
cmake ../src
when you are inside bin. This will take all files from the src directory and put the output to the bin directory.
You can easily create a second output directory, say bin2, where you specify different build flags. The ccmake provides a very minimalistic GUI for that.
This helped me to start with cmake examples.html
How do I tell cmake where it should output its build data?
Let's say I have a dir with the source code called src/,
and then since cmake outputs a lot of files I would like him to put all of that in
a dir called build/.
BUT I would like him to put the generated Makefile in the project root,
so I don't have to go into the build dir to build the application.
Is this possible with cmake?
I have managed to get the cmake out put if I fun cmake in the build dir like this:
cd build/
cmake ../src/
make
./hello
But it would be nice to stay in the project root and type something like this
cmake
make
./hello
I guess that I need to put a CMakeList.txt in the project root with some magic commands telling him where he could put the object files and where he can find the source code.
Thanks
Update:
Since my question is a little bit vague.
After I have run the cmake commands this is how I would like my tree to look like:
src/CMakeLists.txt
src/hello.c
src/hello.h
build/CMakeCache.txt
build/CMakeFiles/
build/cmake_install.cmake
CMakeLists.txt
Makefile
So the question is how should the CMakeLists.txt look like in this setup.
CMakeLists.txt
src/CMakeLists.txt
But maybe that is not possible?
BUT I would like him to put the generated Makefile in the project root, so I don't have to go into the build
dir to build the application.
cmake not designed for that, as I know,
BUT you can stay in the project root and type:
make -C build
./hello
with custom build rules or set_target_properties,
you can force cmake to put result executable to
sources directory or you can use
./build/hello
Type "cd build && cmake .." you need only once,
after that make will automaticaly start cmake, if something
changed.
cmake wants you to have a fresh build directory.
Okay, i get what you want. I think, you can achieve this with some machinery in CMakeLists.txt. Of course, it's not option if you are not project developer.
In root CMakeLists.txt you can add file(WRITE ...) command, which would write Makefile into ${CMAKE_SOURCE_DIR}. This Makefile would contain these commands for every target:
<target>:
cd ${CMAKE_BUILD_DIR} && ${CMAKE_MAKE_PROGRAM} <target>
So, now you can run make from source dir and it will build your project in build dir.
Simply use
cmake .
make
in your src directory. The (.) dot on unix systems addresses the current directory. Keep in mind doing so is actually not recommended since there will be a lot of build files in your src directory you'll have to clean up afterwards or at release time.
I'm a newbie and I've a problem!
I've to work with a c++ code and I don't know how to import it and how to compile it on eclips ( I compiled it by command line).
The code has a particular structure and it is organized in this way:
repos____lib____configure (execute the configure file inside the libraries folders)
I I___makefile (execute the make file inside the libraries folders,
requires make/make.def)
I I___ib1____.cpp
I I I____.h
I ... I____configure (it requires make/configure_lib and
make/configure_includes
I ... I____makefile (generated by configure)
I I___lib2___....
i I___.......
I I___libn____.cpp
i I____.h
i I____configure
i I____makefile (generated by configure)
I
I___make(folder)__bashrc (are set the some environment variables)
I I__configure_bin
I I__configure_includes
I I__configure_lib
I I__make.def (are set all the include path and library path used
I in the configure file)
I___application__main.cpp
I__configure
I__makefile(generated by the configure file)
to be sure that you understand my problem...(sure... :) )
the first configure file is:
cd lib1; ./configure
cd ../lib2; ./configure
.....
....
cd ../libn; ./configure
cd
and the first makefile is
include /media/Dati/WORKHOME/repos/make/make.def
this is the makefile for the whole library
lib:
make -C lib1
make -C lib2
make -C libn
an example of configure file (the one inside lib1):
#!/usr/bin/perl
$INC = '$(OPENCVINC) $(FLTKINC) $(DC1394V2INC)'; ##<-DEFINED IN /make.def
$LIB = '$(OPENCVLIB) $(FLTKLIB) $(DC1394V2LIB)'; #####################
#-------------------------------------------------------------------------------
require '/media/Dati/WORKHOME/repos/make/configure_lib';
print "Created Makefile.\n";
# this will create a include file for the whole directory,
# using the template <dirname>.h.templ
require '/media/Dati/WORKHOME/repos/make/configure_includes';
print "Created $libname.h\n";
compile it without eclipse is simple
type /.configure in the lib folder
type make
go into the application folder
type ./configure
type make
run the program
my question is....in eclipse???
I imported the three with import/ import existing code as makefile project but now I don't know how compile it.
could you please help me? it's important!
thank you very much
gabriele
You have done the right thing by using "import existing code as makefile project".
Now eclipse know that it needs to call make and use your makefile. But Your build process is not only driven by make.
One solution is to write a makefile that call all your build steps. Something Like :
all:
cd dir1 && ./configure && make
cd dir2 && ./configure && make
etc.
my2c
Edit:
I currently have no eclipse installed, so I can not send you detailled steps ... sorry