Running compilation scripts only if the source file is more recent than the compiled program












3














I am trying to do is create a bash script that will run another bash script to compile some programs only if the source has changed. What I have so far is a way to get the timestamps for each file in seconds since J2000 epoch:



#get a list of the source timestamps
sourceTimes=$(stat -f "%Sm" -t "%s" *.f)

#get a list of the program timestamps
exeTimes=$(stat -f "%Sm" -t "%s")


and an install script



./make_common_lib.bsh build
./make_common_lib.bsh install


I want to figure out how to create an if state such that (in semi-pseudocode)



if [any of $sourceTimes>$exeTimes];
then #run make_common_lib.bsh script
else #Do nothing
fi


My best guess so far is to somehow use read but I am not sure how I could index both variables at the same time.



If there is a really easy way to do this I apologize as I am very new to bash scripting, but so far none of my google searches have really returned anything useful.



Some more information:



The timestamp variables are in a format like



1432326068 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326068 1432326069 1432326069









share|improve this question




















  • 3




    Why not use make? It is explicitly designed to handle this requirement.
    – Stephen Kitt
    Aug 4 '15 at 16:11










  • I do realize this but I'm actually working with someone else's program and for some reason they didn't use make. The problem with make (I think) is that I would need to write out each dependency and there are more than 100 in the common libraries alone (and there's an entire other group of files that I would have to do the same thing for).
    – Andrew
    Aug 4 '15 at 16:26










  • That's what wildcards are for.
    – bahamat
    Aug 4 '15 at 19:58










  • @Andrew What people usually do is to automatically generate the list of dependencies (usually you run make depend or make dep to regenerate the list).
    – Gilles
    Aug 4 '15 at 23:10
















3














I am trying to do is create a bash script that will run another bash script to compile some programs only if the source has changed. What I have so far is a way to get the timestamps for each file in seconds since J2000 epoch:



#get a list of the source timestamps
sourceTimes=$(stat -f "%Sm" -t "%s" *.f)

#get a list of the program timestamps
exeTimes=$(stat -f "%Sm" -t "%s")


and an install script



./make_common_lib.bsh build
./make_common_lib.bsh install


I want to figure out how to create an if state such that (in semi-pseudocode)



if [any of $sourceTimes>$exeTimes];
then #run make_common_lib.bsh script
else #Do nothing
fi


My best guess so far is to somehow use read but I am not sure how I could index both variables at the same time.



If there is a really easy way to do this I apologize as I am very new to bash scripting, but so far none of my google searches have really returned anything useful.



Some more information:



The timestamp variables are in a format like



1432326068 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326068 1432326069 1432326069









share|improve this question




















  • 3




    Why not use make? It is explicitly designed to handle this requirement.
    – Stephen Kitt
    Aug 4 '15 at 16:11










  • I do realize this but I'm actually working with someone else's program and for some reason they didn't use make. The problem with make (I think) is that I would need to write out each dependency and there are more than 100 in the common libraries alone (and there's an entire other group of files that I would have to do the same thing for).
    – Andrew
    Aug 4 '15 at 16:26










  • That's what wildcards are for.
    – bahamat
    Aug 4 '15 at 19:58










  • @Andrew What people usually do is to automatically generate the list of dependencies (usually you run make depend or make dep to regenerate the list).
    – Gilles
    Aug 4 '15 at 23:10














3












3








3







I am trying to do is create a bash script that will run another bash script to compile some programs only if the source has changed. What I have so far is a way to get the timestamps for each file in seconds since J2000 epoch:



#get a list of the source timestamps
sourceTimes=$(stat -f "%Sm" -t "%s" *.f)

#get a list of the program timestamps
exeTimes=$(stat -f "%Sm" -t "%s")


and an install script



./make_common_lib.bsh build
./make_common_lib.bsh install


I want to figure out how to create an if state such that (in semi-pseudocode)



if [any of $sourceTimes>$exeTimes];
then #run make_common_lib.bsh script
else #Do nothing
fi


