Menu

#1085 Unable to build makensis on OSX 10.9

3.0 Alpha Series
closed-fixed
nobody
None
5
2015-02-19
2013-11-10
jive
No

I have been a long time user of makensis on mac. Unfortantly the application will not compile after upgrading to OSX 10.9 Mavericks.

Version of NSIS you are using: 2.46

Error message you get if any

==> scons makensis
int      close(int) __DARWIN_ALIAS_C(close);
         ^
1 error generated.
scons: *** [build/release/makensis/script.o] Error 1
scons: building terminated because of errors.

A script that reproduces this bug if acceptable:

Using home-brew to install, near as I can tell it just launches a normal scons build.

brew install makensis

A screen shot if something is wrong with the user interface

Additional details here:

https://github.com/mxcl/homebrew/issues/23913

Including complete build output:

https://gist.github.com/anonymous/7286964

The good part looks to be:

g++ -o build/release/makensis/script.o -c -Wno-non-virtual-dtor -Wall -O2 -m32 "-DNSISCALL= __attribute__((__stdcall__))" -D_WIN32_IE=0x0500 -Ibuild/release/config Source/script.cpp
In file included from Source/script.cpp:22:
Source/util.h:145:20: error: call to function 'close' that is neither visible in the template definition nor found by argument-dependent lookup
RM_DEFINE_FREEFUNC(close);
                   ^
Source/util.h:128:49: note: expanded from macro 'RM_DEFINE_FREEFUNC'
  template <typename T> void operator()(T& x) { freefunc(x); } \
                                                ^
Source/util.h:114:32: note: in instantiation of function template specialization '__free_with_close::operator()<int>' requested here
  virtual ~ResourceManager() { m_free_resource(m_resource); };
                               ^
Source/util.h:135:16: note: in instantiation of member function 'ResourceManager<int, __free_with_close>::~ResourceManager' requested here
        ptr.reset(new ResourceManager<_RESOURCE, _FREE_RESOURCE>(resource));
                      ^
Source/script.cpp:6198:3: note: in instantiation of function template specialization 'createResourceManager<__free_with_close, int>' requested here
  MANAGE_WITH(fd, close);
  ^
