DaemonR's assorted tricks

All about the OSDev Wiki. Discussions about the organization and general structure of articles and how to use the wiki. Request changes here if you don't know how to use the wiki.
User avatar
Wajideu
Member
Member
Posts: 153
Joined: Wed Jul 30, 2014 1:05 am

DaemonR's assorted tricks

Post by Wajideu »

These are just some suggestions for the wiki's tutorial on building a GCC cross compiler.


1. Building an x86_64 compiler

If you're building an x86_64 compiler on a 32-bit pc, make sure you pass the option '--enable-64-bit-bfd' to the configure scripts for both binutils and the gcc


2. Removing the program prefixes
  • Export variables for all of your host tools (the ones being used to compile your toolchain) like so

    Code: Select all

    export SDK_PATH=/C/MinGW
    
    export CPP=$SDK_PATH/bin/cpp
    export CC=$SDK_PATH/bin/gcc
    export CXX=$SDK_PATH/bin/g++
    export AS=$SDK_PATH/bin/as
    export LD=$SDK_PATH/bin/ld
    export NM=$SDK_PATH/bin/nm
    export READELF=$SDK_PAth/bin/readelf
    export OBJCOPY=$SDK_PATH/bin/objcopy
    export OBJDUMP=$SDK_PATH/bin/objdump
    export DLLTOOL=$SDK_PATH/bin/dlltool
    export AR=$SDK_PATH/bin/ar
    export RANLIB=$SDK_PATH/bin/ranlib
    export STRIP=$SDK_PATH/bin/strip
    export WINDMC=$SDK_PATH/bin/windmc
    export WINDRES=$SDK_PATH/bin/windres
    
    This is to prevent the build process from confusing the host toolchain with the target toolchain. If you don't do this, your build process will probably halt with a linking error; probably something about libiberty or libiconv.
  • Pass the option '--program-prefix=""' to the configuration scripts for both binutils and gcc

3. How to change the architecture path.

When you build your toolchain, you'll notice that the architecture dependent files are stored in a subdirectory that has the same name as the target. Like:

Code: Select all

cross
 +- bin
 +- i686-pc-elf
 +- include
 +- lib
 '- share
However, this looks rather unsightly. To change "i686-pc-elf" to something else, in both binutils and gcc open up config.sub and below where it says "# Recognize the various machine names and aliases" add:

Code: Select all

	arch)
		basic_machine=i686-pc
		os=-elf
		;;
Where "arch" is what you want the directory to be called and the variables 'basic_machine' and 'os' are set to the appropriate parts of the target architecture. Then, configure your binutils and gcc with '--target="arch"'. I like consistency, so I just leave the "arch" part the same and change the later 2 for whatever I'm compiling.
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: GCC Cross Compiler Tutorial Suggestions

Post by sortie »

Hi,

Thanks for compiling this list. Unfortunately, I fear many of these suggestions are bad. I'll try to explain why:

I really don't think --enable-64-bit-bfd is required when making a cross-compiler for a 64-bit system on a 32-bit system. Do you have evidence for this? I would consider it a serious bug in binutils if it is the case. --target should be sufficient. That option only sounds like it would have any effect when making a 32-bit compiler where 64-bit additional targets are not included by default, and this option includes them anyway. I am not absolutely certain here, I'll need to install a 32-bit system in a virtual machine (as all my computers run 64-bit operating systems) and verify.

Why would you possibly want your cross-tools to not be prefixed with a target triplet or something unique? That is mad and causes conflicts with the local toolchain as you discovered. Always prefix your cross-tools.

