How does the command prompt know where to find the requested compiler/interpreter? - shell

When compiling/interpreting a program from the command prompt, how does the command prompt know where to find the requested compiler/interpreter?
Are these files stored in a specific place or something like that? I'm just about getting a hang of high-level programming, but I find it pretty hard to wrap my head around what happens under the hood.

There are two parts: Where to find the file just from it's filename, and what to do with it.
Where files (programs) are searched if just the name is entered:
Windows (CMD):
There is a variable %PATH% which has a list of ;-separated directories, eg. C:\Windows;C:\Windows\system32;C.\somethingelse. It is saved somewhere in the registry and can be set either in CMD itself or with a GUI somewhere in the OS configs.
Linux etc. (Bash and many more):
Similar, there is a variable $PATH which can be set at least in the shell and various config files, and the entries are separated by :, eg. /bin:/usr/bin/even/more. Priority is from left to right.
Additionally, some shells (eg. Bash) cache lookup results in their own implementation-specific way (depending on the configuration), because it's faster than having to check every directory in the path variable (at least if the searched program is in the last dir, everything has to be checked).
What to do with the file once it's found:
Windows:
In Windows, everything works with the filename suffix.
.exe and some others are native programs to start.
.bat is a shell script which is executed like it's manually written to the shell.
For every other suffix, it's configurable which program belongs to the suffix (stored in the registry, how to comfortably change it depends heavily on the used Windows version). Eg. you could say that .py belongs to your Python interpreter, the a file foo.py will start the interpreter. Btw., the same suffix-program configuration is usen when a file is double-clicked in the GUI file explorer, and of course program installers can add their entries too without the user having to do it.
Linux:
For Linux, the suffix is not as important. The first relevant thing is a binary (yes/no) flag x (x like executable) which exists for each file on the file system, just like file name, creation timestamp etc.etc.
If the x flag is set to yes:
Linux tries to detect what kind of program it is from the content. The difference between a native compiled binary program and a not-compiled script of some scripting language is pretty clear.
A native linux program is started by the kernel, like expected. Additional binary program types could be configured, eg. there is the Wine software which runs some Windows programs on Linux, and one could add a specification how Windows exe`s can be recognized inside and that they should be started with Wine.
For a text file with the x flag, the next step is to look at the first line, which should start with a '#!' (called shebang), followed by the path of the interpreter (eg. #!/bin/bash). Shell scripts (like the bat files on Windows) are realized this way, but it's not limited to classical shell scripts: Nothing prevents anyone from making a #!/bin/python script which Python content (of course, Python has to be installed for this to work).
If the x flag is set to no:
Shells like bash with usual configuration won't do anything, independent if it is a real program just without flag or a jpg image etc. For the GUI file managers:
Again, the content (and possibly the file name suffix too) is inspected to get the type, like jpg images, mp3 music, C++ source code etc.etc. (Linux knows pretty many types), and then the fitting program is looked up in a list configurable by the user and/or program installations (mime file type id <-> program).
...
Note that in the case of eg. Python scripts (which are just normal text files, not something for the kernel to work with), it can be done with and without x flag: With flag and a shebang line, or without flag and a matching mime list entry. In the "without flag" case, the shebang won't hurt if it is there, because Python (and many other scripting languages) consider it a comment because of the #.

Regarding interpreters on unix-based systems, lots of scripts start with a so-called shebang or hashbang (#! on the first line of the script) that tells what interpreter to invoke, see https://en.wikipedia.org/wiki/Shebang_%28Unix%29 .

When you enter something like some-program some-arguments, the shell will look through each directory listed in the environment variable $PATH for an executable file named some-program (on Windows it's %PATH% and some-program.exe).
This is not specific to compilers and interpreters - it happens whether some-program is gcc, python, firefox or notepad.

Related

Makefile.mak giving error [duplicate]

I have Windows 7 and tried to use the 'make' command but 'make' is not recognized as an internal or external command.
I did Start -> cmd -> run -> make, which outputs:
'make' is not recognized as an internal or external command,operable program or batch file.
Then I typed 'mingw32-make' instead of 'make' (Start -> cmd -> run -> mingw32-make) and I get the same output:
'mingw32-make' is not recognized as an internal or external command,operable program or batch file.
What shall I do next in order to fix this problem?
In Windows10, I solved this issue by adding C:\MinGW\bin to Path and then called it using MinGW32-make not make.
Your problem is most likely that the shell does not know where to find your make program. If you want to use it from "anywhere", then you must do this, or else you will need to add the full path each time you want to call it, which is quite cumbersome. For instance:
"c:\program files\gnuwin32\bin\make.exe" option1=thisvalue option2=thatvalue
This is to be taken as an example, it used to look like something like this on XP, I can't say on W7. But gnuwin32 used to provide useful "linux-world" packages for Windows. Check details on your provider for make.
So to avoid entering the path, you can add the path to your PATH environment variable. You will find this easily.
To make sure it is registered by the OS, open a console (run cmd.exe) and entering $PATH should give you a list of default pathes. Check that the location of your make program is there.
This is an old question, but none of the answers here provide enough context for a beginner to choose which one to pick.
What is make?
make is a traditional Unix utility which reads a Makefile to decide what programs to run to reach a particular goal. Typically, that goal is to build a piece of software from a set of source files and libraries; but make is general enough to be used for various other tasks, too, like assembling a PDF from a collection of TeX source files, or retrieving the newest versions of each of a list of web pages.
Besides encapsulating the steps to reach an individual target, make reduces processing time by avoiding to re-execute steps which are already complete. It does this by comparing time stamps between dependencies; if A depends on B but A already exists and is newer than B, there is no need to make A. Of course, in order for this to work properly, the Makefile needs to document all such dependencies.
A: B
commands to produce A from B
Notice that the indentation needs to consist of a literal tab character. This is a common beginner mistake.
Common Versions of make
The original make was rather pedestrian. Its lineage continues to this day into BSD make, from which nmake is derived. Roughly speaking, this version provides the make functionality defined by POSIX, with a few minor enhancements and variations.
GNU make, by contrast, significantly extends the formalism, to the point where a GNU Makefile is unlikely to work with other versions (or occasionally even older versions of GNU make). There is a convention to call such files GNUmakefile instead of Makefile, but this convention is widely ignored, especially on platforms like Linux where GNU make is the de facto standard make.
Telltale signs that a Makefile uses GNU make conventions are the use of := instead of = for variable assignments (though this is not exclusively a GNU feature) and a plethora of functions like $(shell ...), $(foreach ...), $(patsubst ...) etc.
So Which Do I Need?
Well, it really depends on what you are hoping to accomplish.
If the software you are hoping to build has a vcproj file or similar, you probably want to use that instead, and not try to use make at all.
In the general case, MinGW make is a Windows port of GNU make for Windows, It should generally cope with any Makefile you throw at it.
If you know the software was written to use nmake and you already have it installed, or it is easy for you to obtain, maybe go with that.
You should understand that if the software was not written for, or explicitly ported to, Windows, it is unlikely to compile without significant modifications. In this scenario, getting make to run is the least of your problems, and you will need a good understanding of the differences between the original platform and Windows to have a chance of pulling it off yourself.
In some more detail, if the Makefile contains Unix commands like grep or curl or yacc then your system needs to have those commands installed, too. But quite apart from that, C or C++ (or more generally, source code in any language) which was written for a different platform might simply not work - at all, or as expected (which is often worse) - on Windows.
First make sure you have MinGW installed.
From MinGW installation manager check if you have the mingw32-make package installed.
Check if you have added the MinGW bin folder to your PATH. type PATH in your command line and look for the folder. Or on windows 10 go to Control Panel\System and Security\System --> Advanced system settings --> Environment Variables --> System Variables find Path variable, select, Edit and check if it is there. If not just add it!
As explained here, create a new file in any of your PATH folders. For example create mingwstartup.bat in the MinGW bin folder. write the line doskey make=mingw32-make.exe inside, save and close it.
open Registry Editor by running regedit. As explained here in HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER go to \Software\Microsoft\Command Processor right click on the right panel New --> Expandable String Value and name it AutoRun. double click and enter the path to your .bat file as the Value data (e.g. "C:\MinGW\bin\mingwstartup.bat") the result should look like this:
now every time you open a new terminal make command will run the mingw32-make.exe. I hope it helps.
P.S. If you don't want to see the commands of the .bat file to be printed out to the terminal put #echo off at the top of the batch file.
If you already have MinGW installed in Windows 7, just simply do the following:
Make another copy of C:\MinGW\bin\mingw32-make.exe file in the same folder.
Rename the file name from mingw32-make.exe to make.exe.
Run make command again.
Tested working in my laptop for above steps.
For window-10 resolved error- make' is not recognized as an internal or external command.
Download MinGW - Minimalist GNU for Windows from here https://sourceforge.net/projects/mingw/
install it
While installation mark all basic setup packages like shown in image
Apply changes
After completion of installation
copy C:\MinGW\bin
paste in system variable
Open MyComputer properties and follow as shown in image
You may also need to install this
https://sourceforge.net/projects/gnuwin32/
As other answers already suggested, you must have MinGW installed. The additional part is to add the following two folders to the PATH environment variable.
C:\MinGW\bin
C:\MinGW\msys\1.0\bin
Obviously, adjust the path based on where you installed MinGW. Also, dont forget to open a new command line terminal.
'make' is a command for UNIX/Linux. Instead of it, use 'nmake' command in MS Windows. Or you'd better use an emulator like CYGWIN.
Search for make.exe using the search feature, when found, note down the absolute path to the file. You can do that by right-clicking on the filename in the search result and then properties, or open location folder (not sure of the exact wording, I'm not using an English locale).
When you open the command line console (cmd) instead of typing make, type the whole path and name, e.g. C:\Windows\System32\java (this is for java...).
Alternatively, if you don't want to provide the full path each time, then you have to possibilities:
make C:\Windows\System32\ the current working directory, using cd at cmd level.
add C:\Windows\System32\ to you PATH environment variable.
Refs:
use full path: http://technet.microsoft.com/en-us/magazine/ff678296.aspx
cd: http://technet.microsoft.com/en-us/library/cc731237.aspx
PATH: http://technet.microsoft.com/en-us/library/bb490963.aspx
I am using windows 8. I had the same problem. I added the path "C:\MinGW\bin" to system environment variable named 'path' then it worked. May be, you can try the same. Hope it'll help!
try download & run my bat code
======run 'cmd' as admin 2 use 'setx'=====
setx scoop "C:\Users%username%\scoop" /M
echo %scoop%
setx scoopApps "%scoop%\apps" /M
echo %scoopApps%
scoop install make
=======Phase 3: Create the makePath environment variable===
setx makePath "%scoopApps%/make" /M
echo %makePath%
setx makeBin "%makePath%/Bin" /M
echo %makeBin%
setx Path "%Path%;%makeBin%" /M
echo %Path%
use mingw32-make instead of cmake in windows

Location of Command Prompt Commands

Where are the commands located for Command Prompt? I know this is possible in Linux, but what about windows?
I want to rename certain commands so I can make my own using the original name.
Im doing this on a 32bit Windows XP if that helps.
More specifically, where can I find the tree command?
https://superuser.com/questions/312926/windows-equivalent-of-which-command-in-linux
in windows 7 there's the where command.
You can overwrite the standard commands, but this will break a lot of stuff.
You would also have to modify your path environment variable
in windows 7 tree is located in C:\Windows\System32\tree.com
This might be a useful site for you
http://ss64.com/nt/
Use a bat file of the same name to override an inbuilt external command. Some commands are internal so you have to specify .bat. Also if calling the overridden program specify the extension.
There are two types of commands in Windows command prompt. The internal commands are built-in inside the command processor program, that is called cmd.exe. You may inspect such commands if you open cmd.exe file with an Hex editor, or even directly with Notepad (although doing that requires a lot of patience!); to know the location of cmd.exe file, type: set comspec. Examples of internal commands are DIR, COPY, TYPE, MD, etc. (the simplest ones) and all Batch-file commands, like GOTO, IF, FOR, REM, etc. There is no way to change the name of an internal command, unless you modify the cmd.exe file (for example, using the same Hex editor) that, although possible, is NEVER recommended!!!
The external commands reside in disk files with .com or .exe extension that are grouped in certain subdirectories, usually in C:\Windows\System or C:\Windows\System32; these subdirectories must appear in %PATH% variable in order to execute the external commands directly in the command prompt. You may locate the folder where an executable file resides using the following command, that review folders included in PATH variable only (you can not use wild-cards in this case):
for %a in (tree.com tree.exe) do #echo/%~$PATH:a
You may directly change the name of any command-name.exe file; however, this practice is not recommended. A simpler option is create a Batch file with the same name of a standard command (and .bat extension) and place it in a folder that will be included in PATH variable before the standard commands folder (or in the current directory). For example, create a file named tree.bat and place it in C:\Users\MyName\MyCommands; then, modify PATH variable this way: path=C:\Users\MyName\MyCommands;C:\Windows;C:\Windows\System32. If you need to use the standard tree command inside your tree.bat file, just include the proper extension: tree.com.

Making only some Lua scripts on the path runnable from the command line in Windows XP

Note: this trick also applies to scripting languages other than Lua, or to any other document type that might be considered an application in some contexts and a document in others.
If an interpreter is already associated to handle .lua files in Windows (i.e. if double clicking on a .lua file runs it in the interpreter) it is easy to make them executable directly on the command line.
You need to:
put the script in a directory that is listed in the PATH environment variable;
add the .lua extension to the PATHEXT environment variable.
In this way you can run any Lua script by typing its name on the command line. The problem now is that you cannot put another Lua script in any directory on the PATH without risking it to be executed, even if you don't want it to be executed. (An example of such a .lua file would be a module private to your program that will be loaded by require. Modules are by convention also named .lua, but rarely support execution as a free-standing program.)
So it is an all-or-nothing situation. Either you allow any script in a directory on the path to be executed or none.
Is there a way to allow only some scripts in a directory on the path to be runnable typing their name?
The trick is that the console PATHEXT mechanism understands "double extensions", i.e. adding a .exe.lua "extension" to PATHEXT will make executable only those Lua scripts which have their full-name ending in .exe.lua (of course you can choose another extension, say .run.lua). Note: I used the quotes to avoid possible confusion and for lack of better terminology (remember that, conventionally, the file extension is the part of the file name after the last dot).
Therefore by adding .exe.lua to PATHEXT only whatevername.exe.lua will be executable, whereas any other Lua script won't (provided it doesn't have the same "double extension").
This allows to distinguish "normal" scripts from "executable" ones without either separating them in different directories or define a new custom file extension, which involves modification to the registry.
Moreover since this behaviour is controlled by an environment variable, it is a per-process setting - you can enable it only for a specific console window. For example if you create a batch file with this content:
#set PATHEXT=%PATHEXT%;.exe.lua &cmd /K
and you run it, it will open a console that will be able to execute all .exe.lua scripts found on the path, but not any other .lua script.

When to use .exe and when not?

I dont really understand whats going on and cant see the difference:
I'm downloaded the base64.exe for creating base64 text under windows. i copied it to C:\Windows\ because its in the %PATH% variable.
Now i want to try it: echo Hello | base64 works great. Okay i dont need to append .exe and as far as i know i dont need to do it also with .bat and .com files.
But now i have some cygwin tools installed and for example tried which base64, which doesnt work, because it says that base64 is not in path. Then i typed in which base64.exe and got C:\Windows.
So my question is now: when i need to use .exe and when i dont? Is it only when i'm using cygwin tools that i need to append .exe?
Cygwin is a shell which emulates UNIX behaviour. UNIX doesn't know anything about .exe, thats why Cygwin can't find base64.exe. Under UNIX, binaries are stored without an extionsion added to their filename, e.g. just base64.
Windows CMD automatically appends .bat, .com, .exe and the like to your file names. Cygwin does not. So if you are using a linux shell you have to append it manually.
Since Cygwin is aware that it always runs under Windows it might append .exe if you want to perform certain actions in the shell itself (e.g. opening a file), to behave more friendyl to Windows users who expect this behaviour. However programs running under Cygwin might not integrate those features since they were mainly devoloped for usage under UNIX. That could be a reason why which base64 fails.

Bash: Getting standard program for file type

the background is a shell script to open the .m3u file of a web radio station. Therefore I want to know inside the script, what's the user's program to open such files. At the moment, he has to set the environment variable $PLAYER, but obviously that is not a good way to go.
Alternative: Is there a command that takes a filename and searches itself for an appropriate program to handle that file? Like file, e.g.,
open-file my_playlist.m3u
The script should be portable, it will run at least on Ubuntu, Debian and Windows/Cygwin machines.
Cheers,
This will have to be done differently on each platform. On Mac OS X the "open" command will do what you want.
In Linux it gets murky, since the desktop environment (GNOME or KDE) keeps its own list of applications to run for each file type.
There are two files you can look for in Ubuntu / GNOME that hold this info:
~/.local/share/applications/defaults.list and
~/.local/share/applications/mimeinfo.cache
Someone else hopefully knows how to do this in Windows and can chime in.
Edit: Stealing from the other answers:
Linux:
xdg-open [filename]
Cygwin:
cygstart [filename]
And for completeness, here's a link to a previous question about how to detect which operating system you are running on: Detect OS from bash Script
I'd like if there were a different answer to this but I think you'll have to check the file association configs for every desktop environment and file manager out there (so, nautilus, konqueror, thunar, mc... all in different places and in different formats AFAIK), as well as ascertaining which one of these the user is actually using...
If someone has a different idea I'm keen to hear it.

Resources