Linking separate projects in GHC - haskell

Ok this should be simple, but can't seem to figure this out. I have two projects, ProjectA and ProjectB. ProjectB depends on the old project, ProjectA. Now I want to build ProjectB. And I do not want to change the directory structure for ProjectA now. Problem is, I always used -outputdir bin with ProjectA.
ProjectA looked like this:
ProjectA/
bin/
(*.o, *.hi in proper paths, sometimes also *.p_o and *.p_hi)
Foo/
ModuleX.hs
ModuleA.hs
ModuleB.hs
Now I have a different folder with ProjectB, with its own separate -outputdir. I just need to link to the old project object files (without having ProjectA files recompiled). I realize that I can probably cabalize ProjectA ... but is there no simpler way?

The "simple way" is to use Cabal. Once you've installed Project A, you never need to worry about where the hell it's actually stored ever again; GHC will just find it.
If you don't want to do this, try using the -i switch to GHC to tell what folders to search for your compiled stuff.
http://www.haskell.org/ghc/docs/7.0.1/html/users_guide/separate-compilation.html

Related

packages on a build machine without permanent access to internet

I am in the process of migrating a machine from an older Linux version to a newer one. We have some node projects that seem to be more difficult to transplant to the newly desired setup.
On the old machine the build script from package.json could be run without problems because node_modules is tracked by the source control.
We don't want to use that method anymore since it is not very scalable as we want to make sure we can easily upgrade all the packages for all the users at once without the hassle of putting hundreds of subfolders (from node_modules) together with various resources.
Did you encounter such issues and, if so, how did you manage it?
Can we use a global node_modules somehow to avoid multiple node_modules for each project?
Thank you!
Can we use a global node_modules somehow to avoid multiple node_modules for each project?
There are (at least) three possibilities. Here they are in the order that I would recommend using them:
If Node.js does not find a package in the application's/module's own node_modules directory, it will check in the parent directory (../node_modules) and then that directory's parent directory (../../node_modules) etc. So if all your projects have a shared parent directory, you can put the dependencies in a node_modules directory. See "Loading from node_modules folders" in the Node.js documentation.
A second option is to set the NODE_PATH environment variable to the directory where you would like your projects to search for modules not found elsewhere. See "Loading from the global folders" in the Node.js documentation.
Lastly, it's legacy behavior, but Node.js will also search in three other locations before giving up, so you can use one of those as well: $HOME/.node_modules, $HOME/.node_libraries, and $PREFIX/lib/node. See (again) "Loading from the global folders" for more information.
All that said, please note that the docs also correctly say "It is strongly encouraged to place dependencies in the local node_modules folder. These will be loaded faster, and more reliably."
If you must do this, I would use the first option above and place the node_modules folder as far down in the directory hierarchy as you can.

How to prevent SCons to clean specific part of build tree

My project contains third-party library sources that located in separate directory:
/prj
/src
/app
/lib1
/lib2
/third-party-lib
SConscript
...
SConstruct
Compiling of the third-party-lib is quite long because of large library size. I'm never change the sources of the library and the only case when the library needs to be rebuild is changes of the build options (compiler flags, for example).
To rebuild the project I issue commands:
scons -c && scons
In this case SCons removes all build products including the third-party-lib and subsequent build consumes a significant time due to third-party-lib compiling which, as said above, never changed. Method:
lib = env.StaticLibrary(Target, obj)
env.NoClean(lib)
does not give desired result - this preserves only final library file (lib.a) from clean. I've tried to preserve object files:
obj = env.Object(Sources)
env.NoClean(obj)
but this solves the problem only partially, because some object files compiled implicitly - the library code contains Qt code which processed by Qt meta-object compiler (MOC), therefore these object files do not included in 'obj' list.
Is there a way to prevent such third-part library rebuilding every time when the project rebuild carried out?
The SCons way of doing things would be to not call "scons -c", but only
scons
if you want to rebuild your project.
It is SCons main strength to get all the dependencies (implicit and explicit) right, even for an iterative rebuild where only a handful of files have changed. By using the "-c" option, like you may be used from other build tools like "make", you're shortcutting this feature and creating problems where there would be none usually.
I assume that you're using your "make clean; make all" approach because you haven't properly defined all the dependencies in your project yet. Please do that first, it will help your build in the long run.
And no, there is no method that will prevent "cleaning" for a whole folder and its subdirs.
Use env.Glob(), it will see files which SCons knows about but are not yet created when that logic is run.

How do Happy and Alex bootstrap themselves into being?

