I'm writing a Java compiler in C just as a recreational project. But, I've noticed that when we compile files in the command line, such as "gcc example.c", the compiler is able to find example.c in the working directory of the terminal without error. How does the compiler know what directory to search example.c for? Does OS find example.c in the directory for the compiler? Also, how may I emulate this action in my C program so that the user can compile their java program from any working directory by calling my compiler such as: "compiler example.java"?
fopen will treat relatives paths as relative to the current directory, not the directory where the executable resides. This is the same with most (or even all) file handling function in most other languages.
So to emulate the behaviour of the Java compiler, all you need to do is to iterate over the file names in argv, fopen(the_file_name), generate code for that file, then fopen(class_file_name, "wb") (where class_file_name is file_name with .java replaced by .class) and write the generated bytecode to that.
Getting the full path of the current directory is neither necessary nor helpful. Note that if you just appended each argument to the current directory name, the code would break for absolute paths, whereas simply doing nothing will do the correct thing both for relative and for absolute paths.
If I understand correctly, you need to obtain the full path of the current working directory. There is a POSIX function getcwd (on Windows _getcwd) that can be used to retrieve current working directory of your program.
Then it should be simple to search this directory and find your sources (if they are present).
Related
I was trying to execute Makefile and wanted to execute a C program with it. First, how can I include test.c file for makefile?
I've placed makefile in root directly as there will be other .c files later added.
Can anyone hep me executing this?
File structure:
Makefile code so far not working (it will work if I place it inside src still not getting the output of file.)
# -o : object file
Test: test.c
gcc -o Test test.c
Glad if anyone can help or suggest anything!
I don't usually follow links but I was curious so I did so. Your problem isn't related to make or makefiles or how your code is built. As best as can be determined from the screenshots, all that is fine.
The problem is that when you try to run the program, it's not found.
When the shell tries to run a program it looks in the directories contained in the PATH environment variable, and only there. It won't look in the current directory, unless the current directory is on the PATH.
So when you type the name of a program without a pathname to tell the shell where to find it, such as Test (by the way it's not a good idea to call your program Test because there is a system program named test on POSIX systems and it can cause confusion), it will search the directories on PATH for Test, and if the program is not found there it will fail.
If you don't want to rely on PATH you need to give the shell the pathname of the program you want to run. So you can run .\Test instead (on POSIX systems it would be ./Test), to tell the shell that you want to run Test from the current directory.
I once tried to compile a C program I made that was for a chess game (thanks to YouTube's Bluefever Software for the tutorial), but when I went to compile the program, I executed this line of code:
C:\TDM-GCC-64\>gcc Chess/chess.c Chess/init.c -o chess
The compiling worked (there were no syntax errors or anything), but when I got to my file directory, I saw this (circled in blue):
An unexpected application (but there were no viruses!):
How did this happen? It may had something to do with the line I was compiling, but what is the "intel" behind this?
It is normal for the compiler to generate an application!
What is surprising is the location for the executable, it should have been generated in the parent directory:
C:\TDM-GCC-64\> gcc Chess/chess.c Chess/init.c -o chess
The explanation is interesting:
You are using the Windows operating system, where the filenames are case insensitive.
You instructed gcc to generate the executable into chess, but this is the name of the Chess directory. In this case, gcc generates the executable in the named directory and gives it a name that is the basename of the first source file chess.c -> chess.
Furthermore, the application name really is chess.exe in Windows, but the default setting for the file manager is to not display file extensions. This is a very unfortunate choice. I suggest you change this setting in the Windows/File Explorer Options window to always show file extensions. This will allow you to distinguish chess.c, chess.exe and chess.h more easily.
You have a Makefile in the Chess directory, you should use the make command to build the executable:
C:\TDM-GCC-64\> make -C Chess
Or simply cd to the Chess subdirectory and type:
C:\TDM-GCC-64\Chess> make
That's the file you told the compiler to make.
The -o option to gcc is the output file. In this case, you told it to create an executable file named chess. And that's exactly what was created.
The compiler is automatically creating an executable file while compiling.
i know there a a few posts already about this but I do not seem to be able to get it right.
I am working on a shared project using geany and gcc. The file structure looks something like this:
`/Documents/.../project/ main directory of project with makefile`
`/Documents/.../project/src here are some sourcefiles and headers`
`/Documents/.../project/src/extended here are some other source and header files`
`/Documents/.../project/src/tools other header and source files`
now lets say I am working on a sourcefile in /tools that includes from extened with
#include"/extended/some_header.h"
because my makefile is configured to search for files from /src. However when I am trying to compile the file I am working on right now (by using geany compile option which just calls gcc) I cannot compile it obviously because it cannot find /extended/some_header.h in the /src folder. I have tried adding
-iquotes/Documents/.../project/src
to the gcc call by geany but it doesn't work either.
The -I flag tells the gcc compiler where it should look for the header files. Passing the -Idir to the compiler is appending the dir path to the head of the search list, effectively making this path higher priority than the previously (or system) defined paths. As for the source path - there is no such an option for gcc itself. Each source file passed to the compiler has to have it's path (absolute or relative). In order to work it around, a Makefile can be provided, defining a list of files to be compiled.
Can someone explain to me why, in particular, we are using ./a.out to run a program?
Is there any meaning behind this?
Can someone please provide an explanation?
The name stands for "assembler output", and was (and still is) the default name for the executable generated by the compiler. The reason you need ./ in front of it is because the current directory (.) is not in $PATH therefore the path to the executable must be explicitly given.
If you mean the ./ part, it's for safety. Windows by default appends current directory to PATH, which is bad (there's a risk of DLL injection, and so on).
If you mean a.out part, it's just a name (which came from name of format a.out), which you can change by modifying gcc -o parameter.
When running an executable like a shell like bash the executable must be in your PATH environment variable for bash to locate and run the program.
The ./ prefix is a shorthand way of specifying the full path to the executable, so that bash does not need to the consult the PATH variable (which usually does not contain the current directory) to run it.
[For a.out (short for "assembler output"), it is the default executable output for a compiler like gcc if no output filename is specified.]
It'd be worth you looking a bit more into C and the way that C programs are compiled.
Essentially, your source code is sent to the preprocessor, where directives like #define and #include are loaded (e.g. into memory). So any libraries you want to use are loaded, e.g.
#include <math.h>
will basically 'paste' the contents of math.h into source code at the point at which it is defined.
Once all this stuff has been expanded out, the compiler turns your source code into object code, which is your source in binary code. a.out is the default name for output if you do not specify a build name.
gcc -o mynewprogram mynewprogram.c
a.out is the default name for the compiler. AFAIK it is because the linking process is skipped and it is not compiled as an object or library.
I am still fairly new to programming with C and I am working on a program where I want to control the power to various ports on a hub I have. That is, however, not the issue I am having right now.
I found a program online that does what I want I am trying to compile it. However it uses #include<lsusb.h>. lsusb is located in a totally different folder than the file I am wanting to run (and not in a sub folder) and when I try to compile it, I, logically enough, get the error that the file lsusb.h is not found.
How can I link to this file so that it can be found?
This is more of a GCC toolchain question than a C question (although most C compilers do use the same Unixy flags).
The braces around the include file (<>) indicate you want the compiler to search its standard search path for the include file. So you can get access to that new include file either by putting it into a directory on your standard include file search path yourself, or by adding its directory to the file search path. With GCC you do the latter by giving gcc the flag -I"directoryname" where "directoryname" is the full file path to where you are keeping that new include file of yours.
Once your compiler finds it, your linker may have the exact same problem with the library file itself ("liblsusb.a"?). You fix that the same way. The flag GCC's linker will want is -L instead of -I.
See the "-I" parameter in the gcc man page. It allows you specify a directory in which to find a header file. See also -l and -L.
Or try #include "../../path_to_the_file/lsusb.h"