Undefined reference to 'getcwd' and 'mkdir' when building Google test project - c++

even if I have been strictly following the tutorials from this post, I can't get my google test demo program to compile.
I'm using Eclipse on Windows 10 x64, and the ARM GCC embedded toolchain to compile my code, since I will eventually need to run unit tests on embedded devices.
My problem is that when I try to Build the project I get those errors :
c:/program files (x86)/gnu tools arm embedded/9 2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe: ./contrib/gtest/gtest-all.o: in function `testing::internal::FilePath::GetCurrentDir()':
C:\Users\Hugo\eclipse\eclipse-workspace\test_gtest\Debug/../contrib/gtest/gtest-all.cc:9598: undefined reference to `getcwd'
c:/program files (x86)/gnu tools arm embedded/9 2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe: ./contrib/gtest/gtest-all.o: in function `testing::internal::FilePath::CreateFolder() const':
C:\Users\Hugo\eclipse\eclipse-workspace\test_gtest\Debug/../contrib/gtest/gtest-all.cc:9823: undefined reference to `mkdir'
collect2.exe: error: ld returned 1 exit status
make: *** [makefile:61: test_gtest.elf] Error 1
It comes more precisely from those lines of code in the gtest_all.cc file:
For the undefined reference to 'getcwd'
FilePath FilePath::GetCurrentDir() {
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \
GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_ESP32
// These platforms do not have a current directory, so we just return
// something reasonable.
return FilePath(kCurrentDirectoryString);
#elif GTEST_OS_WINDOWS
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd);
#else
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
char* result = getcwd(cwd, sizeof(cwd));
# if GTEST_OS_NACL
// getcwd will likely fail in NaCl due to the sandbox, so return something
// reasonable. The user may have provided a shim implementation for getcwd,
// however, so fallback only when failure is detected.
return FilePath(result == nullptr ? kCurrentDirectoryString : cwd);
# endif // GTEST_OS_NACL
return FilePath(result == nullptr ? "" : cwd);
#endif // GTEST_OS_WINDOWS_MOBILE
}
For the undefined reference to 'mkdir' :
bool FilePath::CreateFolder() const {
#if GTEST_OS_WINDOWS_MOBILE
FilePath removed_sep(this->RemoveTrailingPathSeparator());
LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
int result = CreateDirectory(unicode, nullptr) ? 0 : -1;
delete [] unicode;
#elif GTEST_OS_WINDOWS
int result = _mkdir(pathname_.c_str());
#elif GTEST_OS_ESP8266
// do nothing
int result = 0;
#else
int result = mkdir(pathname_.c_str(), 0777);
#endif // GTEST_OS_WINDOWS_MOBILE
if (result == -1) {
return this->DirectoryExists(); // An error is OK if the directory exists.
}
return true; // No error.
}
I have checked that unistd.h was included. I've been searching a lot but can't seem to find any similar error as mine. The closest I could find has been solved by people using CMake to compile it, but I'm not using CMake at all here.

