Programing

makefile이 대상을 재 빌드하도록 강제하는 방법

crosscheck 2020. 6. 5. 18:54
반응형

makefile이 대상을 재 빌드하도록 강제하는 방법


빌드하고 다른 makefile을 호출하는 makefile이 있습니다. 이 makefile은 작업을 수행하는 더 많은 makefile을 호출하므로 실제로 변경되지 않습니다. 따라서 프로젝트가 최신 상태로 유지되고 있다고 생각합니다.

dnetdev11 ~ # make
make: `release' is up to date.

makefile이 대상을 다시 빌드하도록하려면 어떻게해야합니까?

clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean


build = svn up ~/xxx                                                       \
        $(clean)                                                                \
        ~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace        \
        $(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1)                    \


release:
        $(build )

debug:
        $(build DEBUG=1)

clean:
        $(clean)

install:
        cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
        cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib

참고 : 무고한 사람을 보호하기 위해 이름이 제거되었습니다.

편집 : 최종 고정 버전 :

clean = $(MAKE) -f xxx_compile.workspace.mak clean;


build = svn up;                                         \
        $(clean)                                        \
        ./cbp2mak/cbp2mak -C . xxx_compile.workspace;   \
        $(MAKE) -f xxx_compile.workspace.mak    $(1);   \


.PHONY: release debug clean install

release:
        $(call build,)

debug:
        $(call build,DEBUG=1)

clean:
        $(clean)

install:
        cp ./source/xxx_utillity/release/xxx_util /usr/bin
        cp ./dlls/Release/xxxcore.so /usr/lib

하나 이상의 대상을 가짜라고 선언 할 수 있습니다 .

가짜 대상은 실제로 파일 이름이 아닌 대상입니다. 오히려 명시적인 요청을 할 때 레시피가 실행되는 이름 일뿐입니다. 가짜 대상을 사용해야하는 두 가지 이유가 있습니다. 동일한 이름의 파일과의 충돌을 피하고 성능을 향상시키는 것입니다.

...

A phony target should not be a prerequisite of a real target file; if it is, its recipe will be run every time make goes to update that file. As long as a phony target is never a prerequisite of a real target, the phony target recipe will be executed only when the phony target is a specified goal


The -B switch to make, whose long form is --always-make, tells make to disregard timestamps and make the specified targets. This may defeat the purpose of using make, but it may be what you need.


One trick that used to be documented in a Sun manual for make is to use a (non-existent) target '.FORCE'. You could do this by creating a file, force.mk, that contains:

.FORCE:
$(FORCE_DEPS): .FORCE

Then, assuming your existing makefile is called makefile, you could run:

make FORCE_DEPS=release -f force.mk -f makefile release

Since .FORCE does not exist, anything that depends on it will be out of date and rebuilt.

All this will work with any version of make; on Linux, you have GNU Make and can therefore use the .PHONY target as discussed.

It is also worth considering why make considers release to be up to date. This could be because you have a touch release command in amongst the commands executed; it could be because there is a file or directory called 'release' that exists and has no dependencies and so is up to date. Then there's the actual reason...


Someone else suggested .PHONY which is definitely correct. .PHONY should be used for any rule for which a date comparison between the input and the output is invalid. Since you don't have any targets of the form output: input you should use .PHONY for ALL of them!

All that said, you probably should define some variables at the top of your makefile for the various filenames, and define real make rules that have both input and output sections so you can use the benefits of make, namely that you'll only actually compile things that are necessary to copmile!

Edit: added example. Untested, but this is how you do .PHONY

.PHONY: clean    
clean:
    $(clean)

If I recall correctly, 'make' uses timestamps (file modification time) to determine whether or not a target is up to date. A common way to force a re-build is to update that timestamp, using the 'touch' command. You could try invoking 'touch' in your makefile to update the timestamp of one of the targets (perhaps one of those sub-makefiles), which might force Make to execute that command.


This simple technique will allow the makefile to function normally when forcing is not desired. Create a new target called force at the end of your makefile. The force target will touch a file that your default target depends on. In the example below, I have added touch myprogram.cpp. I also added a recursive call to make. This will cause the default target to get made every time you type make force.

yourProgram: yourProgram.cpp
       g++ -o yourProgram yourProgram.cpp 

force:
       touch yourProgram.cpp
       make

I tried this and it worked for me

add these lines to Makefile

clean:
    rm *.o output

new: clean
    $(MAKE)     #use variable $(MAKE) instead of make to get recursive make calls

save and now call

make new 

and it will recompile everything again

What happened?

1) 'new' calls clean. 'clean' do 'rm' which removes all object files that have the extension of '.o'.

2) 'new' calls 'make'. 'make' see that there is no '.o' files, so it creates all the '.o' again. then the linker links all of the .o file int one executable output

Good luck


As per Miller's Recursive Make Considered Harmful you should avoid calling $(MAKE)! In the case you show, it's harmless, because this isn't really a makefile, just a wrapper script, that might just as well have been written in Shell. But you say you continue like that at deeper recursion levels, so you've probably encountered the problems shown in that eye-opening essay.

Of course with GNU make it's cumbersome to avoid. And even though they are aware of this problem, it's their documented way of doing things.

OTOH, makepp was created as a solution for this problem. You can write your makefiles on a per directory level, yet they all get drawn together into a full view of your project.

But legacy makefiles are written recursively. So there's a workaround where $(MAKE) does nothing but channel the subrequests back to the main makepp process. Only if you do redundant or, worse, contradictory things between your submakes, you must request --traditional-recursive-make (which of course breaks this advantage of makepp). I don't know your other makefiles, but if they're cleanly written, with makepp necessary rebuilds should happen automatically, without the need for any hacks suggested here by others.


If you don't need to preserve any of the outputs you already successfully compiled

nmake /A 

rebuilds all


It actually depends on what the target is. If it is a phony target (i.e. the target is NOT related to a file) you should declare it as .PHONY.

If however the target is not a phony target but you just want to rebuild it for some reason (an example is when you use the __TIME__ preprocessing macro), you should use the FORCE scheme described in answers here.


http://www.gnu.org/software/make/manual/html_node/Force-Targets.html#Force-Targets


It was already mentioned, but thought I could add to using touch

If you touch all the source files to be compiled, the touch command changes the timestamps of a file to the system time the touch command was executed.

The source file timstamp is what make uses to "know" a file has changed, and needs to be re-compiled

For example: If the project was a c++ project, then do touch *.cpp, then run make again, and make should recompile the entire project.


make clean deletes all the already compiled object files.


On my Linux system (Centos 6.2), there is a significant difference between declaring the target .PHONY and creating a fake dependency on FORCE, when the rule actually does create a file matching the target. When the file must be regenerated every time, it required both the fake dependency FORCE on the file, and .PHONY for the fake dependency.

wrong:

date > $@

right:

FORCE
    date > $@
FORCE:
    .PHONY: FORCE

참고URL : https://stackoverflow.com/questions/816370/how-do-you-force-a-makefile-to-rebuild-a-target

반응형