Lastly what you see in the directory tree is the obscure `tools directory'. You can't override it from the configure line, but it's fairly simple to override the toolsdir variable in the makefile. This is really of no concern when cross-compiling, you don't want to actually use the programs in that directory directly, just use the regular ones in the bin directory that have the target triplet prefixed.

These suggestions should not be added to the wiki for these reasons. --enable-64-bit-bfd might need to, if there is a bug like you claim, but I'm not convinced that's true.

Please explain why you wish to have your cross tools not prefixed with the target tripled. I think you are misguided and I might be able to advise you on a better way to proceed.
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: GCC Cross Compiler Tutorial Suggestions

Post by xenos »

DaemonR wrote:Export variables for all of your host tools (the ones being used to compile your toolchain) like so

Code: Select all

...
This is to prevent the build process from confusing the host toolchain with the target toolchain. If you don't do this, your build process will probably halt with a linking error; probably something about libiberty or libiconv.
This linking error never happened to me, and I don't know of anyone else who encountered this problem. I dare to say that a linking error is a lot less probable than you assume.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
Wajideu
Member
Member
Posts: 153
Joined: Wed Jul 30, 2014 1:05 am

Re: GCC Cross Compiler Tutorial Suggestions

Post by Wajideu »

sortie wrote:I really don't think --enable-64-bit-bfd is required when making a cross-compiler for a 64-bit system on a 32-bit system. Do you have evidence for this?
I'm not sure if it's reproducible, but I've tried building the gcc numerous times for x86_64-pc-elf, and while binutils would compile fine the gcc itself would often crash towards the end. I was using a 32-bit MinGW as a host. According to the documentation, the option was made specifically for targeting 64-bit architectures using 32-bit hosts.
sortie wrote:Why would you possibly want your cross-tools to not be prefixed with a target triplet or something unique? That is mad and causes conflicts with the local toolchain as you discovered. Always prefix your cross-tools.
Actually, it doesn't. I use multiple toolchains, so I don't have any of them added to my environment path. I've gotten in the good habit of always typing:

Code: Select all

export PATH=/C/MinGW/bin:$PATH
Every time I open my bash shell. Which is a lot better than having to type "x86_64-pc-linux-gnu-gcc" or "mips64el-none-elf-gcc".

Code: Select all

Lastly what you see in the directory tree is the obscure `tools directory'. You can't override it from the configure line, but it's fairly simple to override the toolsdir variable in the makefile. This is really of no concern when cross-compiling, you don't want to actually use the programs in that directory directly, just use the regular ones in the bin directory that have the target triplet prefixed.
It is of concern when you're making a canadian cross-compiler or finalizing a toolchain for your operating system. I highly doubt the people who have already ported the gcc to their operating system where it is the primary toolchain would like to see it in their face all the time. The main reason I suggested these things (in particular, the 3rd one most of all) is because I myself had scoured the internet for hours on end and nowhere could I find a straight answer for these kind of things. In the end, I just had to experiment by building the gcc a few dozen times with different arguments and tinkering with the configuration files until I figured it out.
XenOS wrote:This linking error never happened to me, and I don't know of anyone else who encountered this problem. I dare to say that a linking error is a lot less probable than you assume.
The error only occurs when you're using --program-prefix="". It happens because the programs in your target toolchain and your host toolchain are both named exactly the same. Alternatively, you could probably get away with changing

Code: Select all

export PATH=$PREFIX/bin:$PATH
to

Code: Select all

export PATH=$PATH:$PREFIX/bin
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: GCC Cross Compiler Tutorial Suggestions

Post by xenos »

DaemonR wrote:The error only occurs when you're using --program-prefix="". It happens because the programs in your target toolchain and your host toolchain are both named exactly the same.[/code]
The obvious solution is not to use --program-prefix="" - it was not in the GCC cross compiler tutorial anyway, so it is not a problem of the tutorial at all. In fact it would be stupid to use it for a cross compiler, exactly because of the problems it would cause.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: GCC Cross Compiler Tutorial Suggestions

Post by Combuster »

64-bit-bfd is mentioned where 64-bit toolchains are created - see for example UEFI
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: GCC Cross Compiler Tutorial Suggestions

Post by jnc100 »

As far as I understand --enable-64bit-bfd is required to enable internal 64-bit support within binutils. In particular it makes the resolved vma addresses of symbols/relocations be 64 bit rather than 32 bit (although these may be converted back to 32-bit symbols/relocations depending on the output file format and relocation type). It is enabled by default, however, if the --target option specifies a 64-bit target, and sometimes is enabled if the host is 64-bit. The only times you should need to specify it explicitly is if the --target is a 32-bit target, but you also specify a 64-bit target with an additional --enable-targets= option.

Regards,
John.
User avatar
Wajideu
Member
Member
Posts: 153
Joined: Wed Jul 30, 2014 1:05 am

Re: GCC Cross Compiler Tutorial Suggestions

Post by Wajideu »

jnc100 wrote:The only times you should need to specify it explicitly is if the --target is a 32-bit target, but you also specify a 64-bit target with an additional --enable-targets= option.
That could have something to do with it. Two of the toolchains I've built use i686-pc-elf and i686-w64-mingw32 as the primary target, and use x86_64-pc-elf and x86_64-w64-mingw32 as additional targets.


@XenOS, As I stated before, the information is necessary to those who are building native toolchains for their operating systems.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: GCC Cross Compiler Tutorial Suggestions

Post by bluemoon »

Why do you want to have those compilers having exactly same names and managed by search path? The rest of the world choose to identify them by different names.
User avatar
Wajideu
Member
Member
Posts: 153
Joined: Wed Jul 30, 2014 1:05 am

Re: GCC Cross Compiler Tutorial Suggestions

Post by Wajideu »

bluemoon wrote:Why do you want to have those compilers having exactly same names and managed by search path? The rest of the world choose to identify them by different names.
As I've already said, it's so that I can easily switch between my toolchains by typing:

Code: Select all

export PATH=$TOOLCHAINPATH:$PATH
Rather than having to add the following to all of my makefiles:

Code: Select all

export PREFIX=x86_64-pc-elf-

export CC=$PREFIXgcc
export CXX=$PREFIXg++
export AS=$PREFIXas
export LD=$PREFIXld
export AR=$PREFIXld
export RANLIB=$PREFIXranlib
export OBJDUMP=$PREFIXobjdump
export OBJCOPY=$PREFIXobjcpy
And again, what I just said in my previous post:
DaemonR wrote:...the information is necessary to those who are building native toolchains for their operating systems.
I don't understand why so many people here are acting like I'm insane saying there are reasons a person would want "gcc" to actually be called "gcc".
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: GCC Cross Compiler Tutorial Suggestions

