Recent

Author Topic: Determine bitness for Linux/OSX  (Read 12526 times)

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Determine bitness for Linux/OSX
« on: September 06, 2011, 08:23:19 pm »
Hi all,

For my version of https://bitbucket.org/reiniero/lazupdater_baremetal/, I want to know whether an operating system is 32 bit or 64 bit, so I can let the user choose between 32 and 64 bit compilers/binutils - if possible.

For Windows, I found a function that does it, thanks to the German Lazarus forum:
http://wiki.lazarus.freepascal.org/Multiplatform_Programming_Guide#Detecting_bitness_at_runtime

How can I detect if you're running on 32 or 64 bit Linux and OSX? (Bonus question: if not on x86 architecture, how can I detect which processor it's running on - but I think that's less pressing)

Something like uname -a might work, but I don't know if the output can be parsed for all Linux distros and OSX.

Linux:
Don't really know if all Linux
Code: [Select]
unames will give the same 64 bit indication...
On Linux, perhaps something in the /proc filesystem?
Found http://www.velocityreviews.com/forums/t147757-how-to-detect-cpu-architecture-bitmode-32-bit-vs-64-bit-for-linux.html; paraphrased:
Code: [Select]
cat /proc/cpuinfo
You will see some parameters with their description
Under "flags" parameter various parameters?/names?, one of them:
1. "rm(real mode)": 16 bit processor
2. "tm(transparent mode)": 32 bit processor
3. "lm(long mode)": 64 bit processor
Would this also apply to non-X86 architectures? (And yes, the obvious next question is, how do I detect Linux on ARM etc)

OSX:
On OSX, I saw a post by Shebuka mentioning system_profiler: http://www.lazarus.freepascal.org/index.php/topic,13109.msg71741.html#msg71741, but the questions are: what setting to query & is there a more elegant way of doing that?
Saw another site http://osxdaily.com/2009/09/07/how-to-tell-if-youre-running-the-32-bit-or-64-bit-kernel-in-mac-os-x-snow-leopard/ that says:
Code: [Select]
uname -athis returns a line ending with:
Code: [Select]
i386 or
Code: [Select]
x86_64Any more elegant way?

Ok, for completeness' sake & my records: other unixes (FreeBSD, Solaris): any tips?

Thanks!
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

Blaazen

  • Hero Member
  • *****
  • Posts: 2782
  • POKE 54296,15
    • Eye-Candy Controls
Re: Determine bitness for Linux/OSX
« Reply #1 on: September 06, 2011, 08:45:29 pm »
Here (64-bit Linux):
Code: [Select]
$ uname -m
x86_64
$
Lazarus 2.1.0 r61214:62238 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Determine bitness for Linux/OSX
« Reply #2 on: September 06, 2011, 09:08:44 pm »
Thanks, Blaazen.

Looking at e.g.
http://serverfault.com/questions/63484/linux-what-are-the-possible-values-returned-by-uname-m-and-uname-p
I found:
Quote
list of architectures supported by "alsa" package, which I believe has all popular archs included
Code: [Select]
i386 i686 x86_64 ia64 alpha amd64 arm armeb armel hppa m32r m68k mips mipsel powerpc ppc64 s390 s390x sh3 sh3eb sh4 sh4eb sparc... and yes, who knows, maybe FPC compiles on s390 (IBM mainframe), as well ;)
Seems I'd be safe to just look for <some letters>64 for 64 bit, and if not present, assume 32 bit...

What do you think?
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Determine bitness for Linux/OSX
« Reply #3 on: September 07, 2011, 08:22:08 am »
On OSX (running OSX Lion), I seem to be able to get results:
- using uname
From man uname:
Code: [Select]
-a      Behave as though all of the options -mnrsv were specified.
-m      print the machine hardware name.
-p      print the machine processor architecture name.

Results:
Code: [Select]
Laptop:~ theuser$ uname -a
Darwin Laptop.local 11.1.0 Darwin Kernel Version 11.1.0: Tue Jul 26 16:07:11 PDT 2011; root:xnu-1699.22.81~1/RELEASE_X86_64 x86_64
Laptop:~ theuser$ uname -m
x86_64
Laptop:~ theuser$ uname -p
i386


- using system_profiler
Code: [Select]
system_profiler SPSoftwareDataType | grep "64-bit Kernel and Extensions"gives
Code: [Select]
64-bit Kernel and Extensions: Yes
So, which one would be most stable and easiest? To align with Linux, I think I'll go with
Code: [Select]
uname -m
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Determine bitness for Linux/OSX
« Reply #4 on: September 07, 2011, 09:10:55 am »
I'm started talking to myself here, but I think I'm having a good conversation  ;)

I think I found a solution, but haven't tested it for Linux/OSX/Unix yet, so comments welcome:
Code: [Select]
{$IFDEF Windows}
function Is64bitOS: boolean;
{
Detect if we are running on a 64 bit or 32 bit operating system/kernel
independently of bitness of this program, or actual hardware.
Original source:
http://www.delphipraxis.net/118485-ermitteln-ob-32-bit-oder-64-bit-betriebssystem.html
modified for FreePascal in German Lazarus forum:
http://www.lazarusforum.de/viewtopic.php?f=55&t=5287
}

