Hi, I just create an OpenCV (http://opencv.org/) project wizard, I will put it here for some days until commit to trunk, comments are welcome.
Steps to use:
1, unzip to share\CodeBlocks\templates\wizard\opencv
2, add one line:
RegisterWizard(wizProject, _T("opencv"), _T("OpenCV project"), _T("Console"));
in share\CodeBlocks\templates\wizard\config.script
Edit1: I'm using this release:
http://sourceforge.net/projects/opencvlibrary/files/opencv-win/, you can download either 2.4.3, 2.4.4 and 2.4.5 Windows installer
Edit2: You need to use MinGW 4.6.1dw2 if you want to link to the prebuild opencv libraries, see this for details: which mingw compiler is used to create the pre-build libs in 2.4.3 release - OpenCV Q&A Forum (http://answers.opencv.org/question/4716/which-mingw-compiler-is-used-to-create-the-pre/)
Edit3: I did not tested this wizard on Linux, so it may have bugs. ;D
[attachment deleted by admin]
I think I've found the bug.
VersionString += Major;
VersionString += Minor;
VersionString += Revision;
Every time there is an error and the adjustment page cannot continue, these lines add 'Major' + 'Minor' + 'Revision' to 'VersionString' again and again.
I managed to get past the wizard by not making a mistake ever in the version adjustment and when I hit compile, it said,
||=== Build: Debug in testcv (compiler: GNU GCC Compiler) ===|
ld.exe||cannot find -lopencv_imgproc244.dll|
ld.exe||cannot find -lopencv_core244.dll|
ld.exe||cannot find -lopencv_highgui244.dll|
||=== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
Then I checked search directories and the entries were,
$(#cv)\x86\mingw\lib
$(#cv)\x86\mingw\bin
but they should be,
because I've changed them in version adjustment page to use these values. And if I change them manually, the wizard works.
Edit: I think the lines under 'function SetupProject(project)'
project.AddIncludeDir(OpenCVPathDefaultInc);
project.AddLibDir(OpenCVPathDefaultLib);
project.AddLibDir(OpenCVPathDefaultBin);
should be
project.AddIncludeDir(OpenCVPathInc);
project.AddLibDir(OpenCVPathLib);
project.AddLibDir(OpenCVPathBin);
I think I've found the bug.
VersionString += Major;
VersionString += Minor;
VersionString += Revision;
Every time there is an error and the adjustment page cannot continue, these lines add 'Major' + 'Minor' + 'Revision' to 'VersionString' again and again.
Thanks, I fixed this bug by adding a line to reset the VersionString
VersionString = _T(""); // set to empty string, then append three version numbers
...
Then I checked search directories and the entries were,
$(#cv)\x86\mingw\lib
$(#cv)\x86\mingw\bin
but they should be,
because I've changed them in version adjustment page to use these values. And if I change them manually, the wizard works.
1. does not exist. If you define a global variable named "cv", cv.include and cv.bin are automatically defined by C::B, but no "cv.bin". (see the code snippet in C::B source below). So if you leave cv.include setting empty in Global variable editor dialog, this value is translated to "include" subfolder of cv base.
wxString UserVariableManager::Replace(const wxString& variable)
{
wxString package = variable.AfterLast(wxT('#')).BeforeFirst(wxT('.')).MakeLower();
wxString member = variable.AfterFirst(wxT('.')).MakeLower();
wxString path(cSets + m_ActiveSet + _T('/') + package + _T('/'));
wxString base = m_CfgMan->Read(path + cBase);
if (base.IsEmpty())
{
if (Manager::Get()->GetProjectManager()->IsLoading())
{
// a project/workspace is being loaded.
// no need to bug the user now about global vars.
// just preempt it; ProjectManager will call Arrogate() when it's done.
Preempt(variable);
return variable;
}
else
{
wxString msg;
msg.Printf(_("In the currently active Set, Code::Blocks does not know\nthe global compiler variable \"%s\".\n\nPlease define it."), package.c_str());
InfoWindow::Display(_("Global Compiler Variables"), msg , 8000, 1000);
UsrGlblMgrEditDialog d;
d.AddVar(package);
PlaceWindow(&d);
d.ShowModal();
}
}
if (member.IsEmpty() || member.IsSameAs(cBase))
return base;
if (member.IsSameAs(cInclude) || member.IsSameAs(cLib) || member.IsSameAs(cObj))
{
wxString ret = m_CfgMan->Read(path + member);
if (ret.IsEmpty())
ret = base + _T('/') + member;
return ret;
}
wxString ret = m_CfgMan->Read(path + member);
return ret;
}
Notice: if (member.IsSameAs(cInclude) || member.IsSameAs(cLib) || member.IsSameAs(cObj))
The reason I use such setting is that when I extract the file: OpenCV-2.4.4.exe, I see such structure:
E:\code\opencv\OpenCV-2.4.4\opencv\build -> I set this folder as "cv" base
E:\code\opencv\OpenCV-2.4.4\opencv\build\include -> this becomes $(#cv.include), in-fact, it is the same as $(cv)\include, but we prefer the former way :).
E:\code\opencv\OpenCV-2.4.4\opencv\build\x86\mingw\lib -> this becomes $(#cv)\x86\mingw\lib
E:\code\opencv\OpenCV-2.4.4\opencv\build\x86\mingw\bin -> this becomes $(#cv)\x86\mingw\bin
The most import thing is the "cv" base, then all the sub-paths are relative paths.
2, In such directory structure, you can either set cv.lib in Global variable editor dialog as $(#cv)\x86\mingw\lib, then you can use $(#cv.lib) in your compiler settings, or you can leave cv.lib in Global variable editor dialog as empty string, then use $(#cv)\x86\mingw\lib in your compiler settings.
3, The reason I have $(#cv)\x86\mingw\bin in linker search paths is that C::B will automatically add this path to PATH when it run the app, so you don't need to add to bin paths to your system's PATH.
Edit: I think the lines under 'function SetupProject(project)'
project.AddIncludeDir(OpenCVPathDefaultInc);
project.AddLibDir(OpenCVPathDefaultLib);
project.AddLibDir(OpenCVPathDefaultBin);
should be
project.AddIncludeDir(OpenCVPathInc);
project.AddLibDir(OpenCVPathLib);
project.AddLibDir(OpenCVPathBin);
Thanks, fixed.
2- You included CV ver1 style headers in 'main.cpp', wouldn't it be better if they are ver2 style? Just a thought.
Ok, updated to new cv::Mat.
The attachment is the new wizard package, feedback are welcome, thanks.
[attachment deleted by admin]
...
Then I checked search directories and the entries were,
$(#cv)\x86\mingw\lib
$(#cv)\x86\mingw\bin
but they should be,
because I've changed them in version adjustment page to use these values. And if I change them manually, the wizard works.
1. does not exist. If you define a global variable named "cv", cv.include and cv.bin are automatically defined by C::B, but no "cv.bin". (see the code snippet in C::B source below). So if you leave cv.include setting empty in Global variable editor dialog, this value is translated to "include" subfolder of cv base.
When I said 'they should be, $(#cv.lib) and $(#cv.bin)', I meant my system, not general. Sorry for the confusion.
I made a user-defined 'bin' entry in global settings to point to the cv's bin directory which is '\cvfolder\bin' in my self build and NOT '\cvfolder\x86\mingw\bin'. But the wizard still use
project.AddLibDir(OpenCVPathDefaultBin);
So this will always add '\cvfolder\x86\mingw\bin' to the project and not the one user defines on the settings page, '\cvfolder\bin' in my case. Was that on purpose?
One last thing, isn't it better to define '$(#cv.lib)' as the default value for 'OpenCVPathDefaultLib', in case there is a global variable setting already?
Wizard works ok now, thnx again. ;)
I think if I add a sub-field named "bin", but left its value as empty string, C::B should default set it to "$(#cv)\bin", just the similar way as "lib" and "include", but this is just a feature request in C::B. :)
I think it is quite easy to implement this feature request, look at the last lines of function: UserVariableManager::Replace
wxString UserVariableManager::Replace(const wxString& variable)
{
wxString package = variable.AfterLast(wxT('#')).BeforeFirst(wxT('.')).MakeLower();
wxString member = variable.AfterFirst(wxT('.')).MakeLower();
...
...
if (member.IsEmpty() || member.IsSameAs(cBase))
return base;
if (member.IsSameAs(cInclude) || member.IsSameAs(cLib) || member.IsSameAs(cObj))
{
wxString ret = m_CfgMan->Read(path + member);
if (ret.IsEmpty())
ret = base + _T('/') + member;
return ret;
}
wxString ret = m_CfgMan->Read(path + member);
return ret;
}
The last two line:
wxString ret = m_CfgMan->Read(path + member);
return ret;
Can change to:
wxString ret = m_CfgMan->Read(path + member);
if (ret.IsEmpty())
ret = base + _T('/') + member;
return ret;
So, if member-field "bin" has defined but have an empty value string, we use the sub-folder of "bin", any ideas?
This patch implement the pre-defined "bin" member field.
Index: resources/global_uservars.xrc
===================================================================
--- resources/global_uservars.xrc (revision 9011)
+++ resources/global_uservars.xrc (working copy)
@@ -241,6 +241,32 @@
<flag>wxBOTTOM|wxRIGHT|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL</flag>
<border>5</border>
</object>
+ <object class="sizeritem">
+ <object class="wxStaticText" name="ID_STATICTEXT_BIN">
+ <label>bin</label>
+ <font>
+ <size>10</size>
+ <weight>bold</weight>
+ <family>swiss</family>
+ <face>Arial</face>
+ </font>
+ </object>
+ <flag>wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxTextCtrl" name="bin" />
+ <flag>wxBOTTOM|wxRIGHT|wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="fs5">
+ <label>...</label>
+ <size>20,-1</size>
+ </object>
+ <flag>wxBOTTOM|wxRIGHT|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ </object>
<object class="spacer">
<flag>wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL</flag>
<border>5</border>
Index: uservarmanager.cpp
===================================================================
--- uservarmanager.cpp (revision 9011)
+++ uservarmanager.cpp (working copy)
@@ -47,6 +47,7 @@
const wxString cInclude (_T("include"));
const wxString cLib (_T("lib"));
const wxString cObj (_T("obj"));
+const wxString cBin (_T("bin"));
const wxString cCflags (_T("cflags"));
const wxString cLflags (_T("lflags"));
const wxString cSets (_T("/sets/"));
@@ -75,6 +76,7 @@
wxTextCtrl *m_Include;
wxTextCtrl *m_Lib;
wxTextCtrl *m_Obj;
+ wxTextCtrl *m_Bin;
wxTextCtrl *m_Name[7];
wxTextCtrl *m_Value[7];
@@ -155,7 +157,7 @@
if (member.IsEmpty() || member.IsSameAs(cBase))
return base;
- if (member.IsSameAs(cInclude) || member.IsSameAs(cLib) || member.IsSameAs(cObj))
+ if (member.IsSameAs(cInclude) || member.IsSameAs(cLib) || member.IsSameAs(cObj) || member.IsSameAs(cBin))
{
wxString ret = m_CfgMan->Read(path + member);
if (ret.IsEmpty())
@@ -292,6 +294,7 @@
m_Include = XRCCTRL(*this, "include", wxTextCtrl);
m_Lib = XRCCTRL(*this, "lib", wxTextCtrl);
m_Obj = XRCCTRL(*this, "obj", wxTextCtrl);
+ m_Bin = XRCCTRL(*this, "bin", wxTextCtrl);
wxSplitterWindow *splitter = XRCCTRL(*this, "splitter", wxSplitterWindow);
if (splitter)
@@ -629,6 +632,8 @@
c = m_Lib;
else if (id == XRCID("fs4"))
c = m_Obj;
+ else if (id == XRCID("fs5"))
+ c = m_Bin;
else
cbThrow(_T("Encountered invalid button ID"));