AFAIK, getcwd() and mkdir() is platform dependent.
It seem there have been similar issue with other library:
https://github.com/purduesigbots/pros/issues/176
As above link, you can try to define stub for missing symbols.
In my working platform, getcwd() and mkdir() even get removed from the header.
In such case, you can edit gtest directly, for example:
FilePath FilePath::GetCurrentDir() {
#if GTEST_OS_CUSTOM_PLATFORM
return kCurrentDirectoryString;
...

Related

C/C++ Threading in Linux (Raspbian) using VS2019 on Windows 10 -pthread - Can't compile

I'm trying to do my first bit of threading but no matter what I've tried I can't get this to compile.
I've gone back to trying to compile some demo code and I'm getting the same problem as in my program.
If I run a simple print hello world it compiles and deploys the program fine and I can simply navigate to and run it directly on the Pi4.
Threading demo code
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
pthread_t tid[2];
void* doSomeThing(void* arg)
{
unsigned long i = 0;
pthread_t id = pthread_self();
if (pthread_equal(id, tid[0]))
{
printf("\n First thread processing\n");
}
else
{
printf("\n Second thread processing\n");
}
for (i = 0; i < (0xFFFFFFFF); i++);
return NULL;
}
int main(void)
{
int i = 0;
int err;
while (i < 2)
{
err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
if (err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
else
printf("\n Thread created successfully\n");
i++;
}
sleep(5);
return 0;
}
When I compile I get
Error /home/pi/projects/cpp_raspbian_thread_101/obj/x64/Debug/main.o: in function `main':
Error undefined reference to `pthread_create'
Error ld returned 1 exit status
To resolve this I've tried to add -pthread or -lpthread to
Project > Properties > Configuration Properties > C/C++ > Command Line > Addiitional Options
That does nothing, I'm not really sure if this is the correct place to put this.
I'm building in VS2019 so I'm not building from the command line, I don't know where to add this argument.
I have also tried installing pthreads in NuGet but that doesn't help.
Other software like VSCode seem to have files that could add this to but I'm lost in VS2019
Any help is appreciated.
EDIT:
Thanks for responses
OK so as #Eljay suggested I'm trying to use std::thread (again) but have the same problem.
// thread example
#include <iostream>
#include <thread>
void foo()
{
// do stuff...
}
int main()
{
std::thread first(foo);
return 0;
}
Log file
Validating sources
Copying sources remotely to '10.0.0.2'
Validating architecture
Validating architecture
Starting remote build
Compiling sources:
main.cpp
Linking objects
/usr/bin/ld : error : /home/pi/projects/cpp_raspbian_thread_101/obj/ARM/Debug/main.o: in function `std::thread::thread<void (&)(), , void>(void (&)())':
/usr/include/c++/8/thread(135): error : undefined reference to `pthread_create'
collect2 : error : ld returned 1 exit status
So I'm back to the pthread_create problem again
OK both code examples now compile and run.
As I originally thought, I needed to add -pthread somewhere in VS2019 and I was putting it in the wrong section.
Go to
Project Properties > Configuration Properties > Linker > Command Line
Add -pthread to Additional Options box and Apply.
I hope that saves someone else the 3 days it took me to sort it!

C++ CodeBlocks upgrade to C++17 can't use std::filesystem

I need to be able to list the files in a directory, and so I'm trying to upgrade my C++ version in CodeBlocks to C++ 17 so i can use filesystem. To do this I followed the steps outlined at http://candcplusplus.com/enable-c17-in-code-blocks-mingw-gcc-for-all-version-with-pictures#:~:text=Enabling%20the%20C%2B%2B17,Create%20a%20project.
I didnt have to change much, CodeBlocks 20.03 and MinGW 8.1.0 are already installed. MinGW is already in my path from when I built wxWidgets. The Settings->Compiler...->Toolchain executables tab I didnt have to make any changes to, and appears in CodeBlocks as:
I also checked the box to use C++ 17 in compiler settings like so
I ran the test program on the website with the instructions and got "True!".
However when I change the basic test program to this, to try and use filesystem to read files in a directory, I get an error:
#include <iostream>
#include <filesystem>
using namespace std;
int main()
{
const int i=90;
if constexpr (i) //'if constexpr' is part of C++17
{
cout << "True!";
}
else
{
cout<<"False" ;
}
std::string path = "../MagicProgCPP/files/debug images/";
for (const auto & entry : filesystem::directory_iterator(path))
{
cout << entry.path() << std::endl;
}
cin.get();
return 0;
}
The program stops building, opens the file fs_path.h and stops on this line:
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
if (__p.is_absolute()
|| (__p.has_root_name() && __p.root_name() != root_name())) <----- ******STOPS HERE
operator=(__p);
else
{
string_type __pathname;
if (__p.has_root_directory())
__pathname = root_name().native();
else if (has_filename() || (!has_root_directory() && is_absolute()))
__pathname = _M_pathname + preferred_separator;
__pathname += __p.relative_path().native(); // XXX is this right?
_M_pathname.swap(__pathname);
_M_split_cmpts();
}
#else
// Much simpler, as any path with root-name or root-dir is absolute.
if (__p.is_absolute())
operator=(__p);
else
{
if (has_filename() || (_M_type == _Type::_Root_name))
_M_pathname += preferred_separator;
_M_pathname += __p.native();
_M_split_cmpts();
}
#endif
return *this;
}
I get this error in the build log:
C:\Program Files\CodeBlocks\MinGW\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\bits\fs_path.h|237|error: no match for 'operator!=' (operand types are 'std::filesystem::__cxx11::path' and 'std::filesystem::__cxx11::path')|
I'm prety confident the path exists as I entered it and there's files in it. The build log message suggests maybe I'm not using C++17? But when I click build, this is the line the program uses to build:
g++.exe -Wall -fexceptions -g -Wall -std=c++17 -c E:\testc17\main.cpp -o obj\Debug\main.o
What am I doing wrong? Thanks
The bug 78870 was fixed since 2018-07.
You should add to project options -> linker settings -> link libraries the following library: stdc++fs.
I tried to compile your code with MinGW gcc 8.1.0 (via CodeBlocks) and everything works well (clearly with another path, since I don't have the same directories as you).
You could also add a check on the existence of the search directory like this:
namespace fs = std::filesystem;
std::string mypath { "../MyDir" };
if(fs::exists(mypath))
{
for(const auto & entry : fs::directory_iterator(path))
{
cout << entry.path() << std::endl;
}
}
It appears that this exact problem is a known bug in mingw 8.1. The bug report is here: https://sourceforge.net/p/mingw-w64/bugs/737/
and has the error in the same location:
operator != is declared and defined in line 550, but referenced in line 237.
The problem is triggered by operator/= in line 233:
path& operator/=(const path& __p)
{
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
if (__p.is_absolute()
|| (__p.has_root_name() && __p.root_name() != root_name()))
operator=(__p);
else
{
string_type __pathname;
if (__p.has_root_directory())
__pathname = root_name().native();
else if (has_filename() || (!has_root_directory() && is_absolute()))
__pathname = _M_pathname + preferred_separator;
__pathname += __p.relative_path().native(); // XXX is this right?
_M_pathname.swap(__pathname);
_M_split_cmpts();
}
The bug report said this was fixed in master meaning you need to install a version of mingw with the fix applied. I believe the best method is to upgrade mingw to a version greater than 8.1
user4581301 commented above in the main question that the following link has instructions on how to get a mingw install: How to install MinGW-w64 and MSYS2?

Properly setting up tinycc with visual studio 2019, library libtcc1-32.a not found

I'm using tcclib to compile and run C code on the fly in my C++ project.
I'm using the binaries provided here https://bellard.org/tcc/
I then open a vs2019 developer prompt and run both those command
lib /def:libtcc\libtcc.def /out:libtcc.lib
cl /MD examples/libtcc_test.c -I libtcc libtcc.lib
My code builds fine, I'm using this code. This code is similar to the one found in the tcclib example, which is this one : https://repo.or.cz/tinycc.git/blob/HEAD:/tests/libtcc_test.c (this is another repo, but it's the same code.
The code I run is this one. This is inside an extern "C" {}.
int tcc_stuff(int argc, const char** argv) {
TCCState* s;
int i;
int (*func)(int);
s = tcc_new();
if (!s) {
fprintf(stderr, "Could not create tcc state\n");
exit(1);
}
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
for (i = 1; i < argc; ++i) {
const char* a = argv[i];
if (a[0] == '-') {
if (a[1] == 'B')
tcc_set_lib_path(s, a + 2);
else if (a[1] == 'I')
tcc_add_include_path(s, a + 2);
else if (a[1] == 'L')
tcc_add_library_path(s, a + 2);
}
}
/* MUST BE CALLED before any compilation */
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
{
const char* other_file = ReadFile2(argv[1]);
if (other_file == NULL)
{
printf("invalid filename %s\n", argv[1]);
return 1;
}
if (tcc_compile_string(s, other_file) == -1)
return 1;
}
/* as a test, we add symbols that the compiled program can use.
You may also open a dll with tcc_add_dll() and use symbols from that */
tcc_add_symbol(s, "add", add);
tcc_add_symbol(s, "hello", hello);
/* relocate the code */
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
return 1;
/* get entry symbol */
func = (int(*)(int))tcc_get_symbol(s, "foo");
if (!func)
return 1;
/* run the code */
msg(func(32));
//msg(func2(4));
/* delete the state */
tcc_delete(s);
return 0;
}
When running my code, TCC had the error
tcc: error: library 'libtcc1-32.a' not found
I fixed it by placing this file in the lib/ directory next to my .exe
I also copied the include/ folder to include stdio.h etc.
My question is: why does it need this file in a lib/ folder, instead of the provided tcclib.dll file? Is it possible to "ship" certain headers like stdio.h?
The question has no answer but 360 views, so I thought I'd reply.
The library doesn't necessarily need to be in that folder. To quote the author's command line docs, which still apply to the library,
-Ldir
Specify an additional static library path for the -l option. The default library paths are /usr/local/lib, /usr/lib and /lib.
I inferred your program to be a modified main() of libtcc_test.c & fixed it to the point of functioning. Then I used VS2022 to retrace your steps, put the .a files into the same folder as my new tests_libtcc_test.exe, then I ran this:
tests_libtcc_test c:/lang/tcc/examples/fib.c -Ic:/lang/tcc/include -L.
The library issue appears if I don't -L anything, and disappears if I include at least the ".".
And of course, you can drop the include folder into your redistributable and include it by default right from the code.
Because the tcc DLL is just another interface to the same compiler, it needs the same things tcc.exe would to build an executable; in this case, it needs the same libraries.

fatal error: strtok_r.h: No such file or directory (while compiling tesseract-ocr-3.01 in MinGW)

I'm compiling tesseract-ocr-3.01 in MinGW, and I'm getting this error ambigs.cpp:31:22: fatal error: strtok_r.h: No such file or directory
This is the code where the error is:
#ifdef WIN32
#ifndef __GNUC__
#define strtok_r strtok_s
#else
#include "strtok_r.h"
#endif /* __GNUC__ */
#endif /* WIN32 */
Edit
I found this feature request to add strtok_r.h to MinGW. From the comments there:
strtok_r() is an optional POSIX function, required only for
implementations which support POSIX threads. MinGW does not support
POSIX threads; therefore, I don't think that this function has any
place in a base MinGW distribution.
POSIX threads support for MS-Windows is provided by the pthreads-win32
project. Maybe they already provide a strtok_r() implementation. If
so, then you could use it; if not, you might ask them to consider
adding it.
The problem is most easily solved by adding an strtok_r implementation to the project's sources:
char *strtok_r(char *str, const char *delim, char **save)
{
char *res, *last;
if( !save )
return strtok(str, delim);
if( !str && !(str = *save) )
return NULL;
last = str + strlen(str);
if( (*save = res = strtok(str, delim)) )
{
*save += strlen(res);
if( *save < last )
(*save)++;
else
*save = NULL;
}
return res;
}

Problem with LZO

So I am trying to use LZO in my application. Here is how I have included it:
#include "lzoconf.h"
#include "lzodefs.h"
#include "lzo1x.h"
/* portability layer */
static const char *progname = NULL;
#define WANT_LZO_MALLOC 1
#define WANT_XMALLOC 1
#include "portab.h"
Then in the application I do:
if (lzo_init() != LZO_E_OK)
{
printf("internal error - lzo_init() failed !!!\n");
printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable '-DLZO_DEBUG' for diagnostics)\n");
return 4;
}
It compiles ok. No errors or warnings during compilation.
When I try to run my application though, there are two errors:
/home/richard/client/src/portab.h:145: undefined reference to `__lzo_align_gap'
Which points at this line in portab.h:
if (__lzo_align_gap(p, (lzo_uint) sizeof(lzo_align_t)) != 0)
{
printf("%s: C library problem: malloc() returned mis-aligned pointer!\n", progname);
exit(1);
}
return p;
And in my application:
/home/richard/client/src/main.cc:108: undefined reference to `__lzo_init_v2'
Which points to:
if (lzo_init() != LZO_E_OK)
{
printf("internal error - lzo_init() failed !!!\n");
printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable '-DLZO_DEBUG' for diagnostics)\n");
return 4;
}
I have all the header files inside my source directory:
config.h
lzo1x.h
lzoconf.h
lzodefs.h
miniacc.h
portab.h
portab_a.h
What am I doing wrong?
I am compiling my application in Ubuntu 10.10 in Anjuta ide.
Headers is not enough, you need to link to the libraries. Have you read the documentation?