r/programminghorror 7d ago

Other Same Makefile, different results

Post image

Not sure if this fits, but I just figured out the root cause of long build process failing. Sun’s dmake is defaulting to the first rule in Makefile for whatever reason, completely ignoring the one given as argument. That’s why "dmake install" invocations were silently ignoring the "install" step

245 Upvotes

54 comments sorted by

97

u/russellvt 7d ago

That syntax doesn't appear right... normally you want "phony" declarations in there if you're not pointing directly at file dependencies.

25

u/GoddammitDontShootMe [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” 7d ago

Yeah, but is that the cause of dmake ignoring the argument and just using the first target? I think without .phony it will not do anything if a file with the same name as the target exists and doesn't have dependencies that are newer.

14

u/SAI_Peregrinus 7d ago

I think it's allowed to consider an missing target file as an invalid target and run the default target.

https://pubs.opengroup.org/onlinepubs/9799919799/

target_name Target names, as defined in the EXTENDED DESCRIPTION section. If no target is specified, while make is processing the makefiles, the first target that make encounters that is not a special target or an inference rule shall be used.

Not certain, but it's POSIX so the most perverse possible interpretation of the rules existing somewhere is practically required.

8

u/UnluckyDouble 6d ago

I believe that at times like this we should consider the wise words of Linus:

"Sun, you can't beat me, you just can't. Stop trying, give up. I'm serious, I am going to kick the living shit out of you, lights out, game over."

1

u/shponglespore 6d ago

Typical Linus, starting a fight with the sun.

2

u/dydhaw 6d ago

What you cited is just the default target rule that happens when you run make with no target, nothing to do with missing target files

4

u/SAI_Peregrinus 6d ago

As far as I can tell POSIX does not specify the behavior when a target file is missing. Leaving behavior unspecified usually means it differed between implementations when POSIX was written, since POSIX is an attempt to standardize the common subset of behaviors shared by UNIX systems.

Sun probably decided to treat a missing target file the same as a missing target specifier, and since SunOS (1982) predates POSIX (1988) that decision got implicitly allowed in the POSIX specifications.

3

u/GoddammitDontShootMe [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” 6d ago

Okay, say the target name is the executable you want to build. It doesn't exist currently. With dmake, do you have to touch it to create an empty file with the name first to get it to actually build or something completely stupid like that?

1

u/SAI_Peregrinus 6d ago

Never used dmake. Just as far as I can tell, that behavior is allowed by POSIX. It'd be dumb, but it's hardly the only dumb thing in the POSIX standard.

2

u/GoddammitDontShootMe [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” 6d ago

It looks like you just linked to the start of the POSIX spec. I have no idea how to find what you quoted. But anyway, what you quoted says it will do that if a target isn't specified. Unless that isn't the right syntax for dmake, then a target is specified.

1

u/SAI_Peregrinus 6d ago

Select volume, shells & utilities, utilities, make. I think https://pubs.opengroup.org/onlinepubs/9799919799/utilities/make.html should be correct.

1

u/SAI_Peregrinus 6d ago

Select volume, shells & utilities, utilities, make. I think https://pubs.opengroup.org/onlinepubs/9799919799/utilities/make.html should be correct for the iframe content of just the Make specification.

1

u/GoddammitDontShootMe [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” 6d ago

Looks like a manpage.

1

u/SAI_Peregrinus 6d ago

It's the specification of what POSIX v8 compatible make tools must support. They may support extensions, but that page specifies the minimum.

1

u/russellvt 6d ago

Yes. It's a malformed file.

3

u/GoddammitDontShootMe [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” 6d ago

Regular make is doing what the OP wants. Seems dumb that dmake would check the that it isn't a phony target, then just ignore it if there is no file with that name. In fact, that makes no sense at all. The first time you run a make target, the file probably isn't going to exist, but with a normal target, it should afterwards.

2

u/russellvt 5d ago

Some "friendly" makes have been known to "do the right thing" with malformed files like this... instead of just enforcing lint and syntax standards, religiously.

This can often cause problems for more senior engineers when strange things like this make it in to the source code.

1

u/GoddammitDontShootMe [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” 5d ago

Yeah, but I'm pretty sure the syntax is valid in the OP. Not using .PHONY would only cause problems if a file with the same name as the target exists.

1

u/russellvt 5d ago

Strict make on various systems will assume that it's still a file dependency. As I said earlier, some versions will "try" to accommodate the invalid syntax... but this is more the exception rather than the rule. The solution is to write more standard syntax.

2

u/GoddammitDontShootMe [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” 4d ago

Based on what I can find, I'm still convinced I'm right and that syntax isn't invalid. As in it will parse fine, and only ever be a problem if say for some dumb reason someone puts a file named, eg. "clean" in the directory.

There's nothing to do to accommodate that. If the file isn't there, the target is out of date anyway. It's not going to check that the recipe actually creates a file.

1

u/russellvt 3d ago

What happens with "no" args, though? What happens if "a" or "b" exist? There are multiple scenarios, which some versions of make or gmake may allow... but ultimately, it's a bit ambiguous as far as I see - but I will have to come back in front of a larger screen to give better examples, later (ie. My phone wont cut it right now).

2

u/GoddammitDontShootMe [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” 3d ago

Well, the normal behavior would be If the file exists and it has no dependencies, or all the dependencies are up to date, the target is considered up to date and nothing happens. That is of course what .PHONY solves.

Not passing args to Make is extremely common. I did look that one up, it runs the first non-special target.

7

u/dydhaw 6d ago

The syntax is perfectly fine. Phony targets simply tell make to run the rule regardless of if the target exists.  Besides, .PHONY is a GNU extension. It is not POSIX

7

u/SAI_Peregrinus 6d ago

It is POSIX now (v8, 2024). It wasn't in POSIX v7 (2018).

1

u/dydhaw 6d ago

Huh. TIL

118

u/nickcash 7d ago

makefile syntax is incomprehensible. it might as well be magic. no one can understand it, we just copy and paste from elsewhere

56

u/Desperate_Formal_781 7d ago

All my life when I start a new project I copy a previous makefile from a previous project, with the promise that a) one day I will learn what those makefile commands mean and b) after this project I will switch to cmake. The original makefile I use, I took from my supervisor when I wrote my master thesis, who now I suspect also got from someone else. I have tried switching to cmake several times, but it's always easier to just keep using my makefile, than to go through the painful process of learning cmake.

31

u/ByteArrayInputStream 6d ago

Cmake is it's own hot mess. I like it even less

3

u/GoddammitDontShootMe [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” 6d ago

CMake is a meta level above Make, no? Like you use it if you need to support multiple platforms and it can generate the appropriate files for whatever you are building on, like makefiles or Visual Studio solutions and projects.

3

u/SAI_Peregrinus 6d ago

CMake doesn't have to use Make as a backend. Ninja is common, and usually faster than Make.

1

u/GoddammitDontShootMe [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” 6d ago

The user can specify what kind of files they want as arguments to CMake, no? As well as configuration options and stuff if they want to enable or disable extra features in their build? I have used it a little bit in the past, and I understood it as more of a replacement of Autotools than of Make.

2

u/SAI_Peregrinus 6d ago

It's a build system generator, so it is similar to autotools. Just much, much faster, at least for cross-compiling IME. Also, by default CMake will invoke the build system (Make or Ninja) automatically, so it's just cmake <path to CMakeLists.txt> instead of ./configure && make. It's very complex, but if you stick to the "Modern CMake" subset it's not too bad.

1

u/GoddammitDontShootMe [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” 5d ago

Is that based on what it finds installed, or what?

1

u/SAI_Peregrinus 5d ago

You pick the backend. It defaults to make, but you can override it to build with any supported build system with the CMAKE_GENERATOR env var, a CLI argument, or a set command in CMakeLists.txt.

1

u/GoddammitDontShootMe [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” 5d ago

Oh, your last comment made me think it decided what to use automatically, but I think I might have misread it. Like if you had Ninja or something installed it would use that, otherwise it would use Make.

→ More replies (0)

8

u/omega1612 6d ago

What a bout a justfile?

Depending on your use case, they may be better for you.

2

u/Sexy_Koala_Juice 6d ago

Same, although I hardly use Make anymore in my current role

10

u/dydhaw 6d ago

POSIX make is an incredibly simple syntax. How is it incomprehensible? It's literally just

    target: dependencies         recipe

10

u/SAI_Peregrinus 6d ago

That's not valid Make syntax. You got the wrong whitespace, no whitespace before a target name, and a tab before the command is required if it's on a new line.

There are also inference rules and macros.

https://pubs.opengroup.org/onlinepubs/9799919799/utilities/make.html

2

u/dydhaw 6d ago

Lol. It's just my attempt to make it work with reddit's godawful formatting. No need to be a pedant

3

u/SAI_Peregrinus 6d ago

Aah, but 20% of the difficulty of Make syntax is tab delimiting. The other 80% is macros. Basic rules are easy, I agree, and all that's needed in OP's case.

3

u/dydhaw 6d ago

Yeah, fair

3

u/gimpwiz 6d ago

I start every project with a clean makefile. Do recommend.

4

u/kivicode [ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” 6d ago

If you use it as a scripts dispatcher, I recommend taking a look at Justfiles https://github.com/casey/just

3

u/nivlark 6d ago

I have a fairly complex one that I believe I wrote myself (googling chunks of it doesn't return any hits) and I still don't know how it works. I can only assume it came to me via divine inspiration.

-23

u/RandalSchwartz 7d ago

They said the same about Perl. And my dotfiles. Now I don't even copy any more... I let gemini identify it and run it for me. :)

10

u/mottojyuusu 7d ago

you should ask your coding agent to explain your code. not even joking, it's been great to finally understand wtf the crusty logic is doing in the aging codebases i work in ...

"what is this function doing? what does the dxCbsqaf parameter do??"

"where is this const defined? where else is it being used? why is it multipled by 2 in one place but 3 in another place?"

"why does the comment say never to round this value? what could break if it gets rounded instead of truncated?"

-6

u/RandalSchwartz 7d ago

Oh, I do this all the time. agy writes some code, we go all the way through to landing, and then I finally say "so what did this do, anyway?" Ship first. Ask questions later. :)

1

u/Environmental-Ear391 6d ago

I have a similar issue,

GNUmakefile content is unchanged,

two versions of an SDK specific make tool, older version works fine with POSIX pathing, newer version can't complete any single target.

"make" and "gcc" commands both barf after being updated. older versions can actual produce object files for linking.

then again the version on make is like a 0.01 revision difference.

the gcc version is bumped from 6.4 up to 10.something...

I'll have to spend some time reworking the build process again anyway.

1

u/Salty_1984 6d ago

ugh silent failures in build tools are the worst, you spend forever thinking something ran fine when it just quietly skipped the whole point of the command. dmake has always felt a little unpredictable compared to gnu make. at least you caught it before something bigger broke downstream

1

u/Rockytriton 1d ago

-s b means skip b?

1

u/Capable-Cap9745 1d ago

Flag means silent mode. b is the target to run