Source/util.h:141:3: note: expanded from macro 'MANAGE_WITH'
                createResourceManager<RM_MANGLE_FREEFUNC(freefunc)>( \
                ^
/usr/include/unistd.h:431:6: note: 'close' should be declared prior to the call site
int      close(int) __DARWIN_ALIAS_C(close);
         ^
1 error generated.
scons: *** [build/release/makensis/script.o] Error 1
scons: building terminated because of errors.

Related

Patches: #253

Discussion

  • jive

    jive - 2013-11-12

    The OSX build environment has changed for 10.9. The clang compiler now uses a different stdlib implementation. To use earlier default use: --stdlib=libstdc++

    See discussion here: https://jira.mongodb.org/browse/SERVER-10644

    I was unable to figure out how to modify Sconstruct, and added an #import 'unistd.h' to util.h

     
  • Anders

    Anders - 2013-11-12

    As a workaround you could try scons APPEND_CCFLAGS=--stdlib=libstdc++ (Or CXXFLAGS?)

    include 'unistd.h' inside a #ifndef _WIN32 has already been added in trunk...

     

    Last edit: Anders 2013-11-12
  • jive

    jive - 2013-11-12

    scons APPEND_CCFLAGS=--stdlib=libstdc++ got much further, it now has link failures:

    ''''
    clang: warning: argument unused during compilation: '-pthread'
    ld: warning: option -s is obsolete and being ignored
    Undefined symbols for architecture i386:
    "std::string::find_first_of(char const, unsigned long, unsigned long) const", referenced from:
    dir_reader::dir_reader() in dirreader.o
    dir_reader::exclude(std::string const&) in dirreader.o
    "std::string::find(char, unsigned long) const", referenced from:
    CEXEBuild::do_add_file_create_dir(std::string const&, std::string const&, int) in script.o
    "std::string::rfind(char const
    , unsigned long, unsigned long) const", referenced from:
    get_string_prefix(std::string const&, std::string const&) in util.o
    get_string_suffix(std::string const&, std::string const&) in util.o
    get_dir_name(std::string const&) in util.o
    get_file_name(std::string const&) in util.o
    remove_file_extension(std::string const&) in util.o
    ..etc..
    "non-virtual thunk to std::basic_istream<char, std::char_traits<char=""> >::~basic_istream()", referenced from:
    construction vtable for std::istream-in-std::basic_ifstream<char, std::char_traits<char=""> > in Plugins.o
    ld: symbol(s) not found for architecture i386
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    scons: *** [build/release/makensis/makensis] Error 1
    scons: building terminated because of errors.
    ''''

     
  • jive

    jive - 2013-11-20

    The home-brew bug report has provided a solution. Using the following command line allows OSX 10.9 users to build:

    scons APPEND_CCFLAGS=--stdlib=libstdc++ makensis

     
  • Stephen Drake

    Stephen Drake - 2014-07-04

    I'm attaching a patch that allows me to build trunk [r6510] against libc++. I'm running Mac OS X 10.8, not 10.9, but I'm going the other way around and intentionally building with libc++ instead of libstdc++.

    I had to add STRIP=no to build with clang - this appears to be necessary on 10.8 but not 10.9. I don't know why, ld says "option -s is obsolete and being ignored" and then it fails anyway.

    Note that I got completely different build errors to the ones above, so this patch won't help with version 2.46, only going forward. If you're not having any luck with the workaround posted above, you might want to try also setting APPEND_LINKFLAGS=-stdlib=libstdc++ - that is part of the solution that homebrew used.

    Build system:
    Mac OS X 10.8.5
    Xcode 5.1.1
    Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)

    Command:
    scons APPEND_CCFLAGS=-stdlib=libc++ APPEND_LINKFLAGS=-stdlib=libc++ SKIPUTILS=all STRIP=no makensis

    Index: Source/script.cpp
    ===================================================================
    --- Source/script.cpp   (revision 6510)
    +++ Source/script.cpp   (working copy)
    @@ -38,8 +38,6 @@
     #include <algorithm>
     #include "boost/scoped_ptr.hpp"
    
    -using namespace std;
    -
     #ifdef _WIN32
     #  include <direct.h> // for chdir
     #else
    @@ -52,6 +50,11 @@
    
     #define MAX_INCLUDEDEPTH 10
    
    +using std::exception;
    +using std::max;
    +using std::runtime_error;
    +using std::set;
    +
     static UINT read_line_helper(NStreamLineReader&lr, TCHAR*buf, UINT cch)
     {
       // Helper function for reading lines from text files. buf MUST be valid and cch MUST be > 1!
    
     

    Related

    Commit: [r6510]

    • Anders

      Anders - 2014-07-04

      using namespace std; is perfectly valid C++

       
      • Stephen Drake

        Stephen Drake - 2014-07-07

        Indeed it is, and I have very little experience with C++, so I sure don't want to weigh in on matters of style. Allow me to explain myself a little more clearly. First up, here's the error I see:

        g++ -o build/urelease/makensis/script.o -c -Wno-non-virtual-dtor -Wall -stdlib=libc++ -O2 -DNSISCALL= -D_UNICODE -DUNICODE -DMAKENSIS -D_WIN32_IE=0x0500 -Ibuild/urelease/config Source/script.cpp
        Source/script.cpp:96:20: error: call to 'wcsrchr' is ambiguous
          const TCHAR *p = _tcsrchr(filename,_T('\\')), *p2 = _tcsrchr(filename,_T('/'));
                           ^~~~~~~~
        Source/tchar.h:78:21: note: expanded from macro '_tcsrchr'
        #define _tcsrchr    wcsrchr
                            ^~~~~~~
        /usr/include/wchar.h:161:10: note: candidate function
        wchar_t *wcsrchr(const wchar_t *, wchar_t);
                 ^
        /Applications/Xcode5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/cwchar:186:49: note: candidate function
        inline _LIBCPP_INLINE_VISIBILITY const wchar_t* wcsrchr(const wchar_t* __s, wchar_t __c) {return ::wcsrchr(__s, __c);}
                                                        ^
        

        This is different to the originally reported error, but both cases are triggered by compiling against libc++ instead of libstdc++, so I think it's relevant here.

        The error is a clash between C headers in <wchar.h> and C++ headers in <cwchar>. I guess the libstdc++ headers do some magic to avoid this kind of problem. The patch I posted earlier was the simplest way I could see to resolve the ambiguity, by not bringing the function in question into the global scope from std::. Another possibility could be to change the #defines in tchar.h to specify a namespace?

        I do wonder if there's something not quite right about the error being generated - even this short example won't compile against libc++:

        #include <cwchar>
        using std::wcsrchr;
        int main() {
            wcsrchr(L"foo", L'f');
            return 0;
        }
        

        But I see others have encountered this problem and resolved it similarly: https://qt.gitorious.org/qt/anselmolsm-qttools/commit/bc35938d0d49b04bf98feda3e85da186ecc8184d
        And this seems to suggest that the interaction between the various headers isn't entirely straightforward: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2013-August/031618.html

         

        Last edit: Stephen Drake 2014-07-07
    • Amir Szekely

      Amir Szekely - 2014-07-07

      So are you saying clang actually errors out on this?
      Is it a warning turned into an error?

       
  • Stephen Drake

    Stephen Drake - 2014-07-07

    Yep, I've posted the error above now. The example code fails to compile with just clang++ -stdlib=libc++ -c test.cpp or g++ -nostdinc++ -I/usr/lib/c++/v1/ -c test.cpp.

     
    • Anders

      Anders - 2014-07-07

      What about this:

      #define _tcsrchr ::wcsrchr
      
      // OR
      
      #define _tcsrchr(s,c) ( (wchar_t*) wcsrchr((wchar_t*)(s), (c)) )
      
       
      • Stephen Drake

        Stephen Drake - 2014-07-08

        Yes, both of those compile - as do these variations:

        #define _tcsrchr    std::wcsrchr
        #define _tcsrchr(s,c) ( wcsrchr((wchar_t*)(s), (c)) )
        

        What surprised me is that changing this definition was sufficient by itself - I assumed many similar changes to tchar.h would be required. I take it this only becomes a problem when the signature(s) in cwchar differ from the one in wchar.h?

         
  • Amir Szekely

    Amir Szekely - 2014-10-05
    • status: open --> closed-fixed
    • Group: 2.0 Series --> 3.0 Alpha Series
     
  • Amir Szekely

    Amir Szekely - 2014-10-05

    Anders fixed this with [r6518].
    I don't have Mac OS X to test on, so please re-open if it still doesn't work.

     

    Related

    Commit: [r6518]

    • Stephen Drake

      Stephen Drake - 2014-10-15

      Thanks, I've tested the current trunk [r6557] on both Mac OS X 10.8.5 and 10.9.5 and can confirm that compiling makensis succeeds for:

      scons SKIPUTILS=all STRIP=no makensis
      

      I believe my build enviroments are reasonably standard - on Mac OS X 10.8.5 I have:
      - Xcode 5.1.1
      - default compiler is clang: Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
      - clang -stdlib flag is not set by default (uses libstdc++, same as gcc)

      On Mac OS X 10.9.5 I have:
      - Xcode 6.0.1
      - default compiler is clang: Apple LLVM version 6.0 (clang-600.0.51) (based on LLVM 3.5svn)
      - clang has "-stdlib=libc++" in default flags

      In both cases linking fails without STRIP=no.

      If you have gcc installed, eg from Macports or Homebrew or an old version of Xcode, that works too as of [r6549], eg:

      scons CC=/usr/bin/llvm-gcc-4.2 CXX=/usr/bin/llvm-g++-4.2 SKIPUTILS=all makensis
      
       

      Related

      Commit: [r6549]
      Commit: [r6557]


Log in to post a comment.