Post by xenos »

DaemonR wrote:@XenOS, As I stated before, the information is necessary to those who are building native toolchains for their operating systems.
No, see OS Specific Toolchain. Also in this case there is no need to rename the tools built to run on your build system, i.e., the cross compiler, using --program-prefix. Just use the correct target triplet prefix when invoking your tools. If you build tools to run natively on your OS, this problem does not appear because they should not end up in an executable path on your build system anyway.

If you want to compile stuff for different targets, and choose the correct target triplet prefix automatically each time, use a configure script or autotools, which will generate the correct makefile for you.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
Wajideu
Member
Member
Posts: 153
Joined: Wed Jul 30, 2014 1:05 am

Re: GCC Cross Compiler Tutorial Suggestions

Post by Wajideu »

Oh, I see. I've haven't gotten that far, so I was misunderstanding how the gcc is ported other operating systems. Thanks for the clarification.
Last edited by Wajideu on Sun Aug 17, 2014 3:06 am, edited 1 time in total.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: GCC Cross Compiler Tutorial Suggestions

Post by Combuster »

As I've already said, it's so that I can easily switch between my toolchains by typing
Bogus argument, really. My build needs to call multiple instances of gcc/ld during the entire process. one for the EFI code, one for the actual OS, and the host compiler for building all the tools the build process needs. If I can only use "gcc" this process become nigh impossible.

Claiming you need to set those in each makefile implies you're unnecessarily duplicating code as well. In the end I don't believe there's practical effort differences between coercing the compiler to use a different scheme compared to setting it once in your project. Usability differences are that people will have problem building your project, and will most likely accuse you of not using a cross compiler for failing the sanity checks listed in the Posting Checklist.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Wajideu
Member
Member
Posts: 153
Joined: Wed Jul 30, 2014 1:05 am

Re: GCC Cross Compiler Tutorial Suggestions

Post by Wajideu »

Combuster wrote:Usability differences are that people will have problem building your project, and will most likely accuse you of not using a cross compiler for failing the sanity checks listed in the Posting Checklist.
Thanks :) I wasn't aware there were guidelines for these kind of things.
User avatar
Wajideu
Member
Member
Posts: 153
Joined: Wed Jul 30, 2014 1:05 am

Re: GCC Cross Compiler Tutorial Suggestions

Post by Wajideu »

I'm not advocating for it to be added to the wiki, but here is how to change the default output file extension for the gcc.


Open up binutils-X.XX/ld/ldmain.c and search for

Code: Select all

If the --force-exe-suffix is enabled, and we're making
It should be around line 450. Just below this, you'll see:

Code: Select all

if (! link_info.relocatable && command_line.force_exe_suffix)
Remove the "&& command_line.force_exe_suffix" part. I also use a custom file extension for relocatable files, so I just change this entire statement to "if (1)". Then, shortly below this you'll see:

Code: Select all

if (len < 4
    || (strcasecmp (output_filename + len - 4, ".exe") != 0
    && strcasecmp (output_filename + len - 4, ".dll") != 0))
and

Code: Select all

strcat (dst_name, ".exe");
Change the extensions here to what you want. A tip, if you want shared object files to have a specific extension, there is a value called "link_info.shared" that you can check. eg. Mine is set up like:

Code: Select all

if (!link_info.shared)
{
	if (!link_info.relocatable)
		strcat (dst_name, ".eo");
	else
		strcat (dst_name, ".ro");
}
else
	strcat (dst_name, ".so");
Next, open binutils-X.XX/ld/emultempl/elf32.em and search for

Code: Select all

gld${EMULATION_NAME}_before_parse
In this function, add the line:

Code: Select all

output_filename = "${EXECUTABLE_NAME:-a.exe}";
changing ".exe" to whatever your executable file extension is.


Lastly, before you configure gcc, do:

Code: Select all

export CFLAGS=-DTARGET_EXECUTABLE_SUFFIX='".exe"'
export CXXFLAGS=$CFLAGS
again replacing ".exe" with your executable suffix. GCC will only add this suffix if the output file doesn't have one, but LD will force it to have one. So if you output a file with an invalid extension, like "-o test.derp", you will actually get 2 output files, "test.derp" (from GCC) and "test.derp.exe". (from LD)


-----------------


Note: Be sure to adjust the len appropriately if you're using a file extension that is longer or shorter than 4 characters. eg.

Code: Select all

if (len < 4
    || (strcasecmp (output_filename + len - 4, ".exe") != 0
    && strcasecmp (output_filename + len - 4, ".dll") != 0))
and

Code: Select all

char *dst_name = (char *) xmalloc (len + 5);
in mine are

Code: Select all

if (len < 3
    || (strcasecmp (output_filename + len - 3, ".eo") != 0
    && strcasecmp (output_filename + len - 3, ".ro") != 0
    && strcasecmp (output_filename + len - 3, ".so") != 0))
and

Code: Select all

char *dst_name = (char *) xmalloc (len + 4);
Post Reply