I want to be able to do the POSIX build of NSIS outside of the source tree (and with the source tree being read-only), using SCons' --srcdir=DIR option. Only a few tweaks were needed to get this working, and they may be found in the attached patch.
(Note: This is the first time I've ever worked with SCons, so the patch might be doing some things less than 100% correctly. Please review with care.)
Patch against NSIS SVN
CR (cared review):
* To add include folders, you should be appending to CPPPATH instead of adding -I directly as that won't work on all compilers.
* SKIPPLUGINS doesn't mean all of the plug-ins won't be built, just a few. Why cancel cross-compile for that anyway?
* The whole exehead thing bugs me. Shouldn't it know alone you're using files from there? Surely something else is wrong if you need to do that.
I didn't know that feature of scons. What are you using it for? Does the fink build system require this?
* Okay, I wasn't aware of CPPPATH. That looks good.
* I added the logic to skip the cross_env() call to get around the following error:
Using GNU tools configuration
EnvironmentError: No tool named 'crossmingw': not a Zip file:
File "/tmp/nsis-2.42-src/SConstruct", line 347:
envs = SConscript('SCons/Config/gnu')
File "/tmp/scons-local/scons-local-1.2.0/SCons/Script/SConscript.py", line 612:
return apply(method, args, kw)
File "/tmp/scons-local/scons-local-1.2.0/SCons/Script/SConscript.py", line 549:
return apply(_SConscript, [self.fs,] + files, subst_kw)
File "/tmp/scons-local/scons-local-1.2.0/SCons/Script/SConscript.py", line 259:
exec _file_ in call_stack[-1].globals
File "/tmp/nsis-2.42-src/SCons/Config/gnu", line 67:
cross_env(stub_env)
File "/tmp/nsis-2.42-src/SCons/Config/gnu", line 13:
env.Tool('crossmingw', toolpath = ['../Tools'])
File "/tmp/scons-local/scons-local-1.2.0/SCons/Environment.py", line 1675:
tool = apply(SCons.Tool.Tool, (tool, toolpath), kw)
File "/tmp/scons-local/scons-local-1.2.0/SCons/Tool/__init__.py", line 95:
module = self._tool_module()
File "/tmp/scons-local/scons-local-1.2.0/SCons/Tool/__init__.py", line 155:
raise SCons.Errors.EnvironmentError, m
I didn't know what was going on there, and didn't investigate too much, since I wasn't doing any cross-compiling anyway. I just figured, "hey, I told the build system to skip all the cross-built stuff, so maybe it shouldn't even be making this call in the first place."
(I do see that cross_env() works correctly when you build inside the source tree, so this would appear to be a separate, albeit related, bug.)
* Re exehead: When you #include"sconf.h", the compiler searches for sconf.h in the same directory as the requesting file. This is why config.h could find the file before. Now, however, sconf.h is being written to $top_builddir/Source/exehead/, not necessarily $top_srcdir/Source/exehead/. config.h is present in the latter, so the #include"" no longer works. That has to be changed to #include<>, and because the exehead/ directory is no longer being implied to the compiler, the -Iexehead is needed.
It comes down to the subtle difference between #include"" and #include<>. Most of the time, it doesn't matter, but out-of-source-tree builds are one of the cases where it can bite you.
Out-of-source-tree builds in general aren't what I would call a "feature" of SCons, so much as a standard convention supported by good build systems. GNU Autotools, for example, has always had this---you can do e.g.
mkdir /tmp/build-foo
cd /tmp/build-foo
/nfs-readonly/src/foo-1.2.3/configure --prefix=/opt/foo
make
make install
I wanted this, as the company where I work uses a system somewhat like the above to deploy software. The unpacked source tree is served up via a read-only NFS mount, and various clients then build it. Aside from that, this is also useful when you're working out of version control, because then the build doesn't add all these non-version-controlled files/directories to the source tree. (Also in my case, my company home directory is served via a network filesystem; I don't want to push compiled objects and binaries through the network!)
It seems SCons is looking for crossmingw.py in your build directory as it seems to say it doesn't even find the file. Maybe replacing toolpath in the Tool() call would fix that.
As for the include paths, I don't really like the current solution. Maybe we can tweak it by adding a completely different include folder that would have a subfolder called nsis_generated or something similar and in that folder put all the generated files. Then the #include lines would be a bit more rational and won't have the chance of conflicting with common header file names like defines.h.
The env.Tool() call should probably end up looking something like
env.Tool(srcdir + '/crossmingw', toolpath = [srcdir + '/SCons/Tools', '../Tools'])
(where srcdir would be '.' when building inside the source tree). I don't know what variables the SCons environment provides, however (and the docs don't make clear what to do---there's the "repository" variable, but this appears to be a *list* of repository directories), or what if any functions should be used (along the lines of prependDirIfRelative()). You know more about that business than I do :-]
As for the issue with generic-ish header filenames... why not just have nsis-defines.h or nsis_version.h or the like? Subfolders would help, too, but then you have an extra level or two in the directory hierarchy for no other reason than this.
I propose this patch instead:
http://bonedaddy.net/pabs3/files/tmp/0001-fix-bug-2497148-allow-out-of-tree-builds-on-POSIX.patch
It uses CPPPATH.
It uses scons File.rfile and Dir.rdir to work out where to find SCons/Tools and linker_script are.
It uses nsis-defines.h, nsis-sconf.h & nsis-version.h instead of defines.h, sconf.h & version.h.
I've tested a full out-of-tree build (inc building docs and cross-compiling stubs/plugins/utils etc) with it and I get no errors. It also causes no regressions with normal in-tree builds.
There was one weird failure where it couldn't find halibut with the oot build because the built halibut was in the source tree but not in the build tree. Also fixed this using rfile.
There is a similar thing with PREFIX_DEST and InstallAs, but I'm not sure how to fix that.
BTW, I'll setup my test build stuff to always run things oot so I'll catch issues in the future.
Paul, I tried your patch, and the POSIX build works swimmingly on three platforms here (Solaris, MacOS X, Linux). Building out-of-tree regularly is excellent as well. You'll get no arguments from me :-)
Fixed in SVN r5921. Thanks for your patch.