I have read that a binary is the same for Windows and Linux (I am not sure if it has a different format).
What are the differences between binaries for Linux and binaries for Windows (when speaking about format)?
And if there are none, what stops us from making a single binary for both operating systems (make sure that I mean the last file where you can run and not the source code)?
Since there are differences in the binary format, how are the operating systems themselves compiled?
If I'm not mistaken Microsoft uses Windows to compile the next Windows version/update.
How are these binaries executable by the machine (even the kernel is one of those)?
Aren't they in the same format? (For such a low-level program.)
As mentioned in the comments by #AlanBirtles, this is in fact possible. See Actually Portable Executable, Redbean, and the article about the two.
Even though the binary formats are different, it's possible to come up with a file that's valid in several different formats.
But, this being an obscure hack, I would stay away from it in production (or at all).
I have read that a binary is the same for Windows and Linux (not sure if it has a different format)
Then you have read wrong. They are completely different formats.
What are the differences between binaries for Linux and binaries for Windows (when speaking about format)?
Windows: Portable Executable (PE)
Linux: Executable and Linkable Format (ELF)
And if there are none
There are many differences.
What stops us from making a single binary for both operating systems?
The fact that different OSes require different binary formats for their respective executable files.
Since there are differences in the binary format, how are the operating systems themselves compiled?
Ask the OS manufacturers for details. But basically, they are compiled like any other program (just very complex programs). Like any other program, their source code is compiled into appropriately-formatted executable files for each platform they are targeting, and even for each target CPU. For instance, Windows uses the PE format for all of its executables, but the underlying machine code inside each executable is different whether the executable is running on an x86 CPU vs an x64 CPU vs an ARM CPU.
If I'm not mistaken Microsoft uses Windows to compile the next Windows version/update
Yes. That is commonly known as "dog-fooding" or "bootstrapping". For instance, VC++ running on Windows is used to develop new versions of VC++, Windows, etc.
How are these binaries executable by the machine (even the kernel is one of those)?
When an executable file is run (by the user, by a program, etc.), a request goes to the OS, and the OS's executable loader then parses the file's format as needed to locate the file's machine code, and then runs that code on the target CPU(s) as needed.
As for running the user's OS itself, there is an even more fundamental OS running on the machine (i.e., the BIOS) which (amongst other things) loads the user's OS at machine startup and starts it running on the available CPU(s). See Booting an Operating System for more details about that.
Aren't they in the same format? (For such a low-level program.)
No.
An executable binary compiled for Linux x86-64 (see elf(5)...) won't run on the same computer with Windows (unless you use some emulator which luckily works for your binary, like Wine or QEMU).
Using emulators will slow down the execution. Some emulators don't emulate every aspect of a computer in 2022.
This is one of the reasons I prefer open source application software (e.g. RefPerSys or GCC) ..... With efforts and good design you can (in principle) port them to another platform.
Some corporations designed some kind of fat binary formats. They did not succeed a lot.
Levine's book about Linkers and loaders explain several different binary formats.
Related
I want to detect which operating system my .exe is being run on, so that I could perform specific operations depending on the underlying operating system. I want it to be just for windows and mac.
I want to detect which operating system my .exe is being run on
(notice that on MacOSX executable files are traditionally not suffixed with .exe; that convention is specific to Windows)
You cannot detect that in pure standard C++11 at runtime (so your question makes technically no sense), because the C++11 standard n3337 does not know about operating systems (some C++ source code may be compiled for the bare metal). I would recommend conditional compilation (e.g. #if) and using operating system specific headers (and configuring your build automation to detect them). Some C++ frameworks (boost, poco, Qt....) could be helpful, but you need to decide to choose one (they might try to provide some common abstractions above several OSes, but the evil is still in the details, e.g. file paths are still different on Windows and on MacOSX).
MicroSoft Windows has its own API, called WinAPI (which is only, in practice, used by Windows. Perhaps some day ReactOS would implement most of that API), documented here. MacOSX is more or less conforming to POSIX, which is a standard API about a family of OSes (but Windows don't care much about that standard).
If you want to learn more about OSes in general (a sensible thing to do), read for example Operating Systems: Three Easy Pieces (freely downloadable textbook).
In practice, an executable file compiled from C++ source code is specific to the operating system it is designed to run on, and its file format is also specific to some OS (e.g. PE on Windows, ELF on Linux, Mach-O on MacOSX...). So a Windows executable won't run on MacOSX and vice versa (the fat binary idea is out of fashion in 2018). You probably would adjust your build procedure (e.g. your Makefile, or with cmake, ninja, etc...) for your OS. That build procedure might (and often does) pass extra compilation flags (e.g. some -DBUILD_FOR_MACOSX compiler flag for your preprocessor, if building for MacOSX; then you might -in few places- use some preprocessor directive like #if BUILD_FOR_MACOSX in your C++ source code) specific to the target operating system. You could even customize your build so that on MacOSX some for-macosx.cc C++ file is compiled (and its object file linked into) your software, but on Windows you'll use some other for_windows.cc C++ file. Sometimes, the build procedure is flexible enough to auto-detect at build time what is the operating system (but how to do that is a different question. The GNU autoconf could be inspirational).
Once your build procedure has been configured for (or has auto-detected) your operating system, you could use preprocessor conditional facilities to #include appropriate system-specific headers and to compile calls to OS specific functions (such as POSIX uname) querying further at runtime about the OS.
Some compilers predefine a set of preprocessor symbols, and that set depends upon the target operating system and processor and of your compiler. If you use GCC, you might create some empty file empty.cc and compile it with g++ -c -C -E -dM (perhaps also with other relevant flags, e.g. -std=c++11) to find out which set of preprocessor symbols are predefined in your case.
Consider studying the source code (including the build procedure!) of some cross-platform free software projects (e.g. on github or somewhere else) for inspiration. You can also find many resources about multi-platform C++ builds (e.g. this one and many others).
There are various ways you could do it, like testing for the presence of a C:\Windows directory to detect Windows (edit: if the OS accepts a path like that at all then it's at least part of the DOS family), but none of them are foolproof. Here's one way (although it's cheating):
#include<boost/predef.h>
enum class OperatingSystem {
// ...
Windows
// ...
};
OperatingSystem DetectOperatingSystem()
{
#ifdef BOOST_OS_WINDOWS
return OperatingSystem::Windows;
#endif
}
Also, if you just want a name to show the user, then on POSIX systems you can use uname(2).
To solve this kind of problem you would need to check both at compile time and at run time. You are going to need different code for different both systems. You are going to need Windoze code to check the Windoze version and Mac code to check the Mac version.
You are going to have to use
#if defined ()
at compile time to check which of the two you are on. Then have separate code for each to get the version.
I know that for running c++ on Windows you need to compile specifically for Windows and the same goes for linux and on...
But for example, if I'm compiling program for Windows written in native c++ I can run it on a freshly installed windows pc? I mean, without downloading visual c++ runtime libraries, etc, I can just compile it, let's say, reinstall windows on my computer, and run it without installing anything else?
(The question above using Windows as an example but the same thing can be done on freshly installed linux distro? e.g Ubuntu)
Thanks in advance.
The only answer is "it depends".
There are many ways that an OS can "run" a program, many ways a program can be build, and many way code can be assembled.
A program that uses only "standard libraries" and that links all libraries statically, does not need any other dependency (in the sense that all the code it need is in the binary itself or into OS libraries that -being part of the system itself- are already on the system).
But:
statically link the standard libraries (which are most likely present in all programs) will bloat the memory usage of many copy of the same code. That's the reason library are often linked dynamically, but this requires "installation" of those libraries as well
Programs that use only standard libraries can do only the things that are somehow "common" (or can be commonly represented) into all systems, thus loosing all the peculiarity that makes an OS different from another.
There are "platforms" that - by the nature of their peripherals - are not represented one into the other: a coffee machine has 12 keys and a textual 2 row x 20 col display. A PC has a mouse, a keyboard, and a display that can reach even 10'000 pixel of width, of millions of color each. A tablet has a touch surface that can seize multiple points at the same time.
Can you imagine a program running the same on all those three platform?
No. Often the libraries are different on different systems. If your program involves any GUI then you will definatly have OS specific code that won't run on other OSs.
If you write a C++ program targeting the g++ compiler without GUI code there may still be some OS specific code. But you should be able to port it with minimal effort.
If your program only uses stl and stdio, then it will probably be portable. For example, MS STL's ::c_str() function works a little different than the linux one.
For what it's worth, when using MinGW with static linkage to libc and libc++, It's very likely that your C++ application will work on any Windows system '95 and later, unless you specifically enabled functionality in the Windows API that isn't available, like NT features. All of my SDL applications compiled for Windows 7 (compiled in 32 bit of course) work fine on my '95 machine.
When deploying a Linux application, it's best to just supply the source plus a configure script or makefile. This will ensure that the user has valid dependencies for your application. You could deploy binaries to specific package managers if you wanted to though.
Yes, the standard libraries are everywhere. Just think about it, most of your programs that you get are writen in C/C++. Only dependencies come when you use some specified libraries like winsock etc, therefore some windows applications are unlikely to work on linux and vice versa.
I'm new in programming. From what i know, a program that is compiled in Linux should not be able to run in Windows. So, if we want to run the same program in both platform, we need to compile the source code under both platform, and create 2 different executable files.
Recently I am studying the source code of an open source, cross-platform Java GUI application. I'm surprised to find that the backend engine of that GUI application is a small executable file generated from C++ codes. No matter users use that application in Windows or Linux, the Java GUI will call the same executable file in the bin folder.
I just want to know, how can that executable file run on both Windows and Linux?
I'm also interested to create a cross-platform Java GUI application using a C++ program as the engine. That C++ program is only available for Linux only. I've been googling for a while and i found that I need to use Cygwin to port it to Windows. However, if i use Cygwin, i will end up having 2 different executable files.
How can i combine the Windows executable file with the Linux executable file? Is it possible to generate a single executable file that can run on both platform?
Thanks.
Ok, kids.
Yes, you CAN write a multi-platform binary, but it's difficult. It's called a Fat Binary, and it used to common enough in the 1980's although I haven't seen it done in decades. https://en.wikipedia.org/wiki/Fat_binary
Basically, you compile the machine code for each platform you want to run on and then hand-link the code with different entry points. While the Wikipedia article merely describes packing different architectures into the same binary, its actually possible to make one binary that runs on different operating systems so long as the entry points for the operating systems don't collide.
Some executable formats were intentionally designed to allow this. For example, MZ, NE, LX and PE can be overlaid. Old OS/2 programs sometimes did this... they rarely contained an entire program for both operating systems, but when run on DOS would print a message telling you that you were using the wrong operating system for the program.
As far as Linux and Windows in one binary: While you can't do an ELF and PE, I believe it might be doable with a PIE or a COFF and a PE or COM. Older Linux will run COFF binaries, which PE is descended from, so it seems you might be able to create a universal binary if newer versions of Linux will still run these. I can't say for sure this would work, but it seems plausible.
Another caveat: Usually you need to put a jump in the code right at the beginning to skip past the other operating system's entry point, headers, etc. because you can't locate your code there (obviously).
The problem with this in modern computing is that most anti-virus software will incorrectly identify this as a virus. It used to be common that viruses would attack binaries by inserting such a jump at the beginning of an executable that jumped to the end of the binary, tacking their own code onto the end of the binary, then inserting another jump back to the main executable code. Since you need to do something more-or-less similar to support multiple platforms in one binary, most AV software will heuristically identify this as a virus and quarantine your executable.
So in short: YES it can be done for (some) combinations of platforms. It is not impossible, but you would have to be insane to do it.
The simple answer is, is that you can't.
The PE (Windows) and ELF (Linux) binary executable formats are totally different.
Not to mention that a C/C++ Program requires linking to libraries that won't be available on either platform simultaneously.
However, you could use Wine on Linux to run the Windows executable providing it doesn't attempt exotic Windows specific calls.
Or you could choose to use a more "common" cross-platform language such as a CLI language (C#/IronPython/Java etc.) that .NET for Windows and Mono for linux/others supports.
There is no way to have a single native executable compiled from C++ source that works on different platforms. I don't believe you that the same executable file is run on Windows and Linux, as you state in your second paragraph.
Simply put, it is not possible to run the same executable on different platforms. It is true for Windows, Linux, or any other UNIX platform.
The idea of having a single executable is nothing new and is the idea behind Java Runtime and Windows .Net (Mono for Linux). These themselves rely on different executables compiled on the specific machines.
No matter users use that application in Windows or Linux, the Java GUI
will call the same executable file in the bin folder.
They might simply be using relavant paths to these executables, and these executables are probably compiled separately on different platforms. Hard to tell without looking at the code.
Cygwin is a command line interface on windows that provides UNIX look and feel.
One option to try would be Wine which is a program for Linux to run windows programs on Linux.
It may be possible, if the OSes are on the same platform.
However, Linux can run on a variety of platforms with different processors: VAX, MAC, PC, Sun, etc.
One problem is that an executable contains assembly (machine code) instructions specific to a processor. The machine code for adding a register using ARM processor may be different than a Motorola, Intel or Sun processor. So with this context, one executable may not be guaranteed to run on different platforms.
Another issue is that the Run-Time library may also make calls to specific OS functions (like file open, displaying text, etc.) Some operating systems may not supply the same functionality; while others have a different method to execute the same functionality. An OS on an embedded platform may not support a file system. Windows Vista may block calls from unsecure MSDOS requests.
Other languages become platform independent by generating code which is executed by a "virtual machine". The code is not directly executed by a processor.
The traditional method for porting C and C++ methods is to provide the source and let the customers build the software on their platform. Other delivery processes is to create an executable for every supported platform; this becomes a maintenance nightmare.
You can't do that....i.e. you can't run the same executable on both Unix as well as Windows.
Windows uses executable files, while Unix used elf file format. They are basically different. Unlike the counterpart Java where you can run the same executable( bytecode) on both machines, which in turn uses an interpreter(the JVM) to execute.
Now, said that you have two options...
Either you can actually install C compilers on both windows and linux(unix) and then compile your code on both of them.
Or you can install 'Wine', a porting software on linux which will be able to actually run windows executable file on linux by windows emulation.
Probably, option no 2 would be better suited...Its your call...
Regards,
Can't you make a C++ program load it's respective existing libraries using #ifdef?
I think that's the C++ solution to cross platform binaries. However the code needs to be adjusted to work with both or all chosen libraries.
However without a java front end or a 2 different binaries or a bat and a sh or a program like wine you won't be able to run the respective binary.
If you create a well behaved MS Windows application, it can run unmodified on Linux x86 platforms using the wine utility.
Wine is a compatibility layer which provides Win32 and associated runtime library calls so that the program thinks it is running on MS Windows, but the wine layer translates those into Linuxisms with really good performance.
More detail at http://www.winehq.org/
Can I create a Python program, send it to a remote computer, and run it there without that computer having Python installed? I've heard that you cannot, as Python needs to be interpreted. If this is true, then it seems very odd as it would be hard to distribute your program unless everyone decides to install Python.
Also, what about C and C++? Can they be run on a remote computer without having the language installed? (I think you can, as it is a compiled language).
I'm not exactly sure and would like clarification.
EDIT:
I'm getting some mixed answers on this and am not sure where to go. I see that I can include the Python library in the program and I can use py2exe.
However, I'm confused on C and C++. Do I have to include their libraries in the program? Can they only be run on certain machines? Does the compiler allow it to run on all machines?
Look at py2exe and py2app for Windows and Mac. Macs running OSX and most modern Linuces have Python installed, however.
C/C++ apps are normally compiled to executables which work on one machine/OS architecture (e.g. 32-bit Windows, or 64-bit OSX); such an executable can run on some but not all machines. For example, 64-bit Windows or OSX can run programs built either for the 32-bit or 64-bit flavor of their respective OSes.
python is interpreted, so it won't run without python. However, that doesn't mean that python has to be installed, you can include a copy in your program directory or even bundle your program and the python runtime into a single file.
C and C++ compilers toolchains generate machine code (in most cases, C interpreters do exist, as do C and C++ -> p-code and bytecode compilers). But most C and C++ programs use shared libraries, and will not run unless the shared library is present (again, doesn't have to be installed, can be placed in the program directory). There's also usually a build option (static linking) to include all necessary libraries in the main program file.
But the result is still limited to a particular combination of OS and CPU architecture. Getting a program to run on more than a single platform always requires platform-specific runtime support.
You can use py2exe for distributing Python programs to Windows.
http://www.py2exe.org/
If a you have written a program in any language, and that program is not compiled to machine code, something on the user's computer must convert it to machine code before it can be run.
In the case of JavaScript, that "something" is often a web browser. In the case of Python, that is often a stand-alone interpreter, though it is possible to compile it:
Is it feasible to compile Python to machine code?
However, to be clear: just because your program is not compiled to imachine code does not mean that it will be interpreted. Programs written in C# are usually compiled to MSIL, which is compiled to machine code the first time the program is run. Java programs are also compiled when they are first run.
I will give a practical application of sending code to a remote machine to run. This is typically done in the BOINC project, a community GRID computing initiative which has produced gems such as SETI#Home. The applications typically are compiled C++ versions with multi-platform binaries for x86-linux, AMD64-linux, win32, win64 and Mac OS Universal Binaries (with ppc,x86 and 64-bit). This is a lot of variety for distribution, but a modern make system can easily automate all that (e.g. CMake).
A lot of people prefer the WORA method (write once run anywhere) and stick with VM based language like Java or Python. In this case the boinc projects distribute a version of the VM as well as the code to run on it. Java VM's being encumbered with licensing issues, Python VM is much nicer. Boinc is attempting to embed the Python VM in various BOINC clients to make the distribution of Python based GRID applications easier.
I hope this gives you an idea about application distribution and helps you make an informed decision.
There is a py2exe that can produce an executable that will run on another computer without that user installing the normal Python package.
Yes, C and C++ are (at least normally) implemented as compilers that can produce standalone executables.
Edit: In a typical case, a C or C++ implementation will link the functions from the standard library that are used in the program into the executable. This can (and often does) include quite a bit that's not used directly, but still doesn't normally include (anywhere close to) the entire standard library.
In most cases you can also produce an executable that depends on an implementation of the standard library already being present on the target machine in the form of a shared library, DLL, etc. (different OSes use different names). This reduces the size of the executable, but increases the headaches involved in distribution; I use it for code I'm compiling on my own machine, but generally avoid it when/if I'm distributing an executable to anybody else. Given current hard drive prices, the savings in disk space is rarely worth the headache.
Look into Pyinstaller for standalone executables with no python integration needed. Well, apart from the crucial libraries so it can run!
It's recently updated, well maintained and even supports cython integration though that can get complex. You can compress the files to be smaller or if you have multiple executables, you can link them to one file to reduce size.
You can also of course create a single executable with python installed. Don't use anaconda though (use default python 3.6) to ensure your program is very small in size.
Hope this helps.
What's the difference between a program developed in C++ under Windows and Linux?
Why can't a program developed under Windows in C++ be used under Linux?
Windows and Linux use different container formats to hold the executable code (PE vs ELF).
Windows and Linux have completely different APIs (except for trivial programs that only use the CRT and STL)
Windows and Linux have a completely different directory structure
You could write a program that can use either set of APIs (for example, using Qt), and that can handle either directory structure, but you still won't be able to run the same file on both operating systems because of the differing container formats.
This can be solved by using Wine.
Native programs are not compatible because Windows has a completely different set of API's than Linux, for one. As others have mentioned, each platform uses a different executable format as well. Also both platforms have their own set of libraries that programs will be linked against and/or share. For example, a Windows program will typically be developed in Visual Studio using windows-specific libraries such as MFC, Win32 API, etc. These libraries are not available in linux, so the program will not even compile unless care is taken to make sure cross-platform libraries (such as QT) are used.
If you are careful, however, you can use cross-platform libraries in your code and you can get the same program to compile under both platforms. For such a program you would need to carefully put any platform-specific details (file system locations, etc) in their own files. Then, you would need to setup the proper #define statements and/or makefile directives to ensure the proper files are included in the build for each platform.
Of course, if you use a "cross-platform" language such as Java or Python, and do not use any platform-specific code in your implementation, then your program can run under both environments.
Note Although the executable formats are different, some programs developed on Windows can be executed under Linux using an emulator called WINE.
In a nutshell,
Windows runs PE format executables
Linux runs ELF format executables
Furthermore, even if there were a tool to convert between PE and ELF, the program instructions necessary to interface with the operating system are completely different between Windows and Linux. Only the most restricted computation-only code (that only does calculations and doesn't interact with the operating system at all) could be ported between systems without special action. However, this is rarely done.
I believe some versions of Linux allow you to directly load device drivers designed for Windows without recompiling. However, this is an extremely special purpose application and the technique is not generally used.
Each operating system defines an API. If you code to call the Win32 API, it won't be there on Linux. If you code to the POSIX API, it won't jump right out at you in Windows.
To learn more about this, download a significant open source program (for example, Perl or Python) and see how its 'configure' script makes arrangements to compile in either place.
When a C++ program is compiled on a platform, it ultimately changes into a form that machine can understand (i.e. Machine code). Under the hood, the program uses system calls to perform privileged action. These system calls are implemented via methods or APIs. These methods differ from platform to platform. Hence on every platform, the compiled code is different. There are many cross-compilers available if you want to compile your code for a different platform.
Not to be overly pedantic, but developing a program is different than building it and executing it. In many cases, a program written on one operating system can be built and compiled to execute on another. Other programs, as others have pointed out, rely on certain functionality provided only by a particular OS or libraries resident only on that OS. As a result, it must be built and run on that OS.
C++ is itself portable. But some C++ libraries are not. If a C++ program uses some libraries, which are not portable, then this program is not portable.
For example, a C++ program uses MFC to draw the GUI stuff, because MFC is supported only in Windows, so this C++ program cannot be compiled or run on Linux directly.
There are two major reasons.
Theoretically, the same program (source code) for some languages like C, can run on both Windows and Linux. But the compilation only differs; this means you have to compile the same source code file for each platform.
But actually, each operating system has a different set of APIs. And different techniques to get job done faster... Which usually attract developers to use them. And they don't stick to standards, so they lose portability.
This was for native programs... Anyway, there are the Java and Python languages... They are truly cross-platform, but you have to sacrifice speed for sake of portability.
This is a large topic.
First, Windows and Linux aren't binary comparable. This means that even the simplest of programs will not be recognized from one machine to the other. This is why interpreted languages like PHP, Perl, Python and Java are becoming so popular, but even these don't all support the same set of features on each platform.
Library dependence / OS support: Any significantly complicated program will need to access the system is some way, and many of the features available on one system are not available on the other. There are a million examples; just look on so for the Linux equivalent of blank or Windows equivalent of blank. Moving beyond OS support applications are built mostly on top of libraries of functions and some of those are just not available on both systems.