Statically linked, correctly working readline library under Windows? - c++

We're developing a C++ software package which depends on the GNU readline library and we usually build using gcc (requiring at least version 4). Now we would like to port this to Windows, obtaining a statically linked version which we can redistribute without requiring compilation by users.
I've tried several approaches:
Building using Cygwin (no go with the provided readline combined with -mno-cygwin or a MinGW compiler),
Building using MinGW and readline from GnuWin32 (unresolved dependencies to stat64, which I could not resolve),
Building using MinGW and building readline and required pdcurses from source (most promising approach, got to a static binary! But the obtained interactive shell behaved incorrectly, e.g. backspace was not visualized).
Any ideas how we might get one of the approaches to work?

After similar frustrations, I have just now compiled both a 32bit and 64bit version of libreadline 6.2 using MinGW-w64. Here's my how I did it:
Layout of my dev directory:
c:\dev\msys
c:\dev\mingw32
c:\dev\local32
c:\dev\mingw64
c:\dev\local64
Set some environment variables for the 32 bit build:
export CPPFLAGS=-I/c/dev/local32/include
export LDFLAGS=-L/c/dev/local32/lib
termcap 1.3.1.
Run the configure script:
./configure --host=i686-w64_mingw32 --prefix=/c/dev/local32
Edit termcap.c and fix up a few lines at the top. Mine looks like this:
/* Emacs config.h may rename various library functions such as malloc. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef emacs
#include <lisp.h> /* xmalloc is here */
/* Get the O_* definitions for open et al. */
#include <sys/file.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
//#ifdef HAVE_UNISTD_H
#include <unistd.h>
//#endif
#else /* not emacs */
//#ifdef STDC_HEADERS
#include <stdlib.h>
#include <string.h>
#define bcopy(b1,b2,len) (memmove((b2), (b1), (len)), (void) 0)
//#else
//char *getenv ();
//char *malloc ();
//char *realloc ();
//#endif
and tparam.c
/* Emacs config.h may rename various library functions such as malloc. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef emacs
#include "lisp.h" /* for xmalloc */
#else
//#ifdef STDC_HEADERS
#include <stdlib.h>
#include <string.h>
//#else
//char *malloc ();
//char *realloc ();
//#endif
/* Do this after the include, in case string.h prototypes bcopy. */
//#if (defined(HAVE_STRING_H) || defined(STDC_HEADERS)) && !defined(bcopy)
#define bcopy(s, d, n) memcpy ((d), (s), (n))
//#endif
#endif /* not emacs */
Modify the Makefile:
Line 23: CC = i686-w64-mingw32-gcc
Line 24: AR = i686-w64-mingw32-ar
Line 36: prefix = /c/dev/local32
Line 49: #oldincludedir = /usr/local
After that call make install and it should compile without warnings or errors.
readline 6.2
Set the same CPPFLAGS and LDFLAGS variables as with termcap before calling:
./configure --prefix=/c/dev/local32 --host=i686-w64-mingw32 --enable-static --enable-shared
Edit the Makefile:
Line 40: AR = i686-w64-mingw32-ar
make install should now compile and install readline!
If you want a 64bit library, replace i686-w64-mingw32 with x86_64-w64-mingw32 and local32 with local64.

Check out MinGWEditLine library
An EditLine API implementation for the native Windows Console. This BSD-licensed library provides command line editing and history functions similar to those found in GNU Readline.
Main readline functions are implemented for the native Windows console. BSD license.

gnuwin32 has a port of readline: http://gnuwin32.sourceforge.net/packages/readline.htm
for non-GPL projects, libedit has a more acceptable licensing [uses BSD licensing]

There is now a cygwin distribution of readline, which worked for me. The package name is libreadline-devel

Related

uisng msvc dll from mingw by code::blocks

