My makefile contains a target for node_modules directory, which depends on package.json file:
node_modules: package.json
npm install && touch "$#"
My current project happens to have a "sub-package" with its own set of dependencies. I modify the target above to the following:
%/node_modules: %/package.json
cd $(shell dirname "$<") && npm install && touch node_modules
Now, I can do make path/to/subpackage/node_modules and make runs the expected npm install command. However, I no longer seem to be able to do make node_modules - make exits with status code 0 and message Nothing to be done for 'node_modules'.
This indicates make will now only run the appropriate command for node_modules folders which exist within a subdirectory.
How can I change the target so that it supports both nested and root node_modules directories within the same target?
In other words, I would like to remove the duplicated target definition because the command to make the root's node_modules directory is the same as the command to make the nested path/to/node_modules directory.
As research, I tried to look at the GNU Make tutorial but could not find any relevant information - possibly because I simply do not know what to look for.
It isn't very elegant, but you could use a "canned recipe":
define MAKE_NODE_MODULES
npm install && touch node_modules
endef
node_modules: package.json
$(MAKE_NODE_MODULES)
%/node_modules: %/package.json
cd $* && $(MAKE_NODE_MODULES)
Related
how to write cd NAME_FOLDER and recursively search for it by name and then go to it if necessary (see below for more details).
the NAME_OF_FOLDER is unique so no worried about that.
but the challenging things are:
that it needs to search from the PARENT to the CHILD,
and if it didn't find it that way, search from CHILD to PARENT.
(or you can use any other logic if you think my logic is slow)
example folder
here is an example image of my folder:
possible scenarios
here are some scenarios:
if I am inside
./package -> don't run cd
./test -> cd ./package
./src -> cd ../ && cd ./package
./lib -> cd ../../ && cd ./package
and so on for every deep folder structure
docs:
../ means go from child to parent
./ means go from parent to child
why do I need it?
I am a javascript developer,
and I am using the sveltekit framework
to create a svelte package library.
and I need to publish that library to npm.
and this is ok.
but since I write a lot the same CLI codes.
I am changing the package.json's scripts object,
so I write only one time npm run build to run 6+ commands
{
...
"build": "
svelte-kit sync
&& svelte-package
&& npm version patch
&& cd ./package # only this I need to solve this (the others are solved)
&& npm publish
&& git commit
"
}
this is in one line, but for making you read it easily the code in multiple lines
here how it is in my code:
what does the build command should do?
the command generates a ./package folder always on the root of the folder
(where we can find package.json, .gitignore, ./src, etc...)
increase the number of versions automatically when we use the build command,
then... TODO:
do the script I need to access the ./package folder from every folder I am in now. (like cd ./package)
npm publish
my os?
windows 11 (but using bash with vscode) or also powershell will be good but prefer bash
any other details, I will tell you. thanks
For testing, I created this structure:
test/
package/
src/
lib/
routes/
Then I created that script:
#!/bin/bash
topdir="test"
while [[ $(basename "$(pwd)") != "$topdir" ]]
do
if [[ -d package ]]
then
cd package
pwd
else
cd ..
pwd
fi
done
if [[ -d package ]]
then
cd package
pwd
fi
This script "climbs" the directories until it finds a "package" directory. It the cd into it.
To use the script, you have to source it. If you execute it, it will change directories while the script is running, but it will not affect your current terminal.
So, lets assume the script is ~/bin/cd_package.bash
You would call it like this: . ~/bin/cd_package.bash
Note the pwd commands are just so you can follow what is going on and can be removed once you are convinced it works.
I'm trying to run a makefile as though it is in another directory:
For example something like this but actually works:
cd ../../ && include ./somdir1/somdir2/make_example.mk
Im running the following makefile
which needs to change dir to specific target and run there npm install
The problem is that I was able to see in the output that it print the directory (project/app) to the right directory but the installation (npm install) run on level up (project), why ?
For example
When I run it I see from cd $(DIR)/app
/Users/i03432/go/src/project/app
Now the second command is
npm install
And I got error that id doesn’t find the package json in the project path which is right... it’s only in the app path. Why the cd is not working ?
it try to find it here
/Users/i03432/go/src/project/package.json
and here is the package.json
/Users/i03432/go/src/project/app/package.json
The makefile is
module:
DIR=$(PWD)
#echo $(DIR)
cd $(DIR)/app
npm install
Every command in a rule is run in a single process (sub-shell). Every change you perform on the environment is hence tied to that particular line. You want to change your snippet to
cd $(PWD)/app && npm install
This command runs in a single subprocess and should yield the desired result. Note that this problem occurs for the definition of DIR, too, so you might want to move this a few lines up:
DIR = $(PWD)
module:
cd $(DIR) && npm install
This way, you are referring to a variable that make provides, and you don't rely upon subprocesses here.
Okay, I think I'm missing something in my makefile and it's causing me headaches. In my local build I call it with "dev:" and it does the dev target; Great, but I also want it to always do the "all:" target. When I call make dev it runs the dev but not the all, is there a terminology fail here?
here is my makefile
BUILD="build/"
STATIC="static/"
APP_NAME="Open World"
all:
# Remove the current build folder
rm -rf ${BUILD}
# Create the build directory
mkdir -p ${BUILD}
dev:
all
dev=${STATIC}dev
echo "Doing DEVELOPMENT build"
# Copy the package.json
cp ${dev}package.json ${BUILD}
prod:
echo "production"
The default (first) target is only run if no target is explicitly given. If you want it to run when another target is given then you need to make it a dependency of that target.
dev: all
I want to check if source file exist, so I assign TO_DIR=/dev/null in my gnu makefile.
APPS=a b c d
install:
cp $(APPS) $(TO_DIR)
for normal case, I'll run 'TO_DIR=~/bin make install'
for test case(just make sure file exist for copy), I'll run 'TO_DIR=/dev/null make install'
But it will failed, because /dev/null is not a pseudo directory.
Is there better solution?
You could do another make target, like this:
check:
file $(APPS) > /dev/null
file utility will check the existence of all the files and fail when any of these does not exist. Its output is excessive for this task, so we pipe it to /dev/null
You will run check like this:
make check
Here's a modification of spacediver's answer that just branches based on the value of TO_DIR
install:
[ -z "$(TO_DIR)" ] && make install_for_real || make check
install_for_real:
cp $(APPS) $(TO_DIR)
check:
file $(APPS) > /dev/null
This should do the check for either of
make install
make install TO_DIR=
but the real installation for
make install TO_DIR=/path/to/installation/dir