My best guess so far is to somehow use read but I am not sure how I could index both variables at the same time.



If there is a really easy way to do this I apologize as I am very new to bash scripting, but so far none of my google searches have really returned anything useful.



Some more information:



The timestamp variables are in a format like



1432326068 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326068 1432326069 1432326069









share|improve this question















I am trying to do is create a bash script that will run another bash script to compile some programs only if the source has changed. What I have so far is a way to get the timestamps for each file in seconds since J2000 epoch:



#get a list of the source timestamps
sourceTimes=$(stat -f "%Sm" -t "%s" *.f)

#get a list of the program timestamps
exeTimes=$(stat -f "%Sm" -t "%s")


and an install script



./make_common_lib.bsh build
./make_common_lib.bsh install


I want to figure out how to create an if state such that (in semi-pseudocode)



if [any of $sourceTimes>$exeTimes];
then #run make_common_lib.bsh script
else #Do nothing
fi


My best guess so far is to somehow use read but I am not sure how I could index both variables at the same time.



If there is a really easy way to do this I apologize as I am very new to bash scripting, but so far none of my google searches have really returned anything useful.



Some more information:



The timestamp variables are in a format like



1432326068 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326068 1432326069 1432326069






bash shell-script timestamps






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 2 days ago









Rui F Ribeiro

39.3k1479131




39.3k1479131










asked Aug 4 '15 at 15:45









AndrewAndrew

1183




1183








  • 3




    Why not use make? It is explicitly designed to handle this requirement.
    – Stephen Kitt
    Aug 4 '15 at 16:11










  • I do realize this but I'm actually working with someone else's program and for some reason they didn't use make. The problem with make (I think) is that I would need to write out each dependency and there are more than 100 in the common libraries alone (and there's an entire other group of files that I would have to do the same thing for).
    – Andrew
    Aug 4 '15 at 16:26










  • That's what wildcards are for.
    – bahamat
    Aug 4 '15 at 19:58










  • @Andrew What people usually do is to automatically generate the list of dependencies (usually you run make depend or make dep to regenerate the list).
    – Gilles
    Aug 4 '15 at 23:10














  • 3




    Why not use make? It is explicitly designed to handle this requirement.
    – Stephen Kitt
    Aug 4 '15 at 16:11










  • I do realize this but I'm actually working with someone else's program and for some reason they didn't use make. The problem with make (I think) is that I would need to write out each dependency and there are more than 100 in the common libraries alone (and there's an entire other group of files that I would have to do the same thing for).
    – Andrew
    Aug 4 '15 at 16:26










  • That's what wildcards are for.
    – bahamat
    Aug 4 '15 at 19:58










  • @Andrew What people usually do is to automatically generate the list of dependencies (usually you run make depend or make dep to regenerate the list).
    – Gilles
    Aug 4 '15 at 23:10








3




3




Why not use make? It is explicitly designed to handle this requirement.
– Stephen Kitt
Aug 4 '15 at 16:11




Why not use make? It is explicitly designed to handle this requirement.
– Stephen Kitt
Aug 4 '15 at 16:11












I do realize this but I'm actually working with someone else's program and for some reason they didn't use make. The problem with make (I think) is that I would need to write out each dependency and there are more than 100 in the common libraries alone (and there's an entire other group of files that I would have to do the same thing for).
– Andrew
Aug 4 '15 at 16:26




I do realize this but I'm actually working with someone else's program and for some reason they didn't use make. The problem with make (I think) is that I would need to write out each dependency and there are more than 100 in the common libraries alone (and there's an entire other group of files that I would have to do the same thing for).
– Andrew
Aug 4 '15 at 16:26












That's what wildcards are for.
– bahamat
Aug 4 '15 at 19:58




That's what wildcards are for.
– bahamat
Aug 4 '15 at 19:58












@Andrew What people usually do is to automatically generate the list of dependencies (usually you run make depend or make dep to regenerate the list).
– Gilles
Aug 4 '15 at 23:10




@Andrew What people usually do is to automatically generate the list of dependencies (usually you run make depend or make dep to regenerate the list).
– Gilles
Aug 4 '15 at 23:10