I have a simple dll build by c++ msvc2010. It create a mydll.dll. (it uses some of windows native dlls so this is a c wrapper. It has function in it
exten "c"
{
void myfunc(std::vector<std::string> &names)
)
Then I use mingw utility pexports.exe and dlltool.exe in mingw\bin folder to convert it.
pexports mydll.dll | sed "s/^_//" > mydll.def
dlltool -U -d mydll.def -l mydll.dll
(overwrite the original one. or rename the original one to mydllold.dll. All dlls are in the same folder of executable of code::blocks program below.)
Then I have a code::blocks project myproc. The compiler is MinGW's g++. It links to the mydll.dll in the property->link settings.
The compilation has no error. But when I run the program
myproc.exe. It has run time error:
mydll.dll is either not designed to run on windows or it contains an error.
When I use:
dlltool -U -d mydll.def -l mydll.a
Then rename mydll.dll to mydllold.dll.
And make myproc link settings to mydll.a, it get error message:
The program cannot start because mydll.dll is missing.
When I rename mydll.a to mydll.dll, it get same error message:
mydll.dll is either not designed to run on windows or it contains an error.
Note. it does not say mydll.a, instead mydll.dll even the link is to mydll.a.
If I rename mydllold.dll back to mydll.dll. The error message is:
The procedure entry point _myfunc could not be located in the dynamic link library mydll.dll.
header file mydll.h:
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vector>
extern "C"
{
MYDLL_API int myfunc(std::vector<std::string>& a);
}
mydll.cpp:
#include <mydll.h>
extern "C"
{
MYDLL_API int myfunc( std::vector<std::string> &a)
{
return 0;
}
}

Can't find mkdir() function in dirent.h for windows

I am using dirent.h 1.20 (source) for windows in VC2013.
I can't find mkdir() in it.
How am I supposed to use it? Or can I create a directory somehow only using dirent.h?
simplest way that helped without using any other library is.
#if defined _MSC_VER
#include <direct.h>
#elif defined __GNUC__
#include <sys/types.h>
#include <sys/stat.h>
#endif
void createDir(string dir) {
#if defined _MSC_VER
_mkdir(dir.data());
#elif defined __GNUC__
mkdir(dir.data(), 0777);
#endif
}
Update: Since C++17, <filesystem> is the portable way to go. For earlier compilers, check out Boost.Filesystem.
The header you are linking to is effectively turning your (POSIX) dirent.h calls into (native) Windows calls. But dirent.h is about directory entries, i.e. reading directories, not creating ones.
If you want to create a directory (mkdir()), you need either:
A similar wrapping header turning your (POSIX) mkdir() call into the corresponding (native) Windows function calls (and I cannot point out such a header for you), or
use the Windows API directly, which might be pragmatic but would lead to a really ugly mix of POSIX and Windows functions...
// UGLY - these two don't belong in the same source...
#include <dirent.h>
#include <windows.h>
// ...
CreateDirectory( "D:\\TestDir", NULL );
// ...
Another solution would be to take a look at Cygwin, which provides a POSIX environment running on Windows, including Bash shell, GCC compiler toolchain, and a complete collection of POSIX headers like dirent.h, sys/stat.h, sys/types.h etc., allowing you to use the POSIX API consistently in your programming.
Visual Studio includes the <direct.h> header.
This header declares _mkdir and _wmkdir, which can be used to create a directory, and are part of the C libraries included with Visual Studio.
The other "easy" option would be to use Windows API calls as indicated by DevSolar.
You can use sys/types.h header file and use
mkdir(const char*) method to create a directory
Following is the sample code
#include<stdio.h>
#include<string.h>
#include <unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
int main()
{
if(!mkdir("C:mydir"))
{
printf("File created\n");
}
else
printf("Error\n");
}
mkdir is deprecated. Give #include <direct.h> as a header file. then write
_mkdir("C:/folder")

GCC cross-compiler for VxWorks can't compile C++

I'm trying to port a Linux library to run on VxWorks. I have successfully built binutils and gcc to target i486-wrs-vxworks and I can successfully build a simple C program. However, when I try to compile C++, things break.
I have a simple Hello World program:
#include <string>
#include <iostream>
int main()
{
std::string s = "Hello World";
std::cout << s << std::endl;
return 0;
}
To build it, I call:
i486-wrs-vxworks-gcc -I/home/kyle/vxworks-6.9/target/usr/h -I/home/kyle/vxworks-6.9/target/usr/h/c++ hello.cpp
This always fails with the message:
In file included from /home/kyle/vxworks-6.9/target/usr/h/c++/cerrno:4:0,
from /home/kyle/vxworks-6.9/target/usr/h/c++/xlocnum:4,
from /home/kyle/vxworks-6.9/target/usr/h/c++/ios:4,
from /home/kyle/vxworks-6.9/target/usr/h/c++/ostream:4,
from /home/kyle/vxworks-6.9/target/usr/h/c++/istream:4,
from /home/kyle/vxworks-6.9/target/usr/h/c++/string:4,
from hello.cpp:1:
/usr/local/lib/gcc/i486-wrs-vxworks/4.6.4/../../../../i486-wrs-vxworks/include/yvals.h:4:24: fatal error: yvals.h: No such file or directory
If I go look inside /usr/local/i486-wrs-vxworks/include/yvals.h, this is what I see:
/* yvals.h values header for conforming compilers on various systems */
#if (defined(__cplusplus) && defined(__GNUC__))
/* GCC C++ has it's own yvals.h */
#include_next <yvals.h>
#else /* __cplusplus && __GNUC__ */
#ifndef _YVALS
#define _YVALS
#ifdef _NO_WINDRIVER_MODIFICATIONS
#include <stdarg.h>
#endif
...
It appears that there is another yvals.h that needs to be included, but I can't find it anywhere. Did I just fail at building gcc correctly, or is there a way to fix this?
Which version of VxWorks are you using for this?
I have a fuzzy recollection that when upgrading VxWorks versions in the past there was a syntax error in yvals.h that was I needed to work around and it was fixed in a subsequent version.
Also, you can get the gcc cross compiler pre-built from WindRiver. Just login to windriver.com/support with your licence number and head to "Downloads" for your product version.
I went through a recent cross compiling nightmare myself (not VxWorks related) except that instead of yvals.h, I was having grief with stddef.h. The problem turned out to be that I needed to specify the include paths for the system header files.
Here are the steps it took me to solve my error messages. Feel free to modify as appropriate.
Create a file foo.c
#include <stddef.h> /* The problem header file (yvals.h for you?) */
int main (void) {
return 0;
}
Compile it with your compiler of choice
$(CC) foo.c -E
Note the include paths it uses and set them as your system header file list using the
-isystem <include path>
option.
Hope this helps.

Use of #include <iostream.h>

I am working on an older project that still has the deprecated "#include iostream.h" inclusions. I understand that iostream.h is deprecated and should not be used, but some of the systems that this code has to run/compile on are old solaris machines running CC and do not have iostream available. My question is: how can I make my more modern g++ compiler accept the iostream.h inclusions.
EDIT: The compilier cannot find the iostream.h file so I am assuming that none of the .h versions of the library are available to g++.
The easiest solution is probably to create a local header file called iostream.h which just includes <iostream> and imports the namespace std. Then, in order for the compiler to allow #include <iostream.h> you add the local path to your include file search path. For g++, this works:
g++ -I local_folder [other flags] …
Incidentally, your remark about
… the deprecated "#include iostream.h"
isn’t quite correct: this isn’t deprecated because it has never been legal C++.
I'd take a step back and write another intermediate header you use everywhere instead that does something like:
#if defined(sun) || defined(__sun)
# if defined(__SVR4) || defined(__svr4__)
/* Solaris */
#include <iostream>
# else
/* SunOS */
#include "iostream.h"
# endif
#else
/* Sane, modern system */
#include <iostream>
#endif

XCode 4.5 'tr1/type_traits' file not found

I use the wxwidget library and I have the following problem:
#if defined(HAVE_TYPE_TRAITS)
#include <type_traits>
#elif defined(HAVE_TR1_TYPE_TRAITS)
#ifdef __VISUALC__
#include <type_traits>
#else
#include <tr1/type_traits>
#endif
#endif
here the #include isn't found. I use the Apple LLVM compiler 4.1. (with the c++11 dialect).
If I switch to the LLVM GCC 4.2 compiler I have no error there, but the main problem is that all the c++11 inclusions won't work.
How can I either use the GCC compiler, but with the c++11 standard or make it that the LLVM can find the ?
any help would be really appreciated.
I'm guessing you have "C++ Standard Library" set to "libc++". If this is the case, you want <type_traits>, not <tr1/type_traits>. libc++ gives you a C++11 library, whereas libstdc++ (which is also the default in Xcode 4.5) gives you a C++03 library with tr1 support.
If you want, you can auto-detect which library you're using with:
#include <ciso646> // detect std::lib
#ifdef _LIBCPP_VERSION
// using libc++
#include <type_traits>
#else
// using libstdc++
#include <tr1/type_traits>
#endif
Or in your case perhaps:
#include <ciso646> // detect std::lib
#ifdef _LIBCPP_VERSION
// using libc++
#define HAVE_TYPE_TRAITS
#else
// using libstdc++
#define HAVE_TR1_TYPE_TRAITS
#endif
This is the command I used to build wxWidgets against libc++ (LLVM C++ Standard Library). Should work on Yosemite and later (at least until Apple breaks everything again):
mkdir build-cocoa-debug
cd build-cocoa-debug
../configure --enable-debug --with-macosx-version-min=10.10
make -j8 #This allows make to use 8 parallel jobs
Slightly modified the code above, to avoid compiler complaints:
Paste the following into strvararg.h just before #ifdefined (HAVE_TYPE_TRAITS)
#include <ciso646> // detect std::lib
#ifdef _LIBCPP_VERSION
// using libc++
#ifndef HAVE_TYPE_TRAITS
#define HAVE_TYPE_TRAITS 1
#endif
#else
// using libstdc++
#ifndef HAVE_TR1_TYPE_TRAITS
#define HAVE_TR1_TYPE_TRAITS 1
#endif
#endif