SCONS run target - scons

I've been looking, and looking, and I can't find an answer to my question.
I've just started learning scons tonight, and it looks awesome! I'm running into a little confusion though.
For ease of development, I often like to have my make file build my target, and then run it so that I can test a change with one keystroke. This is very simple in a make file:
run: $(exe)
chmod a+x $(exe)
$(exe)
I have figured out that I can do it using subprocess like so:
import subprocess import os.path
env = Environment();
result = env.Program(target = "FOO", source = "BAR");
location = os.path.abspath(result[0].name)
subprocess.call([location])
But there's a problem with this solution. As far as I have experimented, scons won't wait until your program is finished building before it starts the subprocess call, so you end up running the old executable, or having an error if it's a build after a clean.

What you do in your scons file is a typical beginner error in scons. Your assume that you are writing a script for building your project.
Scons doesn't work like that. The scons files is a script that add targets to the project. This is done through python, and the various objects allows you to create and manipulate targets until the script is done. First then will the project start building.
What you do in your code is to describe the Environment to use, the Program to create, and after that you call a subprocess that runs some program. After this the project will start building - no wonder the old executable is run, the new one haven't started to be built yet.
What you should do is to use a custom builder for executing the program.
env = Environment() #construct your environment
files = "test.cpp" #env.Glob or list some files
#now we create some targets
program = env.Program("test",files) #create the target *program*
execution = env.Command(None,None,"./test") #create the execution target (No input & output
Depends(execution,program) #tell scons that execution depends on program
#there might be a way to get SCons to figure out this dependency itself
#now the script is completed, so the targets are built
Here the dependencies are clear, the program must be built before the execution is done, and it will

