Extconf.rg and #ifdef

Hi, depending whether my Ruby C extension is being compiled on *nix or
Windows, I need some #defines (i.e: OS_UNIX or OS_WIN).

I see no way in MKMF documentation to generate a #define (based on
RbConfig[“host_os”] for example). I’ve seen some “hacks” in extconf.rb
like this:


def add_define(name)
$defs.push("-D#{name}")
end

If I’m on *nix:

add_define “OS_UNIX”

Iñaki Baz C. писал 28.05.2012 14:57:

def add_define(name)
$defs.push("-D#{name}")
end

If I’m on *nix:

add_define “OS_UNIX”

Is this the most ellegant way? any other solution?

Thanks a lot.

Yeah, that’s pretty much how configure scripts work. (More complex ones
like
that from autoconf create config.h with the definitions, but you’re
unlikely
to need this.)

Am 28.05.2012 12:57, schrieb Iñaki Baz C.:

end

If I’m on *nix:

add_define “OS_UNIX”

Is this the most ellegant way? any other solution?

Thanks a lot.

What is wrong with the generic macros the compiler sets itself? If I
remember correctly, every compiler targeting Windows sets a macro called
_WIN32, and I bet there’s something similar for other systems. There
shouldn’t be a need to manually define this in extconf.rb.

Vale,
Marvin


Blog: http://pegasus-alpha.eu/blog

ASCII-Ribbon-Kampagne () | ASCII Ribbon Campaign ()

2012/5/28 Peter Z. [email protected]:

Yeah, that’s pretty much how configure scripts work. (More complex ones like
that from autoconf create config.h with the definitions, but you’re unlikely
to need this.)

Thanks, I understand. However that worries me is the fact that the
“workaround” is modifyng $defs global variable:

$defs.push(“-D#{name}”)

Is it expected that such a $defs variable will exist forever in
extconf.rb/MKMF stuff?

Thanks a lot.

2012/5/28 Quintus [email protected]:

What is wrong with the generic macros the compiler sets itself? If I
remember correctly, every compiler targeting Windows sets a macro called
_WIN32, and I bet there’s something similar for other systems. There
shouldn’t be a need to manually define this in extconf.rb.

That would be, of course, much better than “auto-detecting” in
extconf.rb. However there could be other cases in which I need to
create a #define based on custom requirements.

I will inviestigate about the macro you mean. It seems than in *nix
systems, the compiler “should” set unix define:

Thanks a lot.

From libuv’s include/uv.h header:

#if defined(unix) || defined(POSIX) || defined(APPLE)

include “uv-private/uv-unix.h”

#else

include “uv-private/uv-win.h”

#endif

To help prevent multi-platform lunacy, as I find useful macros I add
them to a simple little C helper such as:

CL and MinGW compiler predefs · GitHub

Also, here’s what MSFT publishes as Visual Studio 10’s predefined C/C++
macros

Predefined macros | Microsoft Learn

Jon


Fail fast. Fail often. Fail publicly. Learn. Adapt. Repeat.
http://thecodeshop.github.com | http://jonforums.github.com/
twitter: @jonforums

On May 28, 2012, at 03:57, Iaki Baz C. wrote:

Hi, depending whether my Ruby C extension is being compiled on *nix or
Windows, I need some #defines (i.e: OS_UNIX or OS_WIN).

I see no way in MKMF documentation to generate a #define (based on
RbConfig[“host_os”] for example).

Do not use host_* values from rbconfig.rb.

Use target_* values from rbconfig.rb.

Using host_* is wrong.

The host_* values come from host that compiled ruby. When ruby is
cross-compiled these values won’t match the target and your gem will
fail to compile.

You should use target_* values as these values match the target ruby was
compiled for.

See: http://sources.redhat.com/autobook/autobook/autobook_261.html

2012/5/31 Eric H. [email protected]:

Use target_* values from rbconfig.rb.

Using host_* is wrong.

The host_* values come from host that compiled ruby. When ruby is
cross-compiled these values won’t match the target and your gem will fail to
compile.

You should use target_* values as these values match the target ruby was
compiled for.

