diff --git a/xs/Build.PL b/xs/Build.PL index 6145777c7..5413952bb 100644 --- a/xs/Build.PL +++ b/xs/Build.PL @@ -7,6 +7,9 @@ use Devel::CheckLib; use ExtUtils::CppGuess; use Module::Build::WithXSpp; +my $cpp_guess = ExtUtils::CppGuess->new; +my $mswin = $^O eq 'MSWin32'; + # _GLIBCXX_USE_C99 : to get the long long type for g++ # HAS_BOOL : stops Perl/lib/CORE/handy.h from doing "# define bool char" for MSVC # NOGDI : prevents inclusion of wingdi.h which defines functions Polygon() and Polyline() in global namespace @@ -16,32 +19,67 @@ my @ldflags = (); if ($^O eq 'darwin') { push @ldflags, qw(-framework IOKit -framework CoreFoundation); } +if ($mswin) { + # In case windows.h is included, we don't want the min / max macros to be active. + # If is included, we want the #defines to be active (M_PI etc.) + push @cflags, qw(-DNOMINMAX -D_USE_MATH_DEFINES); +} my @INC = qw(-Isrc/libslic3r); -my @LIBS = qw(-Lsrc/libslic3r); +my @LIBS = $cpp_guess->is_msvc ? qw(-LIBPATH:src/libslic3r) : qw(-Lsrc/libslic3r); # search for Boost in a number of places -my @boost_include = my @boost_libs = (); -if (defined $ENV{BOOST_DIR}) { - if (-d "$ENV{BOOST_DIR}/include") { - push @boost_include, $ENV{BOOST_DIR} . '/include'; +my @boost_include = (); +if (defined $ENV{BOOST_INCLUDEDIR}) { + push @boost_include, $ENV{BOOST_INCLUDEDIR} +} elsif (defined $ENV{BOOST_DIR}) { + my $subdir = $ENV{BOOST_DIR} . (($mswin == 1) ? '\include' : '/include'); + if (-d $subdir) { + push @boost_include, $subdir; } else { push @boost_include, $ENV{BOOST_DIR}; } - push @boost_libs, $ENV{BOOST_DIR}; } else { - push @boost_include, grep { -d $_ } - qw(/opt/local/include /usr/local/include /opt/include), - qw(/usr/include C:\Boost\include); - push @boost_libs, grep { -d $_ } - qw(/opt/local/lib /usr/local/lib /opt/lib /usr/lib), - qw(C:\Boost\lib /lib); - - if ($^O eq 'MSWin32') { - for my $path (glob('C:\dev\boost*'), glob ('C:\boost*')) { + # Boost library was not defined by the environment. + # Try to guess at some default paths. + if ($mswin) { + for my $path (glob('C:\dev\boost*\include'), glob ('C:\boost*\include')) { push @boost_include, $path; - push @boost_libs, $path . "/stage/lib"; } + if (! @boost_include) { + # No boost\include. Try to include the boost root. + for my $path (glob('C:\dev\boost*'), glob ('C:\boost*')) { + push @boost_include, $path; + } + } + } else { + push @boost_include, grep { -d $_ } + qw(/opt/local/include /usr/local/include /opt/include /usr/include); + } +} + +my @boost_libs = (); +if (defined $ENV{BOOST_LIBRARYDIR}) { + push @boost_libs, $ENV{BOOST_LIBRARYDIR} +} elsif (defined $ENV{BOOST_DIR}) { + my $subdir = $ENV{BOOST_DIR} . ($mswin ? '\stage\lib' : '/stage/lib'); + if (-d $subdir) { + push @boost_libs, $subdir; + } else { + push @boost_libs, $ENV{BOOST_DIR}; + } +} else { + # Boost library was not defined by the environment. + # Try to guess at some default paths. + if ($mswin) { + for my $path ( + glob('C:\dev\boost*\lib'), glob ('C:\boost*\lib'), + glob('C:\dev\boost*\stage\lib'), glob ('C:\boost*\stage\lib')) { + push @boost_libs, $path; + } + } else { + push @boost_libs, grep { -d $_ } + qw(/opt/local/lib /usr/local/lib /opt/lib /usr/lib /lib); } } @@ -50,29 +88,44 @@ my $have_boost = 0; my @boost_libraries = qw(system thread); # we need these # check without explicit lib path (works on Linux) -$have_boost = 1 - if check_lib( - lib => [ map "boost_${_}", @boost_libraries ], - ); +if (! $mswin) { + $have_boost = 1 + if check_lib( + lib => [ map "boost_${_}", @boost_libraries ], + ); +} if (!$ENV{SLIC3R_STATIC} && $have_boost) { + # The boost library was detected by check_lib on Linux. push @LIBS, map "-lboost_${_}", @boost_libraries; } else { - foreach my $path (@boost_libs) { - my @files = glob "$path/libboost_system*"; + # Either static linking, or check_lib could not be used to find the boost libraries. + my $lib_prefix = 'libboost_'; + my $lib_ext = ${$cpp_guess}{config}{lib_ext}; + PATH: foreach my $path (@boost_libs) { + # Try to find the boost system library. + my @files = glob "$path/${lib_prefix}system*$lib_ext"; next if !@files; - if ($files[0] =~ /libboost_system([^.]+)/) { + if ($files[0] =~ /${lib_prefix}system([^.]+)$lib_ext$/) { + # Suffix contains the version number, the build type etc. my $suffix = $1; - check_lib( - lib => [ map "boost_${_}${suffix}", @boost_libraries ], - INC => join(' ', map "-I$_", @INC, @boost_include), - LIBS => "-L$path", - ) or next; - + # Verify existence of all required boost libraries at $path. + for my $lib (map "${lib_prefix}${_}${suffix}${lib_ext}", @boost_libraries) { + # If the library file does not exist, try next library path. + -f "$path/$lib" or next PATH; + } + if (! $cpp_guess->is_msvc) { + # Test the correctness of boost libraries by linking them to a minimal C program. + check_lib( + lib => [ map "boost_${_}${suffix}", @boost_libraries ], + INC => join(' ', map "-I$_", @INC, @boost_include), + LIBS => "-L$path", + ) or next; + } push @INC, (map " -I$_", @boost_include); # TODO: only use the one related to the chosen lib path - if ($ENV{SLIC3R_STATIC}) { - push @LIBS, map "$path/libboost_$_$suffix.a", @boost_libraries; + if ($ENV{SLIC3R_STATIC} || $cpp_guess->is_msvc) { + push @LIBS, map "${path}/${lib_prefix}$_${suffix}${lib_ext}", @boost_libraries; } else { push @LIBS, " -L$path", (map " -lboost_$_$suffix", @boost_libraries); } @@ -91,13 +144,17 @@ path through the BOOST_DIR environment variable: BOOST_DIR=/path/to/boost perl Build.PL +Or you may specify BOOST_INCLUDEPATH and BOOST_LIBRARYPATH separatly, which +is handy, if you have built Boost libraries with mutliple settings. + EOF if ($ENV{SLIC3R_DEBUG}) { # only on newer GCCs: -ftemplate-backtrace-limit=0 - push @cflags, qw(-DSLIC3R_DEBUG -g); + push @cflags, '-DSLIC3R_DEBUG'; + push @cflags, $cpp_guess->is_msvc ? '-Gd' : '-g'; } -if (ExtUtils::CppGuess->new->is_gcc) { +if ($cpp_guess->is_gcc) { # check whether we're dealing with a buggy GCC version # see https://github.com/alexrj/Slic3r/issues/1965 if (`cc --version` =~ / 4\.7\.[012]/) { diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp index cddfa21fa..501349d5c 100644 --- a/xs/src/libslic3r/PlaceholderParser.cpp +++ b/xs/src/libslic3r/PlaceholderParser.cpp @@ -3,14 +3,22 @@ #include #include #include -#include // provides **environ +#ifdef _MSC_VER + #include // provides **_environ +#else + #include // provides **environ +#endif #ifdef __APPLE__ #include #undef environ #define environ (*_NSGetEnviron()) #else - extern char **environ; + #ifdef _MSC_VER + #define environ _environ + #else + extern char **environ; + #endif #endif namespace Slic3r { diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h index eb3fb8f03..168e3f49c 100644 --- a/xs/src/libslic3r/libslic3r.h +++ b/xs/src/libslic3r/libslic3r.h @@ -25,14 +25,17 @@ typedef double coordf_t; namespace Slic3r { -// TODO: make sure X = 0 -enum Axis { X, Y, Z }; +enum Axis { X=0, Y, Z }; } using namespace Slic3r; /* Implementation of CONFESS("foo"): */ -#define CONFESS(...) confess_at(__FILE__, __LINE__, __func__, __VA_ARGS__) +#ifdef _MSC_VER + #define CONFESS(...) confess_at(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) +#else + #define CONFESS(...) confess_at(__FILE__, __LINE__, __func__, __VA_ARGS__) +#endif void confess_at(const char *file, int line, const char *func, const char *pat, ...); /* End implementation of CONFESS("foo"): */ diff --git a/xs/src/xsinit.h b/xs/src/xsinit.h index 69ac337f7..99b0e8f6a 100644 --- a/xs/src/xsinit.h +++ b/xs/src/xsinit.h @@ -40,6 +40,12 @@ extern "C" { #include "ppport.h" #undef do_open #undef do_close +#ifdef _MSC_VER + // Undef some of the macros set by Perl , which cause compilation errors on Win32 + #undef send + #undef connect + #undef bind +#endif /* _MSC_VER */ } #endif