Sunday, March 8, 2015

Override CMake in Cygwin

As of this writing, the CMake bundle with Cygwin is on version 3.1.2. This would be a bad news to me as I can't generate visual studio project using this tool. When I was issued a command cmake --help, this will shows a list of supported platform. Whereas the latest version of this writing would be 3.2.0-rc2. It has far more lists of supported platform.

Available generators on version 3.1.2.
Generators

The following generators are available on this platform:
  Unix Makefiles              = Generates standard UNIX makefiles.
  Ninja                       = Generates build.ninja files (experimental).
  CodeBlocks - Ninja          = Generates CodeBlocks project files.
  CodeBlocks - Unix Makefiles = Generates CodeBlocks project files.
  CodeLite - Ninja            = Generates CodeLite project files.
  CodeLite - Unix Makefiles   = Generates CodeLite project files.
  Eclipse CDT4 - Ninja        = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - Unix Makefiles = Generates Eclipse CDT 4.0 project files.
  KDevelop3                   = Generates KDevelop 3 project files.
  KDevelop3 - Unix Makefiles  = Generates KDevelop 3 project files.
  Kate - Ninja                = Generates Kate project files.
  Kate - Unix Makefiles       = Generates Kate project files.
  Sublime Text 2 - Ninja      = Generates Sublime Text 2 project files.
  Sublime Text 2 - Unix Makefiles = Generates Sublime Text 2 project files.
Available generators on version 3.2.0-rc2
Generators

The following generators are available on this platform:
  Visual Studio 6             = Generates Visual Studio 6 project files.
  Visual Studio 7             = Generates Visual Studio .NET 2002 project files.
  Visual Studio 10 2010       = Generates Visual Studio 10 (VS 2010) project files.
  Visual Studio 11 2012       = Generates Visual Studio 11 (VS 2012) project files.
  Visual Studio 12 2013       = Generates Visual Studio 12 (VS 2013) project files.
  Visual Studio 14 2015       = Generates Visual Studio 14 (VS 2015) project files.
  Visual Studio 7 .NET 2003   = Generates Visual Studio .NET 2003 project files.
  Visual Studio 8 2005        = Generates Visual Studio 8 2005 project files.
  Visual Studio 9 2008        = Generates Visual Studio 9 2008 project files.
  Borland Makefiles           = Generates Borland makefiles.
  NMake Makefiles             = Generates NMake makefiles.
  NMake Makefiles JOM         = Generates JOM makefiles.
  MSYS Makefiles              = Generates MSYS makefiles.
  MinGW Makefiles             = Generates a make file for use with mingw32-make.
  Unix Makefiles              = Generates standard UNIX makefiles.
  Ninja                       = Generates build.ninja files (experimental).
  Watcom WMake                = Generates Watcom WMake makefiles.
  CodeBlocks - MinGW Makefiles= Generates CodeBlocks project files.
  CodeBlocks - NMake Makefiles= Generates CodeBlocks project files.
  CodeBlocks - Ninja          = Generates CodeBlocks project files.
  CodeBlocks - Unix Makefiles = Generates CodeBlocks project files.
  CodeLite - MinGW Makefiles  = Generates CodeLite project files.
  CodeLite - NMake Makefiles  = Generates CodeLite project files.
  CodeLite - Ninja            = Generates CodeLite project files.
  CodeLite - Unix Makefiles   = Generates CodeLite project files.
  Eclipse CDT4 - MinGW Makefiles = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - NMake Makefiles = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - Ninja        = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - Unix Makefiles = Generates Eclipse CDT 4.0 project files.
  Kate - MinGW Makefiles      = Generates Kate project files.
  Kate - NMake Makefiles      = Generates Kate project files.
  Kate - Ninja                = Generates Kate project files.
  Kate - Unix Makefiles       = Generates Kate project files.
  Sublime Text 2 - MinGW Makefiles = Generates Sublime Text 2 project files.
  Sublime Text 2 - NMake Makefiles = Generates Sublime Text 2 project files.
  Sublime Text 2 - Ninja      = Generates Sublime Text 2 project files.
  Sublime Text 2 - Unix Makefiles = Generates Sublime Text 2 project files.
How could I upgrade the CMake in Cygwin? Unfortunately, this can't be done since the latest version I got is the one I had already installed. Try thinking out of the box, download the latest CMake in separate path, then override the Cygwin path with a new CMake path in environment variable, this is how I do it:
  1. Declare CMAKE_PATH pointing to the new CMake file system.
  2. Put this path before CYGWIN_PATH in PATH variable. 
This is how it looks like in PATH variable:

%CMAKE_PATH%\bin;%CYGWIN_PATH%\bin

With this change, I can only use it in DOS command because Cygwin will also reference to version 3.1.2.

Sunday, March 1, 2015

How do CMake determine static or dynamic Boost library?

I was trying to integrate Boost filesystem and system module into CMake in the project, but interestingly, I found out that find_package were not functioning properly:

find_package(Boost 1.54.0 COMPONENTS filesystem system REQUIRED)

I just spot this symptom in this morning. When I am generating a project file from Cmake with this command cmake -G “xxx”, I hit an error as mention below:

CMake Error at D:/tool/cmake-3.2.0-rc1-win32-x86/share/cmake-3.2/Modules/FindBoost.cmake:1182 (message):
  Unable to find the requested Boost libraries.

  Boost version: 1.54.0

  Boost include path: C:/Boost/include/boost-1_54

  Could not find the following Boost libraries:

          boost_filesystem
          boost_system

No Boost libraries were found. You may need to set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.

When I have the debug mode turned on, like this set(Boost_DEBUG 1), I have the following piece captured:
-- [ D:/tool/cmake-3.2.0-rc1-win32-x86/share/cmake-3.2/Modules/FindBoost.cmake:890 ] _boost_LIBRARY_SEARCH_DIRS = C:/Boost/lib;C:/Boost/stage/lib;C:/Boost/include/boost-1_54/lib;C:/Boost/include/boost-1_54/../lib;C:/Boost/include/boost-1_54/stage/lib;PATHS;C:/boost/lib;C:/boost;/sw/local/lib
-- [ D:/tool/cmake-3.2.0-rc1-win32-x86/share/cmake-3.2/Modules/FindBoost.cmake:1001 ] Searching for FILESYSTEM_LIBRARY_RELEASE: boost_filesystem-vc110-mt-1_54;boost_filesystem-vc110-mt;boost_filesystem-mt-1_54;boost_filesystem-mt;boost_filesystem
-- [ D:/tool/cmake-3.2.0-rc1-win32-x86/share/cmake-3.2/Modules/FindBoost.cmake:1037 ] Searching for FILESYSTEM_LIBRARY_DEBUG: boost_filesystem-vc110-mt-gd-1_54;
boost_filesystem-vc110-mt-gd;boost_filesystem-mt-gd-1_54;boost_filesystem-mt-gd;boost_filesystem-mt;boost_filesystem
-- [ D:/tool/cmake-3.2.0-rc1-win32-x86/share/cmake-3.2/Modules/FindBoost.cmake:1001 ] Searching for SYSTEM_LIBRARY_RELEASE: boost_system-vc110-mt-1_54;boost_sys
tem-vc110-mt;boost_system-mt-1_54;boost_system-mt;boost_system
-- [ D:/tool/cmake-3.2.0-rc1-win32-x86/share/cmake-3.2/Modules/FindBoost.cmake:1037 ] Searching for SYSTEM_LIBRARY_DEBUG: boost_system-vc110-mt-gd-1_54;boost_sy
stem-vc110-mt-gd;boost_system-mt-gd-1_54;boost_system-mt-gd;boost_system-mt;boost_system
-- [ D:/tool/cmake-3.2.0-rc1-win32-x86/share/cmake-3.2/Modules/FindBoost.cmake:1088 ] Boost_FOUND = 1

...
CMake was searching for boost_xxx but I had only libboost_xxx installed in my system. I was wondering how could I direct CMake to take libboost_xxx instead of boost_xxx? Thanks to open source that could allow me to dive into the source code to see what is happening actually. From the clue given above, there is a piece of logic in FindBoost.cmake governing CMake whether a boost library prefix with “lib” or without “lib” should be taken. Here is the piece:
...

set(Boost_LIB_PREFIX "")
if ( WIN32 AND Boost_USE_STATIC_LIBS AND NOT CYGWIN )
  set(Boost_LIB_PREFIX "lib")
endif()

...
Since I'm doing this in DOS prompt, WIN32 and NOT CYGWIN are returning true, but Boost_USE_STATIC_LIBS were returning false. This reminds me that I have something in my code:
...

set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
set(Boost_ALL_DYN_LINK ON)

...
Clearly, I should ON the Boost_USE_STATIC_LIBS to resolve this problem. And this is interesting to know that a boost static library is prefixed with “lib”.

Tuesday, February 24, 2015

CMake unable to read Boost's version.hpp

Ever wonder how Boost works together with CMake? I have no knowledge prior to this setup, thus this is my initial code in CMakeLists.txt.
cmake_minimum_required(VERSION 2.8.4)
project("Project A")