See: http://sources.redhat.com/autobook/autobook/autobook_261.html

Good to know. Thanks a lot.

2012/5/28 Jon F. [email protected]:

From libuv’s include/uv.h header:

#if defined(unix) || defined(POSIX) || defined(APPLE)

include “uv-private/uv-unix.h”

#else

include “uv-private/uv-win.h”

#endif

Excellent, I didn’t realize of that :slight_smile:

To help prevent multi-platform lunacy, as I find useful macros I add
them to a simple little C helper such as:

CL and MinGW compiler predefs · GitHub

Really useful. Thanks a lot.

Jon F. wrote in post #1062852:

Eric H. wrote in post #1062725:

On May 28, 2012, at 03:57, Iaki Baz C. wrote:

Hi, depending whether my Ruby C extension is being compiled on *nix or
Windows, I need some #defines (i.e: OS_UNIX or OS_WIN).

I see no way in MKMF documentation to generate a #define (based on
RbConfig[“host_os”] for example).

[…SNIP…]

The host_* values come from host that compiled ruby. When ruby is
cross-compiled these values won’t match the target and your gem will
fail to compile.

You should use target_* values as these values match the target ruby was
compiled for.

See: http://sources.redhat.com/autobook/autobook/autobook_261.html

[…SNIP…]

I believe it’s more correct to use RbConfig::CONFIG['host_os'] to
determine *nix v. Windows.

Forgot to include the following doco link to compare with the link Eric
provided.

Eric H. wrote in post #1062725:

On May 28, 2012, at 03:57, Iaki Baz C. wrote:

Hi, depending whether my Ruby C extension is being compiled on *nix or
Windows, I need some #defines (i.e: OS_UNIX or OS_WIN).

I see no way in MKMF documentation to generate a #define (based on
RbConfig[“host_os”] for example).

Do not use host_* values from rbconfig.rb.

Use target_* values from rbconfig.rb.

Using host_* is wrong.

The host_* values come from host that compiled ruby. When ruby is
cross-compiled these values won’t match the target and your gem will
fail to compile.

You should use target_* values as these values match the target ruby was
compiled for.

See: http://sources.redhat.com/autobook/autobook/autobook_261.html

While this definition of host/target appears wrong, it doesn’t matter in
this case.

IIRC, the powerful-but-hellish autotools system gives these meanings to
build/host/target:

build - the type of the system used to configure and build a package.
Defaults to output of config.guess

host - the type of the system on which the built package executes.
Defaults to the same type as the build system and enables cross
compilation mode.

target - used for building compiler tools for cross compiling. The type
of the system for which any compiler tools built from the package
produce code for. Defaults to the same type as the host.

I believe it’s more correct to use RbConfig::CONFIG['host_os'] to
determine *nix v. Windows.

Here’s output from two builds, the first built natively on Windows with
MinGW, and the second built on Arch Linux cross compiled with MinGW for
Windows.

RbConfig::CONFIG.each do |k,v|
| puts “#{k} = #{v}” if k =~ /build|host|target/
| end

MinGW/GCC 4.6.2 native Windows build

target_os = mingw32
target_vendor = pc
target_cpu = i386
target = i386-pc-mingw32
host_os = mingw32
host_vendor = pc
host_cpu = i686
host = i686-pc-mingw32
build_os = mingw32
build_vendor = pc
build_cpu = i686
build = i686-pc-mingw32
target_alias =
host_alias =
build_alias =

Arch 3.3.7 Linux → Windows cross compiled build

…/configure --enable-shared --disable-install-doc --host=i486-mingw32

target_os = mingw32
target_vendor = pc
target_cpu = i386
target = i386-pc-mingw32
host_os = mingw32
host_vendor = pc
host_cpu = i486
host = i486-pc-mingw32
build_os = linux-gnu
build_vendor = pc
build_cpu = i686
build = i686-pc-linux-gnu
target_alias =
host_alias = i486-mingw32
build_alias =

Jon


Fail fast. Fail often. Fail publicly. Learn. Adapt. Repeat.
http://thecodeshop.github.com | http://jonforums.github.com/
twitter: @jonforums