Junbo Zheng
Junbo Zheng

Reputation: 15

compiler behaving abnormally for make

there is a very strange question about makefile, please let me describe it:

There are two files in my project, one file is makefile, the content of makefile is as follows:

context::
    @echo "hello makefile"

and the other is makefile.out, the content of the makefile.out file is as follows:

all:
    echo "hello makefile.out"

When I am going to compile my project, I will use make -f makefile.out to replace the make operation, because I want to call the makefile.out file, but it is strange What happened, when I executed make -f makefile.out, I would see such an operation on the console:

cp Makefile Makefile.out
hello makefile

and then my makefile.out file was modified as follows:

############################################################################
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.  The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################/


context::
    @echo "hello makefile"

As you have seen, this result is not I want it, but I don't know why this problem occurs.

I don’t know if anyone has encountered a similar problem with me. If so, can you tell me the solution code?

Upvotes: 0

Views: 61

Answers (1)

MadScientist
MadScientist

Reputation: 100876

I know why this happened.

First, there's a built-in rule for GNU make that shows how to build a %.out file from a % file; make -p will show:

%.out: %
#  recipe to execute (built-in):
        @rm -f $@
         cp $< $@

Second, make will always try to rebuild any makefile that it loads or includes; see the How Makefiles are Remade section of the GNU make manual.

So every time you run make -f makefile.out, then IF (and only if) the makefile is newer than makefile.out, make will copy makefile to makefile.out.

You can avoid this in one of a number of ways: any one of the following will solve the problem:

First and probably the best is to avoid having any important file in your system named with a .out suffix. That suffix is traditionally used for log files, output files, etc. There are many environments where those files are treated as temporary by default. It's just a bad name.

Second, you could create an explicit rule for makefile.out which would override the pattern rule:

makefile.out: ;

Third, you can remove that default rule by adding this to your makefile:

%.out: %

(no other prerequisites, no recipe). See Canceling Pattern Rules.

Fourth, you could remove ALL built-in pattern rules by adding the -r option to your MAKEFLAGS; add it to your makefile like this:

MAKEFLAGS += -r

Note this solution requires GNU make 4.0 or better.

Upvotes: 1

Related Questions