I want to use api-easy to test my REST app. I have it in the dependences inside the package.json, so when I run npm install it's installed in ./node_modules
I'm trying to add the api-easy to the path like
this question.
Since I'm using a Makefile I have this:
test:
#PATH="./node_modules/api-easy/node_modules/.bin:$PATH"
#echo $PATH
vows
#node ./test/tests.js
Note: api-easy depends on vows
The PATH var in not being updated, when I do the echo it returns me "ATH"(not the value), and then the command vows in not found.
How can I set properly the PATH in a Makefile?
In a make recipe, each command is executed as a separate process, so setting an environment variable in one command will not affect the others. To do what you want, you need to make sure all the related commands run in a single instance of the shell, where environment variables are passed as you would expect:
test:
#PATH="./node_modules/api-easy/node_modules/.bin:$$PATH"; \
echo $$PATH; \
vows; \
node ./test/tests.js
The trailing backslash tells make to concatenate a line with the one that follows it. Note also that you need to quote $ characters if you want them interpreted by the shell. Hence the $$.
I think something like this should do it:
export PATH="./node_modules/api-easy/node_modules/.bin:$PATH"
test:
vows
#node ./test/tests.js
Related
Normally in node files I just put
#!/usr/bin/env node
at the top and make it executable to create a file that can be run from a bash terminal. However if I do that in a Typescript file, the compiler says "error TS1001: Unexpected character "#"" and refuses to compile it. So how can I make a shell executable node file with Typescript?
See https://github.com/Microsoft/TypeScript/blob/master/bin/tsc for an example. Basically have a dummy file without the .js extension and just require the actual .js file.
E.g. In file named tsc:
#!/usr/bin/env node
require('./tsc.js')
You were right to report the bug to Microsoft, and they were wrong to close it as wontfix.
Until it is fixed, here's a workaround. Paste the following into a text file and save it as shebangify:
#!/usr/bin/env node
var fs = require('fs');
var path = process.argv[2];
var data = "#!/usr/bin/env node\n\n";
data += fs.readFileSync(path);
fs.writeFileSync(path, data);
(N.B. To keep this answer concise, the code above doesn't have any error-checking or other refinements, so use at your own risk or use this instead. Also, see this SO question for more info about prepending to files.)
Make the file executable with by using a terminal to navigate to the file's directory and executing:
$ chmod +x shebangify
Once you have created a Typescript program (e.g. called myscript.ts) that you wish to compile and turn into a shell script (e.g. called myscript), do so by executing a sequence along these lines in your terminal:
$ tsc --out myscript myscript.ts ; ./shebangify myscript ; chmod +x myscript
If you have TypeScript and ts-node installed globally:
npm install typescript ts-node -g
You can now easily do this with:
#!/usr/bin/env ts-node
console.log('Hello world')
I don't have enough reputation points to post a comment, but I'd just thought it'd be good for everyone to know that I opened a new issue on GitHub since that's what the Typescript devs are using to track things like this: https://github.com/Microsoft/TypeScript/issues/2749 .
In case anyone is still struggling with making it work, the ts file should start with #! node instead of #!/usr/bin/env node, and tsc will take care of the rest.
I've never been able to get ts-node to work, so I finally made my own way to write shell scripts in TypeScript. If there were a package manager for Bash I would make a package, but there isn't, so I just put this script in my path as ts-exec:
#!/usr/bin/env bash
file_to_run="$1"
basename=`basename "$1"`
tmp_prefix=`basename "$BASH_SOURCE"`
TMPDIR=`mktemp -d -t "$tmp_prefix-XXXXXXXXXX"`
pushd "$TMPDIR" > /dev/null
cp "$1" "$basename.ts"
tsc "$basename"
node "$basename.js"
popd > /dev/null
rm -rf "$TMPDIR"
And now I can do things like this:
#!/usr/bin/env ts-exec
let greeting: string = "Hello World!";
console.log( greeting );
And it works.
Of course, it does have some limitations
It's only suitable for scripts that are confined to a single file
It doesn't do any error checking
It has implicit dependencies
It doesn't have an installer
... so basically it's for bash nerds who want to use TypeScript for small scripts that would be a pain to write as Bash scripts. I'm still baffled that ts-node doesn't cover this case, and I'd rather not have to futz with temp files that might get left behind and waste space if there's an error, but so far this covers my use-case. (Besides, I've got that cronjob that deletes everything in ~/tmp that's more than 31622400 seconds old every night, so stray temp files can't eat my whole system.)
As of ts-node v8.9.0 it seems like the recommended way to do this is with the following:
#!/usr/bin/env ts-node-script
If you don't want to install TS and ts-node globally and want to make the script runnable by the file path directly, create a file for example cli.ts next to local node_modules and put this as the first line
#!/usr/bin/env ./node_modules/.bin/ts-node
console.log('Wow');
Then execute by calling ./cli.ts
I am trying to add ld_library_path via cmake.
What I have done so far is
add_custom_command(TARGET ${target}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${target}> ${PROJECT_BINARY_DIR}/bin
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND $<TARGET_FILE:${target}>
################ ENV Set here ####################
-E env "LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:${PROJECT_SOURCE_DIR}/boost_linux/lib"
COMMENT "Running Tests Now .. " VERBATIM
)
But I am still getting linking error during runtime. Does any one know how to properly link lib path.
In bash it would be like
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/path/to/lib
It's not clear what exactly you're trying to achieve and how it is related to a linking error. But the way you run commands with custom environment variables is the following:
add_custom_command(
...
COMMAND ${CMAKE_COMMAND} -E env "LD_LIBRARY_PATH=..."
actual command line that you need to execute
)
So, -E env works such that it executes whatever is passed after env variable specification.
Note, however, that you cannot use multiple COMMAND arguments and set env in the first one while using it in the following COMMANDs - it won't work. Or, at least, it is generator-dependent. With Make backend this is translated into multiple calls to shell - so it sets the env but the rest of commands are executed separately and don't see it. Ninja generator translates multiple COMMANDs into something like cmd1 && cmd2 && ... so it works there, AFAIK.
Normally in node files I just put
#!/usr/bin/env node
at the top and make it executable to create a file that can be run from a bash terminal. However if I do that in a Typescript file, the compiler says "error TS1001: Unexpected character "#"" and refuses to compile it. So how can I make a shell executable node file with Typescript?
See https://github.com/Microsoft/TypeScript/blob/master/bin/tsc for an example. Basically have a dummy file without the .js extension and just require the actual .js file.
E.g. In file named tsc:
#!/usr/bin/env node
require('./tsc.js')
You were right to report the bug to Microsoft, and they were wrong to close it as wontfix.
Until it is fixed, here's a workaround. Paste the following into a text file and save it as shebangify:
#!/usr/bin/env node
var fs = require('fs');
var path = process.argv[2];
var data = "#!/usr/bin/env node\n\n";
data += fs.readFileSync(path);
fs.writeFileSync(path, data);
(N.B. To keep this answer concise, the code above doesn't have any error-checking or other refinements, so use at your own risk or use this instead. Also, see this SO question for more info about prepending to files.)
Make the file executable with by using a terminal to navigate to the file's directory and executing:
$ chmod +x shebangify
Once you have created a Typescript program (e.g. called myscript.ts) that you wish to compile and turn into a shell script (e.g. called myscript), do so by executing a sequence along these lines in your terminal:
$ tsc --out myscript myscript.ts ; ./shebangify myscript ; chmod +x myscript
If you have TypeScript and ts-node installed globally:
npm install typescript ts-node -g
You can now easily do this with:
#!/usr/bin/env ts-node
console.log('Hello world')
I don't have enough reputation points to post a comment, but I'd just thought it'd be good for everyone to know that I opened a new issue on GitHub since that's what the Typescript devs are using to track things like this: https://github.com/Microsoft/TypeScript/issues/2749 .
In case anyone is still struggling with making it work, the ts file should start with #! node instead of #!/usr/bin/env node, and tsc will take care of the rest.
I've never been able to get ts-node to work, so I finally made my own way to write shell scripts in TypeScript. If there were a package manager for Bash I would make a package, but there isn't, so I just put this script in my path as ts-exec:
#!/usr/bin/env bash
file_to_run="$1"
basename=`basename "$1"`
tmp_prefix=`basename "$BASH_SOURCE"`
TMPDIR=`mktemp -d -t "$tmp_prefix-XXXXXXXXXX"`
pushd "$TMPDIR" > /dev/null
cp "$1" "$basename.ts"
tsc "$basename"
node "$basename.js"
popd > /dev/null
rm -rf "$TMPDIR"
And now I can do things like this:
#!/usr/bin/env ts-exec
let greeting: string = "Hello World!";
console.log( greeting );
And it works.
Of course, it does have some limitations
It's only suitable for scripts that are confined to a single file
It doesn't do any error checking
It has implicit dependencies
It doesn't have an installer
... so basically it's for bash nerds who want to use TypeScript for small scripts that would be a pain to write as Bash scripts. I'm still baffled that ts-node doesn't cover this case, and I'd rather not have to futz with temp files that might get left behind and waste space if there's an error, but so far this covers my use-case. (Besides, I've got that cronjob that deletes everything in ~/tmp that's more than 31622400 seconds old every night, so stray temp files can't eat my whole system.)
As of ts-node v8.9.0 it seems like the recommended way to do this is with the following:
#!/usr/bin/env ts-node-script
If you don't want to install TS and ts-node globally and want to make the script runnable by the file path directly, create a file for example cli.ts next to local node_modules and put this as the first line
#!/usr/bin/env ./node_modules/.bin/ts-node
console.log('Wow');
Then execute by calling ./cli.ts
I want to write a Makefile which would run tests. Test are in a directory './tests' and executable files to be tested are in the directory './bin'.
When I run the tests, they don't see the exec files, as the directory ./bin is not in the $PATH.
When I do something like this:
EXPORT PATH=bin:$PATH
make test
everything works. However I need to change the $PATH in the Makefile.
Simple Makefile content:
test all:
PATH=bin:${PATH}
#echo $(PATH)
x
It prints the path correctly, however it doesn't find the file x.
When I do this manually:
$ export PATH=bin:$PATH
$ x
everything is OK then.
How could I change the $PATH in the Makefile?
Did you try export directive of Make itself (assuming that you use GNU Make)?
export PATH := bin:$(PATH)
test all:
x
Also, there is a bug in you example:
test all:
PATH=bin:${PATH}
#echo $(PATH)
x
First, the value being echoed is an expansion of PATH variable performed by Make, not the shell. If it prints the expected value then, I guess, you've set PATH variable somewhere earlier in your Makefile, or in a shell that invoked Make. To prevent such behavior you should escape dollars:
test all:
PATH=bin:$$PATH
#echo $$PATH
x
Second, in any case this won't work because Make executes each line of the recipe in a separate shell. This can be changed by writing the recipe in a single line:
test all:
export PATH=bin:$$PATH; echo $$PATH; x
By design make parser executes lines in a separate shell invocations, that's why changing variable (e.g. PATH) in one line, the change may not be applied for the next lines (see this post).
One way to workaround this problem, is to convert multiple commands into a single line (separated by ;), or use One Shell special target (.ONESHELL, as of GNU Make 3.82).
Alternatively you can provide PATH variable at the time when shell is invoked. For example:
PATH := $(PATH):$(PWD)/bin:/my/other/path
SHELL := env PATH=$(PATH) /bin/bash
Path changes appear to be persistent if you set the SHELL variable in your makefile first:
SHELL := /bin/bash
PATH := bin:$(PATH)
test all:
x
I don't know if this is desired behavior or not.
What I usually do is supply the path to the executable explicitly:
EXE=./bin/
...
test all:
$(EXE)x
I also use this technique to run non-native binaries under an emulator like QEMU if I'm cross compiling:
EXE = qemu-mips ./bin/
If make is using the sh shell, this should work:
test all:
PATH=bin:$PATH x
To set the PATH variable, within the Makefile only, use something like:
PATH := $(PATH):/my/dir
test:
#echo my new PATH = $(PATH)
I am trying to use setenv variable in my makefile but when I execute my make file it gives setenv: command not found.
How can I use it?
Actually I wanted to run a shell script which sets multiple environment variables.
Since the list is very huge I dont have an option except to use the scripts. I cant set them manually like
abcd:= /xx/yy/zz
Please suggest.
P.S. the same command
setenv xxx yyy works very well in shell
it just fails when I use in makefile directly or makefile with a script having this command.
'
Why do not you use export command ?
Running the script to set the environment variable will not work as the shell run a separate process & will not reflect in your current shell. You will need to source the shell script. You can use source or . based on your shell. Following is a sample for your reference where setvar.sh sets a variable & print.sh prints it; in the Makefile (mkfile) setvar.sh is being sourced using .
$ cat setvar.sh
export TEST=ABC
$ cat print.sh
echo $TEST
$ cat mkfile
test:
. ./setvar.sh && ./print.sh
.SILENT:test
$ make -f mkfile
ABC
You can also include I guess for example,
$ cat mkfile2
include setvar.sh
test:
./print.sh
.SILENT:test
$ make -f mkfile2
ABC
Hope this helps!
Look at
make -e
and Communicating Variables to a Sub-make
I think setenv is not a builtin to the sh shell. If you are using GNU Make that is the default shell used. In your situation you probably want to use a different shell, like bash. You do this by setting the SHELL variable in the makefile to what you want like:
SHELL := /usr/bin/bash
For more information checkout this section of the GNU Make manual. It details the different behavior of the SHELL variable and how it is, or isn't inherited from the shell make is invoked from on different platforms.
EDIT: I agree with the implication of the other posters that you are probably not setting enviroment variables the way you think you should be and would not be using the setenv command at. I am just responding to your original question. To learn about variables in make files checkout these other sections in the GNU Make manual.
export MY_VAR := "/package/your_path"