type
  TIsWow64Process = function( // Type of IsWow64Process API fn
      Handle: Windows.THandle; var Res: Windows.BOOL): Windows.BOOL; stdcall;
var
  IsWow64Result: Windows.BOOL; // Result from IsWow64Process
  IsWow64Process: TIsWow64Process; // IsWow64Process fn reference
begin
  // Try to load required function from kernel32
  IsWow64Process := TIsWow64Process(Windows.GetProcAddress(
    Windows.GetModuleHandle('kernel32'), 'IsWow64Process'));
  if Assigned(IsWow64Process) then
  begin
    // Function is implemented: call it
    if not IsWow64Process(Windows.GetCurrentProcess, IsWow64Result) then
      raise SysUtils.Exception.Create('IsWindows64: bad process handle');
    // Return result of function
    Result := IsWow64Result;
  end
  else
    // Function not implemented: can't be running on Wow64
    Result := False;
end;
{$ENDIF Windows}

{$IF DEFINED(DARWIN) or DEFINED(Linux) or DEFINED(Unix)}
function Is64bitOS: boolean;
{
Detect if we are running on a 64 bit or 32 bit operating system/kernel
independently of bitness of this program, or actual hardware.
Adapted from Lazarus forum post by Shebuka:
http://www.lazarus.freepascal.org/index.php/topic,13109.msg71741.html#msg71741
}
var
  InfoProcess: TProcess;
  path: string;
  InfoResult: TStringList;
  ResultLine: string;
  NumRows, i: integer;
begin
  result := false; //fail by default

  path := 'sh -c "uname -m"';
  InfoProcess := Tprocess.Create(nil);
  try
    InfoProcess.CommandLine := path;
    InfoProcess.Options := InfoProcess.Options + [poUsePipes, poWaitOnExit];
    InfoProcess.Execute;
  except
    InfoProcess.Free;
    exit; //result already was false...
  end;

  InfoResult := TStringList.Create;
  try
    InfoResult.LoadFromStream(InfoProcess.Output);
  except
    InfoResult.Free;
    exit; //result already was false...
  end;

  InfoProcess.Terminate(0);
  InfoProcess.Free;

  NumRows := InfoResult.Count;
  // Should be just one result; we'll take the first non-empty line
  for i := 0 to NumRows - 1 do
  begin
    ResultLine:=trim(Inforesult[i]);
    if ResultLine<>'' then
    begin
      //Note: we're no only testing x86 architecture!
      //Don't know if s390 s390x are 64 bit, but not a big chance to encounter mainframes for now
      if (
      (ResultLine='x86_64') or
      (ResultLine='amd64') or
      (ResultLine='ia64') or
      (ResultLine='ppc64')
      ) then
      begin
        result:=true;
      end
      else
      begin
        //'Fail' if another, even unknown, architecture is used
        result:=false;
      end;
      Break; //we're done.
    end;
  InfoResult.Free;
  end;
end;
{$ENDIF} //Darwin, Linux, Unix
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

Shebuka

  • Sr. Member
  • ****
  • Posts: 422
Re: Determine bitness for Linux/OSX
« Reply #5 on: September 07, 2011, 11:05:56 am »
I think that for your uses uname is just perfect, ;) system_profile can give many info (like your IP, OS version/architecture ecc.), but it's much slower.

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 8111
Re: Determine bitness for Linux/OSX
« Reply #6 on: September 07, 2011, 12:55:23 pm »
Note that there is a baseunix.fpuname call, you don't need to call the runtime module.

But maybe a fpuname from a 32-bit binary on a 64-bit system returns a 32-bit architecture description.

How to detect that you are not in an emulation mode is harder (Linux binaries can run in a Linux emulation mode on most BSDs)

franciscoluiz

  • New Member
  • *
  • Posts: 25
Re: Determine bitness for Linux/OSX
« Reply #7 on: January 01, 2013, 02:31:34 pm »
mr Banana  :D
isn't simpler something like:


Code: [Select]
function TForm1.IsWindows: boolean;
begin
    {$IFDEF Windows}
         Result  := true;
    {$ENDIF}
    {$IF DEFINED(DARWIN) or DEFINED(Linux) or DEFINED(Unix)}
         Result  := false;
    {$ENDIF}
end;

function TForm1.Is32b: boolean;
begin
    {$ifdef CPU32}
         Result  := true;
    {$ENDIF}
    {$ifdef CPU64}
         Result  := false;
    {$ENDIF}
end;

???

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 8111
Re: Determine bitness for Linux/OSX
« Reply #8 on: January 02, 2013, 03:45:33 pm »
FreeBSD:

 
[Toad] </usr/include/sys> uname -m
amd64
[Toad] </usr/include/sys> uname -p
amd64
[Toad] </usr/include/sys>

« Last Edit: January 02, 2013, 03:54:55 pm by marcov »