1 Answer
1






active

oldest

votes


















3














Your Build Script Method



If you want to keep to the "bash build method", then you are probably best off "touching" a file (touch lastbuild) when the build script is ran and completes the build. In addition the build script could then look for the file generated by touch (if it doesn't exist, assume a build is needed), or if it exists use find to see if any newer files exist:



find . -name "*.[ch]" -newer lastbuild


and then build if that output is 1 or more lines (could be checked with something like wc -l).



Using Make instead



This is best managed by something like a Makefile (specifically used to do this kind of dependency checking).



default: all

all: dependency1.o dependency2.o

dependency1.o: dependency1.c
./make_common_lib.bsh build

dependency2.o: dependency2.c
./make_common_lib.bsh build

install:
./make_common_lib.bsh install


Creating a dummy "build" script:



$ cat make_common_lib.bsh 
#! /bin/sh

echo "Build $1"


We can now run make:



$ make
./make_common_lib.bsh build
Build build
./make_common_lib.bsh build
Build build


You could also replace the ./make_common_lib.bsh build with the command that ./make_common_lib.bsh build would issue to build dependency1.o etc:



dependency1.o: dependency1.c
gcc -c dependency1.c


Makefiles also allow for symbol substitution, so you could declare the complier and compiler flags earlier in the Makefile:



CC=/usr/bin/gcc
CFLAGS=-O2 -Wall


and then make references to them in your rules:



dependency1.o: dependency1.c
$(CC) $(CFLAGS) -c dependency1.c


Note that the line that is indented after a dependency declaration must start with a tab and not spaces.



Shortening dependency rules list



The OP asked if it's possible to do shorter ways of declaring all dependencies. It is possible with a few tricks using GNU's make (note not all these will work with vanilla make).



You can do variable substitution. Given the declaration:



SRCS=dependency1.c dependency2.c dependency3.c


You can then create an objects rule using variable substitution:



OBJS=$(SRCS:.c=.o)


this will replace all .c's with .o's. In effect giving a line of the form:



OBJS=dependency1.o dependency2.o dependency3.o


You can then further do a shortening of the "compile command" using the special variables $< and $@:



.c.o:
$(CC) $(CFLAGS) -c $< -o $@


$< represents the prerequisite in GNU make parlance (or dependency as I've called it) and $@ the target, and so it will end up issuing:



/usr/bin/gcc -Wall -O2 -c dependency1.c  -o dependency1.o
/usr/bin/gcc -Wall -O2 -c dependency2.c -o dependency2.o
.
.
.


Putting this all together, with linking options and a command to link and compile the executable $(TARGET):



# Globals
CC=/usr/bin/gcc
CFLAGS=-Wall -O2
LDFLAGS=-L/usr/local/lib
LIBS=-ldependencylib

# declare all the sources
SRCS=dependency1.c dependency2.c

# declare the objects files using variable substitution (find .c and replace with .o)
OBJS=$(SRCS:.c=.o)

# Target executable name:
TARGET=myexefile

default: all

all: $(TARGET)
@echo Target has been built

$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) $(LIBS)

.c.o:
$(CC) $(CFLAGS) -c $< -o $@

install:
./make_common_lib.bsh install


Note that there are many things you can do with GNU make, and it is well documented here GNU Make Manual.






share|improve this answer























  • thanks for the response. I wish that the people who originally designed this software had done a straight up make file but they haven't. One question I have is, is there someway to do this without having to write out each dependency? There are over 100 separate files that need to be checked and I don't really want to have to write out a dependency for each one.
    – Andrew
    Aug 4 '15 at 16:25










  • I've updated the answer to use some GNU make shortcuts to handle multiple dependencies.
    – Drav Sloan
    Aug 4 '15 at 17:00











Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f220168%2frunning-compilation-scripts-only-if-the-source-file-is-more-recent-than-the-comp%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














Your Build Script Method



If you want to keep to the "bash build method", then you are probably best off "touching" a file (touch lastbuild) when the build script is ran and completes the build. In addition the build script could then look for the file generated by touch (if it doesn't exist, assume a build is needed), or if it exists use find to see if any newer files exist:



find . -name "*.[ch]" -newer lastbuild


and then build if that output is 1 or more lines (could be checked with something like wc -l).



Using Make instead



This is best managed by something like a Makefile (specifically used to do this kind of dependency checking).



default: all

all: dependency1.o dependency2.o

dependency1.o: dependency1.c
./make_common_lib.bsh build

dependency2.o: dependency2.c
./make_common_lib.bsh build

install:
./make_common_lib.bsh install


Creating a dummy "build" script:



$ cat make_common_lib.bsh 
#! /bin/sh

echo "Build $1"


We can now run make:



$ make
./make_common_lib.bsh build
Build build
./make_common_lib.bsh build
Build build


You could also replace the ./make_common_lib.bsh build with the command that ./make_common_lib.bsh build would issue to build dependency1.o etc:



dependency1.o: dependency1.c
gcc -c dependency1.c


Makefiles also allow for symbol substitution, so you could declare the complier and compiler flags earlier in the Makefile:



CC=/usr/bin/gcc
CFLAGS=-O2 -Wall


and then make references to them in your rules:



dependency1.o: dependency1.c
$(CC) $(CFLAGS) -c dependency1.c


Note that the line that is indented after a dependency declaration must start with a tab and not spaces.



Shortening dependency rules list



The OP asked if it's possible to do shorter ways of declaring all dependencies. It is possible with a few tricks using GNU's make (note not all these will work with vanilla make).



You can do variable substitution. Given the declaration:



SRCS=dependency1.c dependency2.c dependency3.c


You can then create an objects rule using variable substitution:



OBJS=$(SRCS:.c=.o)


this will replace all .c's with .o's. In effect giving a line of the form:



OBJS=dependency1.o dependency2.o dependency3.o


You can then further do a shortening of the "compile command" using the special variables $< and $@:



.c.o:
$(CC) $(CFLAGS) -c $< -o $@


$< represents the prerequisite in GNU make parlance (or dependency as I've called it) and $@ the target, and so it will end up issuing:



/usr/bin/gcc -Wall -O2 -c dependency1.c  -o dependency1.o
/usr/bin/gcc -Wall -O2 -c dependency2.c -o dependency2.o
.
.
.


Putting this all together, with linking options and a command to link and compile the executable $(TARGET):



# Globals
CC=/usr/bin/gcc
CFLAGS=-Wall -O2
LDFLAGS=-L/usr/local/lib
LIBS=-ldependencylib

# declare all the sources
SRCS=dependency1.c dependency2.c

# declare the objects files using variable substitution (find .c and replace with .o)
OBJS=$(SRCS:.c=.o)

# Target executable name:
TARGET=myexefile

default: all

all: $(TARGET)
@echo Target has been built

$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) $(LIBS)

.c.o:
$(CC) $(CFLAGS) -c $< -o $@

install:
./make_common_lib.bsh install


Note that there are many things you can do with GNU make, and it is well documented here GNU Make Manual.






share|improve this answer























  • thanks for the response. I wish that the people who originally designed this software had done a straight up make file but they haven't. One question I have is, is there someway to do this without having to write out each dependency? There are over 100 separate files that need to be checked and I don't really want to have to write out a dependency for each one.
    – Andrew
    Aug 4 '15 at 16:25










  • I've updated the answer to use some GNU make shortcuts to handle multiple dependencies.
    – Drav Sloan
    Aug 4 '15 at 17:00
















3














Your Build Script Method



If you want to keep to the "bash build method", then you are probably best off "touching" a file (touch lastbuild) when the build script is ran and completes the build. In addition the build script could then look for the file generated by touch (if it doesn't exist, assume a build is needed), or if it exists use find to see if any newer files exist:



find . -name "*.[ch]" -newer lastbuild


and then build if that output is 1 or more lines (could be checked with something like wc -l).



Using Make instead



This is best managed by something like a Makefile (specifically used to do this kind of dependency checking).



default: all

all: dependency1.o dependency2.o

dependency1.o: dependency1.c
./make_common_lib.bsh build

dependency2.o: dependency2.c
./make_common_lib.bsh build

install:
./make_common_lib.bsh install


Creating a dummy "build" script:



$ cat make_common_lib.bsh 
#! /bin/sh

echo "Build $1"


We can now run make:



$ make
./make_common_lib.bsh build
Build build
./make_common_lib.bsh build
Build build


You could also replace the ./make_common_lib.bsh build with the command that ./make_common_lib.bsh build would issue to build dependency1.o etc:



dependency1.o: dependency1.c
gcc -c dependency1.c


Makefiles also allow for symbol substitution, so you could declare the complier and compiler flags earlier in the Makefile:



CC=/usr/bin/gcc
CFLAGS=-O2 -Wall


and then make references to them in your rules:



dependency1.o: dependency1.c
$(CC) $(CFLAGS) -c dependency1.c


Note that the line that is indented after a dependency declaration must start with a tab and not spaces.



Shortening dependency rules list



The OP asked if it's possible to do shorter ways of declaring all dependencies. It is possible with a few tricks using GNU's make (note not all these will work with vanilla make).



You can do variable substitution. Given the declaration:



SRCS=dependency1.c dependency2.c dependency3.c


You can then create an objects rule using variable substitution:



OBJS=$(SRCS:.c=.o)


this will replace all .c's with .o's. In effect giving a line of the form:



OBJS=dependency1.o dependency2.o dependency3.o


You can then further do a shortening of the "compile command" using the special variables $< and $@:



.c.o:
$(CC) $(CFLAGS) -c $< -o $@


$< represents the prerequisite in GNU make parlance (or dependency as I've called it) and $@ the target, and so it will end up issuing:



/usr/bin/gcc -Wall -O2 -c dependency1.c  -o dependency1.o
/usr/bin/gcc -Wall -O2 -c dependency2.c -o dependency2.o
.
.
.


Putting this all together, with linking options and a command to link and compile the executable $(TARGET):



# Globals
CC=/usr/bin/gcc
CFLAGS=-Wall -O2
LDFLAGS=-L/usr/local/lib
LIBS=-ldependencylib

# declare all the sources
SRCS=dependency1.c dependency2.c

# declare the objects files using variable substitution (find .c and replace with .o)
OBJS=$(SRCS:.c=.o)

# Target executable name:
TARGET=myexefile

default: all

all: $(TARGET)
@echo Target has been built

$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) $(LIBS)

.c.o:
$(CC) $(CFLAGS) -c $< -o $@

install:
./make_common_lib.bsh install


Note that there are many things you can do with GNU make, and it is well documented here GNU Make Manual.






share|improve this answer























  • thanks for the response. I wish that the people who originally designed this software had done a straight up make file but they haven't. One question I have is, is there someway to do this without having to write out each dependency? There are over 100 separate files that need to be checked and I don't really want to have to write out a dependency for each one.
    – Andrew
    Aug 4 '15 at 16:25










  • I've updated the answer to use some GNU make shortcuts to handle multiple dependencies.
    – Drav Sloan
    Aug 4 '15 at 17:00














3












3








3






Your Build Script Method



If you want to keep to the "bash build method", then you are probably best off "touching" a file (touch lastbuild) when the build script is ran and completes the build. In addition the build script could then look for the file generated by touch (if it doesn't exist, assume a build is needed), or if it exists use find to see if any newer files exist:



find . -name "*.[ch]" -newer lastbuild


and then build if that output is 1 or more lines (could be checked with something like wc -l).



Using Make instead



This is best managed by something like a Makefile (specifically used to do this kind of dependency checking).



default: all

all: dependency1.o dependency2.o

dependency1.o: dependency1.c
./make_common_lib.bsh build

dependency2.o: dependency2.c
./make_common_lib.bsh build

install:
./make_common_lib.bsh install


Creating a dummy "build" script:



$ cat make_common_lib.bsh 
#! /bin/sh

echo "Build $1"


We can now run make:



$ make
./make_common_lib.bsh build
Build build
./make_common_lib.bsh build
Build build


You could also replace the ./make_common_lib.bsh build with the command that ./make_common_lib.bsh build would issue to build dependency1.o etc:



dependency1.o: dependency1.c
gcc -c dependency1.c


Makefiles also allow for symbol substitution, so you could declare the complier and compiler flags earlier in the Makefile:



CC=/usr/bin/gcc
CFLAGS=-O2 -Wall


and then make references to them in your rules:



dependency1.o: dependency1.c
$(CC) $(CFLAGS) -c dependency1.c


Note that the line that is indented after a dependency declaration must start with a tab and not spaces.



Shortening dependency rules list



The OP asked if it's possible to do shorter ways of declaring all dependencies. It is possible with a few tricks using GNU's make (note not all these will work with vanilla make).



You can do variable substitution. Given the declaration:



SRCS=dependency1.c dependency2.c dependency3.c


You can then create an objects rule using variable substitution:



OBJS=$(SRCS:.c=.o)


this will replace all .c's with .o's. In effect giving a line of the form:



OBJS=dependency1.o dependency2.o dependency3.o


You can then further do a shortening of the "compile command" using the special variables $< and $@:



.c.o:
$(CC) $(CFLAGS) -c $< -o $@


$< represents the prerequisite in GNU make parlance (or dependency as I've called it) and $@ the target, and so it will end up issuing:



/usr/bin/gcc -Wall -O2 -c dependency1.c  -o dependency1.o
/usr/bin/gcc -Wall -O2 -c dependency2.c -o dependency2.o
.
.
.


Putting this all together, with linking options and a command to link and compile the executable $(TARGET):



# Globals
CC=/usr/bin/gcc
CFLAGS=-Wall -O2
LDFLAGS=-L/usr/local/lib
LIBS=-ldependencylib

# declare all the sources
SRCS=dependency1.c dependency2.c

# declare the objects files using variable substitution (find .c and replace with .o)
OBJS=$(SRCS:.c=.o)

# Target executable name:
TARGET=myexefile

default: all

all: $(TARGET)
@echo Target has been built

$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) $(LIBS)

.c.o:
$(CC) $(CFLAGS) -c $< -o $@

install:
./make_common_lib.bsh install


Note that there are many things you can do with GNU make, and it is well documented here GNU Make Manual.






share|improve this answer














Your Build Script Method



If you want to keep to the "bash build method", then you are probably best off "touching" a file (touch lastbuild) when the build script is ran and completes the build. In addition the build script could then look for the file generated by touch (if it doesn't exist, assume a build is needed), or if it exists use find to see if any newer files exist:



find . -name "*.[ch]" -newer lastbuild


and then build if that output is 1 or more lines (could be checked with something like wc -l).



Using Make instead



This is best managed by something like a Makefile (specifically used to do this kind of dependency checking).



default: all

all: dependency1.o dependency2.o

dependency1.o: dependency1.c
./make_common_lib.bsh build

dependency2.o: dependency2.c
./make_common_lib.bsh build

install:
./make_common_lib.bsh install


Creating a dummy "build" script:



$ cat make_common_lib.bsh 
#! /bin/sh

echo "Build $1"


We can now run make:



$ make
./make_common_lib.bsh build
Build build
./make_common_lib.bsh build
Build build


You could also replace the ./make_common_lib.bsh build with the command that ./make_common_lib.bsh build would issue to build dependency1.o etc:



dependency1.o: dependency1.c
gcc -c dependency1.c


Makefiles also allow for symbol substitution, so you could declare the complier and compiler flags earlier in the Makefile:



CC=/usr/bin/gcc
CFLAGS=-O2 -Wall


and then make references to them in your rules:



dependency1.o: dependency1.c
$(CC) $(CFLAGS) -c dependency1.c


Note that the line that is indented after a dependency declaration must start with a tab and not spaces.



Shortening dependency rules list



The OP asked if it's possible to do shorter ways of declaring all dependencies. It is possible with a few tricks using GNU's make (note not all these will work with vanilla make).



You can do variable substitution. Given the declaration:



SRCS=dependency1.c dependency2.c dependency3.c


You can then create an objects rule using variable substitution:



OBJS=$(SRCS:.c=.o)


this will replace all .c's with .o's. In effect giving a line of the form:



OBJS=dependency1.o dependency2.o dependency3.o


You can then further do a shortening of the "compile command" using the special variables $< and $@:



.c.o:
$(CC) $(CFLAGS) -c $< -o $@


$< represents the prerequisite in GNU make parlance (or dependency as I've called it) and $@ the target, and so it will end up issuing:



/usr/bin/gcc -Wall -O2 -c dependency1.c  -o dependency1.o
/usr/bin/gcc -Wall -O2 -c dependency2.c -o dependency2.o
.
.
.


Putting this all together, with linking options and a command to link and compile the executable $(TARGET):



# Globals
CC=/usr/bin/gcc
CFLAGS=-Wall -O2
LDFLAGS=-L/usr/local/lib
LIBS=-ldependencylib

# declare all the sources
SRCS=dependency1.c dependency2.c

# declare the objects files using variable substitution (find .c and replace with .o)
OBJS=$(SRCS:.c=.o)

# Target executable name:
TARGET=myexefile

default: all

all: $(TARGET)
@echo Target has been built

$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) $(LIBS)

.c.o:
$(CC) $(CFLAGS) -c $< -o $@

install:
./make_common_lib.bsh install


Note that there are many things you can do with GNU make, and it is well documented here GNU Make Manual.







share|improve this answer














share|improve this answer



share|improve this answer








edited Aug 4 '15 at 18:17

























answered Aug 4 '15 at 16:18









Drav SloanDrav Sloan

9,61023138




9,61023138












  • thanks for the response. I wish that the people who originally designed this software had done a straight up make file but they haven't. One question I have is, is there someway to do this without having to write out each dependency? There are over 100 separate files that need to be checked and I don't really want to have to write out a dependency for each one.
    – Andrew
    Aug 4 '15 at 16:25










  • I've updated the answer to use some GNU make shortcuts to handle multiple dependencies.
    – Drav Sloan
    Aug 4 '15 at 17:00


















  • thanks for the response. I wish that the people who originally designed this software had done a straight up make file but they haven't. One question I have is, is there someway to do this without having to write out each dependency? There are over 100 separate files that need to be checked and I don't really want to have to write out a dependency for each one.
    – Andrew
    Aug 4 '15 at 16:25










  • I've updated the answer to use some GNU make shortcuts to handle multiple dependencies.
    – Drav Sloan
    Aug 4 '15 at 17:00
















thanks for the response. I wish that the people who originally designed this software had done a straight up make file but they haven't. One question I have is, is there someway to do this without having to write out each dependency? There are over 100 separate files that need to be checked and I don't really want to have to write out a dependency for each one.
– Andrew
Aug 4 '15 at 16:25




thanks for the response. I wish that the people who originally designed this software had done a straight up make file but they haven't. One question I have is, is there someway to do this without having to write out each dependency? There are over 100 separate files that need to be checked and I don't really want to have to write out a dependency for each one.
– Andrew
Aug 4 '15 at 16:25












I've updated the answer to use some GNU make shortcuts to handle multiple dependencies.
– Drav Sloan
Aug 4 '15 at 17:00




I've updated the answer to use some GNU make shortcuts to handle multiple dependencies.
– Drav Sloan
Aug 4 '15 at 17:00


















draft saved

draft discarded




















































Thanks for contributing an answer to Unix & Linux Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f220168%2frunning-compilation-scripts-only-if-the-source-file-is-more-recent-than-the-comp%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

How to reconfigure Docker Trusted Registry 2.x.x to use CEPH FS mount instead of NFS and other traditional...

is 'sed' thread safe

How to make a Squid Proxy server?