The source tree for happy contains AttrGrammarParser.ly and Parser.ly and the source tree for alex contains Scan.x. Yet, as far as I can tell in order to compile happy, we need to transform the .ly files into .lhs files using... happy, and in order to compile alex we need to transform the .x files into .hs files using... alex.
So it seems like there must be some bootstrapping going on here in order to compile either tool.
The Setup.lhs files for each project contain some template expansion, but, as far as I can tell, don't do anything in particular to do the bootstrapping.
How and where is the bootstrapping done?
I see that you are looking at the source tree of the darcs repositories for these packages on darcs.haskell.org. If you look at the actual tarballs on Hackage, you'll see something a bit different:
https://hackage.haskell.org/package/alex-3.1.4/src/dist/build/alex/alex-tmp/
https://hackage.haskell.org/package/happy-1.19.5/src/dist/build/happy/happy-tmp/
So basically the build artifacts necessary are shipped with the Hackage tarball. Cabal then just uses the build artifacts during the build process, thus avoiding the need to bootstrap locally. Cabal also knows how to preserve such build artifacts when you run cabal sdist for your own packages which you want not to depend on happy or alex, but last I checked this doesn't interoperate well with sandboxes, fwiw.
By the way, alex and happy development has moved to github:
https://github.com/simonmar/alex/
https://github.com/simonmar/happy/

How can I compile individual CoffeeScript files in the assets directory?

I have an application built in Brunch.io that builds the main framework into app.js, but in my assets folder I have various small coffeescript scripts that need to be compiled individually, and not merged together into one.
Is there a way to compile the CS first and then move it to the public folder like everything else in assets?
I notice that there are some plugins for doing this exact thing with Jade templates (so you can have .jade files in your assets folder). Would this need to be a new plugin?
If there's no obvious way to do it, is there at least a way to define the config file so that it can watch a different folder and compile each .coffee file to it's own .js file, without either joining them all together, or needing to specify each file in the config?
Since there are no answers, here's the (slightly hacky) way I ended up doing it:
I installed the After-Brunch plugin and added these two commands to my config file, which get run after every compile by Brunch:
plugins:
afterBrunch: [
'find public/ -type f -name "*.coffee" -delete'
'coffee --compile --output public app/assets/'
]
So this simply explicitly deletes the .coffee files that Brunch moved to public/, and then compiles all the .coffee files in assets/ and moves them to public/. Hacky but it works fine.
This annoyingly feels quite backwards: it would have felt much cleaner (even if only in my head) to compile those .coffee files that were already moved into public/ by Brunch, but Coffee doesn't have an in-place conversion option (i.e. replacing the files) that I know of, and running the converter on the files in public/ first and then deleting all *.coffee files didn't work, because the delete command executed before the compile command was finished... But again, this distinction is probably just in my head -- it's just as efficient doing it this way.
If anyone has a more Brunch-like solution, that would be great.

Output the binaries in the project's root bin subfolder using cmake

I'm currently on a BF interpreter project. I decided to use CMake, and it works properly.
I settled for an out-of-source build, following the following tree :
+ Project root
|
+-- src/
+-- bin/
+-- build/ <- holds the "rubbish" generated by CMake when generating the Makefile
+-- CMakeLists.txt
When I want to build the project, I run, from the project's root folder :
cd build
cmake ..
make
In the CMakeLists.txt, I added the following line :
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
But, I've found it outputs the binaries in the build/bin folder, so I edited the line to :
SET(EXECUTABLE_OUTPUT_PATH "../bin/"
It works perfectly fine, but it is, IMHO, kind of ugly. Is there any "clean" way of doing this, that is without making assumptions about the project's structure, instead using something like set(EXECUTABLE_OUTPUT_PATH ${PROJECT_ROOT}/bin") ?
Thanks in advance for your replies and sorry for any English errors i may have made, as English isn't my first language.
You can set the variable CMAKE_RUNTIME_OUTPUT_DIRECTORY to achieve this - something like:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
Basically, the ${PROJECT_ROOT} variable you are looking for is PROJECT_SOURCE_DIR, CMAKE_SOURCE_DIR, or CMAKE_CURRENT_SOURCE_DIR. Each has a slightly different meaning, but for a basic project, these could well all point to the same directory.
Note that for the CMAKE_RUNTIME_OUTPUT_DIRECTORY variable to take effect, it must be set before the target is created, i.e. before the add_executable call in the CMakeLists.txt.
Also note that multi-configuration generators like MSVC will still append a per-configuration directory to this project root/bin folder.

Resources