I'm trying to find find a substitute for a call to "system" (from stdlib.h) in my C++ program.
So far I've been using it to call g++ in my program to compile and then link a variable number of source files in a directory chosen by the user.
Here I've got an example how the command could approximately look like: "C:/mingw32/bin/g++.exe -L"C:\mingw32\lib" [...]"
However, I have the problem that (at least with the MinGW compiler I'm using) I get the error "Command line is too long" when the command string gets too long.
In my case it was about 12000 characters long. So I probably need another way to call g++.
Additionally, I've read that you generally shouldn't use "system" anyway: http://www.cplusplus.com/forum/articles/11153/
So I'm in need for some substitute (that should also be as platform independent as possible, because I want the program to run on Windows and Linux).
I've found one candidates that would generally look quite well suited:
_execv / execv:
Platform independent, but:
a) http://linux.die.net/man/3/exec says "The exec() family of functions replaces the current process image with a new process image". So do I need to call "fork" first so that the C++ program isn't terminated? Is fork also available on Windows/MSVC?
b) Using "system", I've tested whether the return value was 0 to see if the source file could be compiled. How would this work with exec? If I understand the manpage correctly, will it only return the success of creating the new process and not the status of g++? And with which function could I suspend my program to wait for g++ to finish and get the return value?
All in all, I'm not quite sure how I should handle this. What are your suggestions? How do multiplatform programs like Java (Runtime.getRuntime().exec(command)) or the Eclipse C++ IDE internally solve this? What would you suggest me to do to call g++ in an system independent way - with as many arguments as I want?
EDIT:
Now I'm using the following code - I've only tested it on Windows yet, but at least there it seems to work as expected. Thanks for your idea, jxh!
Maybe I'll look into shortening the commands by using relative paths in the future. Then I would have to find a platform independent way of changing the working directory of the new process.
#ifdef WIN32
int success = spawnv(P_WAIT, sCompiler.c_str(), argv);
#else
pid_t pid;
switch (pid = fork()) {
case -1:
cerr << "Error using fork()" << endl;
return -1;
break;
case 0:
execv(sCompiler.c_str(), argv);
break;
default:
int status;
if (wait(&status) != pid) {
cerr << "Error using wait()" << endl;
return -1;
}
int success = WEXITSTATUS(status);
}
#endif
You might get some traction with some of these command line options if all your files are in (or could be moved to) one (or a small number) of directories. Given your sample path to audio.o, this would reduce your command line by about 90%.
-Ldir
Add directory dir to the list of directories to be searched for `-l'.
From: https://gcc.gnu.org/onlinedocs/gcc-3.0/gcc_3.html#SEC17
-llibrary
Search the library named library when linking.
It makes a difference where in the command you write this option; the linker searches processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o' searches libraryz' after file foo.o' but beforebar.o'. If bar.o' refers to functions inz', those functions may not be loaded.
The linker searches a standard list of directories for the library, which is actually a file named `liblibrary.a'. The linker then uses this file as if it had been specified precisely by name.
The directories searched include several standard system directories plus any that you specify with `-L'.
Normally the files found this way are library files--archive files whose members are object files. The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined. But if the file that is found is an ordinary object file, it is linked in the usual fashion. The only difference between using an -l' option and specifying a file name is that-l' surrounds library with lib' and.a' and searches several directories.
From: http://gcc.gnu.org/onlinedocs/gcc-3.0/gcc_3.html
Here's another option, perhaps closer to what you need. Try changing the directory before calling system(). For example, here's what happens in Ruby...I'm guessing it would act the same in C++.
> system('pwd')
/Users/dhempy/cm/acts_rateable
=> true
> Dir.chdir('..')
=> 0
> system('pwd')
/Users/dhempy/cm
=> true
If none of the other answers pan out, here's another. You could set an environment variable to be the path to the directory, then use that variable before each file that you link in.
I don't like this approach much, as you have to tinker with the environment, and I don't know if that would actually affect the command line limit. It may be that the limit applies after interpolating the command. But, something to thing about, regardless.
Related
I am trying to use dlopen() and dlinfo() to get the path my executable. I am able to get the path to a .so by using the handle returned by dlopen() but when I use the handle returned by dlopen(NULL,RTLD_LAZY); then the path I get back is empty.
void* executable_handle = dlopen(0, RTLD_LAZY);
if (nullptr != executable_handle)
{
char pp_linkmap[sizeof(link_map)];
int r = dlinfo(executable_handle, RTLD_DI_LINKMAP, pp_linkmap);
if (0 == r)
{
link_map* plink = *(link_map**)pp_linkmap;
printf("path: %s\n", plink->l_name);
}
}
Am I wrong in my assumption that the handle for the executable can be used in the dlinfo functions the same way a .so handle can be used?
Am I wrong in my assumption that the handle for the executable can be used in the dlinfo functions the same way a .so handle can be used?
Yes, you are.
The dynamic linker has no idea which file the main executable was loaded from. That's because the kernel performs all mmaps for the main executable, and only passes a file descriptor to the dynamic loader (who's job it is to load other required libraries and star the executable running).
I'm trying to replicate some of the functionality of GetModuleFileName() on linux
There is no reliable way to do that. In fact the executable may no longer exist anywhere on disk at all -- it's perfectly fine to run the executable and remove the executable file while the program is still running.
Also hard links mean that there could be multiple correct answers -- if a.out and b.out are hard linked, there isn't an easy way to tell whether a.out or b.out was used to start the program running.
Your best options probably are reading /proc/self/exe, or parsing /proc/self/cmdline and/or /proc/self/maps.
The BSD utility library has a function getprogname(3) that does exactly what you want. I'd suggest that is more portable and easier to use than procfs in this case.
I'm developing a project on DevC++ which uses MinGW64. On Windows 7 (i don't know if this can be related to my issue).
I had a problem compiling a C++ program where I call the function GetFileVersionInfoSize(), which is:
main.cpp:(.text+0x51): undefined reference to `GetFileVersionInfoSizeA'
After two days of researching, I understood that I have to include in the parameters of the linker the "version.lib" file, which is missing in my computer, I searched it everywhere.
I can't even find a download mirror on the web, so I'm asking, does anybody know where I can find version.lib? Maybe somewhere hidden in my PC or in the web? Maybe with a new installation of MinGW64? I don't know, since my installation of MinGW64 came with DevC++.
Thanks for reading.
Thank all you guys for the suggestions you gave me
In this answer there is how to find Version.lib in this case.
The following is about accomplishing using GetFileVersionInfoSize(), GetFileVersionInfo() and VerQueryValue() to get the Product Name of an executable file, which is why I needed Version.lib, actually being called libversion.a on my machine.
LAST-EDIT: I managed to achieve what I wanted, this is the code that works in my case:
// filename contains the path of the .exe we want to get Product Name
int version_info_size = GetFileVersionInfoSize(filename, NULL);
if(version_info_size > 0) {
BYTE *version_info_buffer = new BYTE[version_info_size];
if(GetFileVersionInfo(filename, 0, version_info_size, version_info_buffer)) {
char *product_name = NULL;
UINT pLenFileInfo = 0;
if(VerQueryValue(version_info_buffer, TEXT("\\StringFileInfo\\040904e4\\ProductName"),
(LPVOID*)&product_name, &pLenFileInfo)) cout << product_name;
}
}
Notice that if you want to compare product_name with another value, you have to do something like string product_name_str = product_name and compare that string variable, otherwise the comparison will always return false. Or maybe just do (string)product_name, I should try.
040904e4 is the lang-code hex translation that I needed in order to do this, I found it thanks to the code in this answer.
Since it's a environment built for GCC, library names will follow Nix conventions:
Start with lib: libversion
Extension can be either .so or .a (depending on the library being dynamic or static)
Typically (depending on default MinGW installation), it should reside in ${MINGW_INSTALL_DIR}/x86_64-w64-mingw32/lib/libversion.a. One installation example is: f:\Install\Qt\Qt\Tools\mingw730_64\x86_64-w64-mingw32\lib\libversion.a.
According to [Archive.Web - MinGW]: HOWTO Specify the Location of Libraries for use with MinGW (Determining MinGW's Default Library Search Path section), it can be retrieved by:
[cfati#cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow]> x86_64-w64-mingw32-ld.exe --verbose | grep SEARCH_DIR | tr -s ' ;' \\012
SEARCH_DIR("=/usr/x86_64-w64-mingw32/lib")
SEARCH_DIR("=/usr/local/lib")
SEARCH_DIR("=/lib")
SEARCH_DIR("=/usr/lib")
But since it's a system library, you shouldn't care about its path, MinGW should find it automatically, all you have to do is pass it to the linker (using the standard ways).
Hey, I've been writing a program (a sort of e-Book viewing type thing) and it loads text files from a folder within the folder of which the executable is located. This gives me a bit of a problem since if I run the program from another directory with the command "./folder/folder/program" for example, my program will not find the text, because the working directory isn't correct. I cannot have an absolute directory because I would like the program to be portable. Is there any way to get the precise directory that the executable is running from even if it has been run from a different directory. I've heard could combine argc[0] and getcwd() but argc is truncated when there is a space in the directory, (I think?) so I would like to avoid that if possible.
I'm on Linux using g++, Thanx in advance
EDIT - don't use getcwd(), it's just where the user is not where the executable is.
See here for details.
On linux /proc/<pid>/exe or /proc/self/exe should be a symbolic link to your executable. Like others, I think the more important question is "why do you need this?" It's not really UNIX form to use the executable path to find ancillary files. Instead you use an environment variable or a default location, or follow one of the other conventions for finding the location of ancillary files (ie, ~/.<myapp>rc).
When you add a book to your library you can remember its absolute path.
It is not a bad when your program rely on the fact that it will be launched from the working dir and not from some other dir. That's why there are all kinds of "links" with "working dir" parameter.
You don't have to handle such situations in the way you want. Just check if all necessary files and dirs structure are in place and log an error with the instructions if they are not.
Or every time when your program starts and doesn't find necessary files the program can ask to point the path to the Books Library.
I still don't see the reason to know your current dir name.
#include <boost/filesystem/convenience.hpp>
#include <iostream>
#include <ostream>
int main(int argc, char** argv)
{
boost::filesystem::path argvPath( argv[0] );
boost::filesystem::path executablePath( argvPath.parent_path() );
boost::filesystem::path runPath( boost::filesystem::initial_path() );
std::cout << executablePath << std::endl;
std::cout << runPath << std::endl;
return 0;
}
You can get the path of the running program by reading the command line. In linux you can get the command line by reading /proc folder as /proc/PID/CommandLine
argv[0] is not truncated when there are spaces. However, it will only have the program name and not the path when a program is run from a directory listed in the PATH environment variable.
In any case, what you are trying to do here is not good design for a Unix/Linux program. Data files are not stored in the same directory as program files because doing so makes it difficult to apply proper security policies.
The best way to get what you want in my opinion is to use a shell script to launch the actual program. This is very similar to how Firefox launches on Linux systems. The shell places the name of the script into $0 and this variable will always have a path. Then you can use an environment variable or command line argument to give your program the location of the data files, like this:
dir=`dirname "$0"`
cd "$dir/../data/"
"$dir/real-program"
And I would arrange your program so that it's files are somewhat like this:
install-dir/bin/program
install-dir/bin/real-program
install-dir/etc/config
install-dir/data/book-file.mobi
This question is many time asked and I referred all, but I need bit different.
I am using macbook -> Clion (IDE) for C++
My program file location
/Users/Kandarp/ClionProjects/SimulationParser/main.cpp
When I use following function for get current directory it gives different file (I think actual path where file is compiled and execute)
string ExePath() {
char cwd[1024];
if (getcwd(cwd, sizeof(cwd)) != NULL) {
fprintf(stdout, "Current working dir: %s\n", cwd);
return cwd;
} else {
perror("getcwd() error");
return 0;
}}
it gives following answer:
/Users/Kandarp/Library/Caches/CLion2016.2/cmake/generated/SimulationParser-50b8dc0e/50b8dc0e/Debug
But I need path where my .cpp file reside.What I am doing wrong ?
Please help
You're doing nothing wrong.
getcwd() gives you the current directory of the executing process.
When you instruct whatever tool you're using to build your C++ code to run it, it simply runs the process from that directory.
There is nothing in the C++ library that tells the application the location of its source code.
If you need your application to know where its source code lives, you need to pass that either as an argument to main(), or put it into some configuration file, that your application reads, or any similar approach.
What you want to do is use the __FILE__ macro, and then use basic tokenization to extract the directory name.
Your method does not work since during execution, the current directory is that of the binary, not of the compilation unit.
The program uses OpenSceneGraph to generate an .osg file.
int main( int, char** )
{
osg::ref_ptr<osg::Node> root = createSceneGraph();
if (!root.valid())
{
osg::notify(osg::FATAL) << "Failed in createSceneGraph()." << endl;
}
bool result = osgDB::writeNodeFile( *(root.get()), "Simple.osg" );
if ( !result )
{
osg::notify(osg::FATAL) << "Failed in osgDB::writeNode()." << endl;
}
}
The code excerpt is from openscenegraph Quick Start Guide http://www.lulu.com/items/volume_51/767000/767629/3/print/OSGQSG.pdf
page 40
The program can be compiled and run in XCode.
But, it shows the following error:
Error writing file Simple.osg: Warning: Could not find plugin to
write nodes to file "Simple.osg".
Failed in osgDB::writeNode().
However, the compiled binary can be executed without error by directly running in the shell.(./program) And the program correctly generates the Simple.osg file.
This is not the end of story. It is most likely because xcode invokes the compile program differently from invoking it in the shell. So, I copy and paste two dependent libraries into the directory where the compiled binary resides. (In case who knows OSG, the two libraries are osgdb_deprecated_osg.so and osgdb_osg.so)
This time, the Xcode correctly runs the program without errors, generating the Simple.osg file.
Therefore, there are two questions.
1) Why the shell is able to locate the dependent libraries automatically whereas the Xcode cannot?
2) How to make Xcode work without manually copying the dependent libraries or via post compile copy options?
This is simply a matter of the shell PATH being different in the shell and in Xcode.
A lot of the time an IDE will let you specify what PATH is in use at executable run-time. Make sure it contains all the important entries the normal shell has.
OK. After several hours I finally get it resolved.
The reason why the libraries are loaded under the shell is because of the shell's default environmental variable settings in ~/.profile, so that the program can search the libraries with these variables.
As XenonofArcticus pointed out, xcode doesn't inherit the environmental variable settings in the ~/.profile so the program running under xcode cannot resolve the actual path of the libraries.
However, at first I copied those variables in the environmental variable settings in the xcode but it didn't work.
It turns out that the environmental variable settings in xcode is not expandable across different ones. e.g:
HELLO=123/hi
WORLD=$HELLO/enter
The second WORLD variable does not replace the HELLO defined previously into the path.
Therefore, I need to manually write like this:
HELLO=123/hi
WORLD=123/hi/enter