set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
set(Boost_ALL_DYN_LINK ON)

find_package(Boost 1.54.0 COMPONENTS filesystem system REQUIRED)

if(Boost_FOUND)
 message(STATUS "Boost library were found")
 
 include_directories(${Boost_INCLUDE_DIRS})
 add_executable(Project_A source/main.cpp)
 target_link_libraries(syncFile ${Boost_LIBRARIES})
else()
 message(STATUS "No Boost library were found")
endif()
As of this writing, I'm using Boost 1.54 and CMake 3.1.2. Anyhow, there is an error when generating the Makefile. Here is the error:
CMake Error at /usr/share/cmake-3.1.2/Modules/FindBoost.cmake:685 (file):
  file STRINGS file "/cygdrive/d/visual studio
  2012/projectA/C:/boost/include/boost-1_54/boost/version.hpp" cannot be
  read.
Call Stack (most recent call first):
  CMakeLists.txt:19 (find_package)


-- Could NOT find Boost
-- No Boost library were found
-- Configuring incomplete, errors occurred!
I have been trying on cygwin, and DOS prompt, it is somewhat weird that the error was happening in FindBoost.cmake. This is the code snippet on the piece that throw an error:
# Set Boost_FOUND based only on header location and version.
# It will be updated below for component libraries.
if(Boost_INCLUDE_DIR)
  if(Boost_DEBUG)
    message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
                   "location of version.hpp: ${Boost_INCLUDE_DIR}/boost/version.hpp")
  endif()

  # Extract Boost_VERSION and Boost_LIB_VERSION from version.hpp
  set(Boost_VERSION 0)
  set(Boost_LIB_VERSION "")
  file(STRINGS "${Boost_INCLUDE_DIR}/boost/version.hpp" _boost_VERSION_HPP_CONTENTS REGEX "#define BOOST_(LIB_)?VERSION ")
A quick check on ${Boost_INCLUDE_DIR}, it shows C:/boost/include/boost-1_54, but I don't know why there is a default path and why ${Boost_INCLUDE_DIR} appended to that default path. I have tried the workaround on BOOST_ROOT as described here, and here, and also try the workaround on CMAKE_PREFIX_PATH as describe here but none of them work. I also found this link were quite useful, but it doesn't work on find_package command.

I'm running out of clues on this problem. Since the default path was bundled together with CMake as one package, I choose to override Boost_INCLUDE_DIR instead of shake him off away.
  ...

  set(Boost_INCLUDE_DIR /cygdrive/c/boost/include/boost-1_54)
But this isn't a perfect solution as it wouldn't work on Linux since the Boost path is referring to Windows. I'm still searching a solution for this.

Sunday, February 15, 2015

undefined reference of copy_file

./source/main.o: In function `boost::filesystem::copy_file(boost::filesystem::path const&, boost::filesystem::path const&)':
/home/kokhoe/tool/boost_1_54_0/boost/filesystem/operations.hpp:384: undefined reference to `boost::filesystem::detail::copy_file(boost::filesystem::path const&, boost::filesystem::path const&, boost::filesystem::copy_option, boost::system::error_code*)'
collect2: error: ld returned 1 exit status
make: *** [syncFile] Error 1
I got this error when I have the following piece executed:
path source = file_A;
path dest = path_B;
copy_file(source, dest);
Luckily, there is already a programmer had the problem solved (read here), what he did is to put this code before #include <boost/filesystem.hpp>.

#define BOOST_NO_CXX11_SCOPED_ENUMS

Do take note also path_B must be a file name rather than a path name.

Tuesday, February 10, 2015

Finding index of Nth occurrence of a string

Recently I was working on a task that require me to find the Nth occurrence of a string. In other words, this function should return the position index of Nth occurrence. For example, the 2nd occurrence of o in a string hello world will locate at 7. Thus, I have following code created for this:
int searchNth(const char* work, const char* find, const int nth) {

 int work_len = strlen(work);
 int find_len = strlen(find);
 int match_count = 0;
 int match_index_pos = -1;
 int occurrence = -1;

 for (int i = 0; i < work_len; i++) {

  if (work[i] == find[match_count]) {
   match_count++;

   if (match_count == 1) {
    match_index_pos = i;
   }
  }
  else if (match_count > 0 && work[i] != find[match_count]) {
   match_count = 0;
   match_index_pos = -1;
  }

  if (find_len == match_count) {
   occurrence++;
  }

  if (nth == occurrence) {
   return match_index_pos;
  }
 }

 return -1;
}
Sample of execution:

searchNth("hello world", "o", 1); // output: 7
searchNth("hello world", "o", 2); // output: -1
searchNth("hello world", "o ", 0); // output: 4

Well, I'm pretty proud of myself because I have created such a nice piece of code that could return the nth occurrence of a string. (Not really!) Someone has better solution than mine. I just found the answer in this thread.
size_t find_Nth(
    const std::string & str ,   // where to work
    unsigned            N ,     // N'th ocurrence
    const std::string & find    // what to 'find'
) {
    if ( 0==N ) { return std::string::npos; }
    size_t pos,from=0;
    unsigned i=0;
    while ( i<N ) {
        pos=str.find(find,from);
        if ( std::string::npos == pos ) { break; }
        from = pos + 1; // from = pos + find.size();
        ++i;
    }
    return pos;
/**
    It would be more efficient to use a variation of KMP to
    benefit from the failure function.
    - Algorithm inspired by James Kanze.
    - http://stackoverflow.com/questions/20406744/
*/
}
What a nice piece. The code is much cleaner than mine, lesser if statement, easier to digest with human brain. (Perfect!) Somehow, here is still better one. Believe or not, Boost library did have such algorithm developed:
    string work = "hello world";
    iterator_range<string::iterator> r = find_nth(work, "o", 1);
    cout << distance(work.begin(), r.begin()) << endl;
Wow!!! This piece was just damn real simple. From the top most till the bottom, although there are producing the same output, but the implementation was totally different. I can see the code is evolving gradually. What is next? What else can be done in the future? Fewer code?

Last but not least, thanks to Boost algorithm, nice work!

class not found in wsgen

When I have finished coding on the web service (using document style), I'm ready to generate extra classes with wsgen. Usually the following command will be used for this purpose.

wsgen -keep -cp . org.huahsin.HelloWorld

Anyhow, this command is incomplete because I receive a class not found error immediately as shown below:
C:\workspace\WebService1>wsgen -verbose -cp . org.huahsin.HelloWorld
Class not found: "org.huahsin.HelloWorld"


Usage: WSGEN [options] 

...
...

Referring to the wsgen documentation, it did mention that the -classpath or -cp is referring to an input class file, not the source file. Thus to ensure the command above work correctly, change to the root of the project directory (not bin/ or src/), then fire the command with -cp point to bin/ instead of current directory like this:

wsgen -verbose -cp ./bin org.huahsin.HelloWorld

Besides that, I notice this command doesn't keep the source files after the extra class files being generated. To keep the source files, command below would help:

wsgen -verbose -cp ./bin -s ./src org.huahsin.HelloWorld

Tuesday, February 3, 2015

How to switch on C++11 on Eclipse?

This is, somehow, quite annoying me. I was compiling C++11 on Eclipse Kepler, but there was an error (as shown below) complaining to me that I must enable C++11 in order to proceed. But where is the C++11 switch?
Invoking: Cygwin C++ Compiler
g++ -I"D:\tool\boost_1_54_0" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/main.d" -MT"src/main.d" -o "src/main.o" "../src/main.cpp"
In file included from /usr/lib/gcc/x86_64-pc-cygwin/4.8.3/include/c++/initializer_list:36:0,
                 from ../src/main.cpp:6:
/usr/lib/gcc/x86_64-pc-cygwin/4.8.3/include/c++/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
 #error This file requires compiler and library support for the \
  ^
In file included from D:\tool\boost_1_54_0/boost/filesystem/path_traits.hpp:23:0,
                 from D:\tool\boost_1_54_0/boost/filesystem/path.hpp:25,
                 from D:\tool\boost_1_54_0/boost/filesystem.hpp:16,
                 from ../src/main.cpp:7:
D:\tool\boost_1_54_0/boost/system/error_code.hpp:222:36: warning: 'boost::system::posix_category' defined but not used [-Wunused-variable]
src/subdir.mk:18: recipe for target 'src/main.o' failed
     static const error_category &  posix_category = generic_category();
                                    ^
D:\tool\boost_1_54_0/boost/system/error_code.hpp:223:36: warning: 'boost::system::errno_ecat' defined but not used [-Wunused-variable]
     static const error_category &  errno_ecat     = generic_category();
                                    ^
D:\tool\boost_1_54_0/boost/system/error_code.hpp:224:36: warning: 'boost::system::native_ecat' defined but not used [-Wunused-variable]
     static const error_category &  native_ecat    = system_category();

The switch was locate at project's properties > C/C++ Build > Settings > Tool Settings tab > Cygwin C++ Compiler > Miscellenous, put -std=c++11 in the Other Flags to switch on C++11 (append on it if it is not empty). Then the compilation will proceed as usual.