I may be a little bit late for you, but I have this solution using Alias.
By using the following command, it will build and run the program:
$ scons run
# Define the different target output
program = env.Program('build/output', Glob('build/test/*.cpp'))
env.Default(program)
env.Alias('run', program, program[0].abspath)
note that we use the abspath, so it can be cross platform win/linux (for linux you need to add the "./" before the program name if your PATH is not correctly set.

Ok, I'm a little nervous to answer my own question, but I found a more or less acceptable solution.
I have just set up a simple chain.
I set up a Makefile with something like this in it:
run:
scons -s
./name_of_executable
This calls scons in silent mode, and runs your program automatically afterwards. It's not a scons-only solution, but it works. I'd still be interested to see if anyone has another answer.
Thanks!
Murphy

Related

Set linker search path for build in CMake

It seems this question has been asked very often before but none of the solutions seem to apply in my case.
I'm in a CMake/Linux environment and have to run an executable binary during the build step (protoc in particular).
This binary needs a library but it's not installed (and cannot be) in the in the standard directories like /usr, so the library cannot be found.
Unfortunately I cannot manipulate the protoc call because it's embedded in a 3rd party script.
I can now set LD_LIBRARY_PATH before every make or set it system wide but this is very inconvenient especially when it comes to IDEs in which the build takes place or distributed build scenarios with continuous build environments.
I tried to set LD_LIBRARY_PATH via
set(ENV{LD_LIBRARY_PATH} "/path/to/library/dir")
but this seems to have no effect during the build step.
So my question is: can I set a library search path in CMake which is used during the build?
Try this
SET(ENV{LD_LIBRARY_PATH} "/path/to/library/dir:$ENV{LD_LIBRARY_PATH}")
I also used this dirty trick to temporary change some environment variables:
LD_LIBRARY_PATH="/path/to/library/dir:$LD_LIBRARY_PATH" cmake ...
After execution of this line LD_LIBRARY_PATH is not changed in the current shell.
Also, I do not find it bad to change LD_LIBRARY_PATH before invoking cmake:
export LD_LIBRARY_PATH=...
It won't change anything system-wide, but it would be used for your current shell, current build process. The same holds for CI builds. You can save the variable and restore it after cmake invocation:
MY_LD=$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=...
cmake...
export LD_LIBRARY_PATH=$MY_LD
I have recently run into a somewhat similar problem.
My solution was to incorporate sourcing a file that set the appropriate environment into every command.
For example, this custom command:
add_custom_command(
OUTPUT some_output
COMMAND some_command
ARGS some_args
DEPENDS some_dependencies
COMMENT "Running some_command some_args to produce some_output"
)
Would become:
set(my_some_command_with_environment "source my_environment_script.sh && some_command")
add_custom_command(
OUTPUT some_output
COMMAND bash
ARGS -c "${my_some_command_with_environment} some_args"
DEPENDS some_dependencies
COMMENT "Running some_command some_args to produce some_output"
VERBATIM
)
Obviously, this has some disadvantages:
It relies on a bash shell being available.
It sources the environment script for every command invocation (performance issue) and you will have to change all invocations of commands that rely on that environment variables.
It changes the normal syntax of having the command follow COMMAND and the arguments follow ARGS, as now the 'real' command is part of the ARGS.
My CMake-Fu has proven insufficient to find a syntactically nicer way of doing this, but maybe somebody can comment a nicer way.
I had a similar issue for an executable provided by a third party library. The binary was linked against a library not provided by the distribution but the required library was included in the libs directory of the third party library.
So running LD_LIBRARY_PATH=/path/to/thirdparty/lib /path/to/thirdparty/bin/executable worked. But the package config script didn't set up the executable to search /path/to/thirdparty/lib for the runtime dependent so CMake would complain when CMake tried to run the executable.
I got around this by configuring a bootstrap script and replacing the IMPORTED_LOCATION property with the configured bootstrapping script.
_thirdpartyExe.in
#!/bin/bash
LD_LIBRARY_PATH=#_thirdpartyLibs# #_thirdpartyExe_LOCATION# "$#"
CMakeLists.txt
find_package(ThirdPartyLib)
get_target_property(_component ThirdPartyLib::component LOCATION)
get_filename_component(_thirdpartyLibs ${_component} DIRECTORY)
get_target_property(_thirdpartyExe_LOCATION ThirdPartyLib::exe IMPORTED_LOCATION)
configure_file(
${CMAKE_CURRENT_LIST_DIR} _thirdpartyExe.in
${CMAKE_BINARY_DIR}/thirdpartyExeWrapper #ONLY
)
set_target_properties(ThirdPartyLib::exe PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/thirdpartyExeWrapper)
Honestly I view this as a hack and temporary stop gap until I fix the third party library itself. But as far as I've tried this seems to work on all the IDE's I've thrown at it, Eclipse, VSCode, Ninja, QtCreator, ... etc

Scons - Invoking a command only when a flag is given

I made a Python script that runs whenever the main binary is changed (using Requires), so at the moment it runs with every build. However, the script can be time consuming in certain cases, and I'm trying to figure out how to run it only if a flag is given.
For example, if I type "scons -script" the script will run after the compilation of the main binary, but typing "scons" will just build the file and do nothing beyond that.
I ended up solving it by using AddOption() to define the flag:
AddOption("--script", action="store_true", help="Run the script")
And writing a method that checks the flag using GetOption() and adds the script to the requirements:
if GetOption("script"):
script = Command(target=...,
source=...,
action=[...])
Requires(script, binary_node)

Can I tell FIND_LIBRARY to run after my *custom* dependency has been built?

[Note: This is ALMOST a duplicate of Linking to a library that hasn't been built yet with CMake, but in this case the unbuilt library is coming from an ADD_CUSTOM_TARGET rather than an ADD_LIBRARY, so CMake can't work its usual magic so effectively.]
One of my CMake 2.8 projects currently has the following code:
# the COMMAND was heavily simplified but you get the idea
ADD_CUSTOM_TARGET(custom_breakpad_target ALL
COMMAND cd ${CMAKE_SOURCE_DIR}/google-breakpad && make
)
# now here we are in the root "CMakeLists.txt"
LINK_DIRECTORIES(${CMAKE_SOURCE_DIR}/google-breakpad/src/client/linux)
ADD_EXECUTABLE(hello)
# ...many lines of code...
ADD_DEPENDENCIES(hello custom_breakpad_target)
TARGET_LINK_LIBRARIES(hello breakpad)
I know that LINK_DIRECTORIES has been deprecated (or at least disdained) because of its weird placement (it has to go before ADD_EXECUTABLE even though we'd really like to put it down next to the TARGET_LINK_LIBRARIES). Also, there's this nifty new command FIND_LIBRARY. So I'd like to write the root "CMakeLists.txt" more like this:
ADD_EXECUTABLE(hello)
# ...many lines of code...
ADD_DEPENDENCIES(hello custom_breakpad_target)
FIND_LIBRARY(breakpad breakpad ${CMAKE_SOURCE_DIR}/google-breakpad/src/client/linux)
TARGET_LINK_LIBRARIES(hello breakpad)
This code works fine... until I "make clean". The next rebuild fails to find breakpad, because it has been rm'ed and not created again yet by the time the FIND_LIBRARY runs.
How can I make this work? or make something work that's more elegant than what I've got?
So far, the best I've got is
ADD_EXECUTABLE(hello)
# ...many lines of code...
ADD_DEPENDENCIES(hello custom_breakpad_target)
TARGET_LINK_LIBRARIES(hello ${CMAKE_SOURCE_DIR}/google-breakpad/src/client/linux/libbreakpad_client.a)
This has the aesthetic disadvantage of having to explicitly write out the "libxxx.a" filename, whereas, as I understand it, FIND_LIBRARY would uncomplainingly continue to work even if we switched to "libxxx.1.so".
Building external targets through custom commands is very difficult to get right. CMake offers the ExternalProject module to assist with that.
With this module external libraries get build at CMake configure time - that is when running cmake for the first time and not when running make to build your actual project. This has the advantage that all of the files are already in place when configuring your project, so it is easy to locate them using a find script or a CMake configure file.
This approach of course only makes sense if the external library does not change frequently, because rebuilding the library requires running CMake again. If you need to recompile the external library upon changes by just running make, the best way to make it work is still to write a full-fledged CMakeLists.txt for it and pull that in with add_subdirectory.

Haskell "Could not find module ---" Quipper

I am extremely new to haskell and I have been searching all over the web but I haven't been able to solve my problem. I downloaded the Quipper package but I have not been able to get haskell to recognize where all of the modules and files are and how to properly link everything.
I have downloaded all of the files and programs and installed them properly, I just dont know how to get haskell to recognize the quipper libraries and templates. Evey time I try:
:load And_gate.hs or some other file.
I get:
Could not find module "Quipper" or its respective modules it requires.
I don't think it is an error or anything, I think it is just my lack of knowledge on how haskell works.
I'm using windows 7.
So I emailed Peter Selinger, one of the professors who created Quipper.
The only thing I need to do extra was inside MSYS:
ghci -iC:/quipper -iC:/quipper/quipper
This complies everything correctly and the files run properly.
Here is his email to me:
Dear -----,
thanks for writing. Let me see if I can help.
Are you following the instructions in the README file? Under "Building
the various algorithms and programs", the instruction is to run
"make". This would build all of the tests in the "tests" directory
automatically.
Next, to compile a Quipper program, you should use the "quipper"
script that is located in quipper/scripts. It works just like "ghc",
except that it automatically includes the correct directories for
Quipper's files in the search path. On Windows, you would be using
"quipper.bat".
Quipper is not really meant to be run interactively, i.e., from ghci.
However, if you do need to run Quipper interactively, I recommend
using the "quipperi" script, also in quipper/scripts. This too would
set the load paths correctly. In Windows, use "quipperi.bat".
Finally, if you need to include Quipper stuff from ghci, but for some
reason can't or don't want to use the quipperi script, you need to
specify those directories with the "-i" option, for example
ghci -iC:/quipper -iC:/quipper/quipper
It could be that in Windows, you need to use "\" instead of "/", but I
am not sure if this is necessary.
I hope this helps, -- Peter
When compiling and exe with ghc just make sure you include the commands:
-iC:/quipper -iC:/quipper/quipper.
If you use the quipper script as suggested by Professor Selinger, inside of MSYS do the following:
Navigate to the folder in which all of the Quipper files are held, this was my case:
cd C:/quipper/quipper/scripts
Then type quipper and your file's location in MSYS to compile an exe like so:
quipper C:/quipper/tests/And_gate.hs
The file will compile and should print updates like so:
[1 of 22] Compiling Libraries.Typeable (......
[2 of 22] Compiling Libraries.Tuple (......
and so on.
The exe (in this case And_gate.exe) will be inside the folder it was compiled from (C:/quipper/tests). You'll need to move it to a folder that contains the acroread.bat which comes in quipper/scripts for it to work properly.
For some reason, this code isn't packaged as a standard Haskell package. It if were, installing it would be fairly simple. As it is, the instructions in the README file look awful (especially under Windows, where it looks like you need MSYS to run the makefile).
Your problem might be as simple as telling GHCi which folder to look in to find the files; you can do that using the :cd command. Since you're on Windows, I'd suggest trying WinGHCi, which should allow you to browse to the right folder using the GUI.
If it isn't that simple... really, as a Haskell beginner, you're probably going to struggle to get this working. The documentation looks pretty minimal.
If you red both README and INSTALLING.windows and did everything as well, then you should add a path to Quipper's script folder to environment variable. Here is the path:
quipper-*/quipper/scripts/
where quipper-* is a <distribution name>-<version>.
There are two important scripts in that folder. The first one is quipper.bat which runs a ghc compiler to run Quipper's modules. The second one is quipperi.bat which is a ghci analogue for Quipper.
Now, when you added a path to variable, you can run And_gate.hs in Quipper's interpreter as follows:
quipperi And_gate.hs

How to determine the directory in which a running Haskell script or application lives?

I have a Haskell script that runs via a shebang line making use of the runhaskell utility. E.g...
#! /usr/bin/env runhaskell
module Main where
main = do { ... }
Now, I'd like to be able to determine the directory in which that script resides from within the script, itself. So, if the script lives in /home/me/my-haskell-app/script.hs, I should be able to run it from anywhere, using a relative or absolute path, and it should know it's located in the /home/me/my-haskell-app/ directory.
I thought the functionality available in the System.Environment module might be able to help, but it fell a little short. getProgName did not seem to provide useful file-path information. I found that the environment variable _ (that's an underscore) would sometimes contain the path to the script, as it was invoked; however, as soon as the script is invoked via some other program or parent script, that environment variable seems to lose its value (and I am needing to invoke my Haskell script from another, parent application).
Also useful-to-know would be whether I can determine the directory in which a pre-compiled Haskell executable lives, using the same technique or otherwise.
As I understand it, this is historically tricky in *nix. There are libraries for some languages to provide this behavior, including FindBin for Haskell:
http://hackage.haskell.org/package/FindBin
I'm not sure what this will report with a script though. Probably the location of the binary that runhaskell compiled just prior to executing it.
Also, for compiled Haskell projects, the Cabal build system provides data-dir and data-files and the corresponding generated Paths_<yourproject>.hs for locating installed files for your project at runtime.
http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#paths-module
There is a FindBin package which seems to suit your needs and it also works for compiled programs.
For compiled executables, In GHC 7.6 or later you can use System.Environment.getExecutablePath.
getExecutablePath :: IO FilePathSource
Returns the absolute pathname of the current executable.
Note that for scripts and interactive sessions, this is the path to the
interpreter (e.g. ghci.)
There is executable-path which worked with my runghc script. FindBin didn't work for me as it returned my current directory instead of the script dir.
I could not find a way to determine script path from Haskell (which is a real pity IMHO). However, as a workaround, you can wrap your Haskell script inside a shell script:
#!/bin/sh
SCRIPT_DIR=`dirname $0`
runhaskell <<EOF
main = putStrLn "My script is in \"$SCRIPT_DIR